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.

246 lines
12 KiB

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