Originally posted by: SystemAdmin
> > 1. An IloRange may encode a quadratic expression, in which case you need to iterate over the quadratic part of the expression itself.
>
> I've tested the code against several quadratic examples, including an example where one variable appears only in the quadratic part of the objective and another appears only in the quadratic part of a cone constraint. It seems to be working correctly, but if you come across a counterexample, please let me know.
>
The code below does not find x and y unless you set CONSIDER_QUAD_EXPRS to true (and if it does find them with CONSIDER_QUAD_EXPR=false then I would consider that a bug).
import ilog.cplex.*;
import ilog.concert.*;
public
final
class ListQuadExpr
{
private
static
final
boolean CONSIDER_QUAD_EXPRS =
false;
private
static IloNumVar[] parse(IloCplex cplex)
throws IloException
{ java.util.HashSet<IloNumVar> vars =
new java.util.HashSet<IloNumVar>(); java.util.Iterator it = cplex.iterator(); IloLinearNumExpr expr; IloLinearNumExprIterator it2;
while (it.hasNext())
{ IloAddable thing = (IloAddable) it.next();
if (thing
instanceof IloRange)
{ expr = (IloLinearNumExpr) ((IloRange) thing).getExpr(); it2 = expr.linearIterator();
while (it2.hasNext())
{ vars.add(it2.nextNumVar());
}
if ( CONSIDER_QUAD_EXPRS )
{ IloQuadNumExpr qexpr = (IloQuadNumExpr) ((IloRange) thing).getExpr(); IloQuadNumExprIterator qit = qexpr.quadIterator();
while (qit.hasNext())
{ qit.next(); vars.add(qit.getNumVar1()); vars.add(qit.getNumVar2());
}
}
}
else
if (thing
instanceof IloObjective)
{ expr = (IloLinearNumExpr) ((IloObjective) thing).getExpr(); it2 = expr.linearIterator();
while (it2.hasNext())
{ vars.add(it2.nextNumVar());
}
}
else
if (thing
instanceof IloSOS1)
{ vars.addAll(java.util.Arrays.asList(((IloSOS1) thing).getNumVars()));
}
else
if (thing
instanceof IloSOS2)
{ vars.addAll(java.util.Arrays.asList(((IloSOS2) thing).getNumVars()));
}
else
if (thing
instanceof IloLPMatrix)
{ vars.addAll(java.util.Arrays.asList(((IloLPMatrix) thing).getNumVars()));
}
} IloNumVar[] varray = vars.toArray(
new IloNumVar[1]);
return varray;
}
public
static
void main(String[] args)
{
try
{ IloCplex cplex =
new IloCplex(); IloNumVar x = cplex.numVar(0, 1,
"x"); IloNumVar y = cplex.numVar(0, 1,
"y"); cplex.addLe(cplex.prod(x, y), 1); System.out.println(
"Variables:");
for (IloNumVar v : parse(cplex)) System.out.println(
"\t" + v);
}
catch (IloException e)
{ System.err.println(e.getMessage()); System.exit(-1);
}
}
}
> > ...
> > In general I would also recommend to sort the resulting array (for example by variable name) so that each run of the code returns the variables in the same order. Sorting only by hash codes may not return the variables in the same order every time.
>
> Hmm. I thought it was more deterministic than that (assuming of course that the model did not change between runs).
>
I am not exactly sure here. I
think unless you override the hash function in a subclass the hash value may depend on the memory address of the object and that may be non-deterministic? And therefore you may depend on correct overriding of this function. But that really goes beyond my Java expertise :-(
> On the other hand, sorting's not a problem; so I did as you suggested and sorted the vector alphabetically by variable name. The one small annoyance is that IloX11 comes between IloX1 and IloX2, etc. I'm
way too lazy to screw with regex just to fix that. :-)
>
Question is: what will happen if the variables have no names?
In C++ I usually sort on the extractable id but no such thing exists in Java :-(
#CPLEXOptimizers#DecisionOptimization