ankane / ankane/or-tools-ruby

General VRP constraints design discussion

Open
#94 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Ruby
Stars
222
Forks
42
Avg merge
20h 35m
Merged PRs (30d)
2

Description

#93 was closed in favor of 44eb655 with the comment:

If quadratic constraints are needed, it should be possible to use index_expression(..., check_linear: false) to extend this.

I'm not sure I understand whether this will cover everything. Just to explain the motivation, I don't personally know of a significant use case for quadratic expressions is the sense of multiplying one scalar by another scalar, though maybe someone has one. The use case I am most familiar with is about disjunctions; if you have a constraint of the form some_dimension.CumulVar(A) - somedimension.CumulVar(B) <= const, there is a gotcha in or-tools where when a node becomes inactive, the cumul values associated with the node are not zeroed out, and the constraint can end up applying eliminating the solution.

Therefore the standard expression when disjunctions may apply is actually ActiveVar(A)*some_dimension.CumulVar(A) - ActiveVar(B)*some_dimension.CumulVar(B) <= const. ActiveVar being the or-tools "booleans" that indicate whether a node is active.

Or (eg. in pickup-delivery cases where the pickup and delivery are not a specific pair and may be independently deactivated) even ActiveVar(A)*ActiveVar(B)*some_dimension.CumulVar(A) - ActiveVar(A)*ActiveVar(B)*some_dimension.CumulVar(B) <= const.

I think this can be done because it's still a sum-of-products type expression, which I believe is what index_expression supports.

But I don't think it can implement arbitrary forms like ActiveVar(A)*ActiveVar(B)*(some_dimension.CumulVar(A) - some_dimension.CumulVar(B)) <= const, or ActiveVar(A)(some_dimension.CumulVar(A) - constA) - ActiveVar(B)(some_dimension.CumulVar(B) - constB) <= constC`? You'd need to rewrite into a form that has one sum-of-products on each side of the op, and if you need more than two, it won't be possible. The forms won't necessarily have equivalent performance, though I have no idea how to test that out.

So I think this would still cover a lot of people's use cases, but I guess I'm struggling to understand design intent of doing the work in index_expression instead of making the Expression support just pass everything through and letting or-tools figure it out? My understanding is that the Python bindings pass through any expression, though I haven't tested them so I could be wrong.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the index_expression and Expression entry points, then review issue #93 and commit 44eb655. Compare the documented expression forms with the disjunction examples and the stated Python-binding behavior. Done means agreeing on the supported constraint forms and recording a clear implementation scope or design decision.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
api
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.