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.

269 lines
15 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/settings/Settings.h"
  6. TEST(GlpkLpSolver, LPOptimizeMax) {
  7. #ifdef STORM_HAVE_GLPK
  8. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE);
  9. uint_fast64_t xIndex;
  10. ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1));
  11. uint_fast64_t yIndex;
  12. ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2));
  13. uint_fast64_t zIndex;
  14. ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1));
  15. ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12));
  16. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5));
  17. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));
  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(xIndex));
  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(yIndex));
  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(zIndex));
  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::MINIMIZE);
  41. uint_fast64_t xIndex;
  42. ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1));
  43. uint_fast64_t yIndex;
  44. ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2));
  45. uint_fast64_t zIndex;
  46. ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::BOUNDED, 1, 5.7, -1));
  47. ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12));
  48. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5));
  49. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));
  50. ASSERT_NO_THROW(solver.optimize());
  51. ASSERT_TRUE(solver.isOptimal());
  52. ASSERT_FALSE(solver.isUnbounded());
  53. ASSERT_FALSE(solver.isInfeasible());
  54. double xValue = 0;
  55. ASSERT_NO_THROW(xValue = solver.getContinuousValue(xIndex));
  56. ASSERT_LT(std::abs(xValue - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  57. double yValue = 0;
  58. ASSERT_NO_THROW(yValue = solver.getContinuousValue(yIndex));
  59. ASSERT_LT(std::abs(yValue - 0), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  60. double zValue = 0;
  61. ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex));
  62. ASSERT_LT(std::abs(zValue - 5.7), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  63. double objectiveValue = 0;
  64. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  65. ASSERT_LT(std::abs(objectiveValue - (-6.7)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  66. #else
  67. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  68. #endif
  69. }
  70. TEST(GlpkLpSolver, MILPOptimizeMax) {
  71. #ifdef STORM_HAVE_GLPK
  72. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE);
  73. uint_fast64_t xIndex;
  74. ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1));
  75. uint_fast64_t yIndex;
  76. ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2));
  77. uint_fast64_t zIndex;
  78. ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1));
  79. ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12));
  80. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5));
  81. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));
  82. ASSERT_NO_THROW(solver.optimize());
  83. ASSERT_TRUE(solver.isOptimal());
  84. ASSERT_FALSE(solver.isUnbounded());
  85. ASSERT_FALSE(solver.isInfeasible());
  86. bool xValue = false;
  87. ASSERT_NO_THROW(xValue = solver.getBinaryValue(xIndex));
  88. ASSERT_EQ(true, xValue);
  89. int_fast64_t yValue = 0;
  90. ASSERT_NO_THROW(yValue = solver.getIntegerValue(yIndex));
  91. ASSERT_EQ(6, yValue);
  92. double zValue = 0;
  93. ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex));
  94. ASSERT_LT(std::abs(zValue - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  95. double objectiveValue = 0;
  96. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  97. ASSERT_LT(std::abs(objectiveValue - 14), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  98. #else
  99. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  100. #endif
  101. }
  102. TEST(GlpkLpSolver, MILPOptimizeMin) {
  103. #ifdef STORM_HAVE_GLPK
  104. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MINIMIZE);
  105. uint_fast64_t xIndex;
  106. ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1));
  107. uint_fast64_t yIndex;
  108. ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2));
  109. uint_fast64_t zIndex;
  110. ASSERT_NO_THROW(zIndex = solver.createIntegerVariable("z", storm::solver::LpSolver::VariableType::BOUNDED, 0, 5, -1));
  111. ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12));
  112. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5));
  113. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));
  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(xIndex));
  120. ASSERT_EQ(true, xValue);
  121. int_fast64_t yValue = 0;
  122. ASSERT_NO_THROW(yValue = solver.getIntegerValue(yIndex));
  123. ASSERT_EQ(0, yValue);
  124. double zValue = 0;
  125. ASSERT_NO_THROW(zValue = solver.getContinuousValue(zIndex));
  126. ASSERT_LT(std::abs(zValue - 5), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  127. double objectiveValue = 0;
  128. ASSERT_NO_THROW(objectiveValue = solver.getObjectiveValue());
  129. ASSERT_LT(std::abs(objectiveValue - (-6)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());
  130. #else
  131. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  132. #endif
  133. }
  134. TEST(GlpkLpSolver, LPInfeasible) {
  135. #ifdef STORM_HAVE_GLPK
  136. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE);
  137. uint_fast64_t xIndex;
  138. ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1));
  139. uint_fast64_t yIndex;
  140. ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2));
  141. uint_fast64_t zIndex;
  142. ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1));
  143. ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12));
  144. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5));
  145. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));
  146. ASSERT_NO_THROW(solver.addConstraint("", {yIndex}, {1}, storm::solver::LpSolver::BoundType::GREATER_EQUAL, 7));
  147. ASSERT_NO_THROW(solver.optimize());
  148. ASSERT_FALSE(solver.isOptimal());
  149. ASSERT_FALSE(solver.isUnbounded());
  150. ASSERT_TRUE(solver.isInfeasible());
  151. double xValue = 0;
  152. ASSERT_THROW(xValue = solver.getContinuousValue(xIndex), storm::exceptions::InvalidStateException);
  153. double yValue = 0;
  154. ASSERT_THROW(yValue = solver.getContinuousValue(yIndex), storm::exceptions::InvalidStateException);
  155. double zValue = 0;
  156. ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException);
  157. double objectiveValue = 0;
  158. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException);
  159. #else
  160. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  161. #endif
  162. }
  163. TEST(GlpkLpSolver, MILPInfeasible) {
  164. #ifdef STORM_HAVE_GLPK
  165. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE);
  166. uint_fast64_t xIndex;
  167. ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1));
  168. uint_fast64_t yIndex;
  169. ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2));
  170. uint_fast64_t zIndex;
  171. ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1));
  172. ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12));
  173. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5));
  174. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));
  175. ASSERT_NO_THROW(solver.addConstraint("", {yIndex}, {1}, storm::solver::LpSolver::BoundType::GREATER_EQUAL, 7));
  176. ASSERT_NO_THROW(solver.optimize());
  177. ASSERT_FALSE(solver.isOptimal());
  178. ASSERT_FALSE(solver.isUnbounded());
  179. ASSERT_TRUE(solver.isInfeasible());
  180. bool xValue = false;
  181. ASSERT_THROW(xValue = solver.getBinaryValue(xIndex), storm::exceptions::InvalidStateException);
  182. int_fast64_t yValue = 0;
  183. ASSERT_THROW(yValue = solver.getIntegerValue(yIndex), storm::exceptions::InvalidStateException);
  184. double zValue = 0;
  185. ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException);
  186. double objectiveValue = 0;
  187. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException);
  188. #else
  189. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  190. #endif
  191. }
  192. TEST(GlpkLpSolver, LPUnbounded) {
  193. #ifdef STORM_HAVE_GLPK
  194. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE);
  195. uint_fast64_t xIndex;
  196. ASSERT_NO_THROW(xIndex = solver.createContinuousVariable("x", storm::solver::LpSolver::VariableType::BOUNDED, 0, 1, -1));
  197. uint_fast64_t yIndex;
  198. ASSERT_NO_THROW(yIndex = solver.createContinuousVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2));
  199. uint_fast64_t zIndex;
  200. ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1));
  201. ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12));
  202. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));
  203. ASSERT_NO_THROW(solver.optimize());
  204. ASSERT_FALSE(solver.isOptimal());
  205. ASSERT_TRUE(solver.isUnbounded());
  206. ASSERT_FALSE(solver.isInfeasible());
  207. double xValue = 0;
  208. ASSERT_THROW(xValue = solver.getContinuousValue(xIndex), storm::exceptions::InvalidStateException);
  209. double yValue = 0;
  210. ASSERT_THROW(yValue = solver.getContinuousValue(yIndex), storm::exceptions::InvalidStateException);
  211. double zValue = 0;
  212. ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException);
  213. double objectiveValue = 0;
  214. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException);
  215. #else
  216. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  217. #endif
  218. }
  219. TEST(GlpkLpSolver, MILPUnbounded) {
  220. #ifdef STORM_HAVE_GLPK
  221. storm::solver::GlpkLpSolver solver(storm::solver::LpSolver::MAXIMIZE);
  222. uint_fast64_t xIndex;
  223. ASSERT_NO_THROW(xIndex = solver.createBinaryVariable("x", -1));
  224. uint_fast64_t yIndex;
  225. ASSERT_NO_THROW(yIndex = solver.createIntegerVariable("y", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 2));
  226. uint_fast64_t zIndex;
  227. ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1));
  228. ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12));
  229. ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));
  230. ASSERT_NO_THROW(solver.optimize());
  231. ASSERT_FALSE(solver.isOptimal());
  232. ASSERT_TRUE(solver.isUnbounded());
  233. ASSERT_FALSE(solver.isInfeasible());
  234. bool xValue = false;
  235. ASSERT_THROW(xValue = solver.getBinaryValue(xIndex), storm::exceptions::InvalidStateException);
  236. int_fast64_t yValue = 0;
  237. ASSERT_THROW(yValue = solver.getIntegerValue(yIndex), storm::exceptions::InvalidStateException);
  238. double zValue = 0;
  239. ASSERT_THROW(zValue = solver.getContinuousValue(zIndex), storm::exceptions::InvalidStateException);
  240. double objectiveValue = 0;
  241. ASSERT_THROW(objectiveValue = solver.getObjectiveValue(), storm::exceptions::InvalidStateException);
  242. #else
  243. ASSERT_TRUE(false) << "StoRM built without glpk support.";
  244. #endif
  245. }