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.

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