or-tools 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/or-tools/ext.cpp CHANGED
@@ -1,8 +1,12 @@
1
1
  // or-tools
2
- #include <ortools/sat/cp_model.h>
3
2
  #include <ortools/algorithms/knapsack_solver.h>
3
+ #include <ortools/constraint_solver/routing.h>
4
+ #include <ortools/constraint_solver/routing_parameters.h>
5
+ #include <ortools/graph/assignment.h>
4
6
  #include <ortools/graph/max_flow.h>
5
7
  #include <ortools/graph/min_cost_flow.h>
8
+ #include <ortools/linear_solver/linear_solver.h>
9
+ #include <ortools/sat/cp_model.h>
6
10
 
7
11
  // rice
8
12
  #include <rice/Array.hpp>
@@ -13,20 +17,36 @@
13
17
  #include <rice/Symbol.hpp>
14
18
 
15
19
  using operations_research::ArcIndex;
20
+ using operations_research::DefaultRoutingSearchParameters;
16
21
  using operations_research::Domain;
22
+ using operations_research::FirstSolutionStrategy;
17
23
  using operations_research::FlowQuantity;
18
24
  using operations_research::KnapsackSolver;
25
+ using operations_research::LinearExpr;
26
+ using operations_research::LinearRange;
27
+ using operations_research::LocalSearchMetaheuristic;
28
+ using operations_research::MPConstraint;
29
+ using operations_research::MPObjective;
30
+ using operations_research::MPSolver;
31
+ using operations_research::MPVariable;
19
32
  using operations_research::NodeIndex;
33
+ using operations_research::RoutingDimension;
34
+ using operations_research::RoutingIndexManager;
35
+ using operations_research::RoutingModel;
36
+ using operations_research::RoutingNodeIndex;
37
+ using operations_research::RoutingSearchParameters;
38
+ using operations_research::SimpleLinearSumAssignment;
20
39
  using operations_research::SimpleMaxFlow;
21
40
  using operations_research::SimpleMinCostFlow;
22
41
 
42
+ using operations_research::sat::BoolVar;
23
43
  using operations_research::sat::CpModelBuilder;
24
44
  using operations_research::sat::CpSolverResponse;
25
45
  using operations_research::sat::CpSolverStatus;
26
- using operations_research::sat::IntVar;
27
46
  using operations_research::sat::SolutionIntegerValue;
28
47
 
29
48
  using Rice::Array;
49
+ using Rice::Class;
30
50
  using Rice::Constructor;
31
51
  using Rice::Hash;
32
52
  using Rice::Module;
@@ -47,12 +67,332 @@ KnapsackSolver::SolverType from_ruby<KnapsackSolver::SolverType>(Object x)
47
67
  }
48
68
  }
49
69
 
70
+ template<>
71
+ inline
72
+ MPSolver::OptimizationProblemType from_ruby<MPSolver::OptimizationProblemType>(Object x)
73
+ {
74
+ std::string s = Symbol(x).str();
75
+ if (s == "glop") {
76
+ return MPSolver::OptimizationProblemType::GLOP_LINEAR_PROGRAMMING;
77
+ } else if (s == "cbc") {
78
+ return MPSolver::OptimizationProblemType::CBC_MIXED_INTEGER_PROGRAMMING;
79
+ } else {
80
+ throw std::runtime_error("Unknown optimization problem type: " + s);
81
+ }
82
+ }
83
+
84
+ template<>
85
+ inline
86
+ RoutingNodeIndex from_ruby<RoutingNodeIndex>(Object x)
87
+ {
88
+ const RoutingNodeIndex index{from_ruby<int>(x)};
89
+ return index;
90
+ }
91
+
92
+ template<>
93
+ inline
94
+ Object to_ruby<RoutingNodeIndex>(RoutingNodeIndex const &x)
95
+ {
96
+ return to_ruby<int>(x.value());
97
+ }
98
+
99
+ template<>
100
+ inline
101
+ operations_research::sat::LinearExpr from_ruby<operations_research::sat::LinearExpr>(Object x)
102
+ {
103
+ operations_research::sat::LinearExpr expr;
104
+
105
+ if (x.respond_to("to_i")) {
106
+ expr = from_ruby<int64>(x.call("to_i"));
107
+ } else if (x.respond_to("vars")) {
108
+ Array vars = x.call("vars");
109
+ for(auto const& var: vars) {
110
+ auto cvar = (Array) var;
111
+ // TODO clean up
112
+ Object o = cvar[0];
113
+ if (((Rice::String) o.call("class").call("name")).str() == "ORTools::BoolVar") {
114
+ expr.AddTerm(from_ruby<operations_research::sat::BoolVar>(cvar[0]), from_ruby<int64>(cvar[1]));
115
+ } else {
116
+ expr.AddTerm(from_ruby<operations_research::sat::IntVar>(cvar[0]), from_ruby<int64>(cvar[1]));
117
+ }
118
+ }
119
+ } else {
120
+ expr = from_ruby<operations_research::sat::IntVar>(x);
121
+ }
122
+
123
+ return expr;
124
+ }
125
+
126
+ // need a wrapper class due to const
127
+ class Assignment {
128
+ const operations_research::Assignment* self;
129
+ public:
130
+ Assignment(const operations_research::Assignment* v) {
131
+ self = v;
132
+ }
133
+ int64 ObjectiveValue() {
134
+ return self->ObjectiveValue();
135
+ }
136
+ int64 Value(const operations_research::IntVar* const var) const {
137
+ return self->Value(var);
138
+ }
139
+ };
140
+
141
+ Class rb_cMPVariable;
142
+ Class rb_cMPConstraint;
143
+ Class rb_cMPObjective;
144
+ Class rb_cIntVar;
145
+ Class rb_cRoutingDimension;
146
+
147
+ template<>
148
+ inline
149
+ Object to_ruby<MPVariable*>(MPVariable* const &x)
150
+ {
151
+ return Rice::Data_Object<MPVariable>(x, rb_cMPVariable, nullptr, nullptr);
152
+ }
153
+
154
+ template<>
155
+ inline
156
+ Object to_ruby<MPConstraint*>(MPConstraint* const &x)
157
+ {
158
+ return Rice::Data_Object<MPConstraint>(x, rb_cMPConstraint, nullptr, nullptr);
159
+ }
160
+
161
+ template<>
162
+ inline
163
+ Object to_ruby<MPObjective*>(MPObjective* const &x)
164
+ {
165
+ return Rice::Data_Object<MPObjective>(x, rb_cMPObjective, nullptr, nullptr);
166
+ }
167
+
168
+ template<>
169
+ inline
170
+ Object to_ruby<operations_research::IntVar*>(operations_research::IntVar* const &x)
171
+ {
172
+ return Rice::Data_Object<operations_research::IntVar>(x, rb_cIntVar, nullptr, nullptr);
173
+ }
174
+
175
+ template<>
176
+ inline
177
+ Object to_ruby<RoutingDimension*>(RoutingDimension* const &x)
178
+ {
179
+ return Rice::Data_Object<RoutingDimension>(x, rb_cRoutingDimension, nullptr, nullptr);
180
+ }
181
+
50
182
  extern "C"
51
183
  void Init_ext()
52
184
  {
53
- Module rb_mORTools = define_module("ORTools");
185
+ Module rb_mORTools = define_module("ORTools")
186
+ .define_singleton_method("default_routing_search_parameters", &DefaultRoutingSearchParameters);
187
+
188
+ define_class_under<RoutingSearchParameters>(rb_mORTools, "RoutingSearchParameters")
189
+ .define_method(
190
+ "first_solution_strategy=",
191
+ *[](RoutingSearchParameters& self, Symbol value) {
192
+ std::string s = Symbol(value).str();
193
+
194
+ FirstSolutionStrategy::Value v;
195
+ if (s == "path_cheapest_arc") {
196
+ v = FirstSolutionStrategy::PATH_CHEAPEST_ARC;
197
+ } else if (s == "path_most_constrained_arc") {
198
+ v = FirstSolutionStrategy::PATH_MOST_CONSTRAINED_ARC;
199
+ } else if (s == "evaluator_strategy") {
200
+ v = FirstSolutionStrategy::EVALUATOR_STRATEGY;
201
+ } else if (s == "savings") {
202
+ v = FirstSolutionStrategy::SAVINGS;
203
+ } else if (s == "sweep") {
204
+ v = FirstSolutionStrategy::SWEEP;
205
+ } else if (s == "christofides") {
206
+ v = FirstSolutionStrategy::CHRISTOFIDES;
207
+ } else if (s == "all_unperformed") {
208
+ v = FirstSolutionStrategy::ALL_UNPERFORMED;
209
+ } else if (s == "best_insertion") {
210
+ v = FirstSolutionStrategy::BEST_INSERTION;
211
+ } else if (s == "parallel_cheapest_insertion") {
212
+ v = FirstSolutionStrategy::PARALLEL_CHEAPEST_INSERTION;
213
+ } else if (s == "sequential_cheapest_insertion") {
214
+ v = FirstSolutionStrategy::SEQUENTIAL_CHEAPEST_INSERTION;
215
+ } else if (s == "local_cheapest_insertion") {
216
+ v = FirstSolutionStrategy::LOCAL_CHEAPEST_INSERTION;
217
+ } else if (s == "global_cheapest_arc") {
218
+ v = FirstSolutionStrategy::GLOBAL_CHEAPEST_ARC;
219
+ } else if (s == "local_cheapest_arc") {
220
+ v = FirstSolutionStrategy::LOCAL_CHEAPEST_ARC;
221
+ } else if (s == "first_unbound_min_value") {
222
+ v = FirstSolutionStrategy::FIRST_UNBOUND_MIN_VALUE;
223
+ } else {
224
+ throw std::runtime_error("Unknown first solution strategy: " + s);
225
+ }
54
226
 
55
- define_class_under<IntVar>(rb_mORTools, "IntVar");
227
+ return self.set_first_solution_strategy(v);
228
+ })
229
+ .define_method(
230
+ "local_search_metaheuristic=",
231
+ *[](RoutingSearchParameters& self, Symbol value) {
232
+ std::string s = Symbol(value).str();
233
+
234
+ LocalSearchMetaheuristic::Value v;
235
+ if (s == "guided_local_search") {
236
+ v = LocalSearchMetaheuristic::GUIDED_LOCAL_SEARCH;
237
+ } else if (s == "tabu_search") {
238
+ v = LocalSearchMetaheuristic::TABU_SEARCH;
239
+ } else if (s == "generic_tabu_search") {
240
+ v = LocalSearchMetaheuristic::GENERIC_TABU_SEARCH;
241
+ } else if (s == "simulated_annealing") {
242
+ v = LocalSearchMetaheuristic::SIMULATED_ANNEALING;
243
+ } else {
244
+ throw std::runtime_error("Unknown local search metaheuristic: " + s);
245
+ }
246
+
247
+ return self.set_local_search_metaheuristic(v);
248
+ })
249
+ .define_method(
250
+ "log_search=",
251
+ *[](RoutingSearchParameters& self, bool value) {
252
+ self.set_log_search(value);
253
+ })
254
+ .define_method(
255
+ "solution_limit=",
256
+ *[](RoutingSearchParameters& self, int64 value) {
257
+ self.set_solution_limit(value);
258
+ })
259
+ .define_method(
260
+ "time_limit=",
261
+ *[](RoutingSearchParameters& self, int64 value) {
262
+ self.mutable_time_limit()->set_seconds(value);
263
+ })
264
+ .define_method(
265
+ "lns_time_limit=",
266
+ *[](RoutingSearchParameters& self, int64 value) {
267
+ self.mutable_lns_time_limit()->set_seconds(value);
268
+ });
269
+
270
+ rb_cMPVariable = define_class_under<MPVariable>(rb_mORTools, "MPVariable")
271
+ .define_method("name", &MPVariable::name)
272
+ .define_method("solution_value", &MPVariable::solution_value)
273
+ .define_method(
274
+ "+",
275
+ *[](MPVariable& self, MPVariable& other) {
276
+ LinearExpr s(&self);
277
+ LinearExpr o(&other);
278
+ return s + o;
279
+ })
280
+ .define_method(
281
+ "*",
282
+ *[](MPVariable& self, double other) {
283
+ LinearExpr s(&self);
284
+ return s * other;
285
+ });
286
+
287
+ define_class_under<LinearExpr>(rb_mORTools, "LinearExpr")
288
+ .define_constructor(Constructor<LinearExpr>())
289
+ .define_method(
290
+ "_add_linear_expr",
291
+ *[](LinearExpr& self, LinearExpr& other) {
292
+ return self + other;
293
+ })
294
+ .define_method(
295
+ "_add_mp_variable",
296
+ *[](LinearExpr& self, MPVariable &other) {
297
+ LinearExpr o(&other);
298
+ return self + o;
299
+ })
300
+ .define_method(
301
+ "_lte_double",
302
+ *[](LinearExpr& self, double other) {
303
+ LinearExpr o(other);
304
+ return self <= o;
305
+ })
306
+ .define_method(
307
+ "_lte_linear_expr",
308
+ *[](LinearExpr& self, LinearExpr& other) {
309
+ return self <= other;
310
+ })
311
+ .define_method(
312
+ "==",
313
+ *[](LinearExpr& self, double other) {
314
+ LinearExpr o(other);
315
+ return self == o;
316
+ })
317
+ .define_method(
318
+ "to_s",
319
+ *[](LinearExpr& self) {
320
+ return self.ToString();
321
+ })
322
+ .define_method(
323
+ "inspect",
324
+ *[](LinearExpr& self) {
325
+ return "#<ORTools::LinearExpr \"" + self.ToString() + "\">";
326
+ });
327
+
328
+ define_class_under<LinearRange>(rb_mORTools, "LinearRange");
329
+
330
+ rb_cMPConstraint = define_class_under<MPConstraint>(rb_mORTools, "MPConstraint")
331
+ .define_method("set_coefficient", &MPConstraint::SetCoefficient);
332
+
333
+ rb_cMPObjective = define_class_under<MPObjective>(rb_mORTools, "MPObjective")
334
+ .define_method("value", &MPObjective::Value)
335
+ .define_method("set_coefficient", &MPObjective::SetCoefficient)
336
+ .define_method("set_maximization", &MPObjective::SetMaximization);
337
+
338
+ define_class_under<MPSolver>(rb_mORTools, "Solver")
339
+ .define_constructor(Constructor<MPSolver, std::string, MPSolver::OptimizationProblemType>())
340
+ .define_method("infinity", &MPSolver::infinity)
341
+ .define_method(
342
+ "int_var",
343
+ *[](MPSolver& self, double min, double max, const std::string& name) {
344
+ return self.MakeIntVar(min, max, name);
345
+ })
346
+ .define_method("num_var", &MPSolver::MakeNumVar)
347
+ .define_method("bool_var", &MPSolver::MakeBoolVar)
348
+ .define_method("num_variables", &MPSolver::NumVariables)
349
+ .define_method("num_constraints", &MPSolver::NumConstraints)
350
+ .define_method("wall_time", &MPSolver::wall_time)
351
+ .define_method("iterations", &MPSolver::iterations)
352
+ .define_method("nodes", &MPSolver::nodes)
353
+ .define_method("objective", &MPSolver::MutableObjective)
354
+ .define_method(
355
+ "minimize",
356
+ *[](MPSolver& self, LinearExpr& expr) {
357
+ return self.MutableObjective()->MinimizeLinearExpr(expr);
358
+ })
359
+ .define_method(
360
+ "add",
361
+ *[](MPSolver& self, const LinearRange& range) {
362
+ return self.MakeRowConstraint(range);
363
+ })
364
+ .define_method(
365
+ "constraint",
366
+ *[](MPSolver& self, double lb, double ub) {
367
+ return self.MakeRowConstraint(lb, ub);
368
+ })
369
+ .define_method(
370
+ "solve",
371
+ *[](MPSolver& self) {
372
+ auto status = self.Solve();
373
+
374
+ if (status == MPSolver::ResultStatus::OPTIMAL) {
375
+ return Symbol("optimal");
376
+ } else if (status == MPSolver::ResultStatus::FEASIBLE) {
377
+ return Symbol("feasible");
378
+ } else if (status == MPSolver::ResultStatus::INFEASIBLE) {
379
+ return Symbol("infeasible");
380
+ } else if (status == MPSolver::ResultStatus::UNBOUNDED) {
381
+ return Symbol("unbounded");
382
+ } else if (status == MPSolver::ResultStatus::ABNORMAL) {
383
+ return Symbol("abnormal");
384
+ } else if (status == MPSolver::ResultStatus::MODEL_INVALID) {
385
+ return Symbol("model_invalid");
386
+ } else if (status == MPSolver::ResultStatus::NOT_SOLVED) {
387
+ return Symbol("not_solved");
388
+ } else {
389
+ throw std::runtime_error("Unknown status");
390
+ }
391
+ });
392
+
393
+ // not to be confused with operations_research::IntVar
394
+ define_class_under<operations_research::sat::IntVar>(rb_mORTools, "SatIntVar");
395
+ define_class_under<BoolVar>(rb_mORTools, "BoolVar");
56
396
 
57
397
  define_class_under<CpModelBuilder>(rb_mORTools, "CpModel")
58
398
  .define_constructor(Constructor<CpModelBuilder>())
@@ -62,11 +402,50 @@ void Init_ext()
62
402
  const Domain domain(start, end);
63
403
  return self.NewIntVar(domain).WithName(name);
64
404
  })
405
+ .define_method(
406
+ "new_bool_var",
407
+ *[](CpModelBuilder& self, std::string name) {
408
+ return self.NewBoolVar().WithName(name);
409
+ })
410
+ .define_method(
411
+ "add_equality",
412
+ *[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
413
+ self.AddEquality(x, y);
414
+ })
65
415
  .define_method(
66
416
  "add_not_equal",
67
- *[](CpModelBuilder& self, IntVar x, IntVar y) {
68
- // TODO return value
417
+ *[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
69
418
  self.AddNotEqual(x, y);
419
+ })
420
+ .define_method(
421
+ "add_greater_than",
422
+ *[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
423
+ self.AddGreaterThan(x, y);
424
+ })
425
+ .define_method(
426
+ "add_greater_or_equal",
427
+ *[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
428
+ self.AddGreaterOrEqual(x, y);
429
+ })
430
+ .define_method(
431
+ "add_less_than",
432
+ *[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
433
+ self.AddLessThan(x, y);
434
+ })
435
+ .define_method(
436
+ "add_less_or_equal",
437
+ *[](CpModelBuilder& self, operations_research::sat::LinearExpr x, operations_research::sat::LinearExpr y) {
438
+ self.AddLessOrEqual(x, y);
439
+ })
440
+ .define_method(
441
+ "maximize",
442
+ *[](CpModelBuilder& self, operations_research::sat::LinearExpr expr) {
443
+ self.Maximize(expr);
444
+ })
445
+ .define_method(
446
+ "minimize",
447
+ *[](CpModelBuilder& self, operations_research::sat::LinearExpr expr) {
448
+ self.Minimize(expr);
70
449
  });
71
450
 
72
451
  define_class_under(rb_mORTools, "CpSolver")
@@ -77,15 +456,17 @@ void Init_ext()
77
456
  })
78
457
  .define_method(
79
458
  "_solution_integer_value",
80
- *[](Object self, CpSolverResponse& response, IntVar& x) {
459
+ *[](Object self, CpSolverResponse& response, operations_research::sat::IntVar& x) {
81
460
  return SolutionIntegerValue(response, x);
82
461
  });
83
462
 
84
463
  define_class_under<CpSolverResponse>(rb_mORTools, "CpSolverResponse")
464
+ .define_method("objective_value", &CpSolverResponse::objective_value)
85
465
  .define_method(
86
466
  "status",
87
467
  *[](CpSolverResponse& self) {
88
468
  auto status = self.status();
469
+
89
470
  if (status == CpSolverStatus::OPTIMAL) {
90
471
  return Symbol("optimal");
91
472
  } else if (status == CpSolverStatus::FEASIBLE) {
@@ -99,6 +480,56 @@ void Init_ext()
99
480
  }
100
481
  });
101
482
 
483
+ define_class_under<RoutingIndexManager>(rb_mORTools, "RoutingIndexManager")
484
+ .define_constructor(Constructor<RoutingIndexManager, int, int, RoutingNodeIndex>())
485
+ .define_method("index_to_node", &RoutingIndexManager::IndexToNode);
486
+
487
+ define_class_under<Assignment>(rb_mORTools, "Assignment")
488
+ .define_method("objective_value", &Assignment::ObjectiveValue)
489
+ .define_method("value", &Assignment::Value);
490
+
491
+ // not to be confused with operations_research::sat::IntVar
492
+ rb_cIntVar = define_class_under<operations_research::IntVar>(rb_mORTools, "IntVar");
493
+
494
+ rb_cRoutingDimension = define_class_under<RoutingDimension>(rb_mORTools, "RoutingDimension")
495
+ .define_method("global_span_cost_coefficient=", &RoutingDimension::SetGlobalSpanCostCoefficient);
496
+
497
+ define_class_under<RoutingModel>(rb_mORTools, "RoutingModel")
498
+ .define_constructor(Constructor<RoutingModel, RoutingIndexManager>())
499
+ .define_method(
500
+ "register_transit_callback",
501
+ *[](RoutingModel& self, Object callback) {
502
+ return self.RegisterTransitCallback(
503
+ [callback](int64 from_index, int64 to_index) -> int64 {
504
+ return from_ruby<int64>(callback.call("call", from_index, to_index));
505
+ }
506
+ );
507
+ })
508
+ .define_method("depot", &RoutingModel::GetDepot)
509
+ .define_method("set_arc_cost_evaluator_of_all_vehicles", &RoutingModel::SetArcCostEvaluatorOfAllVehicles)
510
+ .define_method("set_arc_cost_evaluator_of_vehicle", &RoutingModel::SetArcCostEvaluatorOfVehicle)
511
+ .define_method("set_fixed_cost_of_all_vehicles", &RoutingModel::SetFixedCostOfAllVehicles)
512
+ .define_method("set_fixed_cost_of_vehicle", &RoutingModel::SetFixedCostOfVehicle)
513
+ .define_method("fixed_cost_of_vehicle", &RoutingModel::GetFixedCostOfVehicle)
514
+ .define_method("add_dimension", &RoutingModel::AddDimension)
515
+ .define_method("start", &RoutingModel::Start)
516
+ .define_method("end", &RoutingModel::End)
517
+ .define_method("start?", &RoutingModel::IsStart)
518
+ .define_method("end?", &RoutingModel::IsEnd)
519
+ .define_method("vehicle_index", &RoutingModel::VehicleIndex)
520
+ .define_method("next", &RoutingModel::Next)
521
+ .define_method("vehicle_used?", &RoutingModel::IsVehicleUsed)
522
+ .define_method("next_var", &RoutingModel::NextVar)
523
+ .define_method("arc_cost_for_vehicle", &RoutingModel::GetArcCostForVehicle)
524
+ .define_method("mutable_dimension", &RoutingModel::GetMutableDimension)
525
+ .define_method(
526
+ "solve_with_parameters",
527
+ *[](RoutingModel& self, const RoutingSearchParameters& search_parameters) {
528
+ auto assignment = self.SolveWithParameters(search_parameters);
529
+ // std::cout << assignment->DebugString();
530
+ return (Assignment) assignment;
531
+ });
532
+
102
533
  define_class_under<KnapsackSolver>(rb_mORTools, "KnapsackSolver")
103
534
  .define_constructor(Constructor<KnapsackSolver, KnapsackSolver::SolverType, std::string>())
104
535
  .define_method("_solve", &KnapsackSolver::Solve)
@@ -218,4 +649,31 @@ void Init_ext()
218
649
  throw std::runtime_error("Unknown status");
219
650
  }
220
651
  });
652
+
653
+ define_class_under<SimpleLinearSumAssignment>(rb_mORTools, "LinearSumAssignment")
654
+ .define_constructor(Constructor<SimpleLinearSumAssignment>())
655
+ .define_method("add_arc_with_cost", &SimpleLinearSumAssignment::AddArcWithCost)
656
+ .define_method("num_nodes", &SimpleLinearSumAssignment::NumNodes)
657
+ .define_method("num_arcs", &SimpleLinearSumAssignment::NumArcs)
658
+ .define_method("left_node", &SimpleLinearSumAssignment::LeftNode)
659
+ .define_method("right_node", &SimpleLinearSumAssignment::RightNode)
660
+ .define_method("cost", &SimpleLinearSumAssignment::Cost)
661
+ .define_method("optimal_cost", &SimpleLinearSumAssignment::OptimalCost)
662
+ .define_method("right_mate", &SimpleLinearSumAssignment::RightMate)
663
+ .define_method("assignment_cost", &SimpleLinearSumAssignment::AssignmentCost)
664
+ .define_method(
665
+ "solve",
666
+ *[](SimpleLinearSumAssignment& self) {
667
+ auto status = self.Solve();
668
+
669
+ if (status == SimpleLinearSumAssignment::Status::OPTIMAL) {
670
+ return Symbol("optimal");
671
+ } else if (status == SimpleLinearSumAssignment::Status::INFEASIBLE) {
672
+ return Symbol("infeasible");
673
+ } else if (status == SimpleLinearSumAssignment::Status::POSSIBLE_OVERFLOW) {
674
+ return Symbol("possible_overflow");
675
+ } else {
676
+ throw std::runtime_error("Unknown status");
677
+ }
678
+ });
221
679
  }
@@ -2,7 +2,7 @@ require "mkmf-rice"
2
2
 
3
3
  abort "Missing stdc++" unless have_library("stdc++")
4
4
 
5
- $CXXFLAGS << " -std=c++11"
5
+ $CXXFLAGS << " -std=c++11 -DUSE_CBC"
6
6
 
7
7
  # or-tools warnings
8
8
  $CXXFLAGS << " -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-ignored-qualifiers"
@@ -18,4 +18,63 @@ $LDFLAGS << " -Wl,-rpath,#{lib}"
18
18
  $LDFLAGS << " -L#{lib}"
19
19
  $LDFLAGS << " -lortools"
20
20
 
21
+ %w(
22
+ absl_city
23
+ absl_time_zone
24
+ absl_spinlock_wait
25
+ absl_log_severity
26
+ absl_failure_signal_handler
27
+ absl_bad_optional_access
28
+ absl_hash
29
+ absl_raw_logging_internal
30
+ absl_random_internal_pool_urbg
31
+ absl_base
32
+ absl_bad_any_cast_impl
33
+ absl_periodic_sampler
34
+ absl_random_distributions
35
+ absl_flags_usage_internal
36
+ absl_random_seed_sequences
37
+ absl_throw_delegate
38
+ absl_flags_handle
39
+ absl_dynamic_annotations
40
+ absl_debugging_internal
41
+ absl_strings
42
+ absl_flags
43
+ absl_malloc_internal
44
+ absl_str_format_internal
45
+ absl_flags_usage
46
+ absl_strings_internal
47
+ absl_flags_program_name
48
+ absl_flags_registry
49
+ absl_int128
50
+ absl_scoped_set_env
51
+ absl_raw_hash_set
52
+ absl_random_internal_seed_material
53
+ absl_symbolize
54
+ absl_random_internal_randen_slow
55
+ absl_graphcycles_internal
56
+ absl_exponential_biased
57
+ absl_random_internal_randen_hwaes_impl
58
+ absl_bad_variant_access
59
+ absl_stacktrace
60
+ absl_random_internal_randen_hwaes
61
+ absl_flags_parse
62
+ absl_random_internal_randen
63
+ absl_random_internal_distribution_test_util
64
+ absl_time
65
+ absl_flags_config
66
+ absl_synchronization
67
+ absl_hashtablez_sampler
68
+ absl_demangle_internal
69
+ absl_leak_check
70
+ absl_flags_marshalling
71
+ absl_leak_check_disable
72
+ absl_examine_stack
73
+ absl_flags_internal
74
+ absl_random_seed_gen_exception
75
+ absl_civil_time
76
+ ).each do |lib|
77
+ $LDFLAGS << " -l#{lib}"
78
+ end
79
+
21
80
  create_makefile("or_tools/ext")
data/lib/or-tools.rb CHANGED
@@ -2,8 +2,16 @@
2
2
  require "or_tools/ext"
3
3
 
4
4
  # modules
5
+ require "or_tools/comparison"
6
+ require "or_tools/comparison_operators"
7
+ require "or_tools/cp_model"
5
8
  require "or_tools/cp_solver"
6
9
  require "or_tools/knapsack_solver"
10
+ require "or_tools/linear_expr"
11
+ require "or_tools/routing_model"
12
+ require "or_tools/sat_linear_expr"
13
+ require "or_tools/sat_int_var"
14
+ require "or_tools/solver"
7
15
  require "or_tools/version"
8
16
 
9
17
  module ORTools
@@ -0,0 +1,11 @@
1
+ module ORTools
2
+ class Comparison
3
+ attr_reader :operator, :left, :right
4
+
5
+ def initialize(operator, left, right)
6
+ @operator = operator
7
+ @left = left
8
+ @right = right
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module ORTools
2
+ module ComparisonOperators
3
+ ["==", "!=", ">", ">=", "<", "<="].each do |operator|
4
+ define_method(operator) do |other|
5
+ Comparison.new(operator, self, other)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ module ORTools
2
+ class CpModel
3
+ def add(comparison)
4
+ method_name =
5
+ case comparison.operator
6
+ when "=="
7
+ :add_equality
8
+ when "!="
9
+ :add_not_equal
10
+ when ">"
11
+ :add_greater_than
12
+ when ">="
13
+ :add_greater_or_equal
14
+ when "<"
15
+ :add_less_than
16
+ when "<="
17
+ :add_less_or_equal
18
+ else
19
+ raise ArgumentError, "Unknown operator: #{comparison.operator}"
20
+ end
21
+
22
+ send(method_name, comparison.left, comparison.right)
23
+ end
24
+
25
+ def sum(arr)
26
+ arr.sum(SatLinearExpr.new)
27
+ end
28
+ end
29
+ end
@@ -8,5 +8,9 @@ module ORTools
8
8
  def value(var)
9
9
  _solution_integer_value(@response, var)
10
10
  end
11
+
12
+ def objective_value
13
+ @response.objective_value
14
+ end
11
15
  end
12
16
  end
Binary file