or-tools 0.17.1 → 0.18.1
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 +17 -0
- data/README.md +14 -10
- data/ext/or-tools/assignment.cpp +1 -1
- data/ext/or-tools/bin_packing.cpp +3 -3
- data/ext/or-tools/channel.hpp +37 -0
- data/ext/or-tools/constraint.cpp +685 -63
- data/ext/or-tools/ext.cpp +1 -1
- data/ext/or-tools/linear.cpp +8 -8
- data/ext/or-tools/math_opt.cpp +8 -8
- data/ext/or-tools/network_flows.cpp +2 -2
- data/ext/or-tools/routing.cpp +256 -49
- data/ext/or-tools/vendor.rb +22 -53
- data/lib/or_tools/cp_solver.rb +1 -16
- data/lib/or_tools/cp_solver_solution_callback.rb +4 -0
- data/lib/or_tools/routing_model.rb +22 -0
- data/lib/or_tools/version.rb +1 -1
- metadata +4 -3
data/ext/or-tools/routing.cpp
CHANGED
|
@@ -10,6 +10,7 @@ using operations_research::Assignment;
|
|
|
10
10
|
using operations_research::ConstraintSolverParameters;
|
|
11
11
|
using operations_research::DefaultRoutingSearchParameters;
|
|
12
12
|
using operations_research::FirstSolutionStrategy;
|
|
13
|
+
using operations_research::IntervalVarElement;
|
|
13
14
|
using operations_research::LocalSearchMetaheuristic;
|
|
14
15
|
using operations_research::RoutingDimension;
|
|
15
16
|
using operations_research::RoutingDisjunctionIndex;
|
|
@@ -22,6 +23,7 @@ using operations_research::RoutingSearchStatus;
|
|
|
22
23
|
|
|
23
24
|
using Rice::Array;
|
|
24
25
|
using Rice::Class;
|
|
26
|
+
using Rice::Hash;
|
|
25
27
|
using Rice::Module;
|
|
26
28
|
using Rice::Object;
|
|
27
29
|
using Rice::String;
|
|
@@ -58,7 +60,7 @@ namespace Rice::detail {
|
|
|
58
60
|
|
|
59
61
|
explicit To_Ruby(Arg* arg) : arg_(arg) { }
|
|
60
62
|
|
|
61
|
-
VALUE convert(
|
|
63
|
+
VALUE convert(const RoutingNodeIndex& x) {
|
|
62
64
|
return To_Ruby<int>().convert(x.value());
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -81,13 +83,13 @@ namespace Rice::detail {
|
|
|
81
83
|
double is_convertible(VALUE value) { return Convertible::Exact; }
|
|
82
84
|
|
|
83
85
|
RoutingModel::PenaltyCostBehavior convert(VALUE x) {
|
|
84
|
-
|
|
86
|
+
std::string s = Symbol(x).str();
|
|
85
87
|
if (s == "penalize_once") {
|
|
86
88
|
return RoutingModel::PenaltyCostBehavior::PENALIZE_ONCE;
|
|
87
89
|
} else if (s == "penalize_per_inactive") {
|
|
88
90
|
return RoutingModel::PenaltyCostBehavior::PENALIZE_PER_INACTIVE;
|
|
89
91
|
} else {
|
|
90
|
-
throw std::runtime_error
|
|
92
|
+
throw std::runtime_error{"Unknown penalty cost behavior: " + s};
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
|
|
@@ -96,13 +98,111 @@ namespace Rice::detail {
|
|
|
96
98
|
};
|
|
97
99
|
} // namespace Rice::detail
|
|
98
100
|
|
|
101
|
+
int64_t int64_strict(VALUE v) {
|
|
102
|
+
if (!Object(v).is_a(rb_cInteger)) {
|
|
103
|
+
throw std::invalid_argument{"Coefficient must be integer"};
|
|
104
|
+
}
|
|
105
|
+
return Rice::detail::From_Ruby<int64_t>().convert(v);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
operations_research::IntExpr* int_expr(operations_research::Solver& solver, Object o) {
|
|
109
|
+
Object utils = Rice::define_module("ORTools").const_get("Utils");
|
|
110
|
+
Hash rb_coeffs = utils.call("index_expression", o);
|
|
111
|
+
|
|
112
|
+
std::vector<operations_research::IntVar*> vars;
|
|
113
|
+
std::vector<int64_t> coeffs;
|
|
114
|
+
int64_t constant = 0;
|
|
115
|
+
|
|
116
|
+
for (const auto& entry : rb_coeffs) {
|
|
117
|
+
auto coeff = int64_strict(entry.value.value());
|
|
118
|
+
if (Object(entry.key).is_nil()) {
|
|
119
|
+
constant = coeff;
|
|
120
|
+
} else {
|
|
121
|
+
vars.push_back(Rice::detail::From_Ruby<operations_research::IntVar*>().convert(entry.key.value()));
|
|
122
|
+
coeffs.push_back(coeff);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
operations_research::IntExpr* expr = solver.MakeScalProd(vars, coeffs);
|
|
127
|
+
if (constant != 0) {
|
|
128
|
+
expr = solver.MakeSum(expr, constant);
|
|
129
|
+
}
|
|
130
|
+
return expr;
|
|
131
|
+
}
|
|
132
|
+
|
|
99
133
|
void init_routing(Rice::Module& m) {
|
|
100
134
|
auto rb_cRoutingSearchParameters = Rice::define_class_under<RoutingSearchParameters>(m, "RoutingSearchParameters");
|
|
101
135
|
auto rb_cIntVar = Rice::define_class_under<operations_research::IntVar>(m, "RoutingIntVar");
|
|
102
136
|
|
|
103
137
|
m.define_singleton_function("default_routing_search_parameters", &DefaultRoutingSearchParameters);
|
|
104
138
|
|
|
139
|
+
Rice::define_class_under<RoutingSearchParameters::ImprovementSearchLimitParameters>(rb_cRoutingSearchParameters, "ImprovementSearchLimitParameters")
|
|
140
|
+
.define_method("improvement_rate_coefficient", &RoutingSearchParameters::ImprovementSearchLimitParameters::improvement_rate_coefficient)
|
|
141
|
+
.define_method("improvement_rate_coefficient=", &RoutingSearchParameters::ImprovementSearchLimitParameters::set_improvement_rate_coefficient)
|
|
142
|
+
.define_method("improvement_rate_solutions_distance", &RoutingSearchParameters::ImprovementSearchLimitParameters::improvement_rate_solutions_distance)
|
|
143
|
+
.define_method("improvement_rate_solutions_distance=", &RoutingSearchParameters::ImprovementSearchLimitParameters::set_improvement_rate_solutions_distance);
|
|
144
|
+
|
|
105
145
|
rb_cRoutingSearchParameters
|
|
146
|
+
.define_method("christofides_use_minimum_matching", &RoutingSearchParameters::christofides_use_minimum_matching)
|
|
147
|
+
.define_method("christofides_use_minimum_matching=", &RoutingSearchParameters::set_christofides_use_minimum_matching)
|
|
148
|
+
.define_method("fallback_to_cp_sat_size_threshold", &RoutingSearchParameters::fallback_to_cp_sat_size_threshold)
|
|
149
|
+
.define_method("fallback_to_cp_sat_size_threshold=", &RoutingSearchParameters::set_fallback_to_cp_sat_size_threshold)
|
|
150
|
+
.define_method("first_solution_optimization_period", &RoutingSearchParameters::first_solution_optimization_period)
|
|
151
|
+
.define_method("first_solution_optimization_period=", &RoutingSearchParameters::set_first_solution_optimization_period)
|
|
152
|
+
.define_method("guided_local_search_lambda_coefficient", &RoutingSearchParameters::guided_local_search_lambda_coefficient)
|
|
153
|
+
.define_method("guided_local_search_lambda_coefficient=", &RoutingSearchParameters::set_guided_local_search_lambda_coefficient)
|
|
154
|
+
.define_method("guided_local_search_penalize_with_vehicle_classes", &RoutingSearchParameters::guided_local_search_penalize_with_vehicle_classes)
|
|
155
|
+
.define_method("guided_local_search_penalize_with_vehicle_classes=", &RoutingSearchParameters::set_guided_local_search_penalize_with_vehicle_classes)
|
|
156
|
+
.define_method("guided_local_search_reset_penalties_on_new_best_solution", &RoutingSearchParameters::guided_local_search_reset_penalties_on_new_best_solution)
|
|
157
|
+
.define_method("guided_local_search_reset_penalties_on_new_best_solution=", &RoutingSearchParameters::set_guided_local_search_reset_penalties_on_new_best_solution)
|
|
158
|
+
.define_method("heuristic_close_nodes_lns_num_nodes", &RoutingSearchParameters::heuristic_close_nodes_lns_num_nodes)
|
|
159
|
+
.define_method("heuristic_close_nodes_lns_num_nodes=", &RoutingSearchParameters::set_heuristic_close_nodes_lns_num_nodes)
|
|
160
|
+
.define_method("heuristic_expensive_chain_lns_num_arcs_to_consider", &RoutingSearchParameters::heuristic_expensive_chain_lns_num_arcs_to_consider)
|
|
161
|
+
.define_method("heuristic_expensive_chain_lns_num_arcs_to_consider=", &RoutingSearchParameters::set_heuristic_expensive_chain_lns_num_arcs_to_consider)
|
|
162
|
+
.define_method("log_cost_offset", &RoutingSearchParameters::log_cost_offset)
|
|
163
|
+
.define_method("log_cost_offset=", &RoutingSearchParameters::set_log_cost_offset)
|
|
164
|
+
.define_method("log_cost_scaling_factor", &RoutingSearchParameters::log_cost_scaling_factor)
|
|
165
|
+
.define_method("log_cost_scaling_factor=", &RoutingSearchParameters::set_log_cost_scaling_factor)
|
|
166
|
+
.define_method("log_search", &RoutingSearchParameters::log_search)
|
|
167
|
+
.define_method("log_search=", &RoutingSearchParameters::set_log_search)
|
|
168
|
+
.define_method("log_tag", &RoutingSearchParameters::log_tag)
|
|
169
|
+
// .define_method("log_tag=", &RoutingSearchParameters::set_log_tag)
|
|
170
|
+
.define_method("ls_operator_min_neighbors", &RoutingSearchParameters::ls_operator_min_neighbors)
|
|
171
|
+
.define_method("ls_operator_min_neighbors=", &RoutingSearchParameters::set_ls_operator_min_neighbors)
|
|
172
|
+
.define_method("ls_operator_neighbors_ratio", &RoutingSearchParameters::ls_operator_neighbors_ratio)
|
|
173
|
+
.define_method("ls_operator_neighbors_ratio=", &RoutingSearchParameters::set_ls_operator_neighbors_ratio)
|
|
174
|
+
.define_method("max_swap_active_chain_size", &RoutingSearchParameters::max_swap_active_chain_size)
|
|
175
|
+
.define_method("max_swap_active_chain_size=", &RoutingSearchParameters::set_max_swap_active_chain_size)
|
|
176
|
+
.define_method("multi_armed_bandit_compound_operator_exploration_coefficient", &RoutingSearchParameters::multi_armed_bandit_compound_operator_exploration_coefficient)
|
|
177
|
+
.define_method("multi_armed_bandit_compound_operator_exploration_coefficient=", &RoutingSearchParameters::set_multi_armed_bandit_compound_operator_exploration_coefficient)
|
|
178
|
+
.define_method("multi_armed_bandit_compound_operator_memory_coefficient", &RoutingSearchParameters::multi_armed_bandit_compound_operator_memory_coefficient)
|
|
179
|
+
.define_method("multi_armed_bandit_compound_operator_memory_coefficient=", &RoutingSearchParameters::set_multi_armed_bandit_compound_operator_memory_coefficient)
|
|
180
|
+
.define_method("num_max_local_optima_before_metaheuristic_switch", &RoutingSearchParameters::num_max_local_optima_before_metaheuristic_switch)
|
|
181
|
+
.define_method("num_max_local_optima_before_metaheuristic_switch=", &RoutingSearchParameters::set_num_max_local_optima_before_metaheuristic_switch)
|
|
182
|
+
.define_method("number_of_solutions_to_collect", &RoutingSearchParameters::number_of_solutions_to_collect)
|
|
183
|
+
.define_method("number_of_solutions_to_collect=", &RoutingSearchParameters::set_number_of_solutions_to_collect)
|
|
184
|
+
.define_method("optimization_step", &RoutingSearchParameters::optimization_step)
|
|
185
|
+
.define_method("optimization_step=", &RoutingSearchParameters::set_optimization_step)
|
|
186
|
+
.define_method("relocate_expensive_chain_num_arcs_to_consider", &RoutingSearchParameters::relocate_expensive_chain_num_arcs_to_consider)
|
|
187
|
+
.define_method("relocate_expensive_chain_num_arcs_to_consider=", &RoutingSearchParameters::set_relocate_expensive_chain_num_arcs_to_consider)
|
|
188
|
+
.define_method("report_intermediate_cp_sat_solutions", &RoutingSearchParameters::report_intermediate_cp_sat_solutions)
|
|
189
|
+
.define_method("report_intermediate_cp_sat_solutions=", &RoutingSearchParameters::set_report_intermediate_cp_sat_solutions)
|
|
190
|
+
.define_method("secondary_ls_time_limit_ratio", &RoutingSearchParameters::secondary_ls_time_limit_ratio)
|
|
191
|
+
.define_method("secondary_ls_time_limit_ratio=", &RoutingSearchParameters::set_secondary_ls_time_limit_ratio)
|
|
192
|
+
.define_method("solution_limit", &RoutingSearchParameters::solution_limit)
|
|
193
|
+
.define_method("solution_limit=", &RoutingSearchParameters::set_solution_limit)
|
|
194
|
+
.define_method("use_depth_first_search", &RoutingSearchParameters::use_depth_first_search)
|
|
195
|
+
.define_method("use_depth_first_search=", &RoutingSearchParameters::set_use_depth_first_search)
|
|
196
|
+
.define_method("use_full_propagation", &RoutingSearchParameters::use_full_propagation)
|
|
197
|
+
.define_method("use_full_propagation=", &RoutingSearchParameters::set_use_full_propagation)
|
|
198
|
+
.define_method("use_guided_local_search_penalties_in_local_search_operators", &RoutingSearchParameters::use_guided_local_search_penalties_in_local_search_operators)
|
|
199
|
+
.define_method("use_guided_local_search_penalties_in_local_search_operators=", &RoutingSearchParameters::set_use_guided_local_search_penalties_in_local_search_operators)
|
|
200
|
+
.define_method("use_iterated_local_search", &RoutingSearchParameters::use_iterated_local_search)
|
|
201
|
+
.define_method("use_iterated_local_search=", &RoutingSearchParameters::set_use_iterated_local_search)
|
|
202
|
+
.define_method("use_multi_armed_bandit_concatenate_operators", &RoutingSearchParameters::use_multi_armed_bandit_concatenate_operators)
|
|
203
|
+
.define_method("use_multi_armed_bandit_concatenate_operators=", &RoutingSearchParameters::set_use_multi_armed_bandit_concatenate_operators)
|
|
204
|
+
.define_method("use_unfiltered_first_solution_strategy", &RoutingSearchParameters::use_unfiltered_first_solution_strategy)
|
|
205
|
+
.define_method("use_unfiltered_first_solution_strategy=", &RoutingSearchParameters::set_use_unfiltered_first_solution_strategy)
|
|
106
206
|
.define_method(
|
|
107
207
|
"first_solution_strategy=",
|
|
108
208
|
[](RoutingSearchParameters& self, Object value) {
|
|
@@ -138,7 +238,7 @@ void init_routing(Rice::Module& m) {
|
|
|
138
238
|
} else if (s == "first_unbound_min_value") {
|
|
139
239
|
v = FirstSolutionStrategy::FIRST_UNBOUND_MIN_VALUE;
|
|
140
240
|
} else {
|
|
141
|
-
throw std::runtime_error
|
|
241
|
+
throw std::runtime_error{"Unknown first solution strategy: " + s};
|
|
142
242
|
}
|
|
143
243
|
|
|
144
244
|
return self.set_first_solution_strategy(v);
|
|
@@ -158,21 +258,12 @@ void init_routing(Rice::Module& m) {
|
|
|
158
258
|
} else if (s == "simulated_annealing") {
|
|
159
259
|
v = LocalSearchMetaheuristic::SIMULATED_ANNEALING;
|
|
160
260
|
} else {
|
|
161
|
-
throw std::runtime_error
|
|
261
|
+
throw std::runtime_error{"Unknown local search metaheuristic: " + s};
|
|
162
262
|
}
|
|
163
263
|
|
|
164
264
|
return self.set_local_search_metaheuristic(v);
|
|
165
265
|
})
|
|
166
|
-
.define_method(
|
|
167
|
-
"log_search=",
|
|
168
|
-
[](RoutingSearchParameters& self, bool value) {
|
|
169
|
-
self.set_log_search(value);
|
|
170
|
-
})
|
|
171
|
-
.define_method(
|
|
172
|
-
"solution_limit=",
|
|
173
|
-
[](RoutingSearchParameters& self, int64_t value) {
|
|
174
|
-
self.set_solution_limit(value);
|
|
175
|
-
})
|
|
266
|
+
.define_method("improvement_limit_parameters", &RoutingSearchParameters::mutable_improvement_limit_parameters)
|
|
176
267
|
.define_method(
|
|
177
268
|
"time_limit=",
|
|
178
269
|
[](RoutingSearchParameters& self, int64_t value) {
|
|
@@ -192,20 +283,38 @@ void init_routing(Rice::Module& m) {
|
|
|
192
283
|
})
|
|
193
284
|
.define_singleton_function(
|
|
194
285
|
"_new_starts_ends",
|
|
195
|
-
[](int num_nodes, int num_vehicles, std::vector<RoutingNodeIndex
|
|
286
|
+
[](int num_nodes, int num_vehicles, const std::vector<RoutingNodeIndex>& starts, const std::vector<RoutingNodeIndex>& ends) {
|
|
196
287
|
return RoutingIndexManager(num_nodes, num_vehicles, starts, ends);
|
|
197
288
|
})
|
|
198
289
|
.define_method("index_to_node", &RoutingIndexManager::IndexToNode)
|
|
199
290
|
.define_method("node_to_index", &RoutingIndexManager::NodeToIndex);
|
|
200
291
|
|
|
292
|
+
|
|
293
|
+
Rice::define_class_under<IntervalVarElement>(m, "IntervalVarElement")
|
|
294
|
+
.define_method("var", &IntervalVarElement::Var)
|
|
295
|
+
.define_method("start_value", &IntervalVarElement::StartValue)
|
|
296
|
+
.define_method("duration_value", &IntervalVarElement::DurationValue)
|
|
297
|
+
.define_method("end_value", &IntervalVarElement::EndValue)
|
|
298
|
+
.define_method("performed_value", &IntervalVarElement::PerformedValue);
|
|
299
|
+
|
|
300
|
+
Rice::define_class_under<Assignment::IntervalContainer>(m, "IntervalContainer")
|
|
301
|
+
.define_method("size", &Assignment::IntervalContainer::Size)
|
|
302
|
+
.define_method(
|
|
303
|
+
"element",
|
|
304
|
+
[](Assignment::IntervalContainer& self, int index) {
|
|
305
|
+
return self.Element(index);
|
|
306
|
+
});
|
|
307
|
+
|
|
201
308
|
Rice::define_class_under<Assignment>(m, "Assignment")
|
|
202
309
|
.define_method("objective_value", &Assignment::ObjectiveValue)
|
|
203
310
|
.define_method("value", &Assignment::Value)
|
|
204
311
|
.define_method("min", &Assignment::Min)
|
|
205
|
-
.define_method("max", &Assignment::Max)
|
|
312
|
+
.define_method("max", &Assignment::Max)
|
|
313
|
+
.define_method("interval_var_container", &Assignment::IntervalVarContainer);
|
|
206
314
|
|
|
207
315
|
// not to be confused with operations_research::sat::IntVar
|
|
208
316
|
rb_cIntVar
|
|
317
|
+
.define_method("name", &operations_research::IntVar::name)
|
|
209
318
|
.define_method("var?", &operations_research::IntVar::IsVar)
|
|
210
319
|
.define_method("value", &operations_research::IntVar::Value)
|
|
211
320
|
.define_method("remove_value", &operations_research::IntVar::RemoveValue)
|
|
@@ -223,6 +332,7 @@ void init_routing(Rice::Module& m) {
|
|
|
223
332
|
});
|
|
224
333
|
|
|
225
334
|
Rice::define_class_under<operations_research::IntervalVar>(m, "IntervalVar")
|
|
335
|
+
.define_method("name", &operations_research::IntervalVar::name)
|
|
226
336
|
.define_method("start_min", &operations_research::IntervalVar::StartMin)
|
|
227
337
|
.define_method("start_max", &operations_research::IntervalVar::StartMax)
|
|
228
338
|
.define_method("set_start_min", &operations_research::IntervalVar::SetStartMin)
|
|
@@ -250,6 +360,8 @@ void init_routing(Rice::Module& m) {
|
|
|
250
360
|
.define_method("set_global_span_cost_coefficient", &RoutingDimension::SetGlobalSpanCostCoefficient)
|
|
251
361
|
// alias
|
|
252
362
|
.define_method("global_span_cost_coefficient=", &RoutingDimension::SetGlobalSpanCostCoefficient)
|
|
363
|
+
.define_method("set_slack_cost_coefficient_for_vehicle", &RoutingDimension::SetSlackCostCoefficientForVehicle)
|
|
364
|
+
.define_method("set_slack_cost_coefficient_for_all_vehicles", &RoutingDimension::SetSlackCostCoefficientForAllVehicles)
|
|
253
365
|
.define_method("set_cumul_var_soft_upper_bound", &RoutingDimension::SetCumulVarSoftUpperBound)
|
|
254
366
|
.define_method("cumul_var_soft_upper_bound?", &RoutingDimension::HasCumulVarSoftUpperBound)
|
|
255
367
|
.define_method("cumul_var_soft_upper_bound", &RoutingDimension::GetCumulVarSoftUpperBound)
|
|
@@ -257,7 +369,12 @@ void init_routing(Rice::Module& m) {
|
|
|
257
369
|
.define_method("set_cumul_var_soft_lower_bound", &RoutingDimension::SetCumulVarSoftLowerBound)
|
|
258
370
|
.define_method("cumul_var_soft_lower_bound?", &RoutingDimension::HasCumulVarSoftLowerBound)
|
|
259
371
|
.define_method("cumul_var_soft_lower_bound", &RoutingDimension::GetCumulVarSoftLowerBound)
|
|
260
|
-
.define_method("cumul_var_soft_lower_bound_coefficient", &RoutingDimension::GetCumulVarSoftLowerBoundCoefficient)
|
|
372
|
+
.define_method("cumul_var_soft_lower_bound_coefficient", &RoutingDimension::GetCumulVarSoftLowerBoundCoefficient)
|
|
373
|
+
.define_method(
|
|
374
|
+
"set_break_intervals_of_vehicle",
|
|
375
|
+
[](RoutingDimension& self, std::vector<operations_research::IntervalVar*> breaks, int vehicle, std::vector<int64_t> node_visit_transits) {
|
|
376
|
+
self.SetBreakIntervalsOfVehicle(breaks, vehicle, node_visit_transits);
|
|
377
|
+
});
|
|
261
378
|
|
|
262
379
|
Rice::define_class_under<RoutingDisjunctionIndex>(m, "RoutingDisjunctionIndex");
|
|
263
380
|
|
|
@@ -271,15 +388,24 @@ void init_routing(Rice::Module& m) {
|
|
|
271
388
|
[](operations_research::Solver& self, Object o) {
|
|
272
389
|
operations_research::Constraint* constraint;
|
|
273
390
|
if (o.respond_to("left")) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
391
|
+
auto left = int_expr(self, o.call("left"));
|
|
392
|
+
auto right = int_expr(self, o.call("right"));
|
|
393
|
+
std::string op = o.call("op").to_s().str();
|
|
394
|
+
|
|
277
395
|
if (op == "==") {
|
|
278
396
|
constraint = self.MakeEquality(left, right);
|
|
397
|
+
} else if (op == "!=") {
|
|
398
|
+
constraint = self.MakeNonEquality(left, right);
|
|
399
|
+
} else if (op == ">") {
|
|
400
|
+
constraint = self.MakeGreater(left, right);
|
|
401
|
+
} else if (op == ">=") {
|
|
402
|
+
constraint = self.MakeGreaterOrEqual(left, right);
|
|
403
|
+
} else if (op == "<") {
|
|
404
|
+
constraint = self.MakeLess(left, right);
|
|
279
405
|
} else if (op == "<=") {
|
|
280
406
|
constraint = self.MakeLessOrEqual(left, right);
|
|
281
407
|
} else {
|
|
282
|
-
throw std::runtime_error
|
|
408
|
+
throw std::runtime_error{"Unknown operator"};
|
|
283
409
|
}
|
|
284
410
|
} else {
|
|
285
411
|
constraint = Rice::detail::From_Ruby<operations_research::Constraint*>().convert(o);
|
|
@@ -288,12 +414,17 @@ void init_routing(Rice::Module& m) {
|
|
|
288
414
|
})
|
|
289
415
|
.define_method(
|
|
290
416
|
"fixed_duration_interval_var",
|
|
291
|
-
[](operations_research::Solver& self, operations_research::IntVar
|
|
292
|
-
return self.MakeFixedDurationIntervalVar(start_variable, duration, name);
|
|
417
|
+
[](operations_research::Solver& self, operations_research::IntVar& start_variable, int64_t duration, const std::string& name) {
|
|
418
|
+
return self.MakeFixedDurationIntervalVar(&start_variable, duration, name);
|
|
419
|
+
})
|
|
420
|
+
.define_method(
|
|
421
|
+
"fixed_duration_interval_var",
|
|
422
|
+
[](operations_research::Solver& self, int64_t start_min, int64_t start_max, int64_t duration, bool optional, const std::string& name) {
|
|
423
|
+
return self.MakeFixedDurationIntervalVar(start_min, start_max, duration, optional, name);
|
|
293
424
|
})
|
|
294
425
|
.define_method(
|
|
295
426
|
"cumulative",
|
|
296
|
-
[](operations_research::Solver& self, Array rb_intervals, std::vector<int64_t
|
|
427
|
+
[](operations_research::Solver& self, Array rb_intervals, const std::vector<int64_t>& demands, int64_t capacity, const std::string& name) {
|
|
297
428
|
std::vector<operations_research::IntervalVar*> intervals;
|
|
298
429
|
for (const auto& v : rb_intervals) {
|
|
299
430
|
intervals.push_back(Rice::detail::From_Ruby<operations_research::IntervalVar*>().convert(v.value()));
|
|
@@ -302,18 +433,64 @@ void init_routing(Rice::Module& m) {
|
|
|
302
433
|
});
|
|
303
434
|
|
|
304
435
|
Rice::define_class_under<ConstraintSolverParameters>(m, "ConstraintSolverParameters")
|
|
305
|
-
.define_method(
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
.define_method(
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
436
|
+
.define_method("array_split_size", &ConstraintSolverParameters::array_split_size)
|
|
437
|
+
.define_method("array_split_size=", &ConstraintSolverParameters::set_array_split_size)
|
|
438
|
+
.define_method("check_solution_period", &ConstraintSolverParameters::check_solution_period)
|
|
439
|
+
.define_method("check_solution_period=", &ConstraintSolverParameters::set_check_solution_period)
|
|
440
|
+
.define_method("diffn_use_cumulative", &ConstraintSolverParameters::diffn_use_cumulative)
|
|
441
|
+
.define_method("diffn_use_cumulative=", &ConstraintSolverParameters::set_diffn_use_cumulative)
|
|
442
|
+
.define_method("disable_solve", &ConstraintSolverParameters::disable_solve)
|
|
443
|
+
.define_method("disable_solve=", &ConstraintSolverParameters::set_disable_solve)
|
|
444
|
+
.define_method("max_edge_finder_size", &ConstraintSolverParameters::max_edge_finder_size)
|
|
445
|
+
.define_method("max_edge_finder_size=", &ConstraintSolverParameters::set_max_edge_finder_size)
|
|
446
|
+
.define_method("name_all_variables", &ConstraintSolverParameters::name_all_variables)
|
|
447
|
+
.define_method("name_all_variables=", &ConstraintSolverParameters::set_name_all_variables)
|
|
448
|
+
.define_method("name_cast_variables", &ConstraintSolverParameters::name_cast_variables)
|
|
449
|
+
.define_method("name_cast_variables=", &ConstraintSolverParameters::set_name_cast_variables)
|
|
450
|
+
.define_method("print_added_constraints", &ConstraintSolverParameters::print_added_constraints)
|
|
451
|
+
.define_method("print_added_constraints=", &ConstraintSolverParameters::set_print_added_constraints)
|
|
452
|
+
.define_method("print_local_search_profile", &ConstraintSolverParameters::print_local_search_profile)
|
|
453
|
+
.define_method("print_local_search_profile=", &ConstraintSolverParameters::set_print_local_search_profile)
|
|
454
|
+
.define_method("print_model", &ConstraintSolverParameters::print_model)
|
|
455
|
+
.define_method("print_model=", &ConstraintSolverParameters::set_print_model)
|
|
456
|
+
.define_method("print_model_stats", &ConstraintSolverParameters::print_model_stats)
|
|
457
|
+
.define_method("print_model_stats=", &ConstraintSolverParameters::set_print_model_stats)
|
|
458
|
+
.define_method("profile_file", &ConstraintSolverParameters::profile_file)
|
|
459
|
+
// .define_method("profile_file=", &ConstraintSolverParameters::set_profile_file)
|
|
460
|
+
.define_method("profile_local_search", &ConstraintSolverParameters::profile_local_search)
|
|
461
|
+
.define_method("profile_local_search=", &ConstraintSolverParameters::set_profile_local_search)
|
|
462
|
+
.define_method("profile_propagation", &ConstraintSolverParameters::profile_propagation)
|
|
463
|
+
.define_method("profile_propagation=", &ConstraintSolverParameters::set_profile_propagation)
|
|
464
|
+
.define_method("skip_locally_optimal_paths", &ConstraintSolverParameters::skip_locally_optimal_paths)
|
|
465
|
+
.define_method("skip_locally_optimal_paths=", &ConstraintSolverParameters::set_skip_locally_optimal_paths)
|
|
466
|
+
.define_method("store_names", &ConstraintSolverParameters::store_names)
|
|
467
|
+
.define_method("store_names=", &ConstraintSolverParameters::set_store_names)
|
|
468
|
+
.define_method("trace_propagation", &ConstraintSolverParameters::trace_propagation)
|
|
469
|
+
.define_method("trace_propagation=", &ConstraintSolverParameters::set_trace_propagation)
|
|
470
|
+
.define_method("trace_search", &ConstraintSolverParameters::trace_search)
|
|
471
|
+
.define_method("trace_search=", &ConstraintSolverParameters::set_trace_search)
|
|
472
|
+
.define_method("trail_block_size", &ConstraintSolverParameters::trail_block_size)
|
|
473
|
+
.define_method("trail_block_size=", &ConstraintSolverParameters::set_trail_block_size)
|
|
474
|
+
.define_method("use_all_possible_disjunctions", &ConstraintSolverParameters::use_all_possible_disjunctions)
|
|
475
|
+
.define_method("use_all_possible_disjunctions=", &ConstraintSolverParameters::set_use_all_possible_disjunctions)
|
|
476
|
+
.define_method("use_cumulative_edge_finder", &ConstraintSolverParameters::use_cumulative_edge_finder)
|
|
477
|
+
.define_method("use_cumulative_edge_finder=", &ConstraintSolverParameters::set_use_cumulative_edge_finder)
|
|
478
|
+
.define_method("use_cumulative_time_table", &ConstraintSolverParameters::use_cumulative_time_table)
|
|
479
|
+
.define_method("use_cumulative_time_table=", &ConstraintSolverParameters::set_use_cumulative_time_table)
|
|
480
|
+
.define_method("use_cumulative_time_table_sync", &ConstraintSolverParameters::use_cumulative_time_table_sync)
|
|
481
|
+
.define_method("use_cumulative_time_table_sync=", &ConstraintSolverParameters::set_use_cumulative_time_table_sync)
|
|
482
|
+
.define_method("use_element_rmq", &ConstraintSolverParameters::use_element_rmq)
|
|
483
|
+
.define_method("use_element_rmq=", &ConstraintSolverParameters::set_use_element_rmq)
|
|
484
|
+
.define_method("use_sequence_high_demand_tasks", &ConstraintSolverParameters::use_sequence_high_demand_tasks)
|
|
485
|
+
.define_method("use_sequence_high_demand_tasks=", &ConstraintSolverParameters::set_use_sequence_high_demand_tasks)
|
|
486
|
+
.define_method("use_small_table", &ConstraintSolverParameters::use_small_table)
|
|
487
|
+
.define_method("use_small_table=", &ConstraintSolverParameters::set_use_small_table);
|
|
315
488
|
|
|
316
489
|
Rice::define_class_under<RoutingModelParameters>(m, "RoutingModelParameters")
|
|
490
|
+
.define_method("reduce_vehicle_cost_model", &RoutingModelParameters::reduce_vehicle_cost_model)
|
|
491
|
+
.define_method("reduce_vehicle_cost_model=", &RoutingModelParameters::set_reduce_vehicle_cost_model)
|
|
492
|
+
.define_method("max_callback_cache_size", &RoutingModelParameters::max_callback_cache_size)
|
|
493
|
+
.define_method("max_callback_cache_size=", &RoutingModelParameters::set_max_callback_cache_size)
|
|
317
494
|
.define_method(
|
|
318
495
|
"solver_parameters",
|
|
319
496
|
[](RoutingModelParameters& self) {
|
|
@@ -332,13 +509,13 @@ void init_routing(Rice::Module& m) {
|
|
|
332
509
|
.define_constructor(Rice::Constructor<RoutingModel, RoutingIndexManager, RoutingModelParameters>(), Rice::Arg("_index_manager"), Rice::Arg("_parameters") = operations_research::DefaultRoutingModelParameters())
|
|
333
510
|
.define_method("register_unary_transit_vector", &RoutingModel::RegisterUnaryTransitVector)
|
|
334
511
|
.define_method(
|
|
335
|
-
"
|
|
512
|
+
"_register_unary_transit_callback",
|
|
336
513
|
[](RoutingModel& self, Object callback) {
|
|
337
514
|
// TODO guard callback?
|
|
338
515
|
return self.RegisterUnaryTransitCallback(
|
|
339
516
|
[callback](int64_t from_index) -> int64_t {
|
|
340
517
|
if (!ruby_native_thread_p()) {
|
|
341
|
-
throw std::runtime_error
|
|
518
|
+
throw std::runtime_error{"Non-Ruby thread"};
|
|
342
519
|
}
|
|
343
520
|
|
|
344
521
|
return Rice::detail::From_Ruby<int64_t>().convert(callback.call("call", from_index));
|
|
@@ -347,13 +524,13 @@ void init_routing(Rice::Module& m) {
|
|
|
347
524
|
}, Rice::Arg("_callback").keepAlive())
|
|
348
525
|
.define_method("register_transit_matrix", &RoutingModel::RegisterTransitMatrix)
|
|
349
526
|
.define_method(
|
|
350
|
-
"
|
|
527
|
+
"_register_transit_callback",
|
|
351
528
|
[](RoutingModel& self, Object callback) {
|
|
352
529
|
// TODO guard callback?
|
|
353
530
|
return self.RegisterTransitCallback(
|
|
354
531
|
[callback](int64_t from_index, int64_t to_index) -> int64_t {
|
|
355
532
|
if (!ruby_native_thread_p()) {
|
|
356
|
-
throw std::runtime_error
|
|
533
|
+
throw std::runtime_error{"Non-Ruby thread"};
|
|
357
534
|
}
|
|
358
535
|
|
|
359
536
|
return Rice::detail::From_Ruby<int64_t>().convert(callback.call("call", from_index, to_index));
|
|
@@ -386,7 +563,11 @@ void init_routing(Rice::Module& m) {
|
|
|
386
563
|
.define_method("perfect_binary_disjunctions", &RoutingModel::GetPerfectBinaryDisjunctions)
|
|
387
564
|
.define_method("ignore_disjunctions_already_forced_to_zero", &RoutingModel::IgnoreDisjunctionsAlreadyForcedToZero)
|
|
388
565
|
.define_method("add_soft_same_vehicle_constraint", &RoutingModel::AddSoftSameVehicleConstraint)
|
|
389
|
-
.define_method(
|
|
566
|
+
.define_method(
|
|
567
|
+
"set_allowed_vehicles_for_index",
|
|
568
|
+
[](RoutingModel& self, const std::vector<int>& vehicles, int64_t index) {
|
|
569
|
+
self.SetAllowedVehiclesForIndex(vehicles, index);
|
|
570
|
+
})
|
|
390
571
|
.define_method("vehicle_allowed_for_index?", &RoutingModel::IsVehicleAllowedForIndex)
|
|
391
572
|
.define_method("add_pickup_and_delivery", &RoutingModel::AddPickupAndDelivery)
|
|
392
573
|
.define_method("add_pickup_and_delivery_sets", &RoutingModel::AddPickupAndDeliverySets)
|
|
@@ -426,14 +607,26 @@ void init_routing(Rice::Module& m) {
|
|
|
426
607
|
.define_method("close_model", &RoutingModel::CloseModel)
|
|
427
608
|
// solve defined in Ruby
|
|
428
609
|
.define_method(
|
|
429
|
-
"
|
|
430
|
-
[](RoutingModel& self, const RoutingSearchParameters& search_parameters) {
|
|
431
|
-
|
|
610
|
+
"_solve_with_parameters",
|
|
611
|
+
[](RoutingModel& self, const RoutingSearchParameters& search_parameters, bool release_gvl) {
|
|
612
|
+
if (release_gvl) {
|
|
613
|
+
return Rice::detail::no_gvl([&]() {
|
|
614
|
+
return self.SolveWithParameters(search_parameters);
|
|
615
|
+
});
|
|
616
|
+
} else {
|
|
617
|
+
return self.SolveWithParameters(search_parameters);
|
|
618
|
+
}
|
|
432
619
|
})
|
|
433
620
|
.define_method(
|
|
434
|
-
"
|
|
435
|
-
[](RoutingModel& self, const Assignment
|
|
436
|
-
|
|
621
|
+
"_solve_from_assignment_with_parameters",
|
|
622
|
+
[](RoutingModel& self, const Assignment& assignment, const RoutingSearchParameters& search_parameters, bool release_gvl) {
|
|
623
|
+
if (release_gvl) {
|
|
624
|
+
return Rice::detail::no_gvl([&]() {
|
|
625
|
+
return self.SolveFromAssignmentWithParameters(&assignment, search_parameters);
|
|
626
|
+
});
|
|
627
|
+
} else {
|
|
628
|
+
return self.SolveFromAssignmentWithParameters(&assignment, search_parameters);
|
|
629
|
+
}
|
|
437
630
|
})
|
|
438
631
|
.define_method("compute_lower_bound", &RoutingModel::ComputeLowerBound)
|
|
439
632
|
.define_method("status",
|
|
@@ -451,17 +644,31 @@ void init_routing(Rice::Module& m) {
|
|
|
451
644
|
} else if (status == RoutingSearchStatus::ROUTING_INVALID) {
|
|
452
645
|
return Symbol("invalid");
|
|
453
646
|
} else {
|
|
454
|
-
throw std::runtime_error
|
|
647
|
+
throw std::runtime_error{"Unknown solver status"};
|
|
455
648
|
}
|
|
456
649
|
})
|
|
457
|
-
.define_method(
|
|
650
|
+
.define_method(
|
|
651
|
+
"apply_locks",
|
|
652
|
+
[](RoutingModel& self, const std::vector<int64_t>& locks) {
|
|
653
|
+
return self.ApplyLocks(locks);
|
|
654
|
+
})
|
|
458
655
|
.define_method("apply_locks_to_all_vehicles", &RoutingModel::ApplyLocksToAllVehicles)
|
|
459
656
|
.define_method("pre_assignment", &RoutingModel::PreAssignment)
|
|
460
657
|
.define_method("mutable_pre_assignment", &RoutingModel::MutablePreAssignment)
|
|
461
658
|
.define_method("write_assignment", &RoutingModel::WriteAssignment)
|
|
462
659
|
.define_method("read_assignment", &RoutingModel::ReadAssignment)
|
|
463
660
|
.define_method("restore_assignment", &RoutingModel::RestoreAssignment)
|
|
464
|
-
.define_method(
|
|
661
|
+
.define_method(
|
|
662
|
+
"_read_assignment_from_routes",
|
|
663
|
+
[](RoutingModel& self, const std::vector<std::vector<int64_t>>& routes, bool ignore_inactive_indices, bool release_gvl) {
|
|
664
|
+
if (release_gvl) {
|
|
665
|
+
return Rice::detail::no_gvl([&]() {
|
|
666
|
+
return self.ReadAssignmentFromRoutes(routes, ignore_inactive_indices);
|
|
667
|
+
});
|
|
668
|
+
} else {
|
|
669
|
+
return self.ReadAssignmentFromRoutes(routes, ignore_inactive_indices);
|
|
670
|
+
}
|
|
671
|
+
})
|
|
465
672
|
.define_method("routes_to_assignment", &RoutingModel::RoutesToAssignment)
|
|
466
673
|
.define_method("assignment_to_routes", &RoutingModel::AssignmentToRoutes)
|
|
467
674
|
.define_method("compact_assignment", &RoutingModel::CompactAssignment)
|
data/ext/or-tools/vendor.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require "digest"
|
|
2
2
|
require "fileutils"
|
|
3
|
-
require "
|
|
3
|
+
require "open-uri"
|
|
4
4
|
require "tmpdir"
|
|
5
5
|
|
|
6
6
|
version = "9.15.6755"
|
|
@@ -70,62 +70,31 @@ end
|
|
|
70
70
|
short_version = version.split(".").first(2).join(".")
|
|
71
71
|
url = "https://github.com/google/or-tools/releases/download/v#{short_version}/#{filename}"
|
|
72
72
|
|
|
73
|
-
$stdout.sync = true
|
|
74
|
-
|
|
75
|
-
def download_file(url, download_path, redirects = 0)
|
|
76
|
-
raise "Too many redirects" if redirects > 10
|
|
77
|
-
|
|
78
|
-
uri = URI(url)
|
|
79
|
-
location = nil
|
|
80
|
-
|
|
81
|
-
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
|
82
|
-
request = Net::HTTP::Get.new(uri)
|
|
83
|
-
http.request(request) do |response|
|
|
84
|
-
case response
|
|
85
|
-
when Net::HTTPRedirection
|
|
86
|
-
location = response["location"]
|
|
87
|
-
when Net::HTTPSuccess
|
|
88
|
-
i = 0
|
|
89
|
-
File.open(download_path, "wb") do |f|
|
|
90
|
-
response.read_body do |chunk|
|
|
91
|
-
f.write(chunk)
|
|
92
|
-
|
|
93
|
-
# print progress
|
|
94
|
-
putc "." if i % 50 == 0
|
|
95
|
-
i += 1
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
puts # newline
|
|
99
|
-
else
|
|
100
|
-
raise "Bad response"
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# outside of Net::HTTP block to close previous connection
|
|
106
|
-
download_file(location, download_path, redirects + 1) if location
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# download
|
|
110
|
-
download_path = "#{Dir.tmpdir}/#{filename}"
|
|
111
|
-
unless File.exist?(download_path)
|
|
112
|
-
puts "Downloading #{url}..."
|
|
113
|
-
download_file(url, download_path)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
# check integrity - do this regardless of if just downloaded
|
|
117
|
-
download_checksum = Digest::SHA256.file(download_path).hexdigest
|
|
118
|
-
raise "Bad checksum: #{download_checksum}" if download_checksum != checksum
|
|
119
|
-
|
|
120
73
|
path = File.expand_path("../../tmp/or-tools", __dir__)
|
|
121
74
|
FileUtils.mkdir_p(path)
|
|
122
75
|
|
|
123
|
-
# extract - can't use Gem::Package#extract_tar_gz from RubyGems
|
|
124
|
-
# since it limits filenames to 100 characters (doesn't support UStar format)
|
|
125
|
-
# for space, only keep licenses, include, and shared library
|
|
126
76
|
Dir.mktmpdir do |extract_path|
|
|
127
|
-
|
|
128
|
-
|
|
77
|
+
# download
|
|
78
|
+
puts "Downloading #{url}..."
|
|
79
|
+
URI.parse(url).open(max_redirects: 10) do |download|
|
|
80
|
+
download_checksum =
|
|
81
|
+
if download.respond_to?(:path)
|
|
82
|
+
download.flush
|
|
83
|
+
Digest::SHA256.file(download.path).hexdigest
|
|
84
|
+
else
|
|
85
|
+
Digest::SHA256.hexdigest(download.string)
|
|
86
|
+
end
|
|
87
|
+
raise "Bad checksum: #{download_checksum}" if download_checksum != checksum
|
|
88
|
+
|
|
89
|
+
# should never happen
|
|
90
|
+
raise "Expected file" if !download.respond_to?(:path)
|
|
91
|
+
|
|
92
|
+
# extract - can't use Gem::Package#extract_tar_gz from RubyGems
|
|
93
|
+
# since it limits filenames to 100 characters (doesn't support UStar format)
|
|
94
|
+
# for space, only keep licenses, include, and shared library
|
|
95
|
+
tar_args = Gem.win_platform? ? ["--force-local"] : []
|
|
96
|
+
system "tar", "zxf", download.path, "-C", extract_path, "--strip-components=1", *tar_args
|
|
97
|
+
end
|
|
129
98
|
|
|
130
99
|
# include
|
|
131
100
|
FileUtils.mv(File.join(extract_path, "include"), File.join(path, "include"))
|
data/lib/or_tools/cp_solver.rb
CHANGED
|
@@ -8,6 +8,7 @@ module ORTools
|
|
|
8
8
|
|
|
9
9
|
def solve(model, observer = nil)
|
|
10
10
|
@response = _solve(model, parameters, observer)
|
|
11
|
+
observer.response = @response if observer
|
|
11
12
|
@response.status
|
|
12
13
|
end
|
|
13
14
|
|
|
@@ -25,22 +26,6 @@ module ORTools
|
|
|
25
26
|
end
|
|
26
27
|
end
|
|
27
28
|
|
|
28
|
-
def solve_with_solution_callback(model, observer)
|
|
29
|
-
warn "[or-tools] solve_with_solution_callback is deprecated; use solve(model, callback)"
|
|
30
|
-
solve(model, observer)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def search_for_all_solutions(model, observer)
|
|
34
|
-
warn "[or-tools] search_for_all_solutions is deprecated; use solve() with solver.parameters.enumerate_all_solutions = true"
|
|
35
|
-
previous_value = parameters.enumerate_all_solutions
|
|
36
|
-
begin
|
|
37
|
-
parameters.enumerate_all_solutions = true
|
|
38
|
-
solve(model, observer)
|
|
39
|
-
ensure
|
|
40
|
-
parameters.enumerate_all_solutions = previous_value
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
29
|
def solution_info
|
|
45
30
|
@response.solution_info
|
|
46
31
|
end
|
|
@@ -21,5 +21,27 @@ module ORTools
|
|
|
21
21
|
def add_disjunction(indices, penalty, max_cardinality = 1, penalty_cost_behavior = :penalize_once)
|
|
22
22
|
_add_disjunction(indices, penalty, max_cardinality, penalty_cost_behavior)
|
|
23
23
|
end
|
|
24
|
+
|
|
25
|
+
def solve_with_parameters(search_parameters)
|
|
26
|
+
_solve_with_parameters(search_parameters, !@ruby_callback)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def solve_from_assignment_with_parameters(assignment, search_parameters)
|
|
30
|
+
_solve_from_assignment_with_parameters(assignment, search_parameters, !@ruby_callback)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def read_assignment_from_routes(routes, ignore_inactive_indices)
|
|
34
|
+
_read_assignment_from_routes(routes, ignore_inactive_indices, !@ruby_callback)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def register_unary_transit_callback(callback)
|
|
38
|
+
@ruby_callback = true
|
|
39
|
+
_register_unary_transit_callback(callback)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def register_transit_callback(callback)
|
|
43
|
+
@ruby_callback = true
|
|
44
|
+
_register_transit_callback(callback)
|
|
45
|
+
end
|
|
24
46
|
end
|
|
25
47
|
end
|