or-tools 0.13.1 → 0.14.0
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 +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
|