You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
17 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #include "src/solver/GlpkLpSolver.h"
  4. #include "src/exceptions/InvalidStateException.h"
  5. #include "src/exceptions/InvalidAccessException.h"
  6. #include "src/settings/Settings.h"
  7. TEST(GlpkLpSolver, LPOptimizeMax) {
  8. #ifdef STORM_HAVE_GLPK
  9. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  10. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1));
  11. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  12. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  13. ASSERT_NO_THROW(solver.update());
  14. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12)));
  15. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5)));
  16. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  17. ASSERT_NO_THROW(solver.update());
  18. ASSERT_NO_THROW(solver.optimize());
  19. ASSERT_TRUE(solver.isOptimal());
  20. ASSERT_FALSE(solver.isUnbounded());
  21. ASSERT_FALSE(solver.isInfeasible());
  22. double xValue = 0;
  23. ASSERT_NO_THROW(xValue = solver.getContinuousValue("x"));
  24. ASSERT_LT(std::abs(xValue - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  25. double yValue = 0;
  26. ASSERT_NO_THROW(yValue = solver.getContinuousValue("y"));
  27. ASSERT_LT(std::abs(yValue - 6.5), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  28. double zValue = 0;
  29. ASSERT_NO_THROW(zValue = solver.getContinuousValue("z"));
  30. ASSERT_LT(std::abs(zValue - 2.75), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  31. double objectiveValue = 0;
  32. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  33. ASSERT_LT(std::abs(objectiveValue - 14.75), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  34. #else
  35. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  36. #endif
  37. }
  38. TEST(GlpkLpSolver, LPOptimizeMin) {
  39. #ifdef STORM_HAVE_GLPK
  40. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Minimize);
  41. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1));
  42. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  43. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("z", 1, 5.7, -1));
  44. ASSERT_NO_THROW(solver.update());
  45. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12)));
  46. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5)));
  47. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  48. ASSERT_NO_THROW(solver.update());
  49. ASSERT_NO_THROW(solver.optimize());
  50. ASSERT_TRUE(solver.isOptimal());
  51. ASSERT_FALSE(solver.isUnbounded());
  52. ASSERT_FALSE(solver.isInfeasible());
  53. double xValue = 0;
  54. ASSERT_NO_THROW(xValue = solver.getContinuousValue("x"));
  55. ASSERT_LT(std::abs(xValue - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  56. double yValue = 0;
  57. ASSERT_NO_THROW(yValue = solver.getContinuousValue("y"));
  58. ASSERT_LT(std::abs(yValue - 0), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  59. double zValue = 0;
  60. ASSERT_NO_THROW(zValue = solver.getContinuousValue("z"));
  61. ASSERT_LT(std::abs(zValue - 5.7), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  62. double objectiveValue = 0;
  63. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  64. ASSERT_LT(std::abs(objectiveValue - (-6.7)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  65. #else
  66. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  67. #endif
  68. }
  69. TEST(GlpkLpSolver, MILPOptimizeMax) {
  70. #ifdef STORM_HAVE_GLPK
  71. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  72. ASSERT_NO_THROW(solver.addBinaryVariable("x", -1));
  73. ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2));
  74. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  75. ASSERT_NO_THROW(solver.update());
  76. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12)));
  77. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5)));
  78. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  79. ASSERT_NO_THROW(solver.update());
  80. ASSERT_NO_THROW(solver.optimize());
  81. ASSERT_TRUE(solver.isOptimal());
  82. ASSERT_FALSE(solver.isUnbounded());
  83. ASSERT_FALSE(solver.isInfeasible());
  84. bool xValue = false;
  85. ASSERT_NO_THROW(xValue = solver.getBinaryValue("x"));
  86. ASSERT_EQ(true, xValue);
  87. int_fast64_t yValue = 0;
  88. ASSERT_NO_THROW(yValue = solver.getIntegerValue("y"));
  89. ASSERT_EQ(6, yValue);
  90. double zValue = 0;
  91. ASSERT_NO_THROW(zValue = solver.getContinuousValue("z"));
  92. ASSERT_LT(std::abs(zValue - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  93. double objectiveValue = 0;
  94. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  95. ASSERT_LT(std::abs(objectiveValue - 14), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  96. #else
  97. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  98. #endif
  99. }
  100. TEST(GlpkLpSolver, MILPOptimizeMin) {
  101. #ifdef STORM_HAVE_GLPK
  102. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Minimize);
  103. ASSERT_NO_THROW(solver.addBinaryVariable("x", -1));
  104. ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2));
  105. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("z", 0, 5, -1));
  106. ASSERT_NO_THROW(solver.update());
  107. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12)));
  108. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5)));
  109. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  110. ASSERT_NO_THROW(solver.update());
  111. ASSERT_NO_THROW(solver.optimize());
  112. ASSERT_TRUE(solver.isOptimal());
  113. ASSERT_FALSE(solver.isUnbounded());
  114. ASSERT_FALSE(solver.isInfeasible());
  115. bool xValue = false;
  116. ASSERT_NO_THROW(xValue = solver.getBinaryValue("x"));
  117. ASSERT_EQ(true, xValue);
  118. int_fast64_t yValue = 0;
  119. ASSERT_NO_THROW(yValue = solver.getIntegerValue("y"));
  120. ASSERT_EQ(0, yValue);
  121. double zValue = 0;
  122. ASSERT_NO_THROW(zValue = solver.getContinuousValue("z"));
  123. ASSERT_LT(std::abs(zValue - 5), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  124. double objectiveValue = 0;
  125. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  126. ASSERT_LT(std::abs(objectiveValue - (-6)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  127. #else
  128. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  129. #endif
  130. }
  131. TEST(GlpkLpSolver, LPInfeasible) {
  132. #ifdef STORM_HAVE_GLPK
  133. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  134. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1));
  135. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  136. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  137. ASSERT_NO_THROW(solver.update());
  138. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12)));
  139. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5)));
  140. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  141. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") > storm::expressions::Expression::createDoubleLiteral(7)));
  142. ASSERT_NO_THROW(solver.update());
  143. ASSERT_NO_THROW(solver.optimize());
  144. ASSERT_FALSE(solver.isOptimal());
  145. ASSERT_FALSE(solver.isUnbounded());
  146. ASSERT_TRUE(solver.isInfeasible());
  147. double xValue = 0;
  148. ASSERT_THROW(xValue = solver.getContinuousValue("x"), storm::exceptions::InvalidAccessException);
  149. double yValue = 0;
  150. ASSERT_THROW(yValue = solver.getContinuousValue("y"), storm::exceptions::InvalidAccessException);
  151. double zValue = 0;
  152. ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException);
  153. double objectiveValue = 0;
  154. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException);
  155. #else
  156. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  157. #endif
  158. }
  159. TEST(GlpkLpSolver, MILPInfeasible) {
  160. #ifdef STORM_HAVE_GLPK
  161. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  162. ASSERT_NO_THROW(solver.addBinaryVariable("x", -1));
  163. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  164. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  165. ASSERT_NO_THROW(solver.update());
  166. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12)));
  167. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleLiteral(0.5) * storm::expressions::Expression::createDoubleVariable("y") + storm::expressions::Expression::createDoubleVariable("z") - storm::expressions::Expression::createDoubleVariable("x") == storm::expressions::Expression::createDoubleLiteral(5)));
  168. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  169. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") > storm::expressions::Expression::createDoubleLiteral(7)));
  170. ASSERT_NO_THROW(solver.update());
  171. ASSERT_NO_THROW(solver.optimize());
  172. ASSERT_FALSE(solver.isOptimal());
  173. ASSERT_FALSE(solver.isUnbounded());
  174. ASSERT_TRUE(solver.isInfeasible());
  175. bool xValue = false;
  176. ASSERT_THROW(xValue = solver.getBinaryValue("x"), storm::exceptions::InvalidAccessException);
  177. int_fast64_t yValue = 0;
  178. ASSERT_THROW(yValue = solver.getIntegerValue("y"), storm::exceptions::InvalidAccessException);
  179. double zValue = 0;
  180. ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException);
  181. double objectiveValue = 0;
  182. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException);
  183. #else
  184. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  185. #endif
  186. }
  187. TEST(GlpkLpSolver, LPUnbounded) {
  188. #ifdef STORM_HAVE_GLPK
  189. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  190. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1));
  191. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  192. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  193. ASSERT_NO_THROW(solver.update());
  194. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12)));
  195. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  196. ASSERT_NO_THROW(solver.update());
  197. ASSERT_NO_THROW(solver.optimize());
  198. ASSERT_FALSE(solver.isOptimal());
  199. ASSERT_TRUE(solver.isUnbounded());
  200. ASSERT_FALSE(solver.isInfeasible());
  201. double xValue = 0;
  202. ASSERT_THROW(xValue = solver.getContinuousValue("x"), storm::exceptions::InvalidAccessException);
  203. double yValue = 0;
  204. ASSERT_THROW(yValue = solver.getContinuousValue("y"), storm::exceptions::InvalidAccessException);
  205. double zValue = 0;
  206. ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException);
  207. double objectiveValue = 0;
  208. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException);
  209. #else
  210. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  211. #endif
  212. }
  213. TEST(GlpkLpSolver, MILPUnbounded) {
  214. #ifdef STORM_HAVE_GLPK
  215. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  216. ASSERT_NO_THROW(solver.addBinaryVariable("x", -1));
  217. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  218. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  219. ASSERT_NO_THROW(solver.update());
  220. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("z") <= storm::expressions::Expression::createDoubleLiteral(12)));
  221. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  222. ASSERT_NO_THROW(solver.update());
  223. ASSERT_NO_THROW(solver.optimize());
  224. ASSERT_FALSE(solver.isOptimal());
  225. ASSERT_TRUE(solver.isUnbounded());
  226. ASSERT_FALSE(solver.isInfeasible());
  227. bool xValue = false;
  228. ASSERT_THROW(xValue = solver.getBinaryValue("x"), storm::exceptions::InvalidAccessException);
  229. int_fast64_t yValue = 0;
  230. ASSERT_THROW(yValue = solver.getIntegerValue("y"), storm::exceptions::InvalidAccessException);
  231. double zValue = 0;
  232. ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException);
  233. double objectiveValue = 0;
  234. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException);
  235. #else
  236. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  237. #endif
  238. }