In general, a single call to getValues() will be faster than a loop over getValue().
There is no special class or similar to explicitly support upper triangular matrices. However, one can do better than what you did: Instead of allocating an array of length n*n you only need an array of length (n*(n+1))/2, the other slots in the n*n arrays would never be used. You could also wrap this into a class and in the accessor functions assert that you never access anything in the lower triangle, never access anything out of bounds, etc. Something like this (untested and not optimized in any way) maybe:
class UpperTriangular {
IloBoolVarArray data;
IloInt dim;
static IloInt map(IloInt row, IloInt col, IloInt d) {
assert(row >= 0 && row < d);
assert(col >= 0 && col < d);
assert(col >= row); // upper triangular
return ((d * (d + 1)) / 2
- ((d - row) * (d - row + 1)) / 2
+ (col - row));
}
public:
UpperTriangular(IloEnv env, IloInt dimension, char const *name = 0)
: data(env, (dimension * (dimension + 1)) / 2),
dim(dimension)
{
if ( name ) {
for (IloInt row = 0; row < dim; ++row)
for (IloInt col = row; col < dim; ++col) {
std::stringstream s;
s << name << "[" << row << "," << col << "]";
data[map(row, col, dim)].setName(s.str().c_str());
}
}
}
void end() { data.end(); }
IloBoolVarArray &getData() { return data; }
IloBoolVarArray const getData() const { return data; }
IloInt getDimension () const { return dim; }
IloInt getIndex(IloInt row, IloInt col) const {
return map(row, col, dim);
}
IloBoolVar operator() (IloInt row, IloInt col) {
return data[map(row, col, dim)];
}
};
Then you can do something like
UpperTriangular ut(env, n);
...
cplex.solve();
IloNumArray vals(env);
cplex.getValues(vals, ut.getData());
IloNum value_at_i_j = vals[ut.getIndex(i, j)];
Of course, the 'vals' array could be wrapped into the UpperTriangular class as well ...
#CPLEXOptimizers#DecisionOptimization