# ILOG OPL cannot distinguish apples from oranges

I used to think about OPL that promotes obligatorily mathematical rigor as one would expect from a mathematical modeling language. I was misunderstood: it seems that OPL deludes itself when comparing apples and oranges. OPL still requires enhancements that address serious idiosyncrasies how the model is handled.

Objectives

The article presents some OPL examples for expressions that do not satisfy type safety. It additionally relates possible error messages.

The Apple and Orange model

Let consider the following “Apple and Orange” model. It does nothing very useful, but is reveals the issues to be discussed. The model defines two kinds of fruits: apple and orange. There is also a set of each fruit and a pair of expressions that perform some arbitrary calculation for each fruit. At last, there are some constants to refer to an arbitrary apple and orange.

```tuple orange { int a; int b; };
tuple apple { int c; int d; };

{orange} oranges = { <0,0>, <1,1>, <0,1>, <1,0>};
{apple} apples = { <0,0>, <1,1>, <0,1>, <1,0>};

dexpr float appleSum[a in apples] = a.c + a.d;
dexpr float orangeSum[o in oranges] = o.a + o.b;

apple oneApple = <1,1>;
orange oneOrange = <0,0>;

minimize 0;
```

Index for an expression is not consistently type safe

Suppose the constants are used as indexes for the expressions, but they were exchanged by mistake. They are not anymore tuples from a domain defined for each expression. OPL counterintuitively accepts the model and proposes a wrong solution generated from cplex.

```subject to {
orangeSum[oneApple] <= 10;
appleSum[oneOrange] <= 10;
}
```

However, this behavior is not consistent if one top level expression relies on another bottom level expression. In the following example, indexes are still exchanged by mistake for the top level expression. Opposed to the previous example, the model is rejected with a not so meaningful error message: Exception from IBM ILOG Concert: IloEvalIntTupleCellExprI::normalize.

```dexpr float appleSum2[a in apples] = appleSum[a];
dexpr float orangeSum2[o in oranges] = orangeSum[o];

subject to {
orangeSum2[oneApple] <= 20;
appleSum2[oneOrange] <= 20;
}
```

The next example has correct indexes for the top level expression. But the referred bottom level expressions are exchanged by mistake. As consequence, the bottom level expression receive incompatible indexes in a identical manner as for the first example. While one would expect the same inconsistent behavior as in the first example, OPL now accuses the error with the same message from the second example: Exception from IBM ILOG Concert: IloEvalIntTupleCellExprI::normalize.

```dexpr float appleSum3[a in apples] = orangeSum[a];
dexpr float orangeSum3[o in oranges] = appleSum[o];

subject to {
orangeSum3[oneOrange] <= 30;
appleSum3[oneApple] <= 30;
}
```

Tuples patterns cannot index expressions

Even though syntactically and grammatically correct, OPL does not accept declaring a top level expression with a tuple index and that references a bottom level expression indexed by a tuple pattern. The observation is really annoying: OPL will reject both the (theoretically) correct and the mistaken model. Therefore, it was not possible to test type safety.

```/* correct */
dexpr float appleSum4A[a in apples] = appleSum[<a.c,0>];
dexpr float orangeSum4A[o in oranges] = orangeSum[<0,o.b>];

/* mistaken */
dexpr float appleSum4B[a in apples] = orangeSum[<a.c,0>];
dexpr float orangeSum4B[o in oranges] = appleSum[<0,o.b>];

subject to {
orangeSum4A[oneOrange] <= 10;
appleSum4A[oneApple] <= 10;

orangeSum4B[oneOrange] <= 10;
appleSum4B[oneApple] <= 10;
}
```

Index for a variable is not type safe

If one repeats the previous examples, but using variables at the bottom level of each expression, OPL will counterintuitively accept any of them and propose a wrong solution generated from cplex.

```dvar float appleVar[a in apples];
dvar float orangeVar[o in oranges];

subject to {
orangeVar[oneApple] <= 10;
appleVar[oneOrange] <= 10;
}
```
```dexpr float appleSum6[a in apples] = orangeVar[a];
dexpr float orangeSum6[o in oranges] = appleVar[o];

subject to {
orangeSum6[oneOrange] <= 10;
appleSum6[oneApple] <= 10;
}
```
```dexpr float appleSum7[a in apples] = appleVar[a];
dexpr float orangeSum7[o in oranges] = orangeVar[o];

subject to {
orangeSum7[oneApple] <= 10;
appleSum7[oneOrange] <= 10;
}
```
```dexpr float appleSum8[a in apples] = orangeVar[<a.c,0>];
dexpr float orangeSum8[o in oranges] = appleVar[<0,o.b>];

subject to {
orangeSum8[oneApple] <= 10;
appleSum8[oneOrange] <= 10;
}
```
```dexpr float appleSum9[a in apples] = appleVar[<a.c,0>];
dexpr float orangeSum9[o in oranges] = orangeVar[<0,o.b>];

subject to {
orangeSum9[oneApple] <= 10;
appleSum9[oneOrange] <= 10;
}
```

Formal parameters

If any of the previous examples happens with formal parameters, the behavior is different, again. At least, OPL detects that there is somewhere a tuple attribute which name does not match with the expected tuple columns: Exception from IBM ILOG Concert: The column does not exist in the schema: a.

```dexpr float appleSum9[a in apples] = appleVar[<a.c,0>];
dexpr float orangeSum9[o in oranges] = orangeVar[<0,o.b>];

subject to {
forall (a in apples) {
orangeSum[a] <= 10;
}
}
```

Conclusion

OPL is a valuable tool to describe mathematical models for linear programming and constraint programming since it allows to express a model in very concise but powerful way. However, the model generation is not sufficiently rigorous nor predictable if there are expressions or variables indexed by tuples. The OPL model generator may reject declarations that are apparently correct. Or it may accept declarations or constraints where indexes are from incorrect domain. OPL still requires enhancements that address serious idiosyncrasies how the model is handled.

### One Response to ILOG OPL cannot distinguish apples from oranges

1. Mark Wallace says:

Hi Daniel,
I’m in a research group in Melbourne who have developed a successor to OPL that is called Zinc.
http://g12.research.nicta.com.au/zinc_current/index_home.php
It seems to avoid the problems revealed by your examples here.
The focus of Zinc is flexibility of mapping it to (combinations of) underlying solvers including Cplex but also Coin solvers, constraint programming solvers, SAT and SMT solvers, etc.
(We would welcome any publicity about our work, if you find it interesting and worthwhile!)