choco-solver
choco-solver copied to clipboard
[FEATURE] ArExpression.intVar should allow naming of the variable
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.
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 ?