or-tools 0.1.0 → 0.1.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.
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