or-tools 0.13.1 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +27 -0
- data/ext/or-tools/constraint.cpp +29 -50
- data/ext/or-tools/ext.cpp +2 -0
- data/ext/or-tools/extconf.rb +8 -2
- data/ext/or-tools/linear.cpp +10 -9
- data/ext/or-tools/math_opt.cpp +179 -0
- data/ext/or-tools/routing.cpp +13 -27
- data/lib/or-tools.rb +29 -18
- data/lib/or_tools/comparison.rb +7 -10
- data/lib/or_tools/constant.rb +16 -13
- data/lib/or_tools/cp_model.rb +8 -8
- data/lib/or_tools/cp_solver_solution_callback.rb +3 -3
- data/lib/or_tools/expression.rb +85 -0
- data/lib/or_tools/math_opt/model.rb +54 -0
- data/lib/or_tools/math_opt/variable.rb +15 -0
- data/lib/or_tools/product.rb +32 -0
- data/lib/or_tools/solver.rb +28 -15
- data/lib/or_tools/utils.rb +107 -0
- data/lib/or_tools/variable.rb +29 -0
- data/lib/or_tools/version.rb +1 -1
- metadata +11 -14
- data/lib/or_tools/bool_var.rb +0 -9
- data/lib/or_tools/comparison_operators.rb +0 -9
- data/lib/or_tools/int_var.rb +0 -5
- data/lib/or_tools/linear_constraint.rb +0 -50
- data/lib/or_tools/linear_expr.rb +0 -85
- data/lib/or_tools/mp_variable.rb +0 -11
- data/lib/or_tools/product_cst.rb +0 -35
- data/lib/or_tools/sat_int_var.rb +0 -29
- data/lib/or_tools/sat_linear_expr.rb +0 -59
- data/lib/or_tools/sum_array.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29ccd0801b240802b1a4c5b3344aeb33feff36381aa3bc714c369ae1ea4912ea
|
4
|
+
data.tar.gz: 3d64b0da4320c77545b75d4830ee23040c5bb3d4eab568db23ab425e9ec0a3dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 660915a87810919150acf5c5e5a67ae51c775a4df66a99293f3f58b6520615fd5519b7298a8d0f1d1127488faffaba8f326c7cd1740ff6d3ea2636a5e5e16062
|
7
|
+
data.tar.gz: 760fc1cf72fe774787b2ae0a28f6b1f3a7f8a954af855a86d7061945e112f88408cbf160117832568878f01bcbac86d8a6078b6c174778be8e51b025d04d6f8f
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -23,6 +23,10 @@ Higher Level Interfaces
|
|
23
23
|
- [Traveling Salesperson Problem (TSP)](#traveling-salesperson-problem-tsp)
|
24
24
|
- [Sudoku](#sudoku)
|
25
25
|
|
26
|
+
MathOpt
|
27
|
+
|
28
|
+
- [Basic example](#basic-example)
|
29
|
+
|
26
30
|
Linear Optimization
|
27
31
|
|
28
32
|
- [Solving an LP Problem](#solving-an-lp-problem)
|
@@ -311,6 +315,29 @@ sudoku = ORTools::Sudoku.new(grid, x: true, anti_knight: true, magic_square: tru
|
|
311
315
|
sudoku.solution
|
312
316
|
```
|
313
317
|
|
318
|
+
## MathOpt
|
319
|
+
|
320
|
+
### Basic Example
|
321
|
+
|
322
|
+
[Guide](https://developers.google.com/optimization/math_opt/basic_example)
|
323
|
+
|
324
|
+
```ruby
|
325
|
+
# build the model
|
326
|
+
model = ORTools::MathOpt::Model.new("getting_started_lp")
|
327
|
+
x = model.add_variable(-1.0, 1.5, "x")
|
328
|
+
y = model.add_variable(0.0, 1.0, "y")
|
329
|
+
model.add_linear_constraint(x + y <= 1.5)
|
330
|
+
model.maximize(x + 2 * y)
|
331
|
+
|
332
|
+
# solve
|
333
|
+
result = model.solve
|
334
|
+
|
335
|
+
# inspect the solution
|
336
|
+
puts "Objective value: #{result.objective_value}"
|
337
|
+
puts "x: #{result.variable_values[x]}"
|
338
|
+
puts "y: #{result.variable_values[y]}"
|
339
|
+
```
|
340
|
+
|
314
341
|
## Linear Optimization
|
315
342
|
|
316
343
|
### Solving an LP Problem
|
data/ext/or-tools/constraint.cpp
CHANGED
@@ -44,58 +44,27 @@ namespace Rice::detail
|
|
44
44
|
public:
|
45
45
|
LinearExpr convert(VALUE v)
|
46
46
|
{
|
47
|
-
Object x(v);
|
48
47
|
LinearExpr expr;
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
} else if (x.respond_to("vars")) {
|
53
|
-
Array vars = x.call("vars");
|
54
|
-
for (const auto& v : vars) {
|
55
|
-
// TODO clean up
|
56
|
-
auto cvar = (Array) v;
|
57
|
-
Object var = cvar[0];
|
58
|
-
auto coeff = From_Ruby<int64_t>().convert(cvar[1].value());
|
49
|
+
Rice::Object utils = Rice::define_module("ORTools").const_get("Utils");
|
50
|
+
Rice::Hash coeffs = utils.call("index_expression", Object(v));
|
59
51
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
} else {
|
69
|
-
if (x.is_a(rb_cBoolVar)) {
|
70
|
-
expr = From_Ruby<BoolVar>().convert(x.value());
|
52
|
+
for (const auto& entry : coeffs) {
|
53
|
+
Object var = entry.key;
|
54
|
+
auto coeff = From_Ruby<int64_t>().convert(entry.value.value());
|
55
|
+
|
56
|
+
if (var.is_nil()) {
|
57
|
+
expr += coeff;
|
58
|
+
} else if (var.is_a(rb_cBoolVar)) {
|
59
|
+
expr += From_Ruby<BoolVar>().convert(var.value()) * coeff;
|
71
60
|
} else {
|
72
|
-
expr
|
61
|
+
expr += From_Ruby<IntVar>().convert(var.value()) * coeff;
|
73
62
|
}
|
74
63
|
}
|
75
64
|
|
76
65
|
return expr;
|
77
66
|
}
|
78
67
|
};
|
79
|
-
|
80
|
-
template<>
|
81
|
-
class From_Ruby<std::vector<BoolVar>>
|
82
|
-
{
|
83
|
-
public:
|
84
|
-
std::vector<BoolVar> convert(VALUE v)
|
85
|
-
{
|
86
|
-
auto a = Array(v);
|
87
|
-
std::vector<BoolVar> vec;
|
88
|
-
vec.reserve(a.size());
|
89
|
-
for (const Object v : a) {
|
90
|
-
if (v.is_a(rb_cSatIntVar)) {
|
91
|
-
vec.push_back(From_Ruby<IntVar>().convert(v.value()).ToBoolVar());
|
92
|
-
} else {
|
93
|
-
vec.push_back(From_Ruby<BoolVar>().convert(v.value()));
|
94
|
-
}
|
95
|
-
}
|
96
|
-
return vec;
|
97
|
-
}
|
98
|
-
};
|
99
68
|
}
|
100
69
|
|
101
70
|
void init_constraint(Rice::Module& m) {
|
@@ -119,13 +88,23 @@ void init_constraint(Rice::Module& m) {
|
|
119
88
|
return self.OnlyEnforceIf(Rice::detail::From_Ruby<IntVar>().convert(literal).ToBoolVar());
|
120
89
|
} else if (literal.is_a(rb_cArray)) {
|
121
90
|
// TODO support IntVarSpan
|
122
|
-
|
91
|
+
auto a = Array(literal);
|
92
|
+
std::vector<BoolVar> vec;
|
93
|
+
vec.reserve(a.size());
|
94
|
+
for (const Object v : a) {
|
95
|
+
if (v.is_a(rb_cSatIntVar)) {
|
96
|
+
vec.push_back(Rice::detail::From_Ruby<IntVar>().convert(v.value()).ToBoolVar());
|
97
|
+
} else {
|
98
|
+
vec.push_back(Rice::detail::From_Ruby<BoolVar>().convert(v.value()));
|
99
|
+
}
|
100
|
+
}
|
101
|
+
return self.OnlyEnforceIf(vec);
|
123
102
|
} else {
|
124
103
|
return self.OnlyEnforceIf(Rice::detail::From_Ruby<BoolVar>().convert(literal));
|
125
104
|
}
|
126
105
|
});
|
127
106
|
|
128
|
-
rb_cBoolVar = Rice::define_class_under<BoolVar>(m, "
|
107
|
+
rb_cBoolVar = Rice::define_class_under<BoolVar>(m, "SatBoolVar")
|
129
108
|
.define_method("name", &BoolVar::Name)
|
130
109
|
.define_method("index", &BoolVar::index)
|
131
110
|
.define_method("not", &BoolVar::Not)
|
@@ -425,17 +404,17 @@ void init_constraint(Rice::Module& m) {
|
|
425
404
|
Model m;
|
426
405
|
|
427
406
|
if (!callback.is_nil()) {
|
428
|
-
//
|
407
|
+
// use a single worker since Ruby code cannot be run in a non-Ruby thread
|
429
408
|
parameters.set_num_search_workers(1);
|
430
409
|
|
431
410
|
m.Add(NewFeasibleSolutionObserver(
|
432
411
|
[&callback](const CpSolverResponse& r) {
|
433
|
-
|
434
|
-
|
435
|
-
// TODO find a better way to do this
|
436
|
-
callback.call("response=", r);
|
437
|
-
callback.call("on_solution_callback");
|
412
|
+
if (!ruby_native_thread_p()) {
|
413
|
+
throw std::runtime_error("Non-Ruby thread");
|
438
414
|
}
|
415
|
+
|
416
|
+
callback.call("response=", r);
|
417
|
+
callback.call("on_solution_callback");
|
439
418
|
})
|
440
419
|
);
|
441
420
|
}
|
data/ext/or-tools/ext.cpp
CHANGED
@@ -10,6 +10,7 @@ void init_assignment(Rice::Module& m);
|
|
10
10
|
void init_bin_packing(Rice::Module& m);
|
11
11
|
void init_constraint(Rice::Module& m);
|
12
12
|
void init_linear(Rice::Module& m);
|
13
|
+
void init_math_opt(Rice::Module& m);
|
13
14
|
void init_network_flows(Rice::Module& m);
|
14
15
|
void init_routing(Rice::Module& m);
|
15
16
|
|
@@ -24,6 +25,7 @@ void Init_ext()
|
|
24
25
|
init_bin_packing(m);
|
25
26
|
init_constraint(m);
|
26
27
|
init_linear(m);
|
28
|
+
init_math_opt(m);
|
27
29
|
init_network_flows(m);
|
28
30
|
init_routing(m);
|
29
31
|
|
data/ext/or-tools/extconf.rb
CHANGED
@@ -2,8 +2,14 @@ require "mkmf-rice"
|
|
2
2
|
|
3
3
|
$CXXFLAGS << " -std=c++17 $(optflags) -DUSE_CBC"
|
4
4
|
|
5
|
-
#
|
6
|
-
$CXXFLAGS << " -
|
5
|
+
# show warnings
|
6
|
+
$CXXFLAGS << " -Wall -Wextra"
|
7
|
+
|
8
|
+
# hide or-tools warnings
|
9
|
+
$CXXFLAGS << " -Wno-sign-compare -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-missing-field-initializers"
|
10
|
+
|
11
|
+
# hide Rice warnings
|
12
|
+
$CXXFLAGS << " -Wno-implicit-fallthrough"
|
7
13
|
|
8
14
|
inc, lib = dir_config("or-tools")
|
9
15
|
if inc || lib
|
data/ext/or-tools/linear.cpp
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
#include "ext.h"
|
4
4
|
|
5
|
-
using operations_research::LinearExpr;
|
6
|
-
using operations_research::LinearRange;
|
7
5
|
using operations_research::MPConstraint;
|
8
6
|
using operations_research::MPObjective;
|
9
7
|
using operations_research::MPSolver;
|
@@ -45,12 +43,7 @@ namespace Rice::detail
|
|
45
43
|
}
|
46
44
|
|
47
45
|
void init_linear(Rice::Module& m) {
|
48
|
-
Rice::define_class_under<
|
49
|
-
|
50
|
-
auto rb_cLinearExpr = Rice::define_class_under<LinearExpr>(m, "LinearExpr");
|
51
|
-
rb_cLinearExpr.define_constructor(Rice::Constructor<LinearExpr>());
|
52
|
-
|
53
|
-
Rice::define_class_under<MPVariable, LinearExpr>(m, "MPVariable")
|
46
|
+
Rice::define_class_under<MPVariable>(m, "MPVariable")
|
54
47
|
.define_method("name", &MPVariable::name)
|
55
48
|
.define_method("solution_value", &MPVariable::solution_value);
|
56
49
|
|
@@ -66,7 +59,15 @@ void init_linear(Rice::Module& m) {
|
|
66
59
|
.define_method("set_minimization", &MPObjective::SetMinimization);
|
67
60
|
|
68
61
|
Rice::define_class_under<MPSolver>(m, "Solver")
|
69
|
-
.
|
62
|
+
.define_singleton_function(
|
63
|
+
"_new",
|
64
|
+
[](const std::string& name, MPSolver::OptimizationProblemType problem_type) {
|
65
|
+
std::unique_ptr<MPSolver> solver(new MPSolver(name, problem_type));
|
66
|
+
if (!solver) {
|
67
|
+
throw std::runtime_error("Unrecognized solver type");
|
68
|
+
}
|
69
|
+
return solver;
|
70
|
+
})
|
70
71
|
.define_singleton_function(
|
71
72
|
"_create",
|
72
73
|
[](const std::string& solver_id) {
|
@@ -0,0 +1,179 @@
|
|
1
|
+
#include "absl/log/check.h"
|
2
|
+
#include "absl/status/statusor.h"
|
3
|
+
#include "ortools/base/init_google.h"
|
4
|
+
#include "ortools/math_opt/cpp/math_opt.h"
|
5
|
+
|
6
|
+
#include "ext.h"
|
7
|
+
|
8
|
+
using operations_research::math_opt::LinearConstraint;
|
9
|
+
using operations_research::math_opt::Model;
|
10
|
+
using operations_research::math_opt::Solve;
|
11
|
+
using operations_research::math_opt::SolveArguments;
|
12
|
+
using operations_research::math_opt::SolveResult;
|
13
|
+
using operations_research::math_opt::SolverType;
|
14
|
+
using operations_research::math_opt::Termination;
|
15
|
+
using operations_research::math_opt::TerminationReason;
|
16
|
+
using operations_research::math_opt::Variable;
|
17
|
+
|
18
|
+
namespace Rice::detail
|
19
|
+
{
|
20
|
+
template<>
|
21
|
+
struct Type<SolverType>
|
22
|
+
{
|
23
|
+
static bool verify()
|
24
|
+
{
|
25
|
+
return true;
|
26
|
+
}
|
27
|
+
};
|
28
|
+
|
29
|
+
template<>
|
30
|
+
struct From_Ruby<SolverType>
|
31
|
+
{
|
32
|
+
static SolverType convert(VALUE x)
|
33
|
+
{
|
34
|
+
auto s = Symbol(x).str();
|
35
|
+
if (s == "gscip") {
|
36
|
+
return SolverType::kGscip;
|
37
|
+
} else if (s == "gurobi") {
|
38
|
+
return SolverType::kGurobi;
|
39
|
+
} else if (s == "glop") {
|
40
|
+
return SolverType::kGlop;
|
41
|
+
} else if (s == "cpsat") {
|
42
|
+
return SolverType::kCpSat;
|
43
|
+
} else if (s == "pdlp") {
|
44
|
+
return SolverType::kPdlp;
|
45
|
+
} else if (s == "glpk") {
|
46
|
+
return SolverType::kGlpk;
|
47
|
+
} else if (s == "ecos") {
|
48
|
+
return SolverType::kEcos;
|
49
|
+
} else if (s == "scs") {
|
50
|
+
return SolverType::kScs;
|
51
|
+
} else if (s == "highs") {
|
52
|
+
return SolverType::kHighs;
|
53
|
+
} else if (s == "santorini") {
|
54
|
+
return SolverType::kSantorini;
|
55
|
+
} else {
|
56
|
+
throw std::runtime_error("Unknown solver type: " + s);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
};
|
60
|
+
}
|
61
|
+
|
62
|
+
void init_math_opt(Rice::Module& m) {
|
63
|
+
auto mathopt = Rice::define_module_under(m, "MathOpt");
|
64
|
+
|
65
|
+
Rice::define_class_under<Variable>(mathopt, "Variable")
|
66
|
+
.define_method("id", &Variable::id)
|
67
|
+
.define_method(
|
68
|
+
"_eql?",
|
69
|
+
[](Variable& self, Variable &other) {
|
70
|
+
return (bool) (self == other);
|
71
|
+
});
|
72
|
+
|
73
|
+
Rice::define_class_under<LinearConstraint>(mathopt, "LinearConstraint");
|
74
|
+
|
75
|
+
Rice::define_class_under<Termination>(mathopt, "Termination")
|
76
|
+
.define_method(
|
77
|
+
"reason",
|
78
|
+
[](Termination& self) {
|
79
|
+
auto reason = self.reason;
|
80
|
+
|
81
|
+
if (reason == TerminationReason::kOptimal) {
|
82
|
+
return Rice::Symbol("optimal");
|
83
|
+
} else if (reason == TerminationReason::kInfeasible) {
|
84
|
+
return Rice::Symbol("infeasible");
|
85
|
+
} else if (reason == TerminationReason::kUnbounded) {
|
86
|
+
return Rice::Symbol("unbounded");
|
87
|
+
} else if (reason == TerminationReason::kInfeasibleOrUnbounded) {
|
88
|
+
return Rice::Symbol("infeasible_or_unbounded");
|
89
|
+
} else if (reason == TerminationReason::kImprecise) {
|
90
|
+
return Rice::Symbol("imprecise");
|
91
|
+
} else if (reason == TerminationReason::kFeasible) {
|
92
|
+
return Rice::Symbol("feasible");
|
93
|
+
} else if (reason == TerminationReason::kNoSolutionFound) {
|
94
|
+
return Rice::Symbol("no_solution_found");
|
95
|
+
} else if (reason == TerminationReason::kNumericalError) {
|
96
|
+
return Rice::Symbol("numerical_error");
|
97
|
+
} else if (reason == TerminationReason::kOtherError) {
|
98
|
+
return Rice::Symbol("other");
|
99
|
+
} else {
|
100
|
+
throw std::runtime_error("Unknown termination reason");
|
101
|
+
}
|
102
|
+
});
|
103
|
+
|
104
|
+
Rice::define_class_under<SolveResult>(mathopt, "SolveResult")
|
105
|
+
.define_method(
|
106
|
+
"termination",
|
107
|
+
[](SolveResult& self) {
|
108
|
+
return self.termination;
|
109
|
+
})
|
110
|
+
.define_method(
|
111
|
+
"objective_value",
|
112
|
+
[](SolveResult& self) {
|
113
|
+
return self.objective_value();
|
114
|
+
})
|
115
|
+
.define_method(
|
116
|
+
"variable_values",
|
117
|
+
[](SolveResult& self) {
|
118
|
+
Rice::Hash map;
|
119
|
+
for (auto& [k, v] : self.variable_values()) {
|
120
|
+
map[k] = v;
|
121
|
+
}
|
122
|
+
return map;
|
123
|
+
});
|
124
|
+
|
125
|
+
Rice::define_class_under<Model>(mathopt, "Model")
|
126
|
+
.define_constructor(Rice::Constructor<Model, std::string>())
|
127
|
+
.define_method("add_variable", &Model::AddContinuousVariable)
|
128
|
+
.define_method("add_integer_variable", &Model::AddIntegerVariable)
|
129
|
+
.define_method("add_binary_variable", &Model::AddBinaryVariable)
|
130
|
+
.define_method(
|
131
|
+
"_add_linear_constraint",
|
132
|
+
[](Model& self) {
|
133
|
+
return self.AddLinearConstraint();
|
134
|
+
})
|
135
|
+
.define_method(
|
136
|
+
"_set_upper_bound",
|
137
|
+
[](Model& self, LinearConstraint constraint, double upper_bound) {
|
138
|
+
self.set_upper_bound(constraint, upper_bound);
|
139
|
+
})
|
140
|
+
.define_method(
|
141
|
+
"_set_lower_bound",
|
142
|
+
[](Model& self, LinearConstraint constraint, double upper_bound) {
|
143
|
+
self.set_lower_bound(constraint, upper_bound);
|
144
|
+
})
|
145
|
+
.define_method("_set_coefficient", &Model::set_coefficient)
|
146
|
+
.define_method(
|
147
|
+
"_set_objective_coefficient",
|
148
|
+
[](Model& self, Variable variable, double value) {
|
149
|
+
self.set_objective_coefficient(variable, value);
|
150
|
+
})
|
151
|
+
.define_method("_clear_objective", &Model::clear_objective)
|
152
|
+
.define_method(
|
153
|
+
"_set_objective_offset",
|
154
|
+
[](Model& self, double value) {
|
155
|
+
self.set_objective_offset(value);
|
156
|
+
})
|
157
|
+
.define_method(
|
158
|
+
"_set_maximize",
|
159
|
+
[](Model& self) {
|
160
|
+
self.set_maximize();
|
161
|
+
})
|
162
|
+
.define_method(
|
163
|
+
"_set_minimize",
|
164
|
+
[](Model& self) {
|
165
|
+
self.set_minimize();
|
166
|
+
})
|
167
|
+
.define_method(
|
168
|
+
"_solve",
|
169
|
+
[](Model& self, SolverType solver_type) {
|
170
|
+
SolveArguments args;
|
171
|
+
auto result = Solve(self, solver_type, args);
|
172
|
+
|
173
|
+
if (!result.ok()) {
|
174
|
+
throw std::invalid_argument(std::string{result.status().message()});
|
175
|
+
}
|
176
|
+
|
177
|
+
return *result;
|
178
|
+
});
|
179
|
+
}
|
data/ext/or-tools/routing.cpp
CHANGED
@@ -56,22 +56,9 @@ namespace Rice::detail
|
|
56
56
|
};
|
57
57
|
}
|
58
58
|
|
59
|
-
namespace Rice::detail
|
60
|
-
{
|
61
|
-
template<class T, class U>
|
62
|
-
class To_Ruby<std::pair<T, U>>
|
63
|
-
{
|
64
|
-
public:
|
65
|
-
VALUE convert(std::pair<T, U> const & x)
|
66
|
-
{
|
67
|
-
return rb_ary_new3(2, To_Ruby<T>().convert(x.first), To_Ruby<U>().convert(x.second));
|
68
|
-
}
|
69
|
-
};
|
70
|
-
}
|
71
|
-
|
72
59
|
void init_routing(Rice::Module& m) {
|
73
60
|
auto rb_cRoutingSearchParameters = Rice::define_class_under<RoutingSearchParameters>(m, "RoutingSearchParameters");
|
74
|
-
auto rb_cIntVar = Rice::define_class_under<operations_research::IntVar>(m, "
|
61
|
+
auto rb_cIntVar = Rice::define_class_under<operations_research::IntVar>(m, "RoutingIntVar");
|
75
62
|
|
76
63
|
m.define_singleton_function("default_routing_search_parameters", &DefaultRoutingSearchParameters);
|
77
64
|
|
@@ -213,7 +200,6 @@ void init_routing(Rice::Module& m) {
|
|
213
200
|
|
214
201
|
Rice::define_class_under<RoutingDimension>(m, "RoutingDimension")
|
215
202
|
.define_method("transit_value", &RoutingDimension::GetTransitValue)
|
216
|
-
// TODO GetTransitValueFromClass
|
217
203
|
.define_method("cumul_var", &RoutingDimension::CumulVar)
|
218
204
|
.define_method("transit_var", &RoutingDimension::TransitVar)
|
219
205
|
.define_method("fixed_transit_var", &RoutingDimension::FixedTransitVar)
|
@@ -239,7 +225,7 @@ void init_routing(Rice::Module& m) {
|
|
239
225
|
.define_method("post", &operations_research::Constraint::Post)
|
240
226
|
.define_method("debug_string", &operations_research::Constraint::DebugString);
|
241
227
|
|
242
|
-
Rice::define_class_under<operations_research::Solver>(m, "
|
228
|
+
Rice::define_class_under<operations_research::Solver>(m, "RoutingSolver")
|
243
229
|
.define_method(
|
244
230
|
"add",
|
245
231
|
[](operations_research::Solver& self, Object o) {
|
@@ -247,7 +233,7 @@ void init_routing(Rice::Module& m) {
|
|
247
233
|
if (o.respond_to("left")) {
|
248
234
|
operations_research::IntExpr* left(Rice::detail::From_Ruby<operations_research::IntVar*>().convert(o.call("left")));
|
249
235
|
operations_research::IntExpr* right(Rice::detail::From_Ruby<operations_research::IntVar*>().convert(o.call("right")));
|
250
|
-
auto op = o.call("
|
236
|
+
auto op = o.call("op").to_s().str();
|
251
237
|
if (op == "==") {
|
252
238
|
constraint = self.MakeEquality(left, right);
|
253
239
|
} else if (op == "<=") {
|
@@ -304,8 +290,13 @@ void init_routing(Rice::Module& m) {
|
|
304
290
|
.define_method(
|
305
291
|
"register_unary_transit_callback",
|
306
292
|
[](RoutingModel& self, Object callback) {
|
293
|
+
// TODO guard callback?
|
307
294
|
return self.RegisterUnaryTransitCallback(
|
308
295
|
[callback](int64_t from_index) -> int64_t {
|
296
|
+
if (!ruby_native_thread_p()) {
|
297
|
+
throw std::runtime_error("Non-Ruby thread");
|
298
|
+
}
|
299
|
+
|
309
300
|
return Rice::detail::From_Ruby<int64_t>().convert(callback.call("call", from_index));
|
310
301
|
}
|
311
302
|
);
|
@@ -314,8 +305,13 @@ void init_routing(Rice::Module& m) {
|
|
314
305
|
.define_method(
|
315
306
|
"register_transit_callback",
|
316
307
|
[](RoutingModel& self, Object callback) {
|
308
|
+
// TODO guard callback?
|
317
309
|
return self.RegisterTransitCallback(
|
318
310
|
[callback](int64_t from_index, int64_t to_index) -> int64_t {
|
311
|
+
if (!ruby_native_thread_p()) {
|
312
|
+
throw std::runtime_error("Non-Ruby thread");
|
313
|
+
}
|
314
|
+
|
319
315
|
return Rice::detail::From_Ruby<int64_t>().convert(callback.call("call", from_index, to_index));
|
320
316
|
}
|
321
317
|
);
|
@@ -328,13 +324,8 @@ void init_routing(Rice::Module& m) {
|
|
328
324
|
.define_method("add_constant_dimension", &RoutingModel::AddConstantDimension)
|
329
325
|
.define_method("add_vector_dimension", &RoutingModel::AddVectorDimension)
|
330
326
|
.define_method("add_matrix_dimension", &RoutingModel::AddMatrixDimension)
|
331
|
-
// TODO AddDimensionDependentDimensionWithVehicleCapacity
|
332
|
-
// .define_method("make_path_spans_and_total_slacks", &RoutingModel::MakePathSpansAndTotalSlacks)
|
333
327
|
.define_method("all_dimension_names", &RoutingModel::GetAllDimensionNames)
|
334
|
-
// .define_method("dimensions", &RoutingModel::GetDimensions)
|
335
|
-
// .define_method("dimensions_with_soft_or_span_costs", &RoutingModel::GetDimensionsWithSoftOrSpanCosts)
|
336
328
|
.define_method("dimension?", &RoutingModel::HasDimension)
|
337
|
-
// .define_method("dimension_or_die", &RoutingModel::GetDimensionOrDie)
|
338
329
|
.define_method("mutable_dimension", &RoutingModel::GetMutableDimension)
|
339
330
|
.define_method("set_primary_constrained_dimension", &RoutingModel::SetPrimaryConstrainedDimension)
|
340
331
|
.define_method("primary_constrained_dimension", &RoutingModel::GetPrimaryConstrainedDimension)
|
@@ -373,9 +364,6 @@ void init_routing(Rice::Module& m) {
|
|
373
364
|
}
|
374
365
|
return positions;
|
375
366
|
})
|
376
|
-
// TODO SetPickupAndDeliveryPolicyOfAllVehicles
|
377
|
-
// TODO SetPickupAndDeliveryPolicyOfVehicle
|
378
|
-
// TODO GetPickupAndDeliveryPolicyOfVehicle
|
379
367
|
.define_method("num_of_singleton_nodes", &RoutingModel::GetNumOfSingletonNodes)
|
380
368
|
.define_method("unperformed_penalty", &RoutingModel::UnperformedPenalty)
|
381
369
|
.define_method("unperformed_penalty_or_value", &RoutingModel::UnperformedPenaltyOrValue)
|
@@ -444,8 +432,6 @@ void init_routing(Rice::Module& m) {
|
|
444
432
|
.define_method("compact_and_check_assignment", &RoutingModel::CompactAndCheckAssignment)
|
445
433
|
.define_method("add_to_assignment", &RoutingModel::AddToAssignment)
|
446
434
|
.define_method("add_interval_to_assignment", &RoutingModel::AddIntervalToAssignment)
|
447
|
-
// TODO PackCumulsOfOptimizerDimensionsFromAssignment
|
448
|
-
// TODO AddLocalSearchFilter
|
449
435
|
.define_method("start", &RoutingModel::Start)
|
450
436
|
.define_method("end", &RoutingModel::End)
|
451
437
|
.define_method("start?", &RoutingModel::IsStart)
|
data/lib/or-tools.rb
CHANGED
@@ -1,39 +1,50 @@
|
|
1
1
|
# ext
|
2
2
|
require "or_tools/ext"
|
3
3
|
|
4
|
-
#
|
4
|
+
# expressions
|
5
|
+
require_relative "or_tools/expression"
|
5
6
|
require_relative "or_tools/comparison"
|
6
|
-
require_relative "or_tools/comparison_operators"
|
7
|
-
require_relative "or_tools/bool_var"
|
8
7
|
require_relative "or_tools/constant"
|
8
|
+
require_relative "or_tools/product"
|
9
|
+
require_relative "or_tools/variable"
|
10
|
+
|
11
|
+
# bin packing
|
12
|
+
require_relative "or_tools/knapsack_solver"
|
13
|
+
|
14
|
+
# constraint
|
9
15
|
require_relative "or_tools/cp_model"
|
10
16
|
require_relative "or_tools/cp_solver"
|
11
17
|
require_relative "or_tools/cp_solver_solution_callback"
|
12
|
-
require_relative "or_tools/int_var"
|
13
|
-
require_relative "or_tools/knapsack_solver"
|
14
|
-
require_relative "or_tools/linear_constraint"
|
15
|
-
require_relative "or_tools/linear_expr"
|
16
|
-
require_relative "or_tools/mp_variable"
|
17
|
-
require_relative "or_tools/product_cst"
|
18
|
-
require_relative "or_tools/routing_index_manager"
|
19
|
-
require_relative "or_tools/routing_model"
|
20
|
-
require_relative "or_tools/sat_linear_expr"
|
21
|
-
require_relative "or_tools/sat_int_var"
|
22
|
-
require_relative "or_tools/solver"
|
23
|
-
require_relative "or_tools/sum_array"
|
24
|
-
require_relative "or_tools/version"
|
25
|
-
|
26
|
-
# solution printers
|
27
18
|
require_relative "or_tools/objective_solution_printer"
|
28
19
|
require_relative "or_tools/var_array_solution_printer"
|
29
20
|
require_relative "or_tools/var_array_and_objective_solution_printer"
|
30
21
|
|
22
|
+
# linear
|
23
|
+
require_relative "or_tools/solver"
|
24
|
+
|
25
|
+
# math opt
|
26
|
+
require_relative "or_tools/math_opt/model"
|
27
|
+
require_relative "or_tools/math_opt/variable"
|
28
|
+
|
29
|
+
# routing
|
30
|
+
require_relative "or_tools/routing_index_manager"
|
31
|
+
require_relative "or_tools/routing_model"
|
32
|
+
|
31
33
|
# higher level interfaces
|
32
34
|
require_relative "or_tools/basic_scheduler"
|
33
35
|
require_relative "or_tools/seating"
|
34
36
|
require_relative "or_tools/sudoku"
|
35
37
|
require_relative "or_tools/tsp"
|
36
38
|
|
39
|
+
# modules
|
40
|
+
require_relative "or_tools/utils"
|
41
|
+
require_relative "or_tools/version"
|
42
|
+
|
37
43
|
module ORTools
|
38
44
|
class Error < StandardError; end
|
45
|
+
|
46
|
+
# previous names
|
47
|
+
Solver2 = RoutingSolver
|
48
|
+
IntVar = RoutingIntVar
|
49
|
+
BoolVar = SatBoolVar
|
39
50
|
end
|
data/lib/or_tools/comparison.rb
CHANGED
@@ -1,19 +1,16 @@
|
|
1
1
|
module ORTools
|
2
2
|
class Comparison
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :left, :op, :right
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@right = right
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_s
|
12
|
-
"#{left} #{operator} #{right}"
|
5
|
+
def initialize(left, op, right)
|
6
|
+
@left = Expression.to_expression(left)
|
7
|
+
@op = op
|
8
|
+
@right = Expression.to_expression(right)
|
13
9
|
end
|
14
10
|
|
15
11
|
def inspect
|
16
|
-
"
|
12
|
+
"#{@left.inspect} #{@op} #{@right.inspect}"
|
17
13
|
end
|
14
|
+
alias_method :to_s, :inspect
|
18
15
|
end
|
19
16
|
end
|
data/lib/or_tools/constant.rb
CHANGED
@@ -1,23 +1,26 @@
|
|
1
1
|
module ORTools
|
2
|
-
class Constant <
|
3
|
-
|
4
|
-
|
2
|
+
class Constant < Expression
|
3
|
+
attr_reader :value
|
4
|
+
|
5
|
+
def initialize(value)
|
6
|
+
@value = value
|
5
7
|
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
# simplify Ruby sum
|
10
|
+
def +(other)
|
11
|
+
@value == 0 ? other : super
|
9
12
|
end
|
10
13
|
|
11
|
-
def
|
12
|
-
|
14
|
+
def inspect
|
15
|
+
@value.to_s
|
13
16
|
end
|
14
|
-
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
1
|
18
|
+
def -@
|
19
|
+
Constant.new(-value)
|
19
20
|
end
|
20
|
-
end
|
21
21
|
|
22
|
-
|
22
|
+
def vars
|
23
|
+
@vars ||= []
|
24
|
+
end
|
25
|
+
end
|
23
26
|
end
|