or-tools 0.3.3 → 0.4.3

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: a0af0b1dc8198bf30ff09350e3c4da587735d5ece10204bf19c6dfc8916e2135
4
- data.tar.gz: 6b685437c9d8cefcb91d52b24d090179a0884ad9a8edf966131493f3c8bc1dbf
3
+ metadata.gz: 7a1064c39ae0b5431b303db41b4fe03da7f80d26beeab576b33b85fe47dee4d8
4
+ data.tar.gz: 5819ef15c9ec8b1b507fb4e4596397a8f2e562fa72de6580b1e78188a404a3db
5
5
  SHA512:
6
- metadata.gz: 80ed4a17f6079d997ef42b8659cea3879f4b0935e8bbfa7e566a76937b2ea0f86f906b3bb236bd43f17cecb6364c3025916074438f768c7853e60a87a025d150
7
- data.tar.gz: 9b9e085b2cf01a3dc7d1f77363c903dfb7d6e41280626c37408da9889534ac7c5c85d49c73714022461ae55df36abb10932b4ae9272d10d910e95a6681cddad6
6
+ metadata.gz: 797f8fdba98a3843f3da03acdee070445e6f4a37650936a700ebab3af58bc779cd57c44b3b68341f28203beb986e6818a884d65588fa14264d0eb89463183d2e
7
+ data.tar.gz: acd539cc1f14467ddd2edfaa65723590a216c709aa3085d2257472600e023e7757109eeade70f995131f26f9769250807c998d0d5e30d8ce51af90536063cf3b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## 0.4.3 (2021-03-26)
2
+
3
+ - Added `add_assumption`, `add_assumptions`, and `clear_assumptions` to `CpModel`
4
+ - Added `add_hint` and `clear_hints` to `CpModel`
5
+ - Added `only_enforce_if` to `SatConstraint`
6
+ - Fixed installation for Debian
7
+
8
+ ## 0.4.2 (2021-03-03)
9
+
10
+ - Updated OR-Tools to 8.2
11
+
12
+ ## 0.4.1 (2021-02-23)
13
+
14
+ - Added solution printers
15
+ - Improved `inspect` and `to_s` for `CpModel`
16
+ - Improved constraint construction
17
+
18
+ ## 0.4.0 (2021-01-14)
19
+
20
+ - Updated OR-Tools to 8.1
21
+
22
+ ## 0.3.4 (2021-01-14)
23
+
24
+ - Added support for time limit for `CpSolver`
25
+ - Added `add_dimension_with_vehicle_transits` and `status` methods to `RoutingModel`
26
+
1
27
  ## 0.3.3 (2020-10-12)
2
28
 
3
29
  - Added support for start and end points for routing
data/NOTICE.txt CHANGED
@@ -1,5 +1,5 @@
1
1
  Copyright 2010-2018 Google LLC
2
- Copyright 2020 Andrew Kane
2
+ Copyright 2020-2021 Andrew Kane
3
3
 
4
4
  Licensed under the Apache License, Version 2.0 (the "License");
5
5
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [OR-Tools](https://github.com/google/or-tools) - operations research tools - for Ruby
4
4
 
5
- [![Build Status](https://travis-ci.org/ankane/or-tools.svg?branch=master)](https://travis-ci.org/ankane/or-tools)
5
+ [![Build Status](https://github.com/ankane/or-tools/workflows/build/badge.svg?branch=master)](https://github.com/ankane/or-tools/actions)
6
6
 
7
7
  ## Installation
8
8
 
@@ -267,6 +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)
270
271
 
271
272
  Assignment
272
273
 
@@ -578,6 +579,39 @@ puts
578
579
  puts "Solutions found : %i" % solution_printer.solution_count
579
580
  ```
580
581
 
582
+ ### Setting Solver Limits
583
+
584
+ [Guide](https://developers.google.com/optimization/cp/cp_tasks)
585
+
586
+ ```ruby
587
+ # create the model
588
+ model = ORTools::CpModel.new
589
+
590
+ # create the variables
591
+ num_vals = 3
592
+ x = model.new_int_var(0, num_vals - 1, "x")
593
+ y = model.new_int_var(0, num_vals - 1, "y")
594
+ z = model.new_int_var(0, num_vals - 1, "z")
595
+
596
+ # add an all-different constraint
597
+ model.add(x != y)
598
+
599
+ # create the solver
600
+ solver = ORTools::CpSolver.new
601
+
602
+ # set a time limit of 10 seconds.
603
+ solver.parameters.max_time_in_seconds = 10
604
+
605
+ # solve the model
606
+ status = solver.solve(model)
607
+
608
+ # display the first solution
609
+ if status == :optimal
610
+ puts "x = #{solver.value(x)}"
611
+ puts "y = #{solver.value(y)}"
612
+ puts "z = #{solver.value(z)}"
613
+ end
614
+ ```
581
615
 
582
616
  ### Assignment
583
617
 
@@ -0,0 +1,39 @@
1
+ #include <ortools/graph/assignment.h>
2
+
3
+ #include <rice/Array.hpp>
4
+ #include <rice/Constructor.hpp>
5
+ #include <rice/Module.hpp>
6
+
7
+ using operations_research::SimpleLinearSumAssignment;
8
+
9
+ using Rice::Array;
10
+ using Rice::Symbol;
11
+
12
+ void init_assignment(Rice::Module& m) {
13
+ Rice::define_class_under<SimpleLinearSumAssignment>(m, "LinearSumAssignment")
14
+ .define_constructor(Rice::Constructor<SimpleLinearSumAssignment>())
15
+ .define_method("add_arc_with_cost", &SimpleLinearSumAssignment::AddArcWithCost)
16
+ .define_method("num_nodes", &SimpleLinearSumAssignment::NumNodes)
17
+ .define_method("num_arcs", &SimpleLinearSumAssignment::NumArcs)
18
+ .define_method("left_node", &SimpleLinearSumAssignment::LeftNode)
19
+ .define_method("right_node", &SimpleLinearSumAssignment::RightNode)
20
+ .define_method("cost", &SimpleLinearSumAssignment::Cost)
21
+ .define_method("optimal_cost", &SimpleLinearSumAssignment::OptimalCost)
22
+ .define_method("right_mate", &SimpleLinearSumAssignment::RightMate)
23
+ .define_method("assignment_cost", &SimpleLinearSumAssignment::AssignmentCost)
24
+ .define_method(
25
+ "solve",
26
+ *[](SimpleLinearSumAssignment& self) {
27
+ auto status = self.Solve();
28
+
29
+ if (status == SimpleLinearSumAssignment::Status::OPTIMAL) {
30
+ return Symbol("optimal");
31
+ } else if (status == SimpleLinearSumAssignment::Status::INFEASIBLE) {
32
+ return Symbol("infeasible");
33
+ } else if (status == SimpleLinearSumAssignment::Status::POSSIBLE_OVERFLOW) {
34
+ return Symbol("possible_overflow");
35
+ } else {
36
+ throw std::runtime_error("Unknown status");
37
+ }
38
+ });
39
+ }
@@ -0,0 +1,55 @@
1
+ #include <ortools/algorithms/knapsack_solver.h>
2
+
3
+ #include <rice/Array.hpp>
4
+ #include <rice/Constructor.hpp>
5
+ #include <rice/Module.hpp>
6
+
7
+ using operations_research::KnapsackSolver;
8
+
9
+ using Rice::Array;
10
+ using Rice::Object;
11
+ using Rice::Symbol;
12
+
13
+ template<>
14
+ inline
15
+ KnapsackSolver::SolverType from_ruby<KnapsackSolver::SolverType>(Object x)
16
+ {
17
+ std::string s = Symbol(x).str();
18
+ if (s == "branch_and_bound") {
19
+ return KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER;
20
+ } else {
21
+ throw std::runtime_error("Unknown solver type: " + s);
22
+ }
23
+ }
24
+
25
+ void init_bin_packing(Rice::Module& m) {
26
+ Rice::define_class_under<KnapsackSolver>(m, "KnapsackSolver")
27
+ .define_constructor(Rice::Constructor<KnapsackSolver, KnapsackSolver::SolverType, std::string>())
28
+ .define_method("_solve", &KnapsackSolver::Solve)
29
+ .define_method("best_solution_contains?", &KnapsackSolver::BestSolutionContains)
30
+ .define_method(
31
+ "init",
32
+ *[](KnapsackSolver& self, Array rb_values, Array rb_weights, Array rb_capacities) {
33
+ std::vector<int64> values;
34
+ for (std::size_t i = 0; i < rb_values.size(); ++i) {
35
+ values.push_back(from_ruby<int64>(rb_values[i]));
36
+ }
37
+
38
+ std::vector<std::vector<int64>> weights;
39
+ for (std::size_t i = 0; i < rb_weights.size(); ++i) {
40
+ Array rb_w = Array(rb_weights[i]);
41
+ std::vector<int64> w;
42
+ for (std::size_t j = 0; j < rb_w.size(); ++j) {
43
+ w.push_back(from_ruby<int64>(rb_w[j]));
44
+ }
45
+ weights.push_back(w);
46
+ }
47
+
48
+ std::vector<int64> capacities;
49
+ for (std::size_t i = 0; i < rb_capacities.size(); ++i) {
50
+ capacities.push_back(from_ruby<int64>(rb_capacities[i]));
51
+ }
52
+
53
+ self.Init(values, weights, capacities);
54
+ });
55
+ }
@@ -0,0 +1,466 @@
1
+ #include <google/protobuf/text_format.h>
2
+ #include <ortools/sat/cp_model.h>
3
+
4
+ #include <rice/Array.hpp>
5
+ #include <rice/Constructor.hpp>
6
+ #include <rice/Module.hpp>
7
+
8
+ using operations_research::sat::BoolVar;
9
+ using operations_research::sat::Constraint;
10
+ using operations_research::sat::CpModelBuilder;
11
+ using operations_research::sat::CpSolverResponse;
12
+ using operations_research::sat::CpSolverStatus;
13
+ using operations_research::sat::LinearExpr;
14
+ using operations_research::sat::IntVar;
15
+ using operations_research::sat::IntervalVar;
16
+ using operations_research::sat::Model;
17
+ using operations_research::sat::NewFeasibleSolutionObserver;
18
+ using operations_research::sat::SatParameters;
19
+ using operations_research::sat::SolutionBooleanValue;
20
+ using operations_research::sat::SolutionIntegerValue;
21
+
22
+ using Rice::Array;
23
+ using Rice::Object;
24
+ using Rice::String;
25
+ using Rice::Symbol;
26
+
27
+ template<>
28
+ inline
29
+ LinearExpr from_ruby<LinearExpr>(Object x)
30
+ {
31
+ LinearExpr expr;
32
+
33
+ if (x.respond_to("to_i")) {
34
+ expr = from_ruby<int64>(x.call("to_i"));
35
+ } else if (x.respond_to("vars")) {
36
+ Array vars = x.call("vars");
37
+ for(auto const& var: vars) {
38
+ auto cvar = (Array) var;
39
+ // TODO clean up
40
+ Object o = cvar[0];
41
+ std::string type = ((String) o.call("class").call("name")).str();
42
+ if (type == "ORTools::BoolVar") {
43
+ expr.AddTerm(from_ruby<BoolVar>(cvar[0]), from_ruby<int64>(cvar[1]));
44
+ } else if (type == "Integer") {
45
+ expr.AddConstant(from_ruby<int64>(cvar[0]) * from_ruby<int64>(cvar[1]));
46
+ } else {
47
+ expr.AddTerm(from_ruby<IntVar>(cvar[0]), from_ruby<int64>(cvar[1]));
48
+ }
49
+ }
50
+ } else {
51
+ std::string type = ((String) x.call("class").call("name")).str();
52
+ if (type == "ORTools::BoolVar") {
53
+ expr = from_ruby<BoolVar>(x);
54
+ } else {
55
+ expr = from_ruby<IntVar>(x);
56
+ }
57
+ }
58
+
59
+ return expr;
60
+ }
61
+
62
+ // need a wrapper class since absl::Span doesn't own
63
+ class IntVarSpan {
64
+ std::vector<IntVar> vec;
65
+ public:
66
+ IntVarSpan(Object x) {
67
+ Array a = Array(x);
68
+ vec.reserve(a.size());
69
+ for (std::size_t i = 0; i < a.size(); ++i) {
70
+ vec.push_back(from_ruby<IntVar>(a[i]));
71
+ }
72
+ }
73
+ operator absl::Span<const IntVar>() {
74
+ return absl::Span<const IntVar>(vec);
75
+ }
76
+ };
77
+
78
+ template<>
79
+ inline
80
+ IntVarSpan from_ruby<IntVarSpan>(Object x)
81
+ {
82
+ return IntVarSpan(x);
83
+ }
84
+
85
+ // need a wrapper class since absl::Span doesn't own
86
+ class IntervalVarSpan {
87
+ std::vector<IntervalVar> vec;
88
+ public:
89
+ IntervalVarSpan(Object x) {
90
+ Array a = Array(x);
91
+ vec.reserve(a.size());
92
+ for (std::size_t i = 0; i < a.size(); ++i) {
93
+ vec.push_back(from_ruby<IntervalVar>(a[i]));
94
+ }
95
+ }
96
+ operator absl::Span<const IntervalVar>() {
97
+ return absl::Span<const IntervalVar>(vec);
98
+ }
99
+ };
100
+
101
+ template<>
102
+ inline
103
+ IntervalVarSpan from_ruby<IntervalVarSpan>(Object x)
104
+ {
105
+ return IntervalVarSpan(x);
106
+ }
107
+
108
+ // need a wrapper class since absl::Span doesn't own
109
+ class LinearExprSpan {
110
+ std::vector<LinearExpr> vec;
111
+ public:
112
+ LinearExprSpan(Object x) {
113
+ Array a = Array(x);
114
+ vec.reserve(a.size());
115
+ for (std::size_t i = 0; i < a.size(); ++i) {
116
+ vec.push_back(from_ruby<LinearExpr>(a[i]));
117
+ }
118
+ }
119
+ operator absl::Span<const LinearExpr>() {
120
+ return absl::Span<const LinearExpr>(vec);
121
+ }
122
+ };
123
+
124
+ template<>
125
+ inline
126
+ LinearExprSpan from_ruby<LinearExprSpan>(Object x)
127
+ {
128
+ return LinearExprSpan(x);
129
+ }
130
+
131
+ Rice::Class rb_cSatIntVar;
132
+
133
+ // need a wrapper class since absl::Span doesn't own
134
+ class BoolVarSpan {
135
+ std::vector<BoolVar> vec;
136
+ public:
137
+ BoolVarSpan(Object x) {
138
+ Array a = Array(x);
139
+ vec.reserve(a.size());
140
+ for (std::size_t i = 0; i < a.size(); ++i) {
141
+ if (((Object) a[i]).is_a(rb_cSatIntVar)) {
142
+ vec.push_back(from_ruby<IntVar>(a[i]).ToBoolVar());
143
+ } else {
144
+ vec.push_back(from_ruby<BoolVar>(a[i]));
145
+ }
146
+ }
147
+ }
148
+ operator absl::Span<const BoolVar>() {
149
+ return absl::Span<const BoolVar>(vec);
150
+ }
151
+ };
152
+
153
+ template<>
154
+ inline
155
+ BoolVarSpan from_ruby<BoolVarSpan>(Object x)
156
+ {
157
+ return BoolVarSpan(x);
158
+ }
159
+
160
+ void init_constraint(Rice::Module& m) {
161
+ rb_cSatIntVar = Rice::define_class_under<IntVar>(m, "SatIntVar")
162
+ .define_method("name", &IntVar::Name);
163
+
164
+ Rice::define_class_under<IntervalVar>(m, "SatIntervalVar")
165
+ .define_method("name", &IntervalVar::Name);
166
+
167
+ Rice::define_class_under<Constraint>(m, "SatConstraint")
168
+ .define_method(
169
+ "only_enforce_if",
170
+ *[](Constraint& self, Object literal) {
171
+ if (literal.is_a(rb_cSatIntVar)) {
172
+ return self.OnlyEnforceIf(from_ruby<IntVar>(literal).ToBoolVar());
173
+ } else if (literal.is_a(rb_cArray)) {
174
+ // TODO support IntVarSpan
175
+ return self.OnlyEnforceIf(from_ruby<BoolVarSpan>(literal));
176
+ } else {
177
+ return self.OnlyEnforceIf(from_ruby<BoolVar>(literal));
178
+ }
179
+ });
180
+
181
+ Rice::define_class_under<BoolVar>(m, "BoolVar")
182
+ .define_method("name", &BoolVar::Name)
183
+ .define_method("index", &BoolVar::index)
184
+ .define_method("not", &BoolVar::Not)
185
+ .define_method(
186
+ "inspect",
187
+ *[](BoolVar& self) {
188
+ String name(self.Name());
189
+ return "#<ORTools::BoolVar @name=" + name.inspect().str() + ">";
190
+ });
191
+
192
+ Rice::define_class_under<SatParameters>(m, "SatParameters")
193
+ .define_constructor(Rice::Constructor<SatParameters>())
194
+ .define_method("max_time_in_seconds=",
195
+ *[](SatParameters& self, double value) {
196
+ self.set_max_time_in_seconds(value);
197
+ });
198
+
199
+ Rice::define_class_under<CpModelBuilder>(m, "CpModel")
200
+ .define_constructor(Rice::Constructor<CpModelBuilder>())
201
+ .define_method(
202
+ "new_int_var",
203
+ *[](CpModelBuilder& self, int64 start, int64 end, const std::string& name) {
204
+ const operations_research::Domain domain(start, end);
205
+ return self.NewIntVar(domain).WithName(name);
206
+ })
207
+ .define_method(
208
+ "new_bool_var",
209
+ *[](CpModelBuilder& self, const std::string& name) {
210
+ return self.NewBoolVar().WithName(name);
211
+ })
212
+ .define_method(
213
+ "new_constant",
214
+ *[](CpModelBuilder& self, int64 value) {
215
+ return self.NewConstant(value);
216
+ })
217
+ .define_method(
218
+ "true_var",
219
+ *[](CpModelBuilder& self) {
220
+ return self.TrueVar();
221
+ })
222
+ .define_method(
223
+ "false_var",
224
+ *[](CpModelBuilder& self) {
225
+ return self.FalseVar();
226
+ })
227
+ .define_method(
228
+ "new_interval_var",
229
+ *[](CpModelBuilder& self, IntVar start, IntVar size, IntVar end, const std::string& name) {
230
+ return self.NewIntervalVar(start, size, end).WithName(name);
231
+ })
232
+ .define_method(
233
+ "new_optional_interval_var",
234
+ *[](CpModelBuilder& self, IntVar start, IntVar size, IntVar end, BoolVar presence, const std::string& name) {
235
+ return self.NewOptionalIntervalVar(start, size, end, presence).WithName(name);
236
+ })
237
+ .define_method(
238
+ "add_bool_or",
239
+ *[](CpModelBuilder& self, BoolVarSpan literals) {
240
+ return self.AddBoolOr(literals);
241
+ })
242
+ .define_method(
243
+ "add_bool_and",
244
+ *[](CpModelBuilder& self, BoolVarSpan literals) {
245
+ return self.AddBoolAnd(literals);
246
+ })
247
+ .define_method(
248
+ "add_bool_xor",
249
+ *[](CpModelBuilder& self, BoolVarSpan literals) {
250
+ return self.AddBoolXor(literals);
251
+ })
252
+ .define_method(
253
+ "add_implication",
254
+ *[](CpModelBuilder& self, BoolVar a, BoolVar b) {
255
+ return self.AddImplication(a, b);
256
+ })
257
+ .define_method(
258
+ "add_equality",
259
+ *[](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
260
+ return self.AddEquality(x, y);
261
+ })
262
+ .define_method(
263
+ "add_greater_or_equal",
264
+ *[](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
265
+ return self.AddGreaterOrEqual(x, y);
266
+ })
267
+ .define_method(
268
+ "add_greater_than",
269
+ *[](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
270
+ return self.AddGreaterThan(x, y);
271
+ })
272
+ .define_method(
273
+ "add_less_or_equal",
274
+ *[](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
275
+ return self.AddLessOrEqual(x, y);
276
+ })
277
+ .define_method(
278
+ "add_less_than",
279
+ *[](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
280
+ return self.AddLessThan(x, y);
281
+ })
282
+ // TODO add domain
283
+ // .define_method(
284
+ // "add_linear_constraint",
285
+ // *[](CpModelBuilder& self, LinearExpr expr, Domain domain) {
286
+ // return self.AddLinearConstraint(expr, domain);
287
+ // })
288
+ .define_method(
289
+ "add_not_equal",
290
+ *[](CpModelBuilder& self, LinearExpr x, LinearExpr y) {
291
+ return self.AddNotEqual(x, y);
292
+ })
293
+ .define_method(
294
+ "add_all_different",
295
+ *[](CpModelBuilder& self, IntVarSpan vars) {
296
+ return self.AddAllDifferent(vars);
297
+ })
298
+ .define_method(
299
+ "add_inverse_constraint",
300
+ *[](CpModelBuilder& self, IntVarSpan variables, IntVarSpan inverse_variables) {
301
+ return self.AddInverseConstraint(variables, inverse_variables);
302
+ })
303
+ .define_method(
304
+ "add_min_equality",
305
+ *[](CpModelBuilder& self, IntVar target, IntVarSpan vars) {
306
+ return self.AddMinEquality(target, vars);
307
+ })
308
+ .define_method(
309
+ "add_lin_min_equality",
310
+ *[](CpModelBuilder& self, LinearExpr target, LinearExprSpan exprs) {
311
+ return self.AddLinMinEquality(target, exprs);
312
+ })
313
+ .define_method(
314
+ "add_max_equality",
315
+ *[](CpModelBuilder& self, IntVar target, IntVarSpan vars) {
316
+ return self.AddMaxEquality(target, vars);
317
+ })
318
+ .define_method(
319
+ "add_lin_max_equality",
320
+ *[](CpModelBuilder& self, LinearExpr target, LinearExprSpan exprs) {
321
+ return self.AddLinMaxEquality(target, exprs);
322
+ })
323
+ .define_method(
324
+ "add_division_equality",
325
+ *[](CpModelBuilder& self, IntVar target, IntVar numerator, IntVar denominator) {
326
+ return self.AddDivisionEquality(target, numerator, denominator);
327
+ })
328
+ .define_method(
329
+ "add_abs_equality",
330
+ *[](CpModelBuilder& self, IntVar target, IntVar var) {
331
+ return self.AddAbsEquality(target, var);
332
+ })
333
+ .define_method(
334
+ "add_modulo_equality",
335
+ *[](CpModelBuilder& self, IntVar target, IntVar var, IntVar mod) {
336
+ return self.AddModuloEquality(target, var, mod);
337
+ })
338
+ .define_method(
339
+ "add_product_equality",
340
+ *[](CpModelBuilder& self, IntVar target, IntVarSpan vars) {
341
+ return self.AddProductEquality(target, vars);
342
+ })
343
+ .define_method(
344
+ "add_no_overlap",
345
+ *[](CpModelBuilder& self, IntervalVarSpan vars) {
346
+ return self.AddNoOverlap(vars);
347
+ })
348
+ .define_method(
349
+ "maximize",
350
+ *[](CpModelBuilder& self, LinearExpr expr) {
351
+ self.Maximize(expr);
352
+ })
353
+ .define_method(
354
+ "minimize",
355
+ *[](CpModelBuilder& self, LinearExpr expr) {
356
+ self.Minimize(expr);
357
+ })
358
+ .define_method(
359
+ "scale_objective_by",
360
+ *[](CpModelBuilder& self, double scaling) {
361
+ self.ScaleObjectiveBy(scaling);
362
+ })
363
+ .define_method(
364
+ "add_hint",
365
+ *[](CpModelBuilder& self, IntVar var, int64 value) {
366
+ self.AddHint(var, value);
367
+ })
368
+ .define_method(
369
+ "clear_hints",
370
+ *[](CpModelBuilder& self) {
371
+ self.ClearHints();
372
+ })
373
+ .define_method(
374
+ "add_assumption",
375
+ *[](CpModelBuilder& self, BoolVar lit) {
376
+ self.AddAssumption(lit);
377
+ })
378
+ .define_method(
379
+ "add_assumptions",
380
+ *[](CpModelBuilder& self, BoolVarSpan literals) {
381
+ self.AddAssumptions(literals);
382
+ })
383
+ .define_method(
384
+ "clear_assumptions",
385
+ *[](CpModelBuilder& self) {
386
+ self.ClearAssumptions();
387
+ })
388
+ .define_method(
389
+ "to_s",
390
+ *[](CpModelBuilder& self) {
391
+ std::string proto_string;
392
+ google::protobuf::TextFormat::PrintToString(self.Proto(), &proto_string);
393
+ return proto_string;
394
+ });
395
+
396
+ Rice::define_class_under(m, "CpSolver")
397
+ .define_method(
398
+ "_solve_with_observer",
399
+ *[](Object self, CpModelBuilder& model, SatParameters& parameters, Object callback, bool all_solutions) {
400
+ Model m;
401
+
402
+ if (all_solutions) {
403
+ // set parameters for SearchForAllSolutions
404
+ parameters.set_enumerate_all_solutions(true);
405
+ }
406
+ m.Add(NewSatParameters(parameters));
407
+
408
+ m.Add(NewFeasibleSolutionObserver(
409
+ [callback](const CpSolverResponse& r) {
410
+ // TODO find a better way to do this
411
+ callback.call("response=", r);
412
+ callback.call("on_solution_callback");
413
+ })
414
+ );
415
+ return SolveCpModel(model.Build(), &m);
416
+ })
417
+ .define_method(
418
+ "_solve",
419
+ *[](Object self, CpModelBuilder& model, SatParameters& parameters) {
420
+ Model m;
421
+ m.Add(NewSatParameters(parameters));
422
+ return SolveCpModel(model.Build(), &m);
423
+ })
424
+ .define_method(
425
+ "_solution_integer_value",
426
+ *[](Object self, CpSolverResponse& response, IntVar& x) {
427
+ return SolutionIntegerValue(response, x);
428
+ })
429
+ .define_method(
430
+ "_solution_boolean_value",
431
+ *[](Object self, CpSolverResponse& response, BoolVar& x) {
432
+ return SolutionBooleanValue(response, x);
433
+ });
434
+
435
+ Rice::define_class_under<CpSolverResponse>(m, "CpSolverResponse")
436
+ .define_method("objective_value", &CpSolverResponse::objective_value)
437
+ .define_method("num_conflicts", &CpSolverResponse::num_conflicts)
438
+ .define_method("num_branches", &CpSolverResponse::num_branches)
439
+ .define_method("wall_time", &CpSolverResponse::wall_time)
440
+ .define_method(
441
+ "solution_integer_value",
442
+ *[](CpSolverResponse& self, IntVar& x) {
443
+ LinearExpr expr(x);
444
+ return SolutionIntegerValue(self, expr);
445
+ })
446
+ .define_method("solution_boolean_value", &SolutionBooleanValue)
447
+ .define_method(
448
+ "status",
449
+ *[](CpSolverResponse& self) {
450
+ auto status = self.status();
451
+
452
+ if (status == CpSolverStatus::OPTIMAL) {
453
+ return Symbol("optimal");
454
+ } else if (status == CpSolverStatus::FEASIBLE) {
455
+ return Symbol("feasible");
456
+ } else if (status == CpSolverStatus::INFEASIBLE) {
457
+ return Symbol("infeasible");
458
+ } else if (status == CpSolverStatus::MODEL_INVALID) {
459
+ return Symbol("model_invalid");
460
+ } else if (status == CpSolverStatus::UNKNOWN) {
461
+ return Symbol("unknown");
462
+ } else {
463
+ throw std::runtime_error("Unknown solver status");
464
+ }
465
+ });
466
+ }