Skip to content

Commit 44eb655

Browse files
ankanewillbryant
andcommitted
Added support for more constraints for routing - #92 and #93 [skip ci]
Co-authored-by: Will Bryant <will.bryant@gmail.com>
1 parent 135ac4e commit 44eb655

1 file changed

Lines changed: 43 additions & 2 deletions

File tree

ext/or-tools/routing.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,38 @@ namespace Rice::detail {
9797
};
9898
} // namespace Rice::detail
9999

100+
int64_t int64_strict(VALUE v) {
101+
if (!Object(v).is_a(rb_cInteger)) {
102+
throw std::invalid_argument{"Coefficient must be integer"};
103+
}
104+
return Rice::detail::From_Ruby<int64_t>().convert(v);
105+
}
106+
107+
operations_research::IntExpr* int_expr(operations_research::Solver& solver, Object o) {
108+
Object utils = Rice::define_module("ORTools").const_get("Utils");
109+
Rice::Hash rb_coeffs = utils.call("index_expression", o);
110+
111+
std::vector<operations_research::IntVar*> vars;
112+
std::vector<int64_t> coeffs;
113+
int64_t constant = 0;
114+
115+
for (const auto& entry : rb_coeffs) {
116+
auto coeff = int64_strict(entry.value.value());
117+
if (Object(entry.key).is_nil()) {
118+
constant = coeff;
119+
} else {
120+
vars.push_back(Rice::detail::From_Ruby<operations_research::IntVar*>().convert(entry.key.value()));
121+
coeffs.push_back(coeff);
122+
}
123+
}
124+
125+
operations_research::IntExpr* expr = solver.MakeScalProd(vars, coeffs);
126+
if (constant != 0) {
127+
expr = solver.MakeSum(expr, constant);
128+
}
129+
return expr;
130+
}
131+
100132
void init_routing(Rice::Module& m) {
101133
auto rb_cRoutingSearchParameters = Rice::define_class_under<RoutingSearchParameters>(m, "RoutingSearchParameters");
102134
auto rb_cIntVar = Rice::define_class_under<operations_research::IntVar>(m, "RoutingIntVar");
@@ -298,11 +330,20 @@ void init_routing(Rice::Module& m) {
298330
[](operations_research::Solver& self, Object o) {
299331
operations_research::Constraint* constraint;
300332
if (o.respond_to("left")) {
301-
operations_research::IntExpr* left(Rice::detail::From_Ruby<operations_research::IntVar*>().convert(o.call("left")));
302-
operations_research::IntExpr* right(Rice::detail::From_Ruby<operations_research::IntVar*>().convert(o.call("right")));
333+
auto left = int_expr(self, o.call("left"));
334+
auto right = int_expr(self, o.call("right"));
303335
std::string op = o.call("op").to_s().str();
336+
304337
if (op == "==") {
305338
constraint = self.MakeEquality(left, right);
339+
} else if (op == "!=") {
340+
constraint = self.MakeNonEquality(left, right);
341+
} else if (op == ">") {
342+
constraint = self.MakeGreater(left, right);
343+
} else if (op == ">=") {
344+
constraint = self.MakeGreaterOrEqual(left, right);
345+
} else if (op == "<") {
346+
constraint = self.MakeLess(left, right);
306347
} else if (op == "<=") {
307348
constraint = self.MakeLessOrEqual(left, right);
308349
} else {

0 commit comments

Comments
 (0)