or-tools 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +1 -1
- data/ext/or-tools/assignment.cpp +39 -0
- data/ext/or-tools/bin_packing.cpp +55 -0
- data/ext/or-tools/constraint.cpp +423 -0
- data/ext/or-tools/ext.cpp +18 -1025
- 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/lib/or-tools.rb +5 -0
- data/lib/or_tools/cp_model.rb +4 -0
- 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 +11 -2
data/ext/or-tools/ext.cpp
CHANGED
@@ -1,1037 +1,30 @@
|
|
1
|
-
// or-tools
|
2
|
-
#include <ortools/algorithms/knapsack_solver.h>
|
3
1
|
#include <ortools/base/version.h>
|
4
|
-
#include <ortools/constraint_solver/routing.h>
|
5
|
-
#include <ortools/constraint_solver/routing_parameters.h>
|
6
|
-
#include <ortools/graph/assignment.h>
|
7
|
-
#include <ortools/graph/max_flow.h>
|
8
|
-
#include <ortools/graph/min_cost_flow.h>
|
9
|
-
#include <ortools/linear_solver/linear_solver.h>
|
10
|
-
#include <ortools/sat/cp_model.h>
|
11
2
|
|
12
|
-
// rice
|
13
|
-
#include <rice/Array.hpp>
|
14
|
-
#include <rice/Class.hpp>
|
15
|
-
#include <rice/Constructor.hpp>
|
16
|
-
#include <rice/Hash.hpp>
|
17
3
|
#include <rice/Module.hpp>
|
18
|
-
#include <rice/String.hpp>
|
19
|
-
#include <rice/Symbol.hpp>
|
20
4
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
using operations_research::LinearExpr;
|
28
|
-
using operations_research::LinearRange;
|
29
|
-
using operations_research::LocalSearchMetaheuristic;
|
30
|
-
using operations_research::MPConstraint;
|
31
|
-
using operations_research::MPObjective;
|
32
|
-
using operations_research::MPSolver;
|
33
|
-
using operations_research::MPVariable;
|
34
|
-
using operations_research::NodeIndex;
|
35
|
-
using operations_research::RoutingDimension;
|
36
|
-
using operations_research::RoutingIndexManager;
|
37
|
-
using operations_research::RoutingModel;
|
38
|
-
using operations_research::RoutingNodeIndex;
|
39
|
-
using operations_research::RoutingSearchParameters;
|
40
|
-
using operations_research::SimpleLinearSumAssignment;
|
41
|
-
using operations_research::SimpleMaxFlow;
|
42
|
-
using operations_research::SimpleMinCostFlow;
|
43
|
-
|
44
|
-
using operations_research::sat::BoolVar;
|
45
|
-
using operations_research::sat::CpModelBuilder;
|
46
|
-
using operations_research::sat::CpSolverResponse;
|
47
|
-
using operations_research::sat::CpSolverStatus;
|
48
|
-
using operations_research::sat::NewFeasibleSolutionObserver;
|
49
|
-
using operations_research::sat::SatParameters;
|
50
|
-
using operations_research::sat::SolutionIntegerValue;
|
51
|
-
|
52
|
-
using Rice::Array;
|
53
|
-
using Rice::Class;
|
54
|
-
using Rice::Constructor;
|
55
|
-
using Rice::Hash;
|
56
|
-
using Rice::Module;
|
57
|
-
using Rice::Object;
|
58
|
-
using Rice::String;
|
59
|
-
using Rice::Symbol;
|
60
|
-
using Rice::define_module;
|
61
|
-
using Rice::define_class_under;
|
62
|
-
|
63
|
-
template<>
|
64
|
-
inline
|
65
|
-
KnapsackSolver::SolverType from_ruby<KnapsackSolver::SolverType>(Object x)
|
66
|
-
{
|
67
|
-
std::string s = Symbol(x).str();
|
68
|
-
if (s == "branch_and_bound") {
|
69
|
-
return KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER;
|
70
|
-
} else {
|
71
|
-
throw std::runtime_error("Unknown solver type: " + s);
|
72
|
-
}
|
73
|
-
}
|
74
|
-
|
75
|
-
template<>
|
76
|
-
inline
|
77
|
-
MPSolver::OptimizationProblemType from_ruby<MPSolver::OptimizationProblemType>(Object x)
|
78
|
-
{
|
79
|
-
std::string s = Symbol(x).str();
|
80
|
-
if (s == "glop") {
|
81
|
-
return MPSolver::OptimizationProblemType::GLOP_LINEAR_PROGRAMMING;
|
82
|
-
} else if (s == "cbc") {
|
83
|
-
return MPSolver::OptimizationProblemType::CBC_MIXED_INTEGER_PROGRAMMING;
|
84
|
-
} else {
|
85
|
-
throw std::runtime_error("Unknown optimization problem type: " + s);
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
template<>
|
90
|
-
inline
|
91
|
-
RoutingNodeIndex from_ruby<RoutingNodeIndex>(Object x)
|
92
|
-
{
|
93
|
-
const RoutingNodeIndex index{from_ruby<int>(x)};
|
94
|
-
return index;
|
95
|
-
}
|
96
|
-
|
97
|
-
template<>
|
98
|
-
inline
|
99
|
-
Object to_ruby<RoutingNodeIndex>(RoutingNodeIndex const &x)
|
100
|
-
{
|
101
|
-
return to_ruby<int>(x.value());
|
102
|
-
}
|
103
|
-
|
104
|
-
std::vector<RoutingNodeIndex> nodeIndexVector(Array x) {
|
105
|
-
std::vector<RoutingNodeIndex> res;
|
106
|
-
for (auto const& v : x) {
|
107
|
-
res.push_back(from_ruby<RoutingNodeIndex>(v));
|
108
|
-
}
|
109
|
-
return res;
|
110
|
-
}
|
111
|
-
|
112
|
-
template<>
|
113
|
-
inline
|
114
|
-
operations_research::sat::LinearExpr from_ruby<operations_research::sat::LinearExpr>(Object x)
|
115
|
-
{
|
116
|
-
operations_research::sat::LinearExpr expr;
|
117
|
-
|
118
|
-
if (x.respond_to("to_i")) {
|
119
|
-
expr = from_ruby<int64>(x.call("to_i"));
|
120
|
-
} else if (x.respond_to("vars")) {
|
121
|
-
Array vars = x.call("vars");
|
122
|
-
for(auto const& var: vars) {
|
123
|
-
auto cvar = (Array) var;
|
124
|
-
// TODO clean up
|
125
|
-
Object o = cvar[0];
|
126
|
-
std::string type = ((String) o.call("class").call("name")).str();
|
127
|
-
if (type == "ORTools::BoolVar") {
|
128
|
-
expr.AddTerm(from_ruby<operations_research::sat::BoolVar>(cvar[0]), from_ruby<int64>(cvar[1]));
|
129
|
-
} else if (type == "Integer") {
|
130
|
-
expr.AddConstant(from_ruby<int64>(cvar[0]));
|
131
|
-
} else {
|
132
|
-
expr.AddTerm(from_ruby<operations_research::sat::IntVar>(cvar[0]), from_ruby<int64>(cvar[1]));
|
133
|
-
}
|
134
|
-
}
|
135
|
-
} else {
|
136
|
-
std::string type = ((String) x.call("class").call("name")).str();
|
137
|
-
if (type == "ORTools::BoolVar") {
|
138
|
-
expr = from_ruby<operations_research::sat::BoolVar>(x);
|
139
|
-
} else {
|
140
|
-
expr = from_ruby<operations_research::sat::IntVar>(x);
|
141
|
-
}
|
142
|
-
}
|
143
|
-
|
144
|
-
return expr;
|
145
|
-
}
|
146
|
-
|
147
|
-
// need a wrapper class due to const
|
148
|
-
class Assignment {
|
149
|
-
const operations_research::Assignment* self;
|
150
|
-
public:
|
151
|
-
Assignment(const operations_research::Assignment* v) {
|
152
|
-
self = v;
|
153
|
-
}
|
154
|
-
int64 ObjectiveValue() {
|
155
|
-
return self->ObjectiveValue();
|
156
|
-
}
|
157
|
-
int64 Value(const operations_research::IntVar* const var) const {
|
158
|
-
return self->Value(var);
|
159
|
-
}
|
160
|
-
int64 Min(const operations_research::IntVar* const var) const {
|
161
|
-
return self->Min(var);
|
162
|
-
}
|
163
|
-
int64 Max(const operations_research::IntVar* const var) const {
|
164
|
-
return self->Max(var);
|
165
|
-
}
|
166
|
-
};
|
167
|
-
|
168
|
-
Class rb_cMPVariable;
|
169
|
-
Class rb_cMPConstraint;
|
170
|
-
Class rb_cMPObjective;
|
171
|
-
Class rb_cIntVar;
|
172
|
-
Class rb_cIntervalVar;
|
173
|
-
Class rb_cRoutingDimension;
|
174
|
-
Class rb_cConstraint;
|
175
|
-
Class rb_cSolver2;
|
176
|
-
|
177
|
-
template<>
|
178
|
-
inline
|
179
|
-
Object to_ruby<MPVariable*>(MPVariable* const &x)
|
180
|
-
{
|
181
|
-
return Rice::Data_Object<MPVariable>(x, rb_cMPVariable, nullptr, nullptr);
|
182
|
-
}
|
183
|
-
|
184
|
-
template<>
|
185
|
-
inline
|
186
|
-
Object to_ruby<MPConstraint*>(MPConstraint* const &x)
|
187
|
-
{
|
188
|
-
return Rice::Data_Object<MPConstraint>(x, rb_cMPConstraint, nullptr, nullptr);
|
189
|
-
}
|
190
|
-
|
191
|
-
template<>
|
192
|
-
inline
|
193
|
-
Object to_ruby<MPObjective*>(MPObjective* const &x)
|
194
|
-
{
|
195
|
-
return Rice::Data_Object<MPObjective>(x, rb_cMPObjective, nullptr, nullptr);
|
196
|
-
}
|
197
|
-
|
198
|
-
template<>
|
199
|
-
inline
|
200
|
-
Object to_ruby<operations_research::IntVar*>(operations_research::IntVar* const &x)
|
201
|
-
{
|
202
|
-
return Rice::Data_Object<operations_research::IntVar>(x, rb_cIntVar, nullptr, nullptr);
|
203
|
-
}
|
204
|
-
|
205
|
-
template<>
|
206
|
-
inline
|
207
|
-
Object to_ruby<operations_research::IntervalVar*>(operations_research::IntervalVar* const &x)
|
208
|
-
{
|
209
|
-
return Rice::Data_Object<operations_research::IntervalVar>(x, rb_cIntervalVar, nullptr, nullptr);
|
210
|
-
}
|
211
|
-
|
212
|
-
template<>
|
213
|
-
inline
|
214
|
-
Object to_ruby<RoutingDimension*>(RoutingDimension* const &x)
|
215
|
-
{
|
216
|
-
return Rice::Data_Object<RoutingDimension>(x, rb_cRoutingDimension, nullptr, nullptr);
|
217
|
-
}
|
218
|
-
|
219
|
-
template<>
|
220
|
-
inline
|
221
|
-
Object to_ruby<operations_research::Constraint*>(operations_research::Constraint* const &x)
|
222
|
-
{
|
223
|
-
return Rice::Data_Object<operations_research::Constraint>(x, rb_cConstraint, nullptr, nullptr);
|
224
|
-
}
|
225
|
-
|
226
|
-
template<>
|
227
|
-
inline
|
228
|
-
Object to_ruby<operations_research::Solver*>(operations_research::Solver* const &x)
|
229
|
-
{
|
230
|
-
return Rice::Data_Object<operations_research::Solver>(x, rb_cSolver2, nullptr, nullptr);
|
231
|
-
}
|
232
|
-
|
233
|
-
// need a wrapper class since absl::Span doesn't own
|
234
|
-
class IntVarSpan {
|
235
|
-
std::vector<operations_research::sat::IntVar> vec;
|
236
|
-
public:
|
237
|
-
IntVarSpan(Object x) {
|
238
|
-
Array a = Array(x);
|
239
|
-
for (std::size_t i = 0; i < a.size(); ++i) {
|
240
|
-
vec.push_back(from_ruby<operations_research::sat::IntVar>(a[i]));
|
241
|
-
}
|
242
|
-
}
|
243
|
-
operator absl::Span<const operations_research::sat::IntVar>() {
|
244
|
-
return absl::Span<const operations_research::sat::IntVar>(vec);
|
245
|
-
}
|
246
|
-
};
|
247
|
-
|
248
|
-
template<>
|
249
|
-
inline
|
250
|
-
IntVarSpan from_ruby<IntVarSpan>(Object x)
|
251
|
-
{
|
252
|
-
return IntVarSpan(x);
|
253
|
-
}
|
254
|
-
|
255
|
-
// need a wrapper class since absl::Span doesn't own
|
256
|
-
class IntervalVarSpan {
|
257
|
-
std::vector<operations_research::sat::IntervalVar> vec;
|
258
|
-
public:
|
259
|
-
IntervalVarSpan(Object x) {
|
260
|
-
Array a = Array(x);
|
261
|
-
for (std::size_t i = 0; i < a.size(); ++i) {
|
262
|
-
vec.push_back(from_ruby<operations_research::sat::IntervalVar>(a[i]));
|
263
|
-
}
|
264
|
-
}
|
265
|
-
operator absl::Span<const operations_research::sat::IntervalVar>() {
|
266
|
-
return absl::Span<const operations_research::sat::IntervalVar>(vec);
|
267
|
-
}
|
268
|
-
};
|
269
|
-
|
270
|
-
template<>
|
271
|
-
inline
|
272
|
-
IntervalVarSpan from_ruby<IntervalVarSpan>(Object x)
|
273
|
-
{
|
274
|
-
return IntervalVarSpan(x);
|
275
|
-
}
|
276
|
-
|
277
|
-
// need a wrapper class since absl::Span doesn't own
|
278
|
-
class BoolVarSpan {
|
279
|
-
std::vector<operations_research::sat::BoolVar> vec;
|
280
|
-
public:
|
281
|
-
BoolVarSpan(Object x) {
|
282
|
-
Array a = Array(x);
|
283
|
-
for (std::size_t i = 0; i < a.size(); ++i) {
|
284
|
-
vec.push_back(from_ruby<operations_research::sat::BoolVar>(a[i]));
|
285
|
-
}
|
286
|
-
}
|
287
|
-
operator absl::Span<const operations_research::sat::BoolVar>() {
|
288
|
-
return absl::Span<const operations_research::sat::BoolVar>(vec);
|
289
|
-
}
|
290
|
-
};
|
291
|
-
|
292
|
-
template<>
|
293
|
-
inline
|
294
|
-
BoolVarSpan from_ruby<BoolVarSpan>(Object x)
|
295
|
-
{
|
296
|
-
return BoolVarSpan(x);
|
297
|
-
}
|
5
|
+
void init_assignment(Rice::Module& m);
|
6
|
+
void init_bin_packing(Rice::Module& m);
|
7
|
+
void init_constraint(Rice::Module& m);
|
8
|
+
void init_linear(Rice::Module& m);
|
9
|
+
void init_network_flows(Rice::Module& m);
|
10
|
+
void init_routing(Rice::Module& m);
|
298
11
|
|
299
12
|
extern "C"
|
300
13
|
void Init_ext()
|
301
14
|
{
|
302
|
-
|
303
|
-
.define_singleton_method("default_routing_search_parameters", &DefaultRoutingSearchParameters)
|
304
|
-
.define_singleton_method(
|
305
|
-
"lib_version",
|
306
|
-
*[]() {
|
307
|
-
return std::to_string(operations_research::OrToolsMajorVersion()) + "."
|
308
|
-
+ std::to_string(operations_research::OrToolsMinorVersion());
|
309
|
-
});
|
310
|
-
|
311
|
-
define_class_under<RoutingSearchParameters>(rb_mORTools, "RoutingSearchParameters")
|
312
|
-
.define_method(
|
313
|
-
"first_solution_strategy=",
|
314
|
-
*[](RoutingSearchParameters& self, Symbol value) {
|
315
|
-
std::string s = Symbol(value).str();
|
316
|
-
|
317
|
-
FirstSolutionStrategy::Value v;
|
318
|
-
if (s == "path_cheapest_arc") {
|
319
|
-
v = FirstSolutionStrategy::PATH_CHEAPEST_ARC;
|
320
|
-
} else if (s == "path_most_constrained_arc") {
|
321
|
-
v = FirstSolutionStrategy::PATH_MOST_CONSTRAINED_ARC;
|
322
|
-
} else if (s == "evaluator_strategy") {
|
323
|
-
v = FirstSolutionStrategy::EVALUATOR_STRATEGY;
|
324
|
-
} else if (s == "savings") {
|
325
|
-
v = FirstSolutionStrategy::SAVINGS;
|
326
|
-
} else if (s == "sweep") {
|
327
|
-
v = FirstSolutionStrategy::SWEEP;
|
328
|
-
} else if (s == "christofides") {
|
329
|
-
v = FirstSolutionStrategy::CHRISTOFIDES;
|
330
|
-
} else if (s == "all_unperformed") {
|
331
|
-
v = FirstSolutionStrategy::ALL_UNPERFORMED;
|
332
|
-
} else if (s == "best_insertion") {
|
333
|
-
v = FirstSolutionStrategy::BEST_INSERTION;
|
334
|
-
} else if (s == "parallel_cheapest_insertion") {
|
335
|
-
v = FirstSolutionStrategy::PARALLEL_CHEAPEST_INSERTION;
|
336
|
-
} else if (s == "sequential_cheapest_insertion") {
|
337
|
-
v = FirstSolutionStrategy::SEQUENTIAL_CHEAPEST_INSERTION;
|
338
|
-
} else if (s == "local_cheapest_insertion") {
|
339
|
-
v = FirstSolutionStrategy::LOCAL_CHEAPEST_INSERTION;
|
340
|
-
} else if (s == "global_cheapest_arc") {
|
341
|
-
v = FirstSolutionStrategy::GLOBAL_CHEAPEST_ARC;
|
342
|
-
} else if (s == "local_cheapest_arc") {
|
343
|
-
v = FirstSolutionStrategy::LOCAL_CHEAPEST_ARC;
|
344
|
-
} else if (s == "first_unbound_min_value") {
|
345
|
-
v = FirstSolutionStrategy::FIRST_UNBOUND_MIN_VALUE;
|
346
|
-
} else {
|
347
|
-
throw std::runtime_error("Unknown first solution strategy: " + s);
|
348
|
-
}
|
349
|
-
|
350
|
-
return self.set_first_solution_strategy(v);
|
351
|
-
})
|
352
|
-
.define_method(
|
353
|
-
"local_search_metaheuristic=",
|
354
|
-
*[](RoutingSearchParameters& self, Symbol value) {
|
355
|
-
std::string s = Symbol(value).str();
|
356
|
-
|
357
|
-
LocalSearchMetaheuristic::Value v;
|
358
|
-
if (s == "guided_local_search") {
|
359
|
-
v = LocalSearchMetaheuristic::GUIDED_LOCAL_SEARCH;
|
360
|
-
} else if (s == "tabu_search") {
|
361
|
-
v = LocalSearchMetaheuristic::TABU_SEARCH;
|
362
|
-
} else if (s == "generic_tabu_search") {
|
363
|
-
v = LocalSearchMetaheuristic::GENERIC_TABU_SEARCH;
|
364
|
-
} else if (s == "simulated_annealing") {
|
365
|
-
v = LocalSearchMetaheuristic::SIMULATED_ANNEALING;
|
366
|
-
} else {
|
367
|
-
throw std::runtime_error("Unknown local search metaheuristic: " + s);
|
368
|
-
}
|
369
|
-
|
370
|
-
return self.set_local_search_metaheuristic(v);
|
371
|
-
})
|
372
|
-
.define_method(
|
373
|
-
"log_search=",
|
374
|
-
*[](RoutingSearchParameters& self, bool value) {
|
375
|
-
self.set_log_search(value);
|
376
|
-
})
|
377
|
-
.define_method(
|
378
|
-
"solution_limit=",
|
379
|
-
*[](RoutingSearchParameters& self, int64 value) {
|
380
|
-
self.set_solution_limit(value);
|
381
|
-
})
|
382
|
-
.define_method(
|
383
|
-
"time_limit=",
|
384
|
-
*[](RoutingSearchParameters& self, int64 value) {
|
385
|
-
self.mutable_time_limit()->set_seconds(value);
|
386
|
-
})
|
387
|
-
.define_method(
|
388
|
-
"lns_time_limit=",
|
389
|
-
*[](RoutingSearchParameters& self, int64 value) {
|
390
|
-
self.mutable_lns_time_limit()->set_seconds(value);
|
391
|
-
});
|
392
|
-
|
393
|
-
rb_cMPVariable = define_class_under<MPVariable>(rb_mORTools, "MPVariable")
|
394
|
-
.define_method("name", &MPVariable::name)
|
395
|
-
.define_method("solution_value", &MPVariable::solution_value)
|
396
|
-
.define_method(
|
397
|
-
"+",
|
398
|
-
*[](MPVariable& self, LinearExpr& other) {
|
399
|
-
LinearExpr s(&self);
|
400
|
-
return s + other;
|
401
|
-
})
|
402
|
-
.define_method(
|
403
|
-
"-",
|
404
|
-
*[](MPVariable& self, LinearExpr& other) {
|
405
|
-
LinearExpr s(&self);
|
406
|
-
return s - other;
|
407
|
-
})
|
408
|
-
.define_method(
|
409
|
-
"*",
|
410
|
-
*[](MPVariable& self, double other) {
|
411
|
-
LinearExpr s(&self);
|
412
|
-
return s * other;
|
413
|
-
})
|
414
|
-
.define_method(
|
415
|
-
"inspect",
|
416
|
-
*[](MPVariable& self) {
|
417
|
-
return "#<ORTools::MPVariable @name=\"" + self.name() + "\">";
|
418
|
-
});
|
15
|
+
auto m = Rice::define_module("ORTools");
|
419
16
|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
"
|
424
|
-
|
425
|
-
return self + other;
|
426
|
-
})
|
427
|
-
.define_method(
|
428
|
-
"_add_mp_variable",
|
429
|
-
*[](LinearExpr& self, MPVariable &other) {
|
430
|
-
LinearExpr o(&other);
|
431
|
-
return self + o;
|
432
|
-
})
|
433
|
-
.define_method(
|
434
|
-
"_gte_double",
|
435
|
-
*[](LinearExpr& self, double other) {
|
436
|
-
LinearExpr o(other);
|
437
|
-
return self >= o;
|
438
|
-
})
|
439
|
-
.define_method(
|
440
|
-
"_gte_linear_expr",
|
441
|
-
*[](LinearExpr& self, LinearExpr& other) {
|
442
|
-
return self >= other;
|
443
|
-
})
|
444
|
-
.define_method(
|
445
|
-
"_lte_double",
|
446
|
-
*[](LinearExpr& self, double other) {
|
447
|
-
LinearExpr o(other);
|
448
|
-
return self <= o;
|
449
|
-
})
|
450
|
-
.define_method(
|
451
|
-
"_lte_linear_expr",
|
452
|
-
*[](LinearExpr& self, LinearExpr& other) {
|
453
|
-
return self <= other;
|
454
|
-
})
|
455
|
-
.define_method(
|
456
|
-
"==",
|
457
|
-
*[](LinearExpr& self, double other) {
|
458
|
-
LinearExpr o(other);
|
459
|
-
return self == o;
|
460
|
-
})
|
461
|
-
.define_method(
|
462
|
-
"to_s",
|
463
|
-
*[](LinearExpr& self) {
|
464
|
-
return self.ToString();
|
465
|
-
})
|
466
|
-
.define_method(
|
467
|
-
"inspect",
|
468
|
-
*[](LinearExpr& self) {
|
469
|
-
return "#<ORTools::LinearExpr \"" + self.ToString() + "\">";
|
470
|
-
});
|
471
|
-
|
472
|
-
define_class_under<LinearRange>(rb_mORTools, "LinearRange");
|
473
|
-
|
474
|
-
rb_cMPConstraint = define_class_under<MPConstraint>(rb_mORTools, "MPConstraint")
|
475
|
-
.define_method("set_coefficient", &MPConstraint::SetCoefficient);
|
476
|
-
|
477
|
-
rb_cMPObjective = define_class_under<MPObjective>(rb_mORTools, "MPObjective")
|
478
|
-
.define_method("value", &MPObjective::Value)
|
479
|
-
.define_method("set_coefficient", &MPObjective::SetCoefficient)
|
480
|
-
.define_method("set_maximization", &MPObjective::SetMaximization);
|
481
|
-
|
482
|
-
define_class_under<MPSolver>(rb_mORTools, "Solver")
|
483
|
-
.define_constructor(Constructor<MPSolver, std::string, MPSolver::OptimizationProblemType>())
|
484
|
-
.define_method("infinity", &MPSolver::infinity)
|
485
|
-
.define_method(
|
486
|
-
"int_var",
|
487
|
-
*[](MPSolver& self, double min, double max, const std::string& name) {
|
488
|
-
return self.MakeIntVar(min, max, name);
|
489
|
-
})
|
490
|
-
.define_method("num_var", &MPSolver::MakeNumVar)
|
491
|
-
.define_method("bool_var", &MPSolver::MakeBoolVar)
|
492
|
-
.define_method("num_variables", &MPSolver::NumVariables)
|
493
|
-
.define_method("num_constraints", &MPSolver::NumConstraints)
|
494
|
-
.define_method("wall_time", &MPSolver::wall_time)
|
495
|
-
.define_method("iterations", &MPSolver::iterations)
|
496
|
-
.define_method("nodes", &MPSolver::nodes)
|
497
|
-
.define_method("objective", &MPSolver::MutableObjective)
|
498
|
-
.define_method(
|
499
|
-
"maximize",
|
500
|
-
*[](MPSolver& self, LinearExpr& expr) {
|
501
|
-
return self.MutableObjective()->MaximizeLinearExpr(expr);
|
502
|
-
})
|
503
|
-
.define_method(
|
504
|
-
"minimize",
|
505
|
-
*[](MPSolver& self, LinearExpr& expr) {
|
506
|
-
return self.MutableObjective()->MinimizeLinearExpr(expr);
|
507
|
-
})
|
508
|
-
.define_method(
|
509
|
-
"add",
|
510
|
-
*[](MPSolver& self, const LinearRange& range) {
|
511
|
-
return self.MakeRowConstraint(range);
|
512
|
-
})
|
513
|
-
.define_method(
|
514
|
-
"constraint",
|
515
|
-
*[](MPSolver& self, double lb, double ub) {
|
516
|
-
return self.MakeRowConstraint(lb, ub);
|
517
|
-
})
|
518
|
-
.define_method(
|
519
|
-
"solve",
|
520
|
-
*[](MPSolver& self) {
|
521
|
-
auto status = self.Solve();
|
522
|
-
|
523
|
-
if (status == MPSolver::ResultStatus::OPTIMAL) {
|
524
|
-
return Symbol("optimal");
|
525
|
-
} else if (status == MPSolver::ResultStatus::FEASIBLE) {
|
526
|
-
return Symbol("feasible");
|
527
|
-
} else if (status == MPSolver::ResultStatus::INFEASIBLE) {
|
528
|
-
return Symbol("infeasible");
|
529
|
-
} else if (status == MPSolver::ResultStatus::UNBOUNDED) {
|
530
|
-
return Symbol("unbounded");
|
531
|
-
} else if (status == MPSolver::ResultStatus::ABNORMAL) {
|
532
|
-
return Symbol("abnormal");
|
533
|
-
} else if (status == MPSolver::ResultStatus::MODEL_INVALID) {
|
534
|
-
return Symbol("model_invalid");
|
535
|
-
} else if (status == MPSolver::ResultStatus::NOT_SOLVED) {
|
536
|
-
return Symbol("not_solved");
|
537
|
-
} else {
|
538
|
-
throw std::runtime_error("Unknown status");
|
539
|
-
}
|
540
|
-
});
|
541
|
-
|
542
|
-
define_class_under<operations_research::sat::IntVar>(rb_mORTools, "SatIntVar")
|
543
|
-
.define_method("name", &operations_research::sat::IntVar::Name);
|
544
|
-
|
545
|
-
define_class_under<operations_research::sat::IntervalVar>(rb_mORTools, "SatIntervalVar")
|
546
|
-
.define_method("name", &operations_research::sat::IntervalVar::Name);
|
547
|
-
|
548
|
-
define_class_under<operations_research::sat::Constraint>(rb_mORTools, "SatConstraint");
|
549
|
-
|
550
|
-
define_class_under<BoolVar>(rb_mORTools, "BoolVar")
|
551
|
-
.define_method("name", &BoolVar::Name)
|
552
|
-
.define_method("index", &BoolVar::index)
|
553
|
-
.define_method("not", &BoolVar::Not)
|
554
|
-
.define_method(
|
555
|
-
"inspect",
|
556
|
-
*[](BoolVar& self) {
|
557
|
-
String name(self.Name());
|
558
|
-
return "#<ORTools::BoolVar @name=" + name.inspect().str() + ">";
|
559
|
-
});
|
560
|
-
|
561
|
-
define_class_under<CpModelBuilder>(rb_mORTools, "CpModel")
|
562
|
-
.define_constructor(Constructor<CpModelBuilder>())
|
563
|
-
.define_method(
|
564
|
-
"new_int_var",
|
565
|
-
*[](CpModelBuilder& self, int64 start, int64 end, std::string name) {
|
566
|
-
const Domain domain(start, end);
|
567
|
-
return self.NewIntVar(domain).WithName(name);
|
568
|
-
})
|
569
|
-
.define_method(
|
570
|
-
"new_bool_var",
|
571
|
-
*[](CpModelBuilder& self, std::string name) {
|
572
|
-
return self.NewBoolVar().WithName(name);
|
573
|
-
})
|
574
|
-
.define_method(
|
575
|
-
"new_interval_var",
|
576
|
-
*[](CpModelBuilder& self, operations_research::sat::IntVar start, operations_research::sat::IntVar size, operations_research::sat::IntVar end, std::string name) {
|
577
|
-
return self.NewIntervalVar(start, size, end).WithName(name);
|
578
|
-
})
|
579
|
-
.define_method(
|
580
|
-
"add_equality",
|
581
|
-
*[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
|
582
|
-
self.AddEquality(x, y);
|
583
|
-
})
|
584
|
-
.define_method(
|
585
|
-
"add_not_equal",
|
586
|
-
*[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
|
587
|
-
self.AddNotEqual(x, y);
|
588
|
-
})
|
589
|
-
.define_method(
|
590
|
-
"add_greater_than",
|
591
|
-
*[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
|
592
|
-
self.AddGreaterThan(x, y);
|
593
|
-
})
|
594
|
-
.define_method(
|
595
|
-
"add_greater_or_equal",
|
596
|
-
*[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
|
597
|
-
self.AddGreaterOrEqual(x, y);
|
598
|
-
})
|
599
|
-
.define_method(
|
600
|
-
"add_less_than",
|
601
|
-
*[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
|
602
|
-
self.AddLessThan(x, y);
|
603
|
-
})
|
604
|
-
.define_method(
|
605
|
-
"add_less_or_equal",
|
606
|
-
*[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
|
607
|
-
self.AddLessOrEqual(x, y);
|
608
|
-
})
|
609
|
-
.define_method(
|
610
|
-
"add_all_different",
|
611
|
-
*[](CpModelBuilder& self, IntVarSpan vars) {
|
612
|
-
self.AddAllDifferent(vars);
|
613
|
-
})
|
614
|
-
.define_method(
|
615
|
-
"add_max_equality",
|
616
|
-
*[](CpModelBuilder& self, operations_research::sat::IntVar target, IntVarSpan vars) {
|
617
|
-
self.AddMaxEquality(target, vars);
|
618
|
-
})
|
619
|
-
.define_method(
|
620
|
-
"add_no_overlap",
|
621
|
-
*[](CpModelBuilder& self, IntervalVarSpan vars) {
|
622
|
-
self.AddNoOverlap(vars);
|
623
|
-
})
|
624
|
-
.define_method(
|
625
|
-
"add_bool_or",
|
626
|
-
*[](CpModelBuilder& self, BoolVarSpan literals) {
|
627
|
-
self.AddBoolOr(literals);
|
628
|
-
})
|
629
|
-
.define_method("add_implication", &CpModelBuilder::AddImplication)
|
630
|
-
.define_method(
|
631
|
-
"maximize",
|
632
|
-
*[](CpModelBuilder& self, operations_research::sat::LinearExpr expr) {
|
633
|
-
self.Maximize(expr);
|
634
|
-
})
|
635
|
-
.define_method(
|
636
|
-
"minimize",
|
637
|
-
*[](CpModelBuilder& self, operations_research::sat::LinearExpr expr) {
|
638
|
-
self.Minimize(expr);
|
639
|
-
});
|
640
|
-
|
641
|
-
define_class_under<SatParameters>(rb_mORTools, "SatParameters")
|
642
|
-
.define_constructor(Constructor<SatParameters>())
|
643
|
-
.define_method("max_time_in_seconds=",
|
644
|
-
*[](SatParameters& self, double value) {
|
645
|
-
self.set_max_time_in_seconds(value);
|
17
|
+
m.define_singleton_method(
|
18
|
+
"lib_version",
|
19
|
+
*[]() {
|
20
|
+
return std::to_string(operations_research::OrToolsMajorVersion()) + "."
|
21
|
+
+ std::to_string(operations_research::OrToolsMinorVersion());
|
646
22
|
});
|
647
23
|
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
if (all_solutions) {
|
655
|
-
// set parameters for SearchForAllSolutions
|
656
|
-
parameters.set_enumerate_all_solutions(true);
|
657
|
-
}
|
658
|
-
m.Add(NewSatParameters(parameters));
|
659
|
-
|
660
|
-
m.Add(NewFeasibleSolutionObserver(
|
661
|
-
[callback](const CpSolverResponse& r) {
|
662
|
-
// TODO find a better way to do this
|
663
|
-
callback.call("response=", r);
|
664
|
-
callback.call("on_solution_callback");
|
665
|
-
})
|
666
|
-
);
|
667
|
-
return SolveCpModel(model.Build(), &m);
|
668
|
-
})
|
669
|
-
.define_method(
|
670
|
-
"_solve",
|
671
|
-
*[](Object self, CpModelBuilder& model, SatParameters& parameters) {
|
672
|
-
operations_research::sat::Model m;
|
673
|
-
m.Add(NewSatParameters(parameters));
|
674
|
-
return SolveCpModel(model.Build(), &m);
|
675
|
-
})
|
676
|
-
.define_method(
|
677
|
-
"_solution_integer_value",
|
678
|
-
*[](Object self, CpSolverResponse& response, operations_research::sat::IntVar& x) {
|
679
|
-
return SolutionIntegerValue(response, x);
|
680
|
-
})
|
681
|
-
.define_method(
|
682
|
-
"_solution_boolean_value",
|
683
|
-
*[](Object self, CpSolverResponse& response, operations_research::sat::BoolVar& x) {
|
684
|
-
return SolutionBooleanValue(response, x);
|
685
|
-
});
|
686
|
-
|
687
|
-
define_class_under<CpSolverResponse>(rb_mORTools, "CpSolverResponse")
|
688
|
-
.define_method("objective_value", &CpSolverResponse::objective_value)
|
689
|
-
.define_method("num_conflicts", &CpSolverResponse::num_conflicts)
|
690
|
-
.define_method("num_branches", &CpSolverResponse::num_branches)
|
691
|
-
.define_method("wall_time", &CpSolverResponse::wall_time)
|
692
|
-
.define_method(
|
693
|
-
"solution_integer_value",
|
694
|
-
*[](CpSolverResponse& self, operations_research::sat::IntVar& x) {
|
695
|
-
operations_research::sat::LinearExpr expr(x);
|
696
|
-
return SolutionIntegerValue(self, expr);
|
697
|
-
})
|
698
|
-
.define_method("solution_boolean_value", &operations_research::sat::SolutionBooleanValue)
|
699
|
-
.define_method(
|
700
|
-
"status",
|
701
|
-
*[](CpSolverResponse& self) {
|
702
|
-
auto status = self.status();
|
703
|
-
|
704
|
-
if (status == CpSolverStatus::OPTIMAL) {
|
705
|
-
return Symbol("optimal");
|
706
|
-
} else if (status == CpSolverStatus::FEASIBLE) {
|
707
|
-
return Symbol("feasible");
|
708
|
-
} else if (status == CpSolverStatus::INFEASIBLE) {
|
709
|
-
return Symbol("infeasible");
|
710
|
-
} else if (status == CpSolverStatus::MODEL_INVALID) {
|
711
|
-
return Symbol("model_invalid");
|
712
|
-
} else if (status == CpSolverStatus::UNKNOWN) {
|
713
|
-
return Symbol("unknown");
|
714
|
-
} else {
|
715
|
-
throw std::runtime_error("Unknown solver status");
|
716
|
-
}
|
717
|
-
});
|
718
|
-
|
719
|
-
define_class_under<RoutingIndexManager>(rb_mORTools, "RoutingIndexManager")
|
720
|
-
.define_singleton_method(
|
721
|
-
"_new_depot",
|
722
|
-
*[](int num_nodes, int num_vehicles, RoutingNodeIndex depot) {
|
723
|
-
return RoutingIndexManager(num_nodes, num_vehicles, depot);
|
724
|
-
})
|
725
|
-
.define_singleton_method(
|
726
|
-
"_new_starts_ends",
|
727
|
-
*[](int num_nodes, int num_vehicles, Array starts, Array ends) {
|
728
|
-
return RoutingIndexManager(num_nodes, num_vehicles, nodeIndexVector(starts), nodeIndexVector(ends));
|
729
|
-
})
|
730
|
-
.define_method("index_to_node", &RoutingIndexManager::IndexToNode)
|
731
|
-
.define_method("node_to_index", &RoutingIndexManager::NodeToIndex);
|
732
|
-
|
733
|
-
define_class_under<Assignment>(rb_mORTools, "Assignment")
|
734
|
-
.define_method("objective_value", &Assignment::ObjectiveValue)
|
735
|
-
.define_method("value", &Assignment::Value)
|
736
|
-
.define_method("min", &Assignment::Min)
|
737
|
-
.define_method("max", &Assignment::Max);
|
738
|
-
|
739
|
-
// not to be confused with operations_research::sat::IntVar
|
740
|
-
rb_cIntVar = define_class_under<operations_research::IntVar>(rb_mORTools, "IntVar")
|
741
|
-
.define_method(
|
742
|
-
"set_range",
|
743
|
-
*[](operations_research::IntVar& self, int64 new_min, int64 new_max) {
|
744
|
-
self.SetRange(new_min, new_max);
|
745
|
-
});
|
746
|
-
|
747
|
-
rb_cIntervalVar = define_class_under<operations_research::IntervalVar>(rb_mORTools, "IntervalVar");
|
748
|
-
|
749
|
-
rb_cRoutingDimension = define_class_under<RoutingDimension>(rb_mORTools, "RoutingDimension")
|
750
|
-
.define_method("global_span_cost_coefficient=", &RoutingDimension::SetGlobalSpanCostCoefficient)
|
751
|
-
.define_method("cumul_var", &RoutingDimension::CumulVar);
|
752
|
-
|
753
|
-
rb_cConstraint = define_class_under<operations_research::Constraint>(rb_mORTools, "Constraint");
|
754
|
-
|
755
|
-
rb_cSolver2 = define_class_under<operations_research::Solver>(rb_mORTools, "Solver2")
|
756
|
-
.define_method(
|
757
|
-
"add",
|
758
|
-
*[](operations_research::Solver& self, Object o) {
|
759
|
-
operations_research::Constraint* constraint;
|
760
|
-
if (o.respond_to("left")) {
|
761
|
-
operations_research::IntExpr* left(from_ruby<operations_research::IntVar*>(o.call("left")));
|
762
|
-
operations_research::IntExpr* right(from_ruby<operations_research::IntVar*>(o.call("right")));
|
763
|
-
auto op = o.call("operator").to_s().str();
|
764
|
-
if (op == "==") {
|
765
|
-
constraint = self.MakeEquality(left, right);
|
766
|
-
} else if (op == "<=") {
|
767
|
-
constraint = self.MakeLessOrEqual(left, right);
|
768
|
-
} else {
|
769
|
-
throw std::runtime_error("Unknown operator");
|
770
|
-
}
|
771
|
-
} else {
|
772
|
-
constraint = from_ruby<operations_research::Constraint*>(o);
|
773
|
-
}
|
774
|
-
self.AddConstraint(constraint);
|
775
|
-
})
|
776
|
-
.define_method(
|
777
|
-
"fixed_duration_interval_var",
|
778
|
-
*[](operations_research::Solver& self, operations_research::IntVar* const start_variable, int64 duration, const std::string& name) {
|
779
|
-
return self.MakeFixedDurationIntervalVar(start_variable, duration, name);
|
780
|
-
})
|
781
|
-
.define_method(
|
782
|
-
"cumulative",
|
783
|
-
*[](operations_research::Solver& self, Array rb_intervals, Array rb_demands, int64 capacity, const std::string& name) {
|
784
|
-
std::vector<operations_research::IntervalVar*> intervals;
|
785
|
-
for (std::size_t i = 0; i < rb_intervals.size(); ++i) {
|
786
|
-
intervals.push_back(from_ruby<operations_research::IntervalVar*>(rb_intervals[i]));
|
787
|
-
}
|
788
|
-
|
789
|
-
std::vector<int64> demands;
|
790
|
-
for (std::size_t i = 0; i < rb_demands.size(); ++i) {
|
791
|
-
demands.push_back(from_ruby<int64>(rb_demands[i]));
|
792
|
-
}
|
793
|
-
|
794
|
-
return self.MakeCumulative(intervals, demands, capacity, name);
|
795
|
-
});
|
796
|
-
|
797
|
-
define_class_under<RoutingModel>(rb_mORTools, "RoutingModel")
|
798
|
-
.define_constructor(Constructor<RoutingModel, RoutingIndexManager>())
|
799
|
-
.define_method(
|
800
|
-
"register_transit_callback",
|
801
|
-
*[](RoutingModel& self, Object callback) {
|
802
|
-
return self.RegisterTransitCallback(
|
803
|
-
[callback](int64 from_index, int64 to_index) -> int64 {
|
804
|
-
return from_ruby<int64>(callback.call("call", from_index, to_index));
|
805
|
-
}
|
806
|
-
);
|
807
|
-
})
|
808
|
-
.define_method(
|
809
|
-
"register_unary_transit_callback",
|
810
|
-
*[](RoutingModel& self, Object callback) {
|
811
|
-
return self.RegisterUnaryTransitCallback(
|
812
|
-
[callback](int64 from_index) -> int64 {
|
813
|
-
return from_ruby<int64>(callback.call("call", from_index));
|
814
|
-
}
|
815
|
-
);
|
816
|
-
})
|
817
|
-
.define_method("depot", &RoutingModel::GetDepot)
|
818
|
-
.define_method("size", &RoutingModel::Size)
|
819
|
-
.define_method("status", *[](RoutingModel& self) {
|
820
|
-
auto status = self.status();
|
821
|
-
|
822
|
-
if (status == RoutingModel::ROUTING_NOT_SOLVED) {
|
823
|
-
return Symbol("not_solved");
|
824
|
-
} else if (status == RoutingModel::ROUTING_SUCCESS) {
|
825
|
-
return Symbol("success");
|
826
|
-
} else if (status == RoutingModel::ROUTING_FAIL) {
|
827
|
-
return Symbol("fail");
|
828
|
-
} else if (status == RoutingModel::ROUTING_FAIL_TIMEOUT) {
|
829
|
-
return Symbol("fail_timeout");
|
830
|
-
} else if (status == RoutingModel::ROUTING_INVALID) {
|
831
|
-
return Symbol("invalid");
|
832
|
-
} else {
|
833
|
-
throw std::runtime_error("Unknown solver status");
|
834
|
-
}
|
835
|
-
})
|
836
|
-
.define_method("vehicle_var", &RoutingModel::VehicleVar)
|
837
|
-
.define_method("set_arc_cost_evaluator_of_all_vehicles", &RoutingModel::SetArcCostEvaluatorOfAllVehicles)
|
838
|
-
.define_method("set_arc_cost_evaluator_of_vehicle", &RoutingModel::SetArcCostEvaluatorOfVehicle)
|
839
|
-
.define_method("set_fixed_cost_of_all_vehicles", &RoutingModel::SetFixedCostOfAllVehicles)
|
840
|
-
.define_method("set_fixed_cost_of_vehicle", &RoutingModel::SetFixedCostOfVehicle)
|
841
|
-
.define_method("fixed_cost_of_vehicle", &RoutingModel::GetFixedCostOfVehicle)
|
842
|
-
.define_method("add_dimension", &RoutingModel::AddDimension)
|
843
|
-
.define_method(
|
844
|
-
"add_dimension_with_vehicle_capacity",
|
845
|
-
*[](RoutingModel& self, int evaluator_index, int64 slack_max, Array vc, bool fix_start_cumul_to_zero, const std::string& name) {
|
846
|
-
std::vector<int64> vehicle_capacities;
|
847
|
-
for (std::size_t i = 0; i < vc.size(); ++i) {
|
848
|
-
vehicle_capacities.push_back(from_ruby<int64>(vc[i]));
|
849
|
-
}
|
850
|
-
self.AddDimensionWithVehicleCapacity(evaluator_index, slack_max, vehicle_capacities, fix_start_cumul_to_zero, name);
|
851
|
-
})
|
852
|
-
.define_method(
|
853
|
-
"add_dimension_with_vehicle_transits",
|
854
|
-
*[](RoutingModel& self, Array rb_indices, int64 slack_max, int64 capacity, bool fix_start_cumul_to_zero, const std::string& name) {
|
855
|
-
std::vector<int> evaluator_indices;
|
856
|
-
for (std::size_t i = 0; i < rb_indices.size(); ++i) {
|
857
|
-
evaluator_indices.push_back(from_ruby<int>(rb_indices[i]));
|
858
|
-
}
|
859
|
-
self.AddDimensionWithVehicleTransits(evaluator_indices, slack_max, capacity, fix_start_cumul_to_zero, name);
|
860
|
-
})
|
861
|
-
.define_method(
|
862
|
-
"add_disjunction",
|
863
|
-
*[](RoutingModel& self, Array rb_indices, int64 penalty) {
|
864
|
-
std::vector<int64> indices;
|
865
|
-
for (std::size_t i = 0; i < rb_indices.size(); ++i) {
|
866
|
-
indices.push_back(from_ruby<int64>(rb_indices[i]));
|
867
|
-
}
|
868
|
-
self.AddDisjunction(indices, penalty);
|
869
|
-
})
|
870
|
-
.define_method("add_pickup_and_delivery", &RoutingModel::AddPickupAndDelivery)
|
871
|
-
.define_method("solver", &RoutingModel::solver)
|
872
|
-
.define_method("start", &RoutingModel::Start)
|
873
|
-
.define_method("end", &RoutingModel::End)
|
874
|
-
.define_method("start?", &RoutingModel::IsStart)
|
875
|
-
.define_method("end?", &RoutingModel::IsEnd)
|
876
|
-
.define_method("vehicle_index", &RoutingModel::VehicleIndex)
|
877
|
-
.define_method("next", &RoutingModel::Next)
|
878
|
-
.define_method("vehicle_used?", &RoutingModel::IsVehicleUsed)
|
879
|
-
.define_method("next_var", &RoutingModel::NextVar)
|
880
|
-
.define_method("arc_cost_for_vehicle", &RoutingModel::GetArcCostForVehicle)
|
881
|
-
.define_method("mutable_dimension", &RoutingModel::GetMutableDimension)
|
882
|
-
.define_method("add_variable_minimized_by_finalizer", &RoutingModel::AddVariableMinimizedByFinalizer)
|
883
|
-
.define_method(
|
884
|
-
"solve_with_parameters",
|
885
|
-
*[](RoutingModel& self, const RoutingSearchParameters& search_parameters) {
|
886
|
-
auto assignment = self.SolveWithParameters(search_parameters);
|
887
|
-
// std::cout << assignment->DebugString();
|
888
|
-
return (Assignment) assignment;
|
889
|
-
});
|
890
|
-
|
891
|
-
define_class_under<KnapsackSolver>(rb_mORTools, "KnapsackSolver")
|
892
|
-
.define_constructor(Constructor<KnapsackSolver, KnapsackSolver::SolverType, std::string>())
|
893
|
-
.define_method("_solve", &KnapsackSolver::Solve)
|
894
|
-
.define_method("best_solution_contains?", &KnapsackSolver::BestSolutionContains)
|
895
|
-
.define_method(
|
896
|
-
"init",
|
897
|
-
*[](KnapsackSolver& self, Array rb_values, Array rb_weights, Array rb_capacities) {
|
898
|
-
std::vector<int64> values;
|
899
|
-
for (std::size_t i = 0; i < rb_values.size(); ++i) {
|
900
|
-
values.push_back(from_ruby<int64>(rb_values[i]));
|
901
|
-
}
|
902
|
-
|
903
|
-
std::vector<std::vector<int64>> weights;
|
904
|
-
for (std::size_t i = 0; i < rb_weights.size(); ++i) {
|
905
|
-
Array rb_w = Array(rb_weights[i]);
|
906
|
-
std::vector<int64> w;
|
907
|
-
for (std::size_t j = 0; j < rb_w.size(); ++j) {
|
908
|
-
w.push_back(from_ruby<int64>(rb_w[j]));
|
909
|
-
}
|
910
|
-
weights.push_back(w);
|
911
|
-
}
|
912
|
-
|
913
|
-
std::vector<int64> capacities;
|
914
|
-
for (std::size_t i = 0; i < rb_capacities.size(); ++i) {
|
915
|
-
capacities.push_back(from_ruby<int64>(rb_capacities[i]));
|
916
|
-
}
|
917
|
-
|
918
|
-
self.Init(values, weights, capacities);
|
919
|
-
});
|
920
|
-
|
921
|
-
define_class_under<SimpleMaxFlow>(rb_mORTools, "SimpleMaxFlow")
|
922
|
-
.define_constructor(Constructor<SimpleMaxFlow>())
|
923
|
-
.define_method("add_arc_with_capacity", &SimpleMaxFlow::AddArcWithCapacity)
|
924
|
-
.define_method("num_nodes", &SimpleMaxFlow::NumNodes)
|
925
|
-
.define_method("num_arcs", &SimpleMaxFlow::NumArcs)
|
926
|
-
.define_method("tail", &SimpleMaxFlow::Tail)
|
927
|
-
.define_method("head", &SimpleMaxFlow::Head)
|
928
|
-
.define_method("capacity", &SimpleMaxFlow::Capacity)
|
929
|
-
.define_method("optimal_flow", &SimpleMaxFlow::OptimalFlow)
|
930
|
-
.define_method("flow", &SimpleMaxFlow::Flow)
|
931
|
-
.define_method(
|
932
|
-
"solve",
|
933
|
-
*[](SimpleMaxFlow& self, NodeIndex source, NodeIndex sink) {
|
934
|
-
auto status = self.Solve(source, sink);
|
935
|
-
|
936
|
-
if (status == SimpleMaxFlow::Status::OPTIMAL) {
|
937
|
-
return Symbol("optimal");
|
938
|
-
} else if (status == SimpleMaxFlow::Status::POSSIBLE_OVERFLOW) {
|
939
|
-
return Symbol("possible_overflow");
|
940
|
-
} else if (status == SimpleMaxFlow::Status::BAD_INPUT) {
|
941
|
-
return Symbol("bad_input");
|
942
|
-
} else if (status == SimpleMaxFlow::Status::BAD_RESULT) {
|
943
|
-
return Symbol("bad_result");
|
944
|
-
} else {
|
945
|
-
throw std::runtime_error("Unknown status");
|
946
|
-
}
|
947
|
-
})
|
948
|
-
.define_method(
|
949
|
-
"source_side_min_cut",
|
950
|
-
*[](SimpleMaxFlow& self) {
|
951
|
-
std::vector<NodeIndex> result;
|
952
|
-
self.GetSourceSideMinCut(&result);
|
953
|
-
|
954
|
-
Array ret;
|
955
|
-
for(auto const& it: result) {
|
956
|
-
ret.push(it);
|
957
|
-
}
|
958
|
-
return ret;
|
959
|
-
})
|
960
|
-
.define_method(
|
961
|
-
"sink_side_min_cut",
|
962
|
-
*[](SimpleMaxFlow& self) {
|
963
|
-
std::vector<NodeIndex> result;
|
964
|
-
self.GetSinkSideMinCut(&result);
|
965
|
-
|
966
|
-
Array ret;
|
967
|
-
for(auto const& it: result) {
|
968
|
-
ret.push(it);
|
969
|
-
}
|
970
|
-
return ret;
|
971
|
-
});
|
972
|
-
|
973
|
-
define_class_under<SimpleMinCostFlow>(rb_mORTools, "SimpleMinCostFlow")
|
974
|
-
.define_constructor(Constructor<SimpleMinCostFlow>())
|
975
|
-
.define_method("add_arc_with_capacity_and_unit_cost", &SimpleMinCostFlow::AddArcWithCapacityAndUnitCost)
|
976
|
-
.define_method("set_node_supply", &SimpleMinCostFlow::SetNodeSupply)
|
977
|
-
.define_method("optimal_cost", &SimpleMinCostFlow::OptimalCost)
|
978
|
-
.define_method("maximum_flow", &SimpleMinCostFlow::MaximumFlow)
|
979
|
-
.define_method("flow", &SimpleMinCostFlow::Flow)
|
980
|
-
.define_method("num_nodes", &SimpleMinCostFlow::NumNodes)
|
981
|
-
.define_method("num_arcs", &SimpleMinCostFlow::NumArcs)
|
982
|
-
.define_method("tail", &SimpleMinCostFlow::Tail)
|
983
|
-
.define_method("head", &SimpleMinCostFlow::Head)
|
984
|
-
.define_method("capacity", &SimpleMinCostFlow::Capacity)
|
985
|
-
.define_method("supply", &SimpleMinCostFlow::Supply)
|
986
|
-
.define_method("unit_cost", &SimpleMinCostFlow::UnitCost)
|
987
|
-
.define_method(
|
988
|
-
"solve",
|
989
|
-
*[](SimpleMinCostFlow& self) {
|
990
|
-
auto status = self.Solve();
|
991
|
-
|
992
|
-
if (status == SimpleMinCostFlow::Status::NOT_SOLVED) {
|
993
|
-
return Symbol("not_solved");
|
994
|
-
} else if (status == SimpleMinCostFlow::Status::OPTIMAL) {
|
995
|
-
return Symbol("optimal");
|
996
|
-
} else if (status == SimpleMinCostFlow::Status::FEASIBLE) {
|
997
|
-
return Symbol("feasible");
|
998
|
-
} else if (status == SimpleMinCostFlow::Status::INFEASIBLE) {
|
999
|
-
return Symbol("infeasible");
|
1000
|
-
} else if (status == SimpleMinCostFlow::Status::UNBALANCED) {
|
1001
|
-
return Symbol("unbalanced");
|
1002
|
-
} else if (status == SimpleMinCostFlow::Status::BAD_RESULT) {
|
1003
|
-
return Symbol("bad_result");
|
1004
|
-
} else if (status == SimpleMinCostFlow::Status::BAD_COST_RANGE) {
|
1005
|
-
return Symbol("bad_cost_range");
|
1006
|
-
} else {
|
1007
|
-
throw std::runtime_error("Unknown status");
|
1008
|
-
}
|
1009
|
-
});
|
1010
|
-
|
1011
|
-
define_class_under<SimpleLinearSumAssignment>(rb_mORTools, "LinearSumAssignment")
|
1012
|
-
.define_constructor(Constructor<SimpleLinearSumAssignment>())
|
1013
|
-
.define_method("add_arc_with_cost", &SimpleLinearSumAssignment::AddArcWithCost)
|
1014
|
-
.define_method("num_nodes", &SimpleLinearSumAssignment::NumNodes)
|
1015
|
-
.define_method("num_arcs", &SimpleLinearSumAssignment::NumArcs)
|
1016
|
-
.define_method("left_node", &SimpleLinearSumAssignment::LeftNode)
|
1017
|
-
.define_method("right_node", &SimpleLinearSumAssignment::RightNode)
|
1018
|
-
.define_method("cost", &SimpleLinearSumAssignment::Cost)
|
1019
|
-
.define_method("optimal_cost", &SimpleLinearSumAssignment::OptimalCost)
|
1020
|
-
.define_method("right_mate", &SimpleLinearSumAssignment::RightMate)
|
1021
|
-
.define_method("assignment_cost", &SimpleLinearSumAssignment::AssignmentCost)
|
1022
|
-
.define_method(
|
1023
|
-
"solve",
|
1024
|
-
*[](SimpleLinearSumAssignment& self) {
|
1025
|
-
auto status = self.Solve();
|
1026
|
-
|
1027
|
-
if (status == SimpleLinearSumAssignment::Status::OPTIMAL) {
|
1028
|
-
return Symbol("optimal");
|
1029
|
-
} else if (status == SimpleLinearSumAssignment::Status::INFEASIBLE) {
|
1030
|
-
return Symbol("infeasible");
|
1031
|
-
} else if (status == SimpleLinearSumAssignment::Status::POSSIBLE_OVERFLOW) {
|
1032
|
-
return Symbol("possible_overflow");
|
1033
|
-
} else {
|
1034
|
-
throw std::runtime_error("Unknown status");
|
1035
|
-
}
|
1036
|
-
});
|
24
|
+
init_assignment(m);
|
25
|
+
init_bin_packing(m);
|
26
|
+
init_constraint(m);
|
27
|
+
init_linear(m);
|
28
|
+
init_network_flows(m);
|
29
|
+
init_routing(m);
|
1037
30
|
}
|