or-tools 0.3.3 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/NOTICE.txt +1 -1
- data/README.md +35 -1
- data/ext/or-tools/assignment.cpp +39 -0
- data/ext/or-tools/bin_packing.cpp +55 -0
- data/ext/or-tools/constraint.cpp +466 -0
- data/ext/or-tools/ext.cpp +21 -992
- data/ext/or-tools/extconf.rb +1 -1
- data/ext/or-tools/linear.cpp +212 -0
- data/ext/or-tools/network_flows.cpp +105 -0
- data/ext/or-tools/routing.cpp +368 -0
- data/ext/or-tools/vendor.rb +22 -14
- data/lib/or-tools.rb +5 -0
- data/lib/or_tools/cp_model.rb +4 -0
- data/lib/or_tools/cp_solver.rb +7 -3
- data/lib/or_tools/cp_solver_solution_callback.rb +1 -1
- data/lib/or_tools/objective_solution_printer.rb +18 -0
- data/lib/or_tools/sat_int_var.rb +4 -0
- data/lib/or_tools/sat_linear_expr.rb +2 -2
- data/lib/or_tools/var_array_and_objective_solution_printer.rb +20 -0
- data/lib/or_tools/var_array_solution_printer.rb +19 -0
- data/lib/or_tools/version.rb +1 -1
- metadata +20 -67
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7a1064c39ae0b5431b303db41b4fe03da7f80d26beeab576b33b85fe47dee4d8
|
|
4
|
+
data.tar.gz: 5819ef15c9ec8b1b507fb4e4596397a8f2e562fa72de6580b1e78188a404a3db
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
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
|
-
[](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
|
+
}
|