or-tools 0.4.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e557f98fc061c46799334f589a41f1592da361bce8a6e199120d3425efe67c0a
4
- data.tar.gz: be6fa049625b6d9aae8134b34a4731053b1e3b12c7481dd041bdb98e40648c1d
3
+ metadata.gz: 0a848cf114ad9ca6d778daf6cb19ff78b3c4015c4b39eb6b6274e61c4175b87d
4
+ data.tar.gz: bb3c6b79787a0793367ab900b95caf8fa0b242f76fd0c2adc2a434056648e1e9
5
5
  SHA512:
6
- metadata.gz: 5f5542b967fc7fd25afa4598bcfa99c17978e8020ced4af449ca00e8e7e20f2aeb1e5de2b6d562a60cd880afa14f9ea383c12a3d3fe7434dc2f4837d98e18d24
7
- data.tar.gz: 69506b406afe60200592f5b526ce617fba45d8581e253ca12b143d243aa1d9fdda5c2e122e24d5dd516e9e141a542ed5eaef834861ccfa3917693d8f1971ffca
6
+ metadata.gz: 571acd73a42c0e3181e256d30c42f8b18d7bcf01ada104a181c7e2b4034358d14409ba1904017c31a4c3c07b15744ac8eeb9422f5d8074c9e2c818bc38bf7ec3
7
+ data.tar.gz: 762bfc272f728f1b04af4d153591b52798415c2729d4111445779b66c356b9714a4b88eb8ba6546bc43c017184868cf9adcb91df980c105be3a72f2555a8d7f2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,30 @@
1
+ ## 0.5.1 (2021-05-23)
2
+
3
+ - Updated to Rice 4
4
+
5
+ ## 0.5.0 (2021-04-30)
6
+
7
+ - Updated OR-Tools to 9.0
8
+ - Added binary installation for CentOS 7
9
+ - Added `sufficient_assumptions_for_infeasibility` to `CpSolver`
10
+
11
+ ## 0.4.3 (2021-03-26)
12
+
13
+ - Added `add_assumption`, `add_assumptions`, and `clear_assumptions` to `CpModel`
14
+ - Added `add_hint` and `clear_hints` to `CpModel`
15
+ - Added `only_enforce_if` to `SatConstraint`
16
+ - Fixed installation for Debian
17
+
18
+ ## 0.4.2 (2021-03-03)
19
+
20
+ - Updated OR-Tools to 8.2
21
+
22
+ ## 0.4.1 (2021-02-23)
23
+
24
+ - Added solution printers
25
+ - Improved `inspect` and `to_s` for `CpModel`
26
+ - Improved constraint construction
27
+
1
28
  ## 0.4.0 (2021-01-14)
2
29
 
3
30
  - Updated OR-Tools to 8.1
data/README.md CHANGED
@@ -267,7 +267,7 @@ Constraint Optimization
267
267
  - [Solving an Optimization Problem](#solving-an-optimization-problem)
268
268
  - [Cryptarithmetic](#cryptarithmetic)
269
269
  - [The N-queens Problem](#the-n-queens-problem)
270
- - [Setting Solver Limits](#setting-solver-limits) [master]
270
+ - [Setting Solver Limits](#setting-solver-limits)
271
271
 
272
272
  Assignment
273
273
 
@@ -0,0 +1,36 @@
1
+ #include <ortools/graph/assignment.h>
2
+
3
+ #include "ext.h"
4
+
5
+ using operations_research::SimpleLinearSumAssignment;
6
+
7
+ using Rice::Symbol;
8
+
9
+ void init_assignment(Rice::Module& m) {
10
+ Rice::define_class_under<SimpleLinearSumAssignment>(m, "LinearSumAssignment")
11
+ .define_constructor(Rice::Constructor<SimpleLinearSumAssignment>())
12
+ .define_method("add_arc_with_cost", &SimpleLinearSumAssignment::AddArcWithCost)
13
+ .define_method("num_nodes", &SimpleLinearSumAssignment::NumNodes)
14
+ .define_method("num_arcs", &SimpleLinearSumAssignment::NumArcs)
15
+ .define_method("left_node", &SimpleLinearSumAssignment::LeftNode)
16
+ .define_method("right_node", &SimpleLinearSumAssignment::RightNode)
17
+ .define_method("cost", &SimpleLinearSumAssignment::Cost)
18
+ .define_method("optimal_cost", &SimpleLinearSumAssignment::OptimalCost)
19
+ .define_method("right_mate", &SimpleLinearSumAssignment::RightMate)
20
+ .define_method("assignment_cost", &SimpleLinearSumAssignment::AssignmentCost)
21
+ .define_method(
22
+ "solve",
23
+ [](SimpleLinearSumAssignment& self) {
24
+ auto status = self.Solve();
25
+
26
+ if (status == SimpleLinearSumAssignment::Status::OPTIMAL) {
27
+ return Symbol("optimal");
28
+ } else if (status == SimpleLinearSumAssignment::Status::INFEASIBLE) {
29
+ return Symbol("infeasible");
30
+ } else if (status == SimpleLinearSumAssignment::Status::POSSIBLE_OVERFLOW) {
31
+ return Symbol("possible_overflow");
32
+ } else {
33
+ throw std::runtime_error("Unknown status");
34
+ }
35
+ });
36
+ }
@@ -0,0 +1,48 @@
1
+ #include <ortools/algorithms/knapsack_solver.h>
2
+
3
+ #include "ext.h"
4
+
5
+ using operations_research::KnapsackSolver;
6
+
7
+ using Rice::Array;
8
+ using Rice::Object;
9
+ using Rice::Symbol;
10
+
11
+ namespace Rice::detail
12
+ {
13
+ template<>
14
+ struct Type<KnapsackSolver::SolverType>
15
+ {
16
+ static bool verify()
17
+ {
18
+ return true;
19
+ }
20
+ };
21
+
22
+ template<>
23
+ class From_Ruby<KnapsackSolver::SolverType>
24
+ {
25
+ public:
26
+ KnapsackSolver::SolverType convert(VALUE x)
27
+ {
28
+ auto s = Symbol(x).str();
29
+ if (s == "branch_and_bound") {
30
+ return KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER;
31
+ } else {
32
+ throw std::runtime_error("Unknown solver type: " + s);
33
+ }
34
+ }
35
+ };
36
+ }
37
+
38
+ void init_bin_packing(Rice::Module& m) {
39
+ Rice::define_class_under<KnapsackSolver>(m, "KnapsackSolver")
40
+ .define_constructor(Rice::Constructor<KnapsackSolver, KnapsackSolver::SolverType, std::string>())
41
+ .define_method("_solve", &KnapsackSolver::Solve)
42
+ .define_method("best_solution_contains?", &KnapsackSolver::BestSolutionContains)
43
+ .define_method(
44
+ "init",
45
+ [](KnapsackSolver& self, std::vector<int64_t> values, std::vector<std::vector<int64_t>> weights, std::vector<int64_t> capacities) {
46
+ self.Init(values, weights, capacities);
47
+ });
48
+ }
@@ -0,0 +1,416 @@
1
+ #include <google/protobuf/text_format.h>
2
+ #include <ortools/sat/cp_model.h>
3
+
4
+ #include "ext.h"
5
+
6
+ using operations_research::sat::BoolVar;
7
+ using operations_research::sat::Constraint;
8
+ using operations_research::sat::CpModelBuilder;
9
+ using operations_research::sat::CpSolverResponse;
10
+ using operations_research::sat::CpSolverStatus;
11
+ using operations_research::sat::LinearExpr;
12
+ using operations_research::sat::IntVar;
13
+ using operations_research::sat::IntervalVar;
14
+ using operations_research::sat::Model;
15
+ using operations_research::sat::NewFeasibleSolutionObserver;
16
+ using operations_research::sat::SatParameters;
17
+ using operations_research::sat::SolutionBooleanValue;
18
+ using operations_research::sat::SolutionIntegerValue;
19
+
20
+ using Rice::Array;
21
+ using Rice::Class;
22
+ using Rice::Object;
23
+ using Rice::String;
24
+ using Rice::Symbol;
25
+
26
+ Class rb_cBoolVar;
27
+ Class rb_cSatIntVar;
28
+
29
+ namespace Rice::detail
30
+ {
31
+ template<>
32
+ struct Type<LinearExpr>
33
+ {
34
+ static bool verify()
35
+ {
36
+ return true;
37
+ }
38
+ };
39
+
40
+ template<>
41
+ class From_Ruby<LinearExpr>
42
+ {
43
+ public:
44
+ LinearExpr convert(VALUE v)
45
+ {
46
+ Object x(v);
47
+ LinearExpr expr;
48
+
49
+ if (x.respond_to("to_i")) {
50
+ expr = From_Ruby<int64_t>().convert(x.call("to_i").value());
51
+ } else if (x.respond_to("vars")) {
52
+ Array vars = x.call("vars");
53
+ for (const auto& v : vars) {
54
+ // TODO clean up
55
+ auto cvar = (Array) v;
56
+ Object var = cvar[0];
57
+ auto coeff = From_Ruby<int64_t>().convert(cvar[1].value());
58
+
59
+ if (var.is_a(rb_cBoolVar)) {
60
+ expr.AddTerm(From_Ruby<BoolVar>().convert(var.value()), coeff);
61
+ } else if (var.is_a(rb_cInteger)) {
62
+ expr.AddConstant(From_Ruby<int64_t>().convert(var.value()) * coeff);
63
+ } else {
64
+ expr.AddTerm(From_Ruby<IntVar>().convert(var.value()), coeff);
65
+ }
66
+ }
67
+ } else {
68
+ if (x.is_a(rb_cBoolVar)) {
69
+ expr = From_Ruby<BoolVar>().convert(x.value());
70
+ } else {
71
+ expr = From_Ruby<IntVar>().convert(x.value());
72
+ }
73
+ }
74
+
75
+ return expr;
76
+ }
77
+ };
78
+
79
+ template<>
80
+ class From_Ruby<std::vector<BoolVar>>
81
+ {
82
+ public:
83
+ std::vector<BoolVar> convert(VALUE v)
84
+ {
85
+ auto a = Array(v);
86
+ std::vector<BoolVar> vec;
87
+ vec.reserve(a.size());
88
+ for (const Object v : a) {
89
+ if (v.is_a(rb_cSatIntVar)) {
90
+ vec.push_back(From_Ruby<IntVar>().convert(v.value()).ToBoolVar());
91
+ } else {
92
+ vec.push_back(From_Ruby<BoolVar>().convert(v.value()));
93
+ }
94
+ }
95
+ return vec;
96
+ }
97
+ };
98
+ }
99
+
100
+ void init_constraint(Rice::Module& m) {
101
+ rb_cSatIntVar = Rice::define_class_under<IntVar>(m, "SatIntVar")
102
+ .define_method("name", &IntVar::Name);
103
+
104
+ Rice::define_class_under<IntervalVar>(m, "SatIntervalVar")
105
+ .define_method("name", &IntervalVar::Name);
106
+
107
+ Rice::define_class_under<Constraint>(m, "SatConstraint")
108
+ .define_method(
109
+ "only_enforce_if",
110
+ [](Constraint& self, Object literal) {
111
+ if (literal.is_a(rb_cSatIntVar)) {
112
+ return self.OnlyEnforceIf(Rice::detail::From_Ruby<IntVar>().convert(literal).ToBoolVar());
113
+ } else if (literal.is_a(rb_cArray)) {
114
+ // TODO support IntVarSpan
115
+ return self.OnlyEnforceIf(Rice::detail::From_Ruby<std::vector<BoolVar>>().convert(literal));
116
+ } else {
117
+ return self.OnlyEnforceIf(Rice::detail::From_Ruby<BoolVar>().convert(literal));
118
+ }
119
+ });
120
+
121
+ rb_cBoolVar = Rice::define_class_under<BoolVar>(m, "BoolVar")
122
+ .define_method("name", &BoolVar::Name)
123
+ .define_method("index", &BoolVar::index)
124
+ .define_method("not", &BoolVar::Not)
125
+ .define_method(
126
+ "inspect",
127
+ [](BoolVar& self) {
128
+ String name(self.Name());
129
+ return "#<ORTools::BoolVar @name=" + name.inspect().str() + ">";
130
+ });
131
+
132
+ Rice::define_class_under<SatParameters>(m, "SatParameters")
133
+ .define_constructor(Rice::Constructor<SatParameters>())
134
+ .define_method("max_time_in_seconds=",
135
+ [](SatParameters& self, double value) {
136
+ self.set_max_time_in_seconds(value);
137
+ });
138
+
139
+ Rice::define_class_under<CpModelBuilder>(m, "CpModel")
140
+ .define_constructor(Rice::Constructor<CpModelBuilder>())
141
+ .define_method(
142
+ "new_int_var",
143
+ [](CpModelBuilder& self, int64_t start, int64_t end, const std::string& name) {
144
+ const operations_research::Domain domain(start, end);
145
+ return self.NewIntVar(domain).WithName(name);
146
+ })
147
+ .define_method(
148
+ "new_bool_var",
149
+ [](CpModelBuilder& self, const std::string& name) {
150
+ return self.NewBoolVar().WithName(name);
151
+ })
152
+ .define_method(
153
+ "new_constant",
154
+ [](CpModelBuilder& self, int64_t value) {
155
+ return self.NewConstant(value);
156
+ })
157
+ .define_method(
158
+ "true_var",
159
+ [](CpModelBuilder& self) {
160
+ return self.TrueVar();
161
+ })
162
+ .define_method(
163
+ "false_var",
164
+ [](CpModelBuilder& self) {
165
+ return self.FalseVar();
166
+ })
167
+ .define_method(
168
+ "new_interval_var",
169
+ [](CpModelBuilder& self, IntVar start, IntVar size, IntVar end, const std::string& name) {
170
+ return self.NewIntervalVar(start, size, end).WithName(name);
171
+ })
172
+ .define_method(
173
+ "new_optional_interval_var",
174
+ [](CpModelBuilder& self, IntVar start, IntVar size, IntVar end, BoolVar presence, const std::string& name) {
175
+ return self.NewOptionalIntervalVar(start, size, end, presence).WithName(name);
176
+ })
177
+ .define_method(
178
+ "add_bool_or",
179
+ [](CpModelBuilder& self, std::vector<BoolVar> literals) {
180
+ return self.AddBoolOr(literals);
181
+ })
182
+ .define_method(
183
+ "add_bool_and",
184
+ [](CpModelBuilder& self, std::vector<BoolVar> literals) {
185
+ return self.AddBoolAnd(literals);
186
+ })
187
+ .define_method(
188
+ "add_bool_xor",
189
+ [](CpModelBuilder& self, std::vector<BoolVar> literals) {
190
+ return self.AddBoolXor(literals);
191
+ })
192
+ .define_method(
193
+ "add_implication",
194
+ [](CpModelBuilder& self, BoolVar a, BoolVar b) {
195
+ return self.AddImplication(a, b);
196
+ })
197
+ .define_method(
198
+ "add_equality",
199
+ [](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
200
+ return self.AddEquality(x, y);
201
+ })
202
+ .define_method(
203
+ "add_greater_or_equal",
204
+ [](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
205
+ return self.AddGreaterOrEqual(x, y);
206
+ })
207
+ .define_method(
208
+ "add_greater_than",
209
+ [](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
210
+ return self.AddGreaterThan(x, y);
211
+ })
212
+ .define_method(
213
+ "add_less_or_equal",
214
+ [](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
215
+ return self.AddLessOrEqual(x, y);
216
+ })
217
+ .define_method(
218
+ "add_less_than",
219
+ [](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
220
+ return self.AddLessThan(x, y);
221
+ })
222
+ // TODO add domain
223
+ // .define_method(
224
+ // "add_linear_constraint",
225
+ // [](CpModelBuilder& self, LinearExpr expr, Domain domain) {
226
+ // return self.AddLinearConstraint(expr, domain);
227
+ // })
228
+ .define_method(
229
+ "add_not_equal",
230
+ [](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
231
+ return self.AddNotEqual(x, y);
232
+ })
233
+ .define_method(
234
+ "add_all_different",
235
+ [](CpModelBuilder& self, std::vector<IntVar> vars) {
236
+ return self.AddAllDifferent(vars);
237
+ })
238
+ .define_method(
239
+ "add_inverse_constraint",
240
+ [](CpModelBuilder& self, std::vector<IntVar> variables, std::vector<IntVar> inverse_variables) {
241
+ return self.AddInverseConstraint(variables, inverse_variables);
242
+ })
243
+ .define_method(
244
+ "add_min_equality",
245
+ [](CpModelBuilder& self, IntVar target, std::vector<IntVar> vars) {
246
+ return self.AddMinEquality(target, vars);
247
+ })
248
+ .define_method(
249
+ "add_lin_min_equality",
250
+ [](CpModelBuilder& self, LinearExpr target, std::vector<LinearExpr> exprs) {
251
+ return self.AddLinMinEquality(target, exprs);
252
+ })
253
+ .define_method(
254
+ "add_max_equality",
255
+ [](CpModelBuilder& self, IntVar target, std::vector<IntVar> vars) {
256
+ return self.AddMaxEquality(target, vars);
257
+ })
258
+ .define_method(
259
+ "add_lin_max_equality",
260
+ [](CpModelBuilder& self, LinearExpr target, std::vector<LinearExpr> exprs) {
261
+ return self.AddLinMaxEquality(target, exprs);
262
+ })
263
+ .define_method(
264
+ "add_division_equality",
265
+ [](CpModelBuilder& self, IntVar target, IntVar numerator, IntVar denominator) {
266
+ return self.AddDivisionEquality(target, numerator, denominator);
267
+ })
268
+ .define_method(
269
+ "add_abs_equality",
270
+ [](CpModelBuilder& self, IntVar target, IntVar var) {
271
+ return self.AddAbsEquality(target, var);
272
+ })
273
+ .define_method(
274
+ "add_modulo_equality",
275
+ [](CpModelBuilder& self, IntVar target, IntVar var, IntVar mod) {
276
+ return self.AddModuloEquality(target, var, mod);
277
+ })
278
+ .define_method(
279
+ "add_product_equality",
280
+ [](CpModelBuilder& self, IntVar target, std::vector<IntVar> vars) {
281
+ return self.AddProductEquality(target, vars);
282
+ })
283
+ .define_method(
284
+ "add_no_overlap",
285
+ [](CpModelBuilder& self, std::vector<IntervalVar> vars) {
286
+ return self.AddNoOverlap(vars);
287
+ })
288
+ .define_method(
289
+ "maximize",
290
+ [](CpModelBuilder& self, LinearExpr expr) {
291
+ self.Maximize(expr);
292
+ })
293
+ .define_method(
294
+ "minimize",
295
+ [](CpModelBuilder& self, LinearExpr expr) {
296
+ self.Minimize(expr);
297
+ })
298
+ .define_method(
299
+ "scale_objective_by",
300
+ [](CpModelBuilder& self, double scaling) {
301
+ self.ScaleObjectiveBy(scaling);
302
+ })
303
+ .define_method(
304
+ "add_hint",
305
+ [](CpModelBuilder& self, IntVar var, int64_t value) {
306
+ self.AddHint(var, value);
307
+ })
308
+ .define_method(
309
+ "clear_hints",
310
+ [](CpModelBuilder& self) {
311
+ self.ClearHints();
312
+ })
313
+ .define_method(
314
+ "add_assumption",
315
+ [](CpModelBuilder& self, BoolVar lit) {
316
+ self.AddAssumption(lit);
317
+ })
318
+ .define_method(
319
+ "add_assumptions",
320
+ [](CpModelBuilder& self, std::vector<BoolVar> literals) {
321
+ self.AddAssumptions(literals);
322
+ })
323
+ .define_method(
324
+ "clear_assumptions",
325
+ [](CpModelBuilder& self) {
326
+ self.ClearAssumptions();
327
+ })
328
+ .define_method(
329
+ "to_s",
330
+ [](CpModelBuilder& self) {
331
+ std::string proto_string;
332
+ google::protobuf::TextFormat::PrintToString(self.Proto(), &proto_string);
333
+ return proto_string;
334
+ });
335
+
336
+ Rice::define_class_under<CpSolverResponse>(m, "CpSolverResponse")
337
+ .define_method("objective_value", &CpSolverResponse::objective_value)
338
+ .define_method("num_conflicts", &CpSolverResponse::num_conflicts)
339
+ .define_method("num_branches", &CpSolverResponse::num_branches)
340
+ .define_method("wall_time", &CpSolverResponse::wall_time)
341
+ .define_method(
342
+ "solution_integer_value",
343
+ [](CpSolverResponse& self, IntVar& x) {
344
+ LinearExpr expr(x);
345
+ return SolutionIntegerValue(self, expr);
346
+ })
347
+ .define_method("solution_boolean_value", &SolutionBooleanValue)
348
+ .define_method(
349
+ "status",
350
+ [](CpSolverResponse& self) {
351
+ auto status = self.status();
352
+
353
+ if (status == CpSolverStatus::OPTIMAL) {
354
+ return Symbol("optimal");
355
+ } else if (status == CpSolverStatus::FEASIBLE) {
356
+ return Symbol("feasible");
357
+ } else if (status == CpSolverStatus::INFEASIBLE) {
358
+ return Symbol("infeasible");
359
+ } else if (status == CpSolverStatus::MODEL_INVALID) {
360
+ return Symbol("model_invalid");
361
+ } else if (status == CpSolverStatus::UNKNOWN) {
362
+ return Symbol("unknown");
363
+ } else {
364
+ throw std::runtime_error("Unknown solver status");
365
+ }
366
+ })
367
+ .define_method(
368
+ "sufficient_assumptions_for_infeasibility",
369
+ [](CpSolverResponse& self) {
370
+ auto a = Array();
371
+ auto assumptions = self.sufficient_assumptions_for_infeasibility();
372
+ for (const auto& v : assumptions) {
373
+ a.push(v);
374
+ }
375
+ return a;
376
+ });
377
+
378
+ Rice::define_class_under(m, "CpSolver")
379
+ .define_method(
380
+ "_solve_with_observer",
381
+ [](Object self, CpModelBuilder& model, SatParameters& parameters, Object callback, bool all_solutions) {
382
+ Model m;
383
+
384
+ if (all_solutions) {
385
+ // set parameters for SearchForAllSolutions
386
+ parameters.set_enumerate_all_solutions(true);
387
+ }
388
+ m.Add(NewSatParameters(parameters));
389
+
390
+ m.Add(NewFeasibleSolutionObserver(
391
+ [callback](const CpSolverResponse& r) {
392
+ // TODO find a better way to do this
393
+ callback.call("response=", r);
394
+ callback.call("on_solution_callback");
395
+ })
396
+ );
397
+ return SolveCpModel(model.Build(), &m);
398
+ })
399
+ .define_method(
400
+ "_solve",
401
+ [](Object self, CpModelBuilder& model, SatParameters& parameters) {
402
+ Model m;
403
+ m.Add(NewSatParameters(parameters));
404
+ return SolveCpModel(model.Build(), &m);
405
+ })
406
+ .define_method(
407
+ "_solution_integer_value",
408
+ [](Object self, CpSolverResponse& response, IntVar& x) {
409
+ return SolutionIntegerValue(response, x);
410
+ })
411
+ .define_method(
412
+ "_solution_boolean_value",
413
+ [](Object self, CpSolverResponse& response, BoolVar& x) {
414
+ return SolutionBooleanValue(response, x);
415
+ });
416
+ }