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.

231 lines
16 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #ifdef STORM_HAVE_GUROBI
  4. #include "src/solver/GurobiLpSolver.h"
  5. #include "src/exceptions/InvalidStateException.h"
  6. #include "src/exceptions/InvalidAccessException.h"
  7. #include "src/settings/SettingsManager.h"
  8. TEST(GurobiLpSolver, LPOptimizeMax) {
  9. storm::solver::GurobiLpSolver 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::generalSettings().getPrecision());
  25. double yValue = 0;
  26. ASSERT_NO_THROW(yValue = solver.getContinuousValue("y"));
  27. ASSERT_LT(std::abs(yValue - 6.5), storm::settings::generalSettings().getPrecision());
  28. double zValue = 0;
  29. ASSERT_NO_THROW(zValue = solver.getContinuousValue("z"));
  30. ASSERT_LT(std::abs(zValue - 2.75), storm::settings::generalSettings().getPrecision());
  31. double objectiveValue = 0;
  32. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  33. ASSERT_LT(std::abs(objectiveValue - 14.75), storm::settings::generalSettings().getPrecision());
  34. }
  35. TEST(GurobiLpSolver, LPOptimizeMin) {
  36. storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Minimize);
  37. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1));
  38. ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2));
  39. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("z", 1, 5.7, -1));
  40. ASSERT_NO_THROW(solver.update());
  41. 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)));
  42. 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)));
  43. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  44. ASSERT_NO_THROW(solver.update());
  45. ASSERT_NO_THROW(solver.optimize());
  46. ASSERT_TRUE(solver.isOptimal());
  47. ASSERT_FALSE(solver.isUnbounded());
  48. ASSERT_FALSE(solver.isInfeasible());
  49. double xValue = 0;
  50. ASSERT_NO_THROW(xValue = solver.getContinuousValue("x"));
  51. ASSERT_LT(std::abs(xValue - 1), storm::settings::generalSettings().getPrecision());
  52. double yValue = 0;
  53. ASSERT_NO_THROW(yValue = solver.getContinuousValue("y"));
  54. ASSERT_LT(std::abs(yValue - 0), storm::settings::generalSettings().getPrecision());
  55. double zValue = 0;
  56. ASSERT_NO_THROW(zValue = solver.getContinuousValue("z"));
  57. ASSERT_LT(std::abs(zValue - 5.7), storm::settings::generalSettings().getPrecision());
  58. double objectiveValue = 0;
  59. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  60. ASSERT_LT(std::abs(objectiveValue - (-6.7)), storm::settings::generalSettings().getPrecision());
  61. }
  62. TEST(GurobiLpSolver, MILPOptimizeMax) {
  63. storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  64. ASSERT_NO_THROW(solver.addBinaryVariable("x", -1));
  65. ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2));
  66. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  67. ASSERT_NO_THROW(solver.update());
  68. 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)));
  69. 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)));
  70. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  71. ASSERT_NO_THROW(solver.update());
  72. ASSERT_NO_THROW(solver.optimize());
  73. ASSERT_TRUE(solver.isOptimal());
  74. ASSERT_FALSE(solver.isUnbounded());
  75. ASSERT_FALSE(solver.isInfeasible());
  76. bool xValue = false;
  77. ASSERT_NO_THROW(xValue = solver.getBinaryValue("x"));
  78. ASSERT_EQ(true, xValue);
  79. int_fast64_t yValue = 0;
  80. ASSERT_NO_THROW(yValue = solver.getIntegerValue("y"));
  81. ASSERT_EQ(6, yValue);
  82. double zValue = 0;
  83. ASSERT_NO_THROW(zValue = solver.getContinuousValue("z"));
  84. ASSERT_LT(std::abs(zValue - 3), storm::settings::generalSettings().getPrecision());
  85. double objectiveValue = 0;
  86. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  87. ASSERT_LT(std::abs(objectiveValue - 14), storm::settings::generalSettings().getPrecision());
  88. }
  89. TEST(GurobiLpSolver, MILPOptimizeMin) {
  90. storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Minimize);
  91. ASSERT_NO_THROW(solver.addBinaryVariable("x", -1));
  92. ASSERT_NO_THROW(solver.addLowerBoundedIntegerVariable("y", 0, 2));
  93. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("z", 0, 5, -1));
  94. ASSERT_NO_THROW(solver.update());
  95. 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)));
  96. 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)));
  97. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  98. ASSERT_NO_THROW(solver.update());
  99. ASSERT_NO_THROW(solver.optimize());
  100. ASSERT_TRUE(solver.isOptimal());
  101. ASSERT_FALSE(solver.isUnbounded());
  102. ASSERT_FALSE(solver.isInfeasible());
  103. bool xValue = false;
  104. ASSERT_NO_THROW(xValue = solver.getBinaryValue("x"));
  105. ASSERT_EQ(true, xValue);
  106. int_fast64_t yValue = 0;
  107. ASSERT_NO_THROW(yValue = solver.getIntegerValue("y"));
  108. ASSERT_EQ(0, yValue);
  109. double zValue = 0;
  110. ASSERT_NO_THROW(zValue = solver.getContinuousValue("z"));
  111. ASSERT_LT(std::abs(zValue - 5), storm::settings::generalSettings().getPrecision());
  112. double objectiveValue = 0;
  113. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  114. ASSERT_LT(std::abs(objectiveValue - (-6)), storm::settings::generalSettings().getPrecision());
  115. }
  116. TEST(GurobiLpSolver, LPInfeasible) {
  117. storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  118. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1));
  119. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  120. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  121. ASSERT_NO_THROW(solver.update());
  122. 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)));
  123. 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)));
  124. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  125. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") > storm::expressions::Expression::createDoubleLiteral(7)));
  126. ASSERT_NO_THROW(solver.update());
  127. ASSERT_NO_THROW(solver.optimize());
  128. ASSERT_FALSE(solver.isOptimal());
  129. ASSERT_FALSE(solver.isUnbounded());
  130. ASSERT_TRUE(solver.isInfeasible());
  131. double xValue = 0;
  132. ASSERT_THROW(xValue = solver.getContinuousValue("x"), storm::exceptions::InvalidAccessException);
  133. double yValue = 0;
  134. ASSERT_THROW(yValue = solver.getContinuousValue("y"), storm::exceptions::InvalidAccessException);
  135. double zValue = 0;
  136. ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException);
  137. double objectiveValue = 0;
  138. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException);
  139. }
  140. TEST(GurobiLpSolver, MILPInfeasible) {
  141. storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  142. ASSERT_NO_THROW(solver.addBinaryVariable("x", -1));
  143. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  144. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  145. ASSERT_NO_THROW(solver.update());
  146. 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)));
  147. 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)));
  148. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  149. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") > storm::expressions::Expression::createDoubleLiteral(7)));
  150. ASSERT_NO_THROW(solver.update());
  151. ASSERT_NO_THROW(solver.optimize());
  152. ASSERT_FALSE(solver.isOptimal());
  153. ASSERT_FALSE(solver.isUnbounded());
  154. ASSERT_TRUE(solver.isInfeasible());
  155. bool xValue = false;
  156. ASSERT_THROW(xValue = solver.getBinaryValue("x"), storm::exceptions::InvalidAccessException);
  157. int_fast64_t yValue = 0;
  158. ASSERT_THROW(yValue = solver.getIntegerValue("y"), storm::exceptions::InvalidAccessException);
  159. double zValue = 0;
  160. ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException);
  161. double objectiveValue = 0;
  162. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException);
  163. }
  164. TEST(GurobiLpSolver, LPUnbounded) {
  165. storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  166. ASSERT_NO_THROW(solver.addBoundedContinuousVariable("x", 0, 1, -1));
  167. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  168. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  169. ASSERT_NO_THROW(solver.update());
  170. 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)));
  171. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  172. ASSERT_NO_THROW(solver.update());
  173. ASSERT_NO_THROW(solver.optimize());
  174. ASSERT_FALSE(solver.isOptimal());
  175. ASSERT_TRUE(solver.isUnbounded());
  176. ASSERT_FALSE(solver.isInfeasible());
  177. double xValue = 0;
  178. ASSERT_THROW(xValue = solver.getContinuousValue("x"), storm::exceptions::InvalidAccessException);
  179. double yValue = 0;
  180. ASSERT_THROW(yValue = solver.getContinuousValue("y"), storm::exceptions::InvalidAccessException);
  181. double zValue = 0;
  182. ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException);
  183. double objectiveValue = 0;
  184. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException);
  185. }
  186. TEST(GurobiLpSolver, MILPUnbounded) {
  187. storm::solver::GurobiLpSolver solver(storm::solver::LpSolver::ModelSense::Maximize);
  188. ASSERT_NO_THROW(solver.addBinaryVariable("x", -1));
  189. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("y", 0, 2));
  190. ASSERT_NO_THROW(solver.addLowerBoundedContinuousVariable("z", 0, 1));
  191. ASSERT_NO_THROW(solver.update());
  192. 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)));
  193. ASSERT_NO_THROW(solver.addConstraint("", storm::expressions::Expression::createDoubleVariable("y") - storm::expressions::Expression::createDoubleVariable("x") <= storm::expressions::Expression::createDoubleLiteral(5.5)));
  194. ASSERT_NO_THROW(solver.optimize());
  195. ASSERT_FALSE(solver.isOptimal());
  196. ASSERT_TRUE(solver.isUnbounded());
  197. ASSERT_FALSE(solver.isInfeasible());
  198. bool xValue = false;
  199. ASSERT_THROW(xValue = solver.getBinaryValue("x"), storm::exceptions::InvalidAccessException);
  200. int_fast64_t yValue = 0;
  201. ASSERT_THROW(yValue = solver.getIntegerValue("y"), storm::exceptions::InvalidAccessException);
  202. double zValue = 0;
  203. ASSERT_THROW(zValue = solver.getContinuousValue("z"), storm::exceptions::InvalidAccessException);
  204. double objectiveValue = 0;
  205. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidAccessException);
  206. }
  207. #endif