or-tools 0.4.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ #pragma once
2
+
3
+ #include <rice/rice.hpp>
4
+ #include <rice/stl.hpp>
@@ -1,8 +1,6 @@
1
1
  require "mkmf-rice"
2
2
 
3
- raise "Missing stdc++" unless have_library("stdc++")
4
-
5
- $CXXFLAGS << " -std=c++17 -DUSE_CBC"
3
+ $CXXFLAGS << " -std=c++17 $(optflags) -DUSE_CBC"
6
4
 
7
5
  # or-tools warnings
8
6
  $CXXFLAGS << " -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-ignored-qualifiers"
@@ -0,0 +1,201 @@
1
+ #include <ortools/linear_solver/linear_solver.h>
2
+
3
+ #include "ext.h"
4
+
5
+ using operations_research::LinearExpr;
6
+ using operations_research::LinearRange;
7
+ using operations_research::MPConstraint;
8
+ using operations_research::MPObjective;
9
+ using operations_research::MPSolver;
10
+ using operations_research::MPVariable;
11
+
12
+ using Rice::Array;
13
+ using Rice::Class;
14
+ using Rice::Module;
15
+ using Rice::Object;
16
+ using Rice::String;
17
+ using Rice::Symbol;
18
+
19
+ namespace Rice::detail
20
+ {
21
+ template<>
22
+ struct Type<MPSolver::OptimizationProblemType>
23
+ {
24
+ static bool verify()
25
+ {
26
+ return true;
27
+ }
28
+ };
29
+
30
+ template<>
31
+ struct From_Ruby<MPSolver::OptimizationProblemType>
32
+ {
33
+ static MPSolver::OptimizationProblemType convert(VALUE x)
34
+ {
35
+ auto s = Symbol(x).str();
36
+ if (s == "glop") {
37
+ return MPSolver::OptimizationProblemType::GLOP_LINEAR_PROGRAMMING;
38
+ } else if (s == "cbc") {
39
+ return MPSolver::OptimizationProblemType::CBC_MIXED_INTEGER_PROGRAMMING;
40
+ } else {
41
+ throw std::runtime_error("Unknown optimization problem type: " + s);
42
+ }
43
+ }
44
+ };
45
+ }
46
+
47
+ void init_linear(Rice::Module& m) {
48
+ Rice::define_class_under<LinearRange>(m, "LinearRange");
49
+ auto rb_cLinearExpr = Rice::define_class_under<LinearExpr>(m, "LinearExpr");
50
+
51
+ Rice::define_class_under<MPVariable>(m, "MPVariable")
52
+ .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
+ });
129
+
130
+ Rice::define_class_under<MPConstraint>(m, "MPConstraint")
131
+ .define_method("set_coefficient", &MPConstraint::SetCoefficient);
132
+
133
+ Rice::define_class_under<MPObjective>(m, "MPObjective")
134
+ .define_method("value", &MPObjective::Value)
135
+ .define_method("set_coefficient", &MPObjective::SetCoefficient)
136
+ .define_method("set_maximization", &MPObjective::SetMaximization);
137
+
138
+ Rice::define_class_under<MPSolver>(m, "Solver")
139
+ .define_constructor(Rice::Constructor<MPSolver, std::string, MPSolver::OptimizationProblemType>())
140
+ .define_method(
141
+ "infinity",
142
+ [](MPSolver& self) {
143
+ return self.infinity();
144
+ })
145
+ .define_method(
146
+ "int_var",
147
+ [](MPSolver& self, double min, double max, const std::string& name) {
148
+ return self.MakeIntVar(min, max, name);
149
+ })
150
+ .define_method("num_var", &MPSolver::MakeNumVar)
151
+ .define_method("bool_var", &MPSolver::MakeBoolVar)
152
+ .define_method("num_variables", &MPSolver::NumVariables)
153
+ .define_method("num_constraints", &MPSolver::NumConstraints)
154
+ .define_method("wall_time", &MPSolver::wall_time)
155
+ .define_method("iterations", &MPSolver::iterations)
156
+ .define_method("nodes", &MPSolver::nodes)
157
+ .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
+ .define_method(
174
+ "constraint",
175
+ [](MPSolver& self, double lb, double ub) {
176
+ return self.MakeRowConstraint(lb, ub);
177
+ })
178
+ .define_method(
179
+ "solve",
180
+ [](MPSolver& self) {
181
+ auto status = self.Solve();
182
+
183
+ if (status == MPSolver::ResultStatus::OPTIMAL) {
184
+ return Symbol("optimal");
185
+ } else if (status == MPSolver::ResultStatus::FEASIBLE) {
186
+ return Symbol("feasible");
187
+ } else if (status == MPSolver::ResultStatus::INFEASIBLE) {
188
+ return Symbol("infeasible");
189
+ } else if (status == MPSolver::ResultStatus::UNBOUNDED) {
190
+ return Symbol("unbounded");
191
+ } else if (status == MPSolver::ResultStatus::ABNORMAL) {
192
+ return Symbol("abnormal");
193
+ } else if (status == MPSolver::ResultStatus::MODEL_INVALID) {
194
+ return Symbol("model_invalid");
195
+ } else if (status == MPSolver::ResultStatus::NOT_SOLVED) {
196
+ return Symbol("not_solved");
197
+ } else {
198
+ throw std::runtime_error("Unknown status");
199
+ }
200
+ });
201
+ }
@@ -0,0 +1,103 @@
1
+ #include <ortools/graph/max_flow.h>
2
+ #include <ortools/graph/min_cost_flow.h>
3
+
4
+ #include "ext.h"
5
+
6
+ using operations_research::NodeIndex;
7
+ using operations_research::SimpleMaxFlow;
8
+ using operations_research::SimpleMinCostFlow;
9
+
10
+ using Rice::Array;
11
+ using Rice::Symbol;
12
+
13
+ void init_network_flows(Rice::Module& m) {
14
+ Rice::define_class_under<SimpleMaxFlow>(m, "SimpleMaxFlow")
15
+ .define_constructor(Rice::Constructor<SimpleMaxFlow>())
16
+ .define_method("add_arc_with_capacity", &SimpleMaxFlow::AddArcWithCapacity)
17
+ .define_method("num_nodes", &SimpleMaxFlow::NumNodes)
18
+ .define_method("num_arcs", &SimpleMaxFlow::NumArcs)
19
+ .define_method("tail", &SimpleMaxFlow::Tail)
20
+ .define_method("head", &SimpleMaxFlow::Head)
21
+ .define_method("capacity", &SimpleMaxFlow::Capacity)
22
+ .define_method("optimal_flow", &SimpleMaxFlow::OptimalFlow)
23
+ .define_method("flow", &SimpleMaxFlow::Flow)
24
+ .define_method(
25
+ "solve",
26
+ [](SimpleMaxFlow& self, NodeIndex source, NodeIndex sink) {
27
+ auto status = self.Solve(source, sink);
28
+
29
+ if (status == SimpleMaxFlow::Status::OPTIMAL) {
30
+ return Symbol("optimal");
31
+ } else if (status == SimpleMaxFlow::Status::POSSIBLE_OVERFLOW) {
32
+ return Symbol("possible_overflow");
33
+ } else if (status == SimpleMaxFlow::Status::BAD_INPUT) {
34
+ return Symbol("bad_input");
35
+ } else if (status == SimpleMaxFlow::Status::BAD_RESULT) {
36
+ return Symbol("bad_result");
37
+ } else {
38
+ throw std::runtime_error("Unknown status");
39
+ }
40
+ })
41
+ .define_method(
42
+ "source_side_min_cut",
43
+ [](SimpleMaxFlow& self) {
44
+ std::vector<NodeIndex> result;
45
+ self.GetSourceSideMinCut(&result);
46
+
47
+ Array ret;
48
+ for (const auto& it : result) {
49
+ ret.push(it);
50
+ }
51
+ return ret;
52
+ })
53
+ .define_method(
54
+ "sink_side_min_cut",
55
+ [](SimpleMaxFlow& self) {
56
+ std::vector<NodeIndex> result;
57
+ self.GetSinkSideMinCut(&result);
58
+
59
+ Array ret;
60
+ for (const auto& it : result) {
61
+ ret.push(it);
62
+ }
63
+ return ret;
64
+ });
65
+
66
+ Rice::define_class_under<SimpleMinCostFlow>(m, "SimpleMinCostFlow")
67
+ .define_constructor(Rice::Constructor<SimpleMinCostFlow>())
68
+ .define_method("add_arc_with_capacity_and_unit_cost", &SimpleMinCostFlow::AddArcWithCapacityAndUnitCost)
69
+ .define_method("set_node_supply", &SimpleMinCostFlow::SetNodeSupply)
70
+ .define_method("optimal_cost", &SimpleMinCostFlow::OptimalCost)
71
+ .define_method("maximum_flow", &SimpleMinCostFlow::MaximumFlow)
72
+ .define_method("flow", &SimpleMinCostFlow::Flow)
73
+ .define_method("num_nodes", &SimpleMinCostFlow::NumNodes)
74
+ .define_method("num_arcs", &SimpleMinCostFlow::NumArcs)
75
+ .define_method("tail", &SimpleMinCostFlow::Tail)
76
+ .define_method("head", &SimpleMinCostFlow::Head)
77
+ .define_method("capacity", &SimpleMinCostFlow::Capacity)
78
+ .define_method("supply", &SimpleMinCostFlow::Supply)
79
+ .define_method("unit_cost", &SimpleMinCostFlow::UnitCost)
80
+ .define_method(
81
+ "solve",
82
+ [](SimpleMinCostFlow& self) {
83
+ auto status = self.Solve();
84
+
85
+ if (status == SimpleMinCostFlow::Status::NOT_SOLVED) {
86
+ return Symbol("not_solved");
87
+ } else if (status == SimpleMinCostFlow::Status::OPTIMAL) {
88
+ return Symbol("optimal");
89
+ } else if (status == SimpleMinCostFlow::Status::FEASIBLE) {
90
+ return Symbol("feasible");
91
+ } else if (status == SimpleMinCostFlow::Status::INFEASIBLE) {
92
+ return Symbol("infeasible");
93
+ } else if (status == SimpleMinCostFlow::Status::UNBALANCED) {
94
+ return Symbol("unbalanced");
95
+ } else if (status == SimpleMinCostFlow::Status::BAD_RESULT) {
96
+ return Symbol("bad_result");
97
+ } else if (status == SimpleMinCostFlow::Status::BAD_COST_RANGE) {
98
+ return Symbol("bad_cost_range");
99
+ } else {
100
+ throw std::runtime_error("Unknown status");
101
+ }
102
+ });
103
+ }
@@ -0,0 +1,291 @@
1
+ #include <ortools/constraint_solver/routing.h>
2
+ #include <ortools/constraint_solver/routing_parameters.h>
3
+
4
+ #include "ext.h"
5
+
6
+ using operations_research::Assignment;
7
+ using operations_research::DefaultRoutingSearchParameters;
8
+ using operations_research::FirstSolutionStrategy;
9
+ using operations_research::LocalSearchMetaheuristic;
10
+ using operations_research::RoutingDimension;
11
+ using operations_research::RoutingIndexManager;
12
+ using operations_research::RoutingModel;
13
+ using operations_research::RoutingNodeIndex;
14
+ using operations_research::RoutingSearchParameters;
15
+
16
+ using Rice::Array;
17
+ using Rice::Class;
18
+ using Rice::Module;
19
+ using Rice::Object;
20
+ using Rice::String;
21
+ using Rice::Symbol;
22
+
23
+ namespace Rice::detail
24
+ {
25
+ template<>
26
+ struct Type<RoutingNodeIndex>
27
+ {
28
+ static bool verify()
29
+ {
30
+ return true;
31
+ }
32
+ };
33
+
34
+ template<>
35
+ class From_Ruby<RoutingNodeIndex>
36
+ {
37
+ public:
38
+ RoutingNodeIndex convert(VALUE x)
39
+ {
40
+ const RoutingNodeIndex index{From_Ruby<int>().convert(x)};
41
+ return index;
42
+ }
43
+ };
44
+
45
+ template<>
46
+ class To_Ruby<RoutingNodeIndex>
47
+ {
48
+ public:
49
+ VALUE convert(RoutingNodeIndex const & x)
50
+ {
51
+ return To_Ruby<int>().convert(x.value());
52
+ }
53
+ };
54
+ }
55
+
56
+ void init_routing(Rice::Module& m) {
57
+ auto rb_cRoutingSearchParameters = Rice::define_class_under<RoutingSearchParameters>(m, "RoutingSearchParameters");
58
+ auto rb_cIntVar = Rice::define_class_under<operations_research::IntVar>(m, "IntVar");
59
+
60
+ m.define_singleton_function("default_routing_search_parameters", &DefaultRoutingSearchParameters);
61
+
62
+ rb_cRoutingSearchParameters
63
+ .define_method(
64
+ "first_solution_strategy=",
65
+ [](RoutingSearchParameters& self, Symbol value) {
66
+ auto s = Symbol(value).str();
67
+
68
+ FirstSolutionStrategy::Value v;
69
+ if (s == "path_cheapest_arc") {
70
+ v = FirstSolutionStrategy::PATH_CHEAPEST_ARC;
71
+ } else if (s == "path_most_constrained_arc") {
72
+ v = FirstSolutionStrategy::PATH_MOST_CONSTRAINED_ARC;
73
+ } else if (s == "evaluator_strategy") {
74
+ v = FirstSolutionStrategy::EVALUATOR_STRATEGY;
75
+ } else if (s == "savings") {
76
+ v = FirstSolutionStrategy::SAVINGS;
77
+ } else if (s == "sweep") {
78
+ v = FirstSolutionStrategy::SWEEP;
79
+ } else if (s == "christofides") {
80
+ v = FirstSolutionStrategy::CHRISTOFIDES;
81
+ } else if (s == "all_unperformed") {
82
+ v = FirstSolutionStrategy::ALL_UNPERFORMED;
83
+ } else if (s == "best_insertion") {
84
+ v = FirstSolutionStrategy::BEST_INSERTION;
85
+ } else if (s == "parallel_cheapest_insertion") {
86
+ v = FirstSolutionStrategy::PARALLEL_CHEAPEST_INSERTION;
87
+ } else if (s == "sequential_cheapest_insertion") {
88
+ v = FirstSolutionStrategy::SEQUENTIAL_CHEAPEST_INSERTION;
89
+ } else if (s == "local_cheapest_insertion") {
90
+ v = FirstSolutionStrategy::LOCAL_CHEAPEST_INSERTION;
91
+ } else if (s == "global_cheapest_arc") {
92
+ v = FirstSolutionStrategy::GLOBAL_CHEAPEST_ARC;
93
+ } else if (s == "local_cheapest_arc") {
94
+ v = FirstSolutionStrategy::LOCAL_CHEAPEST_ARC;
95
+ } else if (s == "first_unbound_min_value") {
96
+ v = FirstSolutionStrategy::FIRST_UNBOUND_MIN_VALUE;
97
+ } else {
98
+ throw std::runtime_error("Unknown first solution strategy: " + s);
99
+ }
100
+
101
+ return self.set_first_solution_strategy(v);
102
+ })
103
+ .define_method(
104
+ "local_search_metaheuristic=",
105
+ [](RoutingSearchParameters& self, Symbol value) {
106
+ auto s = Symbol(value).str();
107
+
108
+ LocalSearchMetaheuristic::Value v;
109
+ if (s == "guided_local_search") {
110
+ v = LocalSearchMetaheuristic::GUIDED_LOCAL_SEARCH;
111
+ } else if (s == "tabu_search") {
112
+ v = LocalSearchMetaheuristic::TABU_SEARCH;
113
+ } else if (s == "generic_tabu_search") {
114
+ v = LocalSearchMetaheuristic::GENERIC_TABU_SEARCH;
115
+ } else if (s == "simulated_annealing") {
116
+ v = LocalSearchMetaheuristic::SIMULATED_ANNEALING;
117
+ } else {
118
+ throw std::runtime_error("Unknown local search metaheuristic: " + s);
119
+ }
120
+
121
+ return self.set_local_search_metaheuristic(v);
122
+ })
123
+ .define_method(
124
+ "log_search=",
125
+ [](RoutingSearchParameters& self, bool value) {
126
+ self.set_log_search(value);
127
+ })
128
+ .define_method(
129
+ "solution_limit=",
130
+ [](RoutingSearchParameters& self, int64_t value) {
131
+ self.set_solution_limit(value);
132
+ })
133
+ .define_method(
134
+ "time_limit=",
135
+ [](RoutingSearchParameters& self, int64_t value) {
136
+ self.mutable_time_limit()->set_seconds(value);
137
+ })
138
+ .define_method(
139
+ "lns_time_limit=",
140
+ [](RoutingSearchParameters& self, int64_t value) {
141
+ self.mutable_lns_time_limit()->set_seconds(value);
142
+ });
143
+
144
+ Rice::define_class_under<RoutingIndexManager>(m, "RoutingIndexManager")
145
+ .define_singleton_function(
146
+ "_new_depot",
147
+ [](int num_nodes, int num_vehicles, RoutingNodeIndex depot) {
148
+ return RoutingIndexManager(num_nodes, num_vehicles, depot);
149
+ })
150
+ .define_singleton_function(
151
+ "_new_starts_ends",
152
+ [](int num_nodes, int num_vehicles, std::vector<RoutingNodeIndex> starts, std::vector<RoutingNodeIndex> ends) {
153
+ return RoutingIndexManager(num_nodes, num_vehicles, starts, ends);
154
+ })
155
+ .define_method("index_to_node", &RoutingIndexManager::IndexToNode)
156
+ .define_method("node_to_index", &RoutingIndexManager::NodeToIndex);
157
+
158
+ Rice::define_class_under<Assignment>(m, "Assignment")
159
+ .define_method("objective_value", &Assignment::ObjectiveValue)
160
+ .define_method("value", &Assignment::Value)
161
+ .define_method("min", &Assignment::Min)
162
+ .define_method("max", &Assignment::Max);
163
+
164
+ // not to be confused with operations_research::sat::IntVar
165
+ rb_cIntVar
166
+ .define_method(
167
+ "set_range",
168
+ [](operations_research::IntVar& self, int64_t new_min, int64_t new_max) {
169
+ self.SetRange(new_min, new_max);
170
+ });
171
+
172
+ Rice::define_class_under<operations_research::IntervalVar>(m, "IntervalVar");
173
+
174
+ Rice::define_class_under<RoutingDimension>(m, "RoutingDimension")
175
+ .define_method("global_span_cost_coefficient=", &RoutingDimension::SetGlobalSpanCostCoefficient)
176
+ .define_method("cumul_var", &RoutingDimension::CumulVar);
177
+
178
+ Rice::define_class_under<operations_research::Constraint>(m, "Constraint");
179
+
180
+ Rice::define_class_under<operations_research::Solver>(m, "Solver2")
181
+ .define_method(
182
+ "add",
183
+ [](operations_research::Solver& self, Object o) {
184
+ operations_research::Constraint* constraint;
185
+ if (o.respond_to("left")) {
186
+ operations_research::IntExpr* left(Rice::detail::From_Ruby<operations_research::IntVar*>().convert(o.call("left")));
187
+ operations_research::IntExpr* right(Rice::detail::From_Ruby<operations_research::IntVar*>().convert(o.call("right")));
188
+ auto op = o.call("operator").to_s().str();
189
+ if (op == "==") {
190
+ constraint = self.MakeEquality(left, right);
191
+ } else if (op == "<=") {
192
+ constraint = self.MakeLessOrEqual(left, right);
193
+ } else {
194
+ throw std::runtime_error("Unknown operator");
195
+ }
196
+ } else {
197
+ constraint = Rice::detail::From_Ruby<operations_research::Constraint*>().convert(o);
198
+ }
199
+ self.AddConstraint(constraint);
200
+ })
201
+ .define_method(
202
+ "fixed_duration_interval_var",
203
+ [](operations_research::Solver& self, operations_research::IntVar* const start_variable, int64_t duration, const std::string& name) {
204
+ return self.MakeFixedDurationIntervalVar(start_variable, duration, name);
205
+ })
206
+ .define_method(
207
+ "cumulative",
208
+ [](operations_research::Solver& self, std::vector<operations_research::IntervalVar*> intervals, std::vector<int64_t> demands, int64_t capacity, const std::string& name) {
209
+ return self.MakeCumulative(intervals, demands, capacity, name);
210
+ });
211
+
212
+ Rice::define_class_under<RoutingModel>(m, "RoutingModel")
213
+ .define_constructor(Rice::Constructor<RoutingModel, RoutingIndexManager>())
214
+ .define_method(
215
+ "register_transit_callback",
216
+ [](RoutingModel& self, Object callback) {
217
+ return self.RegisterTransitCallback(
218
+ [callback](int64_t from_index, int64_t to_index) -> int64_t {
219
+ return Rice::detail::From_Ruby<int64_t>().convert(callback.call("call", from_index, to_index));
220
+ }
221
+ );
222
+ })
223
+ .define_method(
224
+ "register_unary_transit_callback",
225
+ [](RoutingModel& self, Object callback) {
226
+ return self.RegisterUnaryTransitCallback(
227
+ [callback](int64_t from_index) -> int64_t {
228
+ return Rice::detail::From_Ruby<int64_t>().convert(callback.call("call", from_index));
229
+ }
230
+ );
231
+ })
232
+ .define_method("depot", &RoutingModel::GetDepot)
233
+ .define_method("size", &RoutingModel::Size)
234
+ .define_method("status", [](RoutingModel& self) {
235
+ auto status = self.status();
236
+
237
+ if (status == RoutingModel::ROUTING_NOT_SOLVED) {
238
+ return Symbol("not_solved");
239
+ } else if (status == RoutingModel::ROUTING_SUCCESS) {
240
+ return Symbol("success");
241
+ } else if (status == RoutingModel::ROUTING_FAIL) {
242
+ return Symbol("fail");
243
+ } else if (status == RoutingModel::ROUTING_FAIL_TIMEOUT) {
244
+ return Symbol("fail_timeout");
245
+ } else if (status == RoutingModel::ROUTING_INVALID) {
246
+ return Symbol("invalid");
247
+ } else {
248
+ throw std::runtime_error("Unknown solver status");
249
+ }
250
+ })
251
+ .define_method("vehicle_var", &RoutingModel::VehicleVar)
252
+ .define_method("set_arc_cost_evaluator_of_all_vehicles", &RoutingModel::SetArcCostEvaluatorOfAllVehicles)
253
+ .define_method("set_arc_cost_evaluator_of_vehicle", &RoutingModel::SetArcCostEvaluatorOfVehicle)
254
+ .define_method("set_fixed_cost_of_all_vehicles", &RoutingModel::SetFixedCostOfAllVehicles)
255
+ .define_method("set_fixed_cost_of_vehicle", &RoutingModel::SetFixedCostOfVehicle)
256
+ .define_method("fixed_cost_of_vehicle", &RoutingModel::GetFixedCostOfVehicle)
257
+ .define_method("add_dimension", &RoutingModel::AddDimension)
258
+ .define_method(
259
+ "add_dimension_with_vehicle_capacity",
260
+ [](RoutingModel& self, int evaluator_index, int64_t slack_max, std::vector<int64_t> vehicle_capacities, bool fix_start_cumul_to_zero, const std::string& name) {
261
+ self.AddDimensionWithVehicleCapacity(evaluator_index, slack_max, vehicle_capacities, fix_start_cumul_to_zero, name);
262
+ })
263
+ .define_method(
264
+ "add_dimension_with_vehicle_transits",
265
+ [](RoutingModel& self, std::vector<int> evaluator_indices, int64_t slack_max, int64_t capacity, bool fix_start_cumul_to_zero, const std::string& name) {
266
+ self.AddDimensionWithVehicleTransits(evaluator_indices, slack_max, capacity, fix_start_cumul_to_zero, name);
267
+ })
268
+ .define_method(
269
+ "add_disjunction",
270
+ [](RoutingModel& self, std::vector<int64_t> indices, int64_t penalty) {
271
+ self.AddDisjunction(indices, penalty);
272
+ })
273
+ .define_method("add_pickup_and_delivery", &RoutingModel::AddPickupAndDelivery)
274
+ .define_method("solver", &RoutingModel::solver)
275
+ .define_method("start", &RoutingModel::Start)
276
+ .define_method("end", &RoutingModel::End)
277
+ .define_method("start?", &RoutingModel::IsStart)
278
+ .define_method("end?", &RoutingModel::IsEnd)
279
+ .define_method("vehicle_index", &RoutingModel::VehicleIndex)
280
+ .define_method("next", &RoutingModel::Next)
281
+ .define_method("vehicle_used?", &RoutingModel::IsVehicleUsed)
282
+ .define_method("next_var", &RoutingModel::NextVar)
283
+ .define_method("arc_cost_for_vehicle", &RoutingModel::GetArcCostForVehicle)
284
+ .define_method("mutable_dimension", &RoutingModel::GetMutableDimension)
285
+ .define_method("add_variable_minimized_by_finalizer", &RoutingModel::AddVariableMinimizedByFinalizer)
286
+ .define_method(
287
+ "solve_with_parameters",
288
+ [](RoutingModel& self, const RoutingSearchParameters& search_parameters) {
289
+ return self.SolveWithParameters(search_parameters);
290
+ });
291
+ }