c++ or-tools:琐碎的问题在cpp中不可行,但在python中有效

4zcjmb1e  于 2024-01-09  发布在  Python
关注(0)|答案(1)|浏览(244)

我在一个优化问题中遇到了一个问题,在这个问题中,简单可行的约束导致我的cpp程序在试图求解时返回“不可行”。
为了进行演示,我创建了一个护士排班优化程序,其中包含3名护士和5个插槽。
我有两个微不足道的约束:1)第一个护士占用第一个插槽,2)每个插槽最多允许一个护士。
当一次使用一个约束时,这些约束会导致or-tools返回一个可行的解,但是当我同时使用两个约束时,我得到的是一个不可行的解。
当我设置第一个约束(cp_model.AddEquality(LinearExpr(slots[0][0]), 1);)时,我怀疑我在某种程度上误用了AddEquality,但我无法找出问题所在。
请帮帮我

  1. #include <iostream>
  2. #include <vector>
  3. #include "ortools/sat/cp_model.h"
  4. #include "ortools/sat/sat_parameters.pb.h"
  5. namespace operations_research {
  6. namespace sat {
  7. void slots(bool add_sum, bool add_const) {
  8. CpModelBuilder cp_model;
  9. const int num_nurses = 3;
  10. const int num_slots = 5;
  11. std::vector<std::vector<IntVar>> slots(num_nurses);
  12. for (int n = 0; n < num_nurses; n++) {
  13. for (int d = 0; d < num_slots; d++) {
  14. const IntVar var = cp_model.NewIntVar({0, 1});
  15. slots[n].push_back(var);
  16. }
  17. }
  18. if (add_const) {
  19. // trival constraint
  20. cp_model.AddEquality(LinearExpr(slots[0][0]), 1);
  21. }
  22. if (add_sum) {
  23. // make the first row sum to one; should be trivial too
  24. std::vector<IntVar> this_nurse_vals(num_nurses);
  25. for (int n = 0; n < num_nurses; n++) {
  26. const IntVar var = slots[n][0];
  27. this_nurse_vals.push_back(var);
  28. }
  29. cp_model.AddEquality(LinearExpr::Sum(this_nurse_vals), 1);
  30. }
  31. // solve
  32. const CpSolverResponse response = Solve(cp_model.Build());
  33. LOG(INFO) << CpSolverResponseStats(response);
  34. for (int d = 0; d < num_slots; d++) {
  35. for (int n = 0; n < num_nurses; n++) {
  36. std::cout << SolutionIntegerValue(response, slots[n][d]);
  37. }
  38. std::cout << std::endl;
  39. }
  40. std::cout << std::endl;
  41. // [END solve]
  42. }
  43. } // namespace sat
  44. } // namespace operations_research
  45. // ----- MAIN -----
  46. int main(int argc, char **argv) {
  47. operations_research::sat::slots(false, true); // works
  48. operations_research::sat::slots(true, false); // works
  49. operations_research::sat::slots(true, true); // infeasible
  50. return EXIT_SUCCESS;
  51. }
  52. // [END program]

字符串
在python中运行良好的相同程序:

  1. from ortools.sat.python import cp_model
  2. num_nurses = 3
  3. num_slots = 5
  4. model = cp_model.CpModel()
  5. # make vars
  6. slots = {}
  7. for n in range(num_nurses):
  8. for d in range(num_slots):
  9. slots[(n, d)] = model.NewIntVar(0, 1, "slot")
  10. model.Add(slots[(0, 0)] == 1)
  11. model.Add(sum(slots[(n, 0)] for n in range(num_nurses)) == 1)
  12. solver = cp_model.CpSolver()
  13. solver.Solve(model)
  14. solution = []
  15. for d in range(num_slots):
  16. solution.append([])
  17. for n in range(num_nurses):
  18. solution[d].append(solver.Value(slots[(n, d)]))
  19. print(solution)

eiee3dmh

eiee3dmh1#

你的护士太多了。
这一点:

  1. std::vector<IntVar> this_nurse_vals(num_nurses);

字符串
创建一个包含num_nurses元素的向量。
然后你push_back另一个num_nurses元素,给你两倍于你想要的。
或者从一个空的vector开始,并将push_back插入其中:

  1. std::vector<IntVar> this_nurse_vals;
  2. for (int n = 0; n < num_nurses; n++) {
  3. this_nurse_vals.push_back(IntVar(slots[n][0]));
  4. }


或者从一个“完整的”向量开始,并将其赋值为:

  1. std::vector<IntVar> this_nurse_vals(num_nurses);
  2. for (int n = 0; n < num_nurses; n++) {
  3. this_nurse_vals[n] = IntVar(slots[n][0]);
  4. }

展开查看全部

相关问题