Skip to content

On interval variables and optional interval variables #606

@tias

Description

@tias

So Interval variables and Optional interval variables are the only features of state-of-the-art CP solvers that our library does not yet support...

We don't want to add them as primitive variables because then they can be used in any expression, which requires working out the full semantics and code-wise this would be a lot of special casing etc.

We created #121 DirectVariable prototype for them, to generically support ortools/CP's interval variables, and we actually use it in some projects with companies. But it is also quite some technical debt should we include it in the main code.

But because we do want them for flexible jobshop (e.g. README) and work we do, I gave it some more thought:

So OrTools has 2 types of IntervalVariables (well, also can create versions with implicit 'end', but lets ignore that for now)

  • NewIntervalVar
  • NewOptionalIntervalVar

And those are used in just 3 constraints of OrTools:

  • AddCumulative
  • AddNoOverlap -- special case of Cumulative where demand and capacity=1
  • AddNoOverlap2D -- special case of 2D NoOverlap

Now because these are all special cases of each other, this means that they will never appear together in a model.

So an IntervalVar is not really a variable in the expression-tree sense, its just a construct to post either a Cumul, NoOv or NoOv2D over...

So if its only to the purpose of these constraints, we can just create constraints for each combo; that's just 4 combo's if we ignore the binpacking NoOv2D for now:

  • Cumulative(start, dur, end, demand, capa)
  • NoOverlap(start, dur, end)
  • CumulativeOptional(start, dur, end, demand, capa, option)
  • NoOverlap(start, dur, end, option)

And of those 4, we already have the first two as globals... (although only Cumulative is in the docs, a different TODO)

Now this does ignore one thing: creating an IntervalVar also enforces it to be an interval, e.g. start+dur=end. For solvers like OrTools that have IntervalVars, this is implicit when using our Cumulative (as we create the IntervalVar behind the scenes), but for a solver that decomposes this is not implicit...

So that means we also either need two more constraints:

  • IsInterval(start, dur, end)
  • IsOptionalInterval(start, dur, end, option)

or, we need to change the signature of the 4 constraints above to include an enforceInterval=True argument...

(the latter will avoid users using a solver that supports IntervalVars to still manually post start+dur=end; the former will mean that solvers with IntervalVars will have twice the interval variables created by our model, once in IsInterval, once in Cumulative, which I hope will be very little overhead in practice)


Does this reasoning make sense?

Do we want to add the 2Optional globals and hence abort the DirectVar approach?

Should we have IsInterval's, or have an enforeInterval argument, or maybe even both?

Discussion welcome...

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions