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.

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