or-tools 0.4.0 → 0.5.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.
@@ -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
+ }