[FlopCpp] Question on indexing constraints
Michal Kaut
mail at michalkaut.net
Mon Jun 11 04:14:20 EDT 2007
Hello,
I forgot to attach the example file to my previous email, so I am
sending it again - so please ignore the previous one. I apologize for
any inconvenience...
I have been struggling to understand the indexing of FlopC++ constraints
and must admit I still do not understand it properly. What confuses me
most is that for each type of constraints I wanted to test, I was able
to find several "seemingly equivalent" formulations, all of which
compile, but only one of which gives the expected results.
I have tried to demonstrate it on the attached example, where the
constraints with a name differing only in number are supposed to do the
same thing, but only those that have "WORKS" in the comment actually
generate the expected result. (I should probably confess that I am an
AMPL user, so I have probably different understanding what an "index"
means, compared to the GAMS-influenced designers of FlopC++.)
- Could someone try to explain to me why the bad formulations do not
work, i.e. what they actually do? (They do something, as they compile.)
- Note that the example is only to illustrate indexing, the resulting
model is not supposed to make any sense.
In addition, I was rather disappointed by the compilation speed (i.e.
the lack of it): this very small example takes over a minute to compile
on mu 3GHz Pentium 4 machine with gcc 3.4.5 (mingw on WinXP).
Of this time, 39 seconds are spend on the last three sets of constraints
(getIndx1-3), i.e. the compile+link time is 26 seconds without those
constraints. Is this normal/expected behaviour?
(Another interesting thing is that adding each of the three sets of
constraints individually adds 5s, 10s and 10s respectively, i.e. 25
seconds in total, while adding all three adds 39 seconds to the
compilation time...)
And one more question: is it possible to get rid of the "eval subsetref"
messages? Even with this small example, I get hundreds of them and
setting model.silent() does not switch them off...
Thanks a lot in advance.
Regards,
Michal Kaut
-------------- next part --------------
// $Id$
#include "flopc.hpp"
using namespace flopc;
#include "OsiClpSolverInterface.hpp"
int main() {
int i;
MP_model &model = MP_model::getDefaultModel();
model.setSolver(new OsiClpSolverInterface);
model.verbose();
// model.silent();
enum {a1, a2, a3, numA};
enum {b1, b2, numB};
enum {c1, c2, numC};
MP_set A(numA);
MP_set B(numB);
MP_set C(numC);
MP_subset<2> AB(A,B);
AB.insert(a1, b1);
AB.insert(a1, b2);
AB.insert(a2, b1);
AB.insert(a3, b2);
MP_subset<1> As(A);
As.insert(a1);
As.insert(a3);
MP_index a, b, c, ab;
MP_data dA(A); // dA = {2,4,6}
for (i=0; i<numA; i++)
dA(i) = 2*(i+1);
MP_data dB(B); // dB = {1,2}
for (i=0; i<numB; i++)
dB(i) = i+1;
MP_data dAB(AB); // dAB = {{3,4},{5,.},{.,8}}
MP_data dAB2(AB);
MP_data dAB3(AB);
MP_data dAB4(AB);
// Using 2-dim set name and component set names -> WORKS
dAB(AB(A,B)) = dA(A) + dB(B);
// Using 2-dim set name and component indices -> WORKS
dAB2(AB(a,b)) = dA(a) + dB(b);
// Using component set names only
dAB3(A,B) = dA(A) + dB(B);
// Using only indices
dAB4(a,b) = dA(a) + dB(b);
MP_data dC(C); // dC = {5,6}
for (i=0; i<numC; i++)
dC(i) = i+5;
MP_data dBC(B,C); // dBC = {{5,6},{10,12}}
MP_data dBC2(B,C);
MP_data dBC3(B,C);
// Using set names only -> WORKS
forall(B*C, dBC(B,C) = dB(B) * dC(C));
// Using set names and indices
forall(B(b)*C(c), dBC(b,c) = dB(b) * dC(c));
// Using set names and indices, different syntax
forall((B(b),C(c)), dBC(b,c) = dB(b) * dC(c));
MP_variable xA(A);
MP_variable xAB(AB);
MP_variable xAC(A,C);
MP_variable xABC(AB,C);
// AMPL: for a given 'a' in 'A', want "sum{b in B : (a,b) in AB} x[a,b]"
MP_constraint cA0(A); cA0.setName("cA0");
MP_constraint cA1(A); cA1.setName("cA1");
MP_constraint cA2(A); cA2.setName("cA2");
// Using the two-dim set name -> WORKS
cA0(A) = sum(AB(A,B), dAB(AB) * xAB(AB)) <= 1;
// Using set names
cA1(A) = sum(AB(A,B), dAB(A,B) * xAB(A,B)) <= 1;
// Using indices
cA2(a) = sum(AB(a,b), dAB(a,b) * xAB(a,b)) <= 1;
//
MP_constraint cAB1(AB); cAB1.setName("cAB1");
MP_constraint cAB2(AB); cAB2.setName("cAB2");
MP_constraint cAB3(AB); cAB3.setName("cAB3");
// Using only set names -> WORKS
cAB1(AB) = xAB(AB) <= sum(C, dC(C) * xABC(AB,C));
// Using only indices
cAB2(a,b) = xAB(a,b) <= sum(C(c), dC(c) * xABC(a,b,c));
// Using mixture of set names and indices
cAB3(a,b) = xAB(a,b) <= sum(C, dC(C) * xABC(a,b,C));
//
MP_constraint cAC1(A,C); cAC1.setName("cAC1");
MP_constraint cAC2(A,C); cAC2.setName("cAC2");
// Using set names -> WORKS
cAC1(A,C) = (dA(A) + dC(C)) * xAC(A,C) <= xA(A);
// Using indices -> Works in this case, not in another one
cAC2(a,c) = (dA(a) + dC(c)) * xAC(a,c) <= xA(a);
//
MP_constraint cABC0(AB,C); cABC0.setName("cABC0");
MP_constraint cABC1(AB,C); cABC1.setName("cABC1");
MP_constraint cABC2(AB,C); cABC2.setName("cABC2");
MP_constraint cABC3(AB,C); cABC3.setName("cABC3");
// Using only set names, with AB(A,B) sub-indices -> WORKS
cABC0(AB(A,B),C) = xAC(A,C) + xABC(AB,C) == dBC(B,C);
// Using only set names
cABC1(AB,C) = xAC(A,C) + xABC(AB,C) == dBC(B,C);
// Using indices
cABC2(a,b,c) = xAC(a,c) + xABC(a,b,c) == dBC(b,c);
// Using a mixture of set names and indices
cABC3(AB(a,b),C) = xAC(a,C) + xABC(a,b,C) == dBC(B,C);
//
MP_constraint cAs1(As); cAs1.setName("cAs1");
MP_constraint cAs2(As); cAs2.setName("cAs2");
MP_constraint cAs3(As); cAs3.setName("cAs3");
// Using the superset name for indexing -> WORKS
cAs1(As(A)) = xA(A) <= dA(A);
// Using the (sub)set name for indexing
cAs2(As) = xA(As) <= dA(As);
// Using the (sub)set + index for indexing -> WORKS
cAs3(As(a)) = xA(a) <= dA(a);
//
// These constraints use all variables -> get the variable indices...
MP_constraint getIndx1; getIndx1.setName("getIndx1");
MP_constraint getIndx2; getIndx2.setName("getIndx2");
MP_constraint getIndx3; getIndx3.setName("getIndx3");
// Using only sets (no indices) - WORKS
getIndx1 = sum(A, dA(A) * xA(A)) - sum(AB, dAB(AB) * xAB(AB))
+ sum(A*C, xAC(A,C))
- sum(AB*C, dAB(AB) * dC(C) * xABC(AB,C)) <= 100;
// Using indices; single index for set AB
getIndx2 = sum(A(a), dA(a) * xA(a)) - sum(AB(ab), dAB(ab) * xAB(ab))
+ sum(A(a)*C(c), xAC(a,c))
- sum(AB(ab)*C(c), dAB(ab) * dC(c) * xABC(ab,c)) <= 100;
// Using indices; double index for set AB
getIndx3 = sum(A(a), dA(a) * xA(a)) - sum(AB(a,b), dAB(a,b) * xAB(a,b))
+ sum(A(a)*C(c), xAC(a,c))
- sum(AB(a,b)*C(c), dAB(a,b) * dC(c) * xABC(a,b,c)) <= 100;
MP_expression ObjF = sum(AB, dAB(AB) * xAB(AB));
model.setObjective(ObjF);
model.attach();
model->writeMps("sup_boat");
/**********************************************************************/
cout << "Set AB has " << AB.size() << " elements." << endl;
dA.display("Data dA:");
dB.display("Data dB:");
dAB.display("Data dAB:");
dAB2.display("Data dAB2:");
dAB3.display("Data dAB3 [WRONG]:");
dAB4.display("Data dAB4 [WRONG]:");
dBC.display("Data dBC:");
dBC2.display("Data dBC2 [WRONG]:");
dBC3.display("Data dBC3 [WRONG]:");
/**********************************************************************/
model.minimize();
return 0;
}
More information about the FlopCpp
mailing list