or-tools 0.5.3 → 0.6.2
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 +21 -0
- data/NOTICE.txt +2 -2
- data/README.md +21 -10
- data/ext/or-tools/constraint.cpp +30 -30
- data/ext/or-tools/linear.cpp +7 -93
- data/ext/or-tools/vendor.rb +43 -20
- data/lib/or-tools.rb +5 -0
- data/lib/or_tools/comparison.rb +6 -1
- data/lib/or_tools/constant.rb +23 -0
- data/lib/or_tools/cp_solver.rb +12 -6
- data/lib/or_tools/linear_constraint.rb +50 -0
- data/lib/or_tools/linear_expr.rb +58 -12
- data/lib/or_tools/mp_variable.rb +12 -0
- data/lib/or_tools/product_cst.rb +31 -0
- data/lib/or_tools/sat_int_var.rb +6 -2
- data/lib/or_tools/sat_linear_expr.rb +6 -1
- data/lib/or_tools/solver.rb +19 -1
- data/lib/or_tools/sum_array.rb +23 -0
- data/lib/or_tools/version.rb +1 -1
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0e0f455741da72e3a215287df4ef1858893fb31d0b4be40db6ef9ab025e339c
|
4
|
+
data.tar.gz: 9291933eee08f800f48f3d83ca4f2d0fc71efb0a328134ba9667ca2ac8efb185
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61ccc7c5f3a6c3cdf1e3dffb1ee6572d0b8cde09d4684d50353efd6f2efcb93ca4ba940343f994a3bf65992e518331bd62a02ef74ecc52f2427e12350ea7a430
|
7
|
+
data.tar.gz: 589423f5b52c872b453569400ff1fd60bb1fcd3b0035e70aadbb47eedefec9b7f4187a5442893e50608529f836d2009bd77333aae3f64ce1b9d700df6fe020e7
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
## 0.6.2 (2022-02-09)
|
2
|
+
|
3
|
+
- Fixed segfaults with `Solver`
|
4
|
+
|
5
|
+
## 0.6.1 (2022-01-22)
|
6
|
+
|
7
|
+
- Added installation instructions for Mac ARM
|
8
|
+
- Removed dependency on `lsb_release` for binary installation on Linux
|
9
|
+
|
10
|
+
## 0.6.0 (2021-12-16)
|
11
|
+
|
12
|
+
- Updated OR-Tools to 9.2
|
13
|
+
- Renamed `add_product_equality` to `add_multiplication_equality`
|
14
|
+
- Removed `scale_objective_by`
|
15
|
+
|
16
|
+
## 0.5.4 (2021-10-01)
|
17
|
+
|
18
|
+
- Updated OR-Tools to 9.1
|
19
|
+
- Added binary installation for Debian 11
|
20
|
+
- Deprecated `solve_with_solution_callback` and `search_for_all_solutions`
|
21
|
+
|
1
22
|
## 0.5.3 (2021-08-02)
|
2
23
|
|
3
24
|
- Added more methods to `IntVar`, `IntervalVar`, and `Constraint`
|
data/NOTICE.txt
CHANGED
data/README.md
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
# OR-Tools
|
1
|
+
# OR-Tools Ruby
|
2
2
|
|
3
3
|
[OR-Tools](https://github.com/google/or-tools) - operations research tools - for Ruby
|
4
4
|
|
5
|
-
[](https://github.com/ankane/or-tools/actions)
|
5
|
+
[](https://github.com/ankane/or-tools-ruby/actions)
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
9
|
Add this line to your application’s Gemfile:
|
10
10
|
|
11
11
|
```ruby
|
12
|
-
gem
|
12
|
+
gem "or-tools"
|
13
13
|
```
|
14
14
|
|
15
|
-
Installation can take a few minutes as OR-Tools downloads and builds.
|
15
|
+
Installation can take a few minutes as OR-Tools downloads and builds. For Mac ARM, also follow [these instructions](#additional-instructions).
|
16
16
|
|
17
17
|
## Higher Level Interfaces
|
18
18
|
|
@@ -2139,7 +2139,7 @@ model.add(seats[[0, 0]] == 1)
|
|
2139
2139
|
# Solve model
|
2140
2140
|
solver = ORTools::CpSolver.new
|
2141
2141
|
solution_printer = WeddingChartPrinter.new(seats, names, num_tables, num_guests)
|
2142
|
-
solver.
|
2142
|
+
solver.solve(model, solution_printer)
|
2143
2143
|
|
2144
2144
|
puts "Statistics"
|
2145
2145
|
puts " - conflicts : %i" % solver.num_conflicts
|
@@ -2201,24 +2201,35 @@ possible_tables.each do |table|
|
|
2201
2201
|
end
|
2202
2202
|
```
|
2203
2203
|
|
2204
|
+
## Additional Instructions
|
2205
|
+
|
2206
|
+
### Mac ARM
|
2207
|
+
|
2208
|
+
ARM binaries are not available for Mac yet, so use Homebrew to install OR-Tools before installing the gem.
|
2209
|
+
|
2210
|
+
```sh
|
2211
|
+
brew install or-tools
|
2212
|
+
bundle config build.or-tools --with-or-tools-dir=/opt/homebrew
|
2213
|
+
```
|
2214
|
+
|
2204
2215
|
## History
|
2205
2216
|
|
2206
|
-
View the [changelog](https://github.com/ankane/or-tools/blob/master/CHANGELOG.md)
|
2217
|
+
View the [changelog](https://github.com/ankane/or-tools-ruby/blob/master/CHANGELOG.md)
|
2207
2218
|
|
2208
2219
|
## Contributing
|
2209
2220
|
|
2210
2221
|
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
2211
2222
|
|
2212
|
-
- [Report bugs](https://github.com/ankane/or-tools/issues)
|
2213
|
-
- Fix bugs and [submit pull requests](https://github.com/ankane/or-tools/pulls)
|
2223
|
+
- [Report bugs](https://github.com/ankane/or-tools-ruby/issues)
|
2224
|
+
- Fix bugs and [submit pull requests](https://github.com/ankane/or-tools-ruby/pulls)
|
2214
2225
|
- Write, clarify, or fix documentation
|
2215
2226
|
- Suggest or add new features
|
2216
2227
|
|
2217
2228
|
To get started with development:
|
2218
2229
|
|
2219
2230
|
```sh
|
2220
|
-
git clone https://github.com/ankane/or-tools.git
|
2221
|
-
cd or-tools
|
2231
|
+
git clone https://github.com/ankane/or-tools-ruby.git
|
2232
|
+
cd or-tools-ruby
|
2222
2233
|
bundle install
|
2223
2234
|
bundle exec rake compile
|
2224
2235
|
bundle exec rake test
|
data/ext/or-tools/constraint.cpp
CHANGED
@@ -131,10 +131,21 @@ void init_constraint(Rice::Module& m) {
|
|
131
131
|
|
132
132
|
Rice::define_class_under<SatParameters>(m, "SatParameters")
|
133
133
|
.define_constructor(Rice::Constructor<SatParameters>())
|
134
|
-
.define_method(
|
135
|
-
|
136
|
-
self
|
137
|
-
|
134
|
+
.define_method(
|
135
|
+
"max_time_in_seconds=",
|
136
|
+
[](SatParameters& self, double value) {
|
137
|
+
self.set_max_time_in_seconds(value);
|
138
|
+
})
|
139
|
+
.define_method(
|
140
|
+
"enumerate_all_solutions=",
|
141
|
+
[](SatParameters& self, bool value) {
|
142
|
+
self.set_enumerate_all_solutions(value);
|
143
|
+
})
|
144
|
+
.define_method(
|
145
|
+
"enumerate_all_solutions",
|
146
|
+
[](SatParameters& self) {
|
147
|
+
return self.enumerate_all_solutions();
|
148
|
+
});
|
138
149
|
|
139
150
|
Rice::define_class_under<CpModelBuilder>(m, "CpModel")
|
140
151
|
.define_constructor(Rice::Constructor<CpModelBuilder>())
|
@@ -276,9 +287,9 @@ void init_constraint(Rice::Module& m) {
|
|
276
287
|
return self.AddModuloEquality(target, var, mod);
|
277
288
|
})
|
278
289
|
.define_method(
|
279
|
-
"
|
290
|
+
"add_multiplication_equality",
|
280
291
|
[](CpModelBuilder& self, IntVar target, std::vector<IntVar> vars) {
|
281
|
-
return self.
|
292
|
+
return self.AddMultiplicationEquality(target, vars);
|
282
293
|
})
|
283
294
|
.define_method(
|
284
295
|
"add_no_overlap",
|
@@ -295,11 +306,6 @@ void init_constraint(Rice::Module& m) {
|
|
295
306
|
[](CpModelBuilder& self, LinearExpr expr) {
|
296
307
|
self.Minimize(expr);
|
297
308
|
})
|
298
|
-
.define_method(
|
299
|
-
"scale_objective_by",
|
300
|
-
[](CpModelBuilder& self, double scaling) {
|
301
|
-
self.ScaleObjectiveBy(scaling);
|
302
|
-
})
|
303
309
|
.define_method(
|
304
310
|
"add_hint",
|
305
311
|
[](CpModelBuilder& self, IntVar var, int64_t value) {
|
@@ -377,29 +383,23 @@ void init_constraint(Rice::Module& m) {
|
|
377
383
|
|
378
384
|
Rice::define_class_under(m, "CpSolver")
|
379
385
|
.define_method(
|
380
|
-
"
|
381
|
-
[](Object self, CpModelBuilder& model, SatParameters& parameters, Object callback
|
386
|
+
"_solve",
|
387
|
+
[](Object self, CpModelBuilder& model, SatParameters& parameters, Object callback) {
|
382
388
|
Model m;
|
383
389
|
|
384
|
-
if (
|
385
|
-
//
|
386
|
-
parameters.
|
390
|
+
if (!callback.is_nil()) {
|
391
|
+
// TODO figure out how to use callback with multiple cores
|
392
|
+
parameters.set_num_search_workers(1);
|
393
|
+
|
394
|
+
m.Add(NewFeasibleSolutionObserver(
|
395
|
+
[callback](const CpSolverResponse& r) {
|
396
|
+
// TODO find a better way to do this
|
397
|
+
callback.call("response=", r);
|
398
|
+
callback.call("on_solution_callback");
|
399
|
+
})
|
400
|
+
);
|
387
401
|
}
|
388
|
-
m.Add(NewSatParameters(parameters));
|
389
402
|
|
390
|
-
m.Add(NewFeasibleSolutionObserver(
|
391
|
-
[callback](const CpSolverResponse& r) {
|
392
|
-
// TODO find a better way to do this
|
393
|
-
callback.call("response=", r);
|
394
|
-
callback.call("on_solution_callback");
|
395
|
-
})
|
396
|
-
);
|
397
|
-
return SolveCpModel(model.Build(), &m);
|
398
|
-
})
|
399
|
-
.define_method(
|
400
|
-
"_solve",
|
401
|
-
[](Object self, CpModelBuilder& model, SatParameters& parameters) {
|
402
|
-
Model m;
|
403
403
|
m.Add(NewSatParameters(parameters));
|
404
404
|
return SolveCpModel(model.Build(), &m);
|
405
405
|
})
|
data/ext/or-tools/linear.cpp
CHANGED
@@ -46,86 +46,14 @@ namespace Rice::detail
|
|
46
46
|
|
47
47
|
void init_linear(Rice::Module& m) {
|
48
48
|
Rice::define_class_under<LinearRange>(m, "LinearRange");
|
49
|
+
|
50
|
+
// TODO remove in 0.7.0
|
49
51
|
auto rb_cLinearExpr = Rice::define_class_under<LinearExpr>(m, "LinearExpr");
|
52
|
+
rb_cLinearExpr.define_constructor(Rice::Constructor<LinearExpr>());
|
50
53
|
|
51
|
-
Rice::define_class_under<MPVariable>(m, "MPVariable")
|
54
|
+
Rice::define_class_under<MPVariable, LinearExpr>(m, "MPVariable")
|
52
55
|
.define_method("name", &MPVariable::name)
|
53
|
-
.define_method("solution_value", &MPVariable::solution_value)
|
54
|
-
.define_method(
|
55
|
-
"+",
|
56
|
-
[](MPVariable& self, LinearExpr& other) {
|
57
|
-
LinearExpr s(&self);
|
58
|
-
return s + other;
|
59
|
-
})
|
60
|
-
.define_method(
|
61
|
-
"-",
|
62
|
-
[](MPVariable& self, LinearExpr& other) {
|
63
|
-
LinearExpr s(&self);
|
64
|
-
return s - other;
|
65
|
-
})
|
66
|
-
.define_method(
|
67
|
-
"*",
|
68
|
-
[](MPVariable& self, double other) {
|
69
|
-
LinearExpr s(&self);
|
70
|
-
return s * other;
|
71
|
-
})
|
72
|
-
.define_method(
|
73
|
-
"inspect",
|
74
|
-
[](MPVariable& self) {
|
75
|
-
return "#<ORTools::MPVariable @name=\"" + self.name() + "\">";
|
76
|
-
});
|
77
|
-
|
78
|
-
rb_cLinearExpr
|
79
|
-
.define_constructor(Rice::Constructor<LinearExpr>())
|
80
|
-
.define_method(
|
81
|
-
"_add_linear_expr",
|
82
|
-
[](LinearExpr& self, LinearExpr& other) {
|
83
|
-
return self + other;
|
84
|
-
})
|
85
|
-
.define_method(
|
86
|
-
"_add_mp_variable",
|
87
|
-
[](LinearExpr& self, MPVariable &other) {
|
88
|
-
LinearExpr o(&other);
|
89
|
-
return self + o;
|
90
|
-
})
|
91
|
-
.define_method(
|
92
|
-
"_gte_double",
|
93
|
-
[](LinearExpr& self, double other) {
|
94
|
-
LinearExpr o(other);
|
95
|
-
return self >= o;
|
96
|
-
})
|
97
|
-
.define_method(
|
98
|
-
"_gte_linear_expr",
|
99
|
-
[](LinearExpr& self, LinearExpr& other) {
|
100
|
-
return self >= other;
|
101
|
-
})
|
102
|
-
.define_method(
|
103
|
-
"_lte_double",
|
104
|
-
[](LinearExpr& self, double other) {
|
105
|
-
LinearExpr o(other);
|
106
|
-
return self <= o;
|
107
|
-
})
|
108
|
-
.define_method(
|
109
|
-
"_lte_linear_expr",
|
110
|
-
[](LinearExpr& self, LinearExpr& other) {
|
111
|
-
return self <= other;
|
112
|
-
})
|
113
|
-
.define_method(
|
114
|
-
"==",
|
115
|
-
[](LinearExpr& self, double other) {
|
116
|
-
LinearExpr o(other);
|
117
|
-
return self == o;
|
118
|
-
})
|
119
|
-
.define_method(
|
120
|
-
"to_s",
|
121
|
-
[](LinearExpr& self) {
|
122
|
-
return self.ToString();
|
123
|
-
})
|
124
|
-
.define_method(
|
125
|
-
"inspect",
|
126
|
-
[](LinearExpr& self) {
|
127
|
-
return "#<ORTools::LinearExpr \"" + self.ToString() + "\">";
|
128
|
-
});
|
56
|
+
.define_method("solution_value", &MPVariable::solution_value);
|
129
57
|
|
130
58
|
Rice::define_class_under<MPConstraint>(m, "MPConstraint")
|
131
59
|
.define_method("set_coefficient", &MPConstraint::SetCoefficient);
|
@@ -133,7 +61,8 @@ void init_linear(Rice::Module& m) {
|
|
133
61
|
Rice::define_class_under<MPObjective>(m, "MPObjective")
|
134
62
|
.define_method("value", &MPObjective::Value)
|
135
63
|
.define_method("set_coefficient", &MPObjective::SetCoefficient)
|
136
|
-
.define_method("set_maximization", &MPObjective::SetMaximization)
|
64
|
+
.define_method("set_maximization", &MPObjective::SetMaximization)
|
65
|
+
.define_method("set_minimization", &MPObjective::SetMinimization);
|
137
66
|
|
138
67
|
Rice::define_class_under<MPSolver>(m, "Solver")
|
139
68
|
.define_constructor(Rice::Constructor<MPSolver, std::string, MPSolver::OptimizationProblemType>())
|
@@ -155,21 +84,6 @@ void init_linear(Rice::Module& m) {
|
|
155
84
|
.define_method("iterations", &MPSolver::iterations)
|
156
85
|
.define_method("nodes", &MPSolver::nodes)
|
157
86
|
.define_method("objective", &MPSolver::MutableObjective)
|
158
|
-
.define_method(
|
159
|
-
"maximize",
|
160
|
-
[](MPSolver& self, LinearExpr& expr) {
|
161
|
-
return self.MutableObjective()->MaximizeLinearExpr(expr);
|
162
|
-
})
|
163
|
-
.define_method(
|
164
|
-
"minimize",
|
165
|
-
[](MPSolver& self, LinearExpr& expr) {
|
166
|
-
return self.MutableObjective()->MinimizeLinearExpr(expr);
|
167
|
-
})
|
168
|
-
.define_method(
|
169
|
-
"add",
|
170
|
-
[](MPSolver& self, const LinearRange& range) {
|
171
|
-
return self.MakeRowConstraint(range);
|
172
|
-
})
|
173
87
|
.define_method(
|
174
88
|
"constraint",
|
175
89
|
[](MPSolver& self, double lb, double ub) {
|
data/ext/or-tools/vendor.rb
CHANGED
@@ -1,31 +1,54 @@
|
|
1
|
+
require "csv"
|
1
2
|
require "digest"
|
2
3
|
require "fileutils"
|
3
4
|
require "net/http"
|
4
5
|
require "tmpdir"
|
5
6
|
|
6
|
-
version = "9.
|
7
|
+
version = "9.2.9972"
|
7
8
|
|
8
9
|
if RbConfig::CONFIG["host_os"] =~ /darwin/i
|
9
|
-
|
10
|
-
|
10
|
+
if RbConfig::CONFIG["host_cpu"] =~ /arm|aarch64/i
|
11
|
+
raise <<~MSG
|
12
|
+
Binary installation not available for this platform: Mac ARM
|
13
|
+
|
14
|
+
Run:
|
15
|
+
brew install or-tools
|
16
|
+
bundle config build.or-tools --with-or-tools-dir=/opt/homebrew
|
17
|
+
|
18
|
+
MSG
|
19
|
+
else
|
20
|
+
filename = "or-tools_MacOsX-12.0.1_v#{version}.tar.gz"
|
21
|
+
checksum = "796791a8ef84507d62e193e647cccb1c7725dae4f1474476e1777fe4a44ee3e0"
|
22
|
+
end
|
11
23
|
else
|
12
|
-
os
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
# try /etc/os-release with fallback to /usr/lib/os-release
|
25
|
+
# https://www.freedesktop.org/software/systemd/man/os-release.html
|
26
|
+
os_filename = File.exist?("/etc/os-release") ? "/etc/os-release" : "/usr/lib/os-release"
|
27
|
+
|
28
|
+
# for safety, parse rather than source
|
29
|
+
os_info = CSV.read(os_filename, col_sep: "=").to_h rescue {}
|
30
|
+
|
31
|
+
os = os_info["ID"]
|
32
|
+
os_version = os_info["VERSION_ID"]
|
33
|
+
|
34
|
+
if os == "ubuntu" && os_version == "20.04"
|
35
|
+
filename = "or-tools_amd64_ubuntu-20.04_v#{version}.tar.gz"
|
36
|
+
checksum = "985e3036eaecacfc8a0258ec2ebef429240491577d4e0896d68fc076e65451ec"
|
37
|
+
elsif os == "ubuntu" && os_version == "18.04"
|
38
|
+
filename = "or-tools_amd64_ubuntu-18.04_v#{version}.tar.gz"
|
39
|
+
checksum = "e36406c4fe8c111e1ace0ede9d0787ff0e98f11afd7db9cc074adfd0f55628a6"
|
40
|
+
elsif os == "debian" && os_version == "11"
|
41
|
+
filename = "or-tools_amd64_debian-11_v#{version}.tar.gz"
|
42
|
+
checksum = "bd49ee916213b2140ab255414d35a28f19dff7caf87632309753d3fc553f85dd"
|
43
|
+
elsif os == "debian" && os_version == "10"
|
44
|
+
filename = "or-tools_amd64_debian-10_v#{version}.tar.gz"
|
45
|
+
checksum = "b152fee584f0c8228fe2ff21b74c789870ff9b7064e42ca26305c6b5653f0064"
|
46
|
+
elsif os == "centos" && os_version == "8"
|
47
|
+
filename = "or-tools_amd64_centos-8_v#{version}.tar.gz"
|
48
|
+
checksum = "66ed4bb800acf92c672f7e68acdf4ea27bbfdb17bbddc02f8326cd55a97305f6"
|
49
|
+
elsif os == "centos" && os_version == "7"
|
50
|
+
filename = "or-tools_amd64_centos-7_v#{version}.tar.gz"
|
51
|
+
checksum = "4a5c1b1639a2828cd7e1ba82a574ef37876557b59e8aab8b81811bb750d53035"
|
29
52
|
else
|
30
53
|
platform =
|
31
54
|
if Gem.win_platform?
|
data/lib/or-tools.rb
CHANGED
@@ -5,17 +5,22 @@ require "or_tools/ext"
|
|
5
5
|
require "or_tools/comparison"
|
6
6
|
require "or_tools/comparison_operators"
|
7
7
|
require "or_tools/bool_var"
|
8
|
+
require "or_tools/constant"
|
8
9
|
require "or_tools/cp_model"
|
9
10
|
require "or_tools/cp_solver"
|
10
11
|
require "or_tools/cp_solver_solution_callback"
|
11
12
|
require "or_tools/int_var"
|
12
13
|
require "or_tools/knapsack_solver"
|
14
|
+
require "or_tools/linear_constraint"
|
13
15
|
require "or_tools/linear_expr"
|
16
|
+
require "or_tools/mp_variable"
|
17
|
+
require "or_tools/product_cst"
|
14
18
|
require "or_tools/routing_index_manager"
|
15
19
|
require "or_tools/routing_model"
|
16
20
|
require "or_tools/sat_linear_expr"
|
17
21
|
require "or_tools/sat_int_var"
|
18
22
|
require "or_tools/solver"
|
23
|
+
require "or_tools/sum_array"
|
19
24
|
require "or_tools/version"
|
20
25
|
|
21
26
|
# solution printers
|
data/lib/or_tools/comparison.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module ORTools
|
2
|
+
class Constant < LinearExpr
|
3
|
+
def initialize(val)
|
4
|
+
@val = val
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_s
|
8
|
+
@val.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_self_to_coeff_map_or_stack(coeffs, multiplier, stack)
|
12
|
+
coeffs[OFFSET_KEY] += @val * multiplier
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class FakeMPVariableRepresentingTheConstantOffset
|
17
|
+
def solution_value
|
18
|
+
1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
OFFSET_KEY = FakeMPVariableRepresentingTheConstantOffset.new
|
23
|
+
end
|
data/lib/or_tools/cp_solver.rb
CHANGED
@@ -6,8 +6,8 @@ module ORTools
|
|
6
6
|
|
7
7
|
def_delegators :@response, :objective_value, :num_conflicts, :num_branches, :wall_time
|
8
8
|
|
9
|
-
def solve(model)
|
10
|
-
@response = _solve(model, parameters)
|
9
|
+
def solve(model, observer = nil)
|
10
|
+
@response = _solve(model, parameters, observer)
|
11
11
|
@response.status
|
12
12
|
end
|
13
13
|
|
@@ -20,13 +20,19 @@ module ORTools
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def solve_with_solution_callback(model, observer)
|
23
|
-
|
24
|
-
|
23
|
+
warn "[or-tools] solve_with_solution_callback is deprecated; use solve(model, callback)"
|
24
|
+
solve(model, observer)
|
25
25
|
end
|
26
26
|
|
27
27
|
def search_for_all_solutions(model, observer)
|
28
|
-
|
29
|
-
|
28
|
+
warn "[or-tools] search_for_all_solutions is deprecated; use solve() with solver.parameters.enumerate_all_solutions = true"
|
29
|
+
previous_value = parameters.enumerate_all_solutions
|
30
|
+
begin
|
31
|
+
parameters.enumerate_all_solutions = true
|
32
|
+
solve(model, observer)
|
33
|
+
ensure
|
34
|
+
parameters.enumerate_all_solutions = previous_value
|
35
|
+
end
|
30
36
|
end
|
31
37
|
|
32
38
|
def sufficient_assumptions_for_infeasibility
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ORTools
|
2
|
+
class LinearConstraint
|
3
|
+
attr_reader :expr, :lb, :ub
|
4
|
+
|
5
|
+
def initialize(expr, lb, ub)
|
6
|
+
@expr = expr
|
7
|
+
@lb = lb
|
8
|
+
@ub = ub
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
if @lb > -Float::INFINITY && @ub < Float::INFINITY
|
13
|
+
if @lb == @ub
|
14
|
+
"#{@expr} == #{@lb}"
|
15
|
+
else
|
16
|
+
"#{@lb} <= #{@expr} <= #{@ub}"
|
17
|
+
end
|
18
|
+
elsif @lb > -Float::INFINITY
|
19
|
+
"#{@expr} >= #{@lb}"
|
20
|
+
elsif @ub < Float::INFINITY
|
21
|
+
"#{@expr} <= #{@ub}"
|
22
|
+
else
|
23
|
+
"Trivial inequality (always true)"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def inspect
|
28
|
+
"#<#{self.class.name} #{to_s}>"
|
29
|
+
end
|
30
|
+
|
31
|
+
def extract(solver)
|
32
|
+
coeffs = @expr.coeffs
|
33
|
+
constant = coeffs.delete(OFFSET_KEY) || 0.0
|
34
|
+
lb = -solver.infinity
|
35
|
+
ub = solver.infinity
|
36
|
+
if @lb > -Float::INFINITY
|
37
|
+
lb = @lb - constant
|
38
|
+
end
|
39
|
+
if @ub < Float::INFINITY
|
40
|
+
ub = @ub - constant
|
41
|
+
end
|
42
|
+
|
43
|
+
constraint = solver.constraint(lb, ub)
|
44
|
+
coeffs.each do |v, c|
|
45
|
+
constraint.set_coefficient(v, c.to_f)
|
46
|
+
end
|
47
|
+
constraint
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/or_tools/linear_expr.rb
CHANGED
@@ -1,27 +1,73 @@
|
|
1
1
|
module ORTools
|
2
2
|
class LinearExpr
|
3
|
-
def
|
4
|
-
|
5
|
-
|
3
|
+
def solution_value
|
4
|
+
coeffs.sum { |var, coeff| var.solution_value * coeff }
|
5
|
+
end
|
6
|
+
|
7
|
+
def coeffs
|
8
|
+
coeffs = Hash.new(0.0)
|
9
|
+
stack = [[1.0, self]]
|
10
|
+
while stack.any?
|
11
|
+
current_multiplier, current_expression = stack.pop
|
12
|
+
|
13
|
+
# skip empty LinearExpr for backwards compatibility
|
14
|
+
next if current_expression.instance_of?(LinearExpr)
|
15
|
+
|
16
|
+
current_expression.add_self_to_coeff_map_or_stack(coeffs, current_multiplier, stack)
|
17
|
+
end
|
18
|
+
coeffs
|
19
|
+
end
|
20
|
+
|
21
|
+
def +(expr)
|
22
|
+
SumArray.new([self, expr])
|
23
|
+
end
|
24
|
+
|
25
|
+
def -(expr)
|
26
|
+
SumArray.new([self, -expr])
|
27
|
+
end
|
28
|
+
|
29
|
+
def *(other)
|
30
|
+
ProductCst.new(self, other)
|
31
|
+
end
|
32
|
+
|
33
|
+
def /(cst)
|
34
|
+
ProductCst.new(self, 1.0 / other)
|
35
|
+
end
|
36
|
+
|
37
|
+
def -@
|
38
|
+
ProductCst.new(self, -1)
|
39
|
+
end
|
40
|
+
|
41
|
+
def ==(arg)
|
42
|
+
if arg.is_a?(Numeric)
|
43
|
+
LinearConstraint.new(self, arg, arg)
|
6
44
|
else
|
7
|
-
|
45
|
+
LinearConstraint.new(self - arg, 0.0, 0.0)
|
8
46
|
end
|
9
47
|
end
|
10
48
|
|
11
|
-
def >=(
|
12
|
-
if
|
13
|
-
|
49
|
+
def >=(arg)
|
50
|
+
if arg.is_a?(Numeric)
|
51
|
+
LinearConstraint.new(self, arg, Float::INFINITY)
|
14
52
|
else
|
15
|
-
|
53
|
+
LinearConstraint.new(self - arg, 0.0, Float::INFINITY)
|
16
54
|
end
|
17
55
|
end
|
18
56
|
|
19
|
-
def <=(
|
20
|
-
if
|
21
|
-
|
57
|
+
def <=(arg)
|
58
|
+
if arg.is_a?(Numeric)
|
59
|
+
LinearConstraint.new(self, -Float::INFINITY, arg)
|
22
60
|
else
|
23
|
-
|
61
|
+
LinearConstraint.new(self - arg, -Float::INFINITY, 0.0)
|
24
62
|
end
|
25
63
|
end
|
64
|
+
|
65
|
+
def to_s
|
66
|
+
"(empty)"
|
67
|
+
end
|
68
|
+
|
69
|
+
def inspect
|
70
|
+
"#<#{self.class.name} #{to_s}>"
|
71
|
+
end
|
26
72
|
end
|
27
73
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ORTools
|
2
|
+
class ProductCst < LinearExpr
|
3
|
+
attr_reader :expr, :coef
|
4
|
+
|
5
|
+
def initialize(expr, coef)
|
6
|
+
@expr = cast_to_lin_exp(expr)
|
7
|
+
# TODO improve message
|
8
|
+
raise TypeError, "expected numeric" unless coef.is_a?(Numeric)
|
9
|
+
@coef = coef
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
if @coef == -1
|
14
|
+
"-#{@expr}"
|
15
|
+
else
|
16
|
+
"(#{@coef} * #{@expr})"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_self_to_coeff_map_or_stack(coeffs, multiplier, stack)
|
21
|
+
current_multiplier = multiplier * @coef
|
22
|
+
if current_multiplier
|
23
|
+
stack << [current_multiplier, @expr]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def cast_to_lin_exp(v)
|
28
|
+
v.is_a?(Numeric) ? Constant.new(v) : v
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/or_tools/sat_int_var.rb
CHANGED
@@ -24,7 +24,7 @@ module ORTools
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
27
|
+
def to_s
|
28
28
|
vars.map do |v|
|
29
29
|
k = v[0]
|
30
30
|
k = k.respond_to?(:name) ? k.name : k.inspect
|
@@ -36,6 +36,11 @@ module ORTools
|
|
36
36
|
end.join(" + ").sub(" + -", " - ")
|
37
37
|
end
|
38
38
|
|
39
|
+
# TODO add class
|
40
|
+
def inspect
|
41
|
+
to_s
|
42
|
+
end
|
43
|
+
|
39
44
|
private
|
40
45
|
|
41
46
|
def add(other, sign)
|
data/lib/or_tools/solver.rb
CHANGED
@@ -1,7 +1,25 @@
|
|
1
1
|
module ORTools
|
2
2
|
class Solver
|
3
3
|
def sum(arr)
|
4
|
-
|
4
|
+
SumArray.new(arr)
|
5
|
+
end
|
6
|
+
|
7
|
+
def add(expr)
|
8
|
+
expr.extract(self)
|
9
|
+
end
|
10
|
+
|
11
|
+
def maximize(expr)
|
12
|
+
expr.coeffs.each do |v, c|
|
13
|
+
objective.set_coefficient(v, c)
|
14
|
+
end
|
15
|
+
objective.set_maximization
|
16
|
+
end
|
17
|
+
|
18
|
+
def minimize(expr)
|
19
|
+
expr.coeffs.each do |v, c|
|
20
|
+
objective.set_coefficient(v, c)
|
21
|
+
end
|
22
|
+
objective.set_minimization
|
5
23
|
end
|
6
24
|
end
|
7
25
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ORTools
|
2
|
+
class SumArray < LinearExpr
|
3
|
+
attr_reader :array
|
4
|
+
|
5
|
+
def initialize(array)
|
6
|
+
@array = array.map { |v| cast_to_lin_exp(v) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_self_to_coeff_map_or_stack(coeffs, multiplier, stack)
|
10
|
+
@array.reverse.each do |arg|
|
11
|
+
stack << [multiplier, arg]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def cast_to_lin_exp(v)
|
16
|
+
v.is_a?(Numeric) ? Constant.new(v) : v
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"(#{@array.map(&:to_s).join(" + ")})"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/or_tools/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: or-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rice
|
@@ -50,13 +50,17 @@ files:
|
|
50
50
|
- lib/or_tools/bool_var.rb
|
51
51
|
- lib/or_tools/comparison.rb
|
52
52
|
- lib/or_tools/comparison_operators.rb
|
53
|
+
- lib/or_tools/constant.rb
|
53
54
|
- lib/or_tools/cp_model.rb
|
54
55
|
- lib/or_tools/cp_solver.rb
|
55
56
|
- lib/or_tools/cp_solver_solution_callback.rb
|
56
57
|
- lib/or_tools/int_var.rb
|
57
58
|
- lib/or_tools/knapsack_solver.rb
|
59
|
+
- lib/or_tools/linear_constraint.rb
|
58
60
|
- lib/or_tools/linear_expr.rb
|
61
|
+
- lib/or_tools/mp_variable.rb
|
59
62
|
- lib/or_tools/objective_solution_printer.rb
|
63
|
+
- lib/or_tools/product_cst.rb
|
60
64
|
- lib/or_tools/routing_index_manager.rb
|
61
65
|
- lib/or_tools/routing_model.rb
|
62
66
|
- lib/or_tools/sat_int_var.rb
|
@@ -64,11 +68,12 @@ files:
|
|
64
68
|
- lib/or_tools/seating.rb
|
65
69
|
- lib/or_tools/solver.rb
|
66
70
|
- lib/or_tools/sudoku.rb
|
71
|
+
- lib/or_tools/sum_array.rb
|
67
72
|
- lib/or_tools/tsp.rb
|
68
73
|
- lib/or_tools/var_array_and_objective_solution_printer.rb
|
69
74
|
- lib/or_tools/var_array_solution_printer.rb
|
70
75
|
- lib/or_tools/version.rb
|
71
|
-
homepage: https://github.com/ankane/or-tools
|
76
|
+
homepage: https://github.com/ankane/or-tools-ruby
|
72
77
|
licenses:
|
73
78
|
- MIT
|
74
79
|
metadata: {}
|
@@ -87,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
92
|
- !ruby/object:Gem::Version
|
88
93
|
version: '0'
|
89
94
|
requirements: []
|
90
|
-
rubygems_version: 3.
|
95
|
+
rubygems_version: 3.3.3
|
91
96
|
signing_key:
|
92
97
|
specification_version: 4
|
93
98
|
summary: Operations research tools for Ruby
|