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.

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