choco-solver icon indicating copy to clipboard operation
choco-solver copied to clipboard

[FEATURE] ArExpression.intVar should allow naming of the variable

Open hugoduncan opened this issue 4 years ago • 1 comments
trafficstars

When creating a variable using an arithmetic expression, the variable would be more identifiable in output if it could be named for a problem domain concept.

Expected behavior

ArExpression.intVar accepts an optional name argument, that is used instead of the generated name.

Actual behavior

Currently ArExpression.intVar implementations generate a name based on the arithmetic operator being used, which makes it hard to trace in output.

Context

When using a model with multiple arithmetic constraints using the same arithmetic operator, it is unclear in any output which variable was generated by which constraint.

hugoduncan avatar Mar 29 '21 13:03 hugoduncan

Hi,

That is not that easy. Indeed, calling intVar() on an expression turns it into a IntVar in several steps.

After executing the following code:

Model model = new Model();
IntVar x = model.intVar("x", 0, 2);
IntVar y = model.intVar("y", 0, 2);
IntVar z = x.add(y).intVar();

The variables will named like:

x -> "x"
y -> "y"
z -> "sum_exp_1"

This is because intVar() method for binary arithmetic expression looks like:

if (me == null) {
    IntVar v1 = e1.intVar();
    IntVar v2 = e2.intVar();
    int[] bounds;
    switch (op) {
        case ADD:
            bounds = VariableUtils.boundsForAddition(v1, v2);
            me = model.intVar(model.generateName("sum_exp_"), bounds[0], bounds[1]);
            model.arithm(v1, "+", v2, "=", me).post();
            break;
        case SUB:
            bounds = VariableUtils.boundsForSubstraction(v1, v2);
            me = model.intVar(model.generateName("sub_exp_"), bounds[0], bounds[1]);
            model.arithm(v1, "-", v2, "=", me).post();
            break;
        case MUL:
            // ...

So, inputing a String to this method will replace sum_exp or sub_exp by the given name (or a default one, even less clear if none is given). I can live with that. What I'm not clear with is the calls to e1.intVar(); and e2.intVar(); at the beginning of the method. When e1 and e2 were created outside (like in my example) there is problem, but what if one of those is an expression itself. Like:

Model model = new Model();
IntVar w = model.intVar("w", 0, 2);
IntVar x = model.intVar("x", 0, 2);
IntVar y = model.intVar("y", 0, 2);
IntVar z = x.add(y.sub(w)).intVar();

In that case, no name can be passed to y.sub(w) which will, thought, be turned into an IntVar on the call to intVar() on z.

Now, I'm ok with adding a new API with an optional name but internal calls will still rely on default naming and I'm afraid the lack of clarity remains or even increases. What do you think ?

cprudhom avatar Apr 09 '21 07:04 cprudhom