[FlopCpp] Problem using FlopC++ with GLPK

Michal Kaut mail at michalkaut.net
Fri Sep 18 11:37:03 EDT 2009


Renato,

the closest I come to a "collection of notes" you have asked for is my 
note "COIN-OR Tools for Stochastic Programming", which you can get from 
http://work.michalkaut.net/ (I apologize for the shameless 
selv-promotion). Have a look at the Flop-related sections; I would esp. 
recommend the introductory part about indexing of subsets, it had caused 
me a lot of trouble at the start.

Apart of that, I have looked at my code for any glpk-specific parts to 
see if it has any special requirements - and the only thing I found was 
some output-related stuff, which should now work via Osi anyway. In 
other words, Glpk seems to work quite well with Osi (and hence with 
FlopC++), at least for me.

But in the process I have remembered some things, so here is a short and 
collection of very random facts, in case you find them useful. 
[Disclaimer: these are things I used, they might not (and most likely 
are not) the best way of doing it..]
- If you need/want to use direct calls to Glpk methods, you need first a 
pointer to OsiGlpkSolverInterface object connected to your MP_model 
model (model-> gives you pointer to the parent class OsiSolverInterface, 
which does not help). You can get it either during model creation using
OsiGlpkSolverInterface *p2solver = new OsiGlpkSolverInterface;
MP_model model(p2solver);
or any time later as
OsiGlpkSolverInterface *p2solver = 
dynamic_cast<OsiGlpkSolverInterface*>(model.operator->());
Then, p2solver->getModelPtr() returns pointer to the GLPK class LPX. 
This allows you to set parameters that you cannot set via Osi, using
lpx_set_int_parm( p2solver->getModelPtr(), param-name, param-val );
(For Glpk-purists: I know that the lpx_xxx methods are being phased out, 
but they are still the most comfortable way of setting a single param..)

- One problem with OsiGlpk is that it won't give you access to the 
interior point method. The reason is that Glpk has a completely 
different set of methods for IP, not only for solving, but also for 
accessing solution etc. (If you solve the model using IP, Osi will say 
there is no solution, because it reads the solution of simplex method.) 
Hence, if you need IP, you can use Flop and Osi only up to the "attach" 
command and then you would need to revert to the low-level approach 
described above.

- Finally, one general FlopC++ comment: as far as I understand it, Flop 
has its own data structures and writes data into the Osi object first 
when asked to (using attach() or minimize() or maximize()).
This becomes important if you want to change the model after it has been 
attached to the solver (a typical case would be change something and 
resolve): you would be changing the Flop object, not the Osi object! And 
the only way to solve this updated Flop model would be to create a new 
Osi and solve it, losing all the advantages of fast resolve. [Tim, if 
you read this and I am wrong, please correct me - I would love to be 
wrong here..]
Anyway, the way I work with Flop is as follows: I write the model in 
Flop and attach() it to the Osi. If I then want to change something, I 
would change it in the Osi directly - but I would still be using Flop to 
get me the indices of the variables and constraints I would be changing. 
For example, if I want to change obj. coefficient of variable x(4), I 
would use Flop to give me the index of the variable in the Osi object 
and then use the Osi method to change the given obj. coeff. Very easy 
(really!).
In other words, Flop is very useful also in the update&resolve 
situation, one just has to remember to change the Osi model, not the 
Flop model...


Hope I have not bored you to death.

Michal


Renato Bruni wrote:
> Thanks for your help. I also find very useful every suggestion like the
> following.
> 
>> One more comment on the example: in many situations, I would find it
>> more practical to replace
>> modello.maximize( x(0) + x(1) + x(2) );
>> by
>> modello.setObjective( x(0) + x(1) + x(4) );
>> modello.attach();
>> modello.maximize();
> 
> In fact, I would be glad to find something like a collection of suggestions
> for using FlopC++, i.e. a user's manual, but I was not able to find it.
> I also noticed that the same FlopC++ code, that may look correct to me, may
> be understood in the right way by some solver but in the wrong way by some
> other solver, without having error messages in compilation. I have of 
> course
> the doxydoc documentation, but I could not learn about those points from
> that. Does anybody have something like a user's manual, even some personal
> collection of notes and pro memoria for using FlopC++ with different 
> solvers
> (and in particular GLPK, which seems to have peculiar behaviour for some
> things)? Something saying "if you need to add constraints so and so, with
> cbc do so, with glpk do so, and so on". I would appreciate that very much.
> Thanks a lot.
> Renato Bruni
> 
> ----- Original Message ----- From: "Michal Kaut" <mail at michalkaut.net>
> To: "Renato Bruni" <renato.bruni at diei.unipg.it>
> Cc: <flopcpp at list.coin-or.org>
> Sent: Thursday, September 17, 2009 9:03 PM
> Subject: Re: [FlopCpp] Problem using FlopC++ with GLPK
> 
> 
>> I think I have found the problem and solution - I tested it only on the
>> first example. It turned out to be a combination of the following:
>> 1. Osi uses upper-bound = infinity to denote unlimited variables.
>> 2. Each solver uses a different value for infinity.
>> 3. Since FlopC++ has to be able to initialize variables even before it
>> has a solver attached, it uses 1e30 as a default (which, I believe, is
>> Clp's infinity). (One could argue that you have solver attached from the
>> beginning and hence it should be possible to set the correct infinity ..
>> well, feel free to update the code.)
>> 3. glpk's uses 9.9e32, so it will work with the 1e30 upper bounds as
>> values. This is asking for numerical problems.
>> 4. glpk does not recognize it has problems and happily report a wrong
>> solution
>>
>> So, the bottom line is that if you have unbounded variables, you should
>> always change their upper bounds to the solver's infinity.
>> In the case of the first example, just add
>> x.upperLimit(N) = modello.getInfinity();
>> to the model. (Note that you can also use modello->getInfinity(), since
>> the -> operator gives you the Osi object and it has the same function.)
>>
>>
>> One more comment on the example: in many situations, I would find it
>> more practical to replace
>> modello.maximize( x(0) + x(1) + x(2) );
>> by
>> modello.setObjective( x(0) + x(1) + x(4) );
>> modello.attach();
>> modello.maximize();
>> The reason is that the attach() method creates an Osi object, so one can
>> use all the Osi methods to work with it (using the overloaded '->'
>> operator). You can, for example, write an MPS file:
>> modello->writeMps("test");
>> You can also replace the maximize() method and start by solving an LP
>> relaxation of the problem:
>> modello->setObjSense(MP_model::MAXIMIZE);
>> modello->initialSolve();
>> modello->branchAndBound();
>>
>>
>> Hope this helped.
>>
>> Regards,
>> Michal
>>
>>
>> Renato Bruni wrote:
>>> Hello everybody,
>>>
>>> we have some strange behaviour using FlopC++ 1.0.6 (having inside Osi
>>> 0.100.0) and GLPK 4.38.
>>>
>>> If we run the following example, with 5 variables and 2 constraints, we
>>> obtain solution x=(0, 2, 0, 0, 0) and objective= 2
>>> but the solution should be x=(4, 0, 0, 0, 0) and objective= 4
>>>
>>> #include "flopc.hpp"
>>> using namespace flopc;
>>> #include <OsiGlpkSolverInterface.hpp>
>>>
>>> int main() {
>>>     MP_model modello(new OsiGlpkSolverInterface);
>>>     MP_set N(5);
>>>     MP_variable x(N);
>>>     x.integer();
>>>
>>>     MP_constraint vinc1;
>>>     MP_constraint vinc2;
>>>     vinc1 = 2*x(0) + 4*x(1) + 6*x(4) == 8;
>>>     vinc2 = x(0) + x(4) <= 100;
>>>     modello.add(vinc1);
>>>     modello.add(vinc2);
>>>
>>>     modello.maximize( x(0) + x(1) + x(4) );
>>>     x.display("Optimal solution per x:");
>>> }
>>>
>>> If we run this other example, that is the same model with 5 variables 
>>> and
>>> 2 constraints, we obtain solution x=(4, 0, 0, 0, 96) and objective= 4
>>> but the solution should be, like before, x=(4, 0, 0, 0, 0) and 
>>> objective=
>>> 4
>>>
>>> #include "flopc.hpp"
>>> using namespace flopc;
>>> #include <OsiGlpkSolverInterface.hpp>
>>>
>>> int main() {
>>>     MP_model modello(new OsiGlpkSolverInterface);
>>>     MP_set N(5);
>>>     MP_set S(5);
>>>     MP_subset<1> Sub(S);
>>>     Sub.insert(0);
>>>     Sub.insert(1);
>>>     Sub.insert(4);
>>>
>>>     MP_variable x(N);
>>>     x.integer();
>>>
>>>     MP_data COEFF(Sub);
>>> int i;
>>> for(i=0; i<Sub.size();i++)
>>> COEFF(i)= 2*(i+1);//vector COEFF={2,4,6}
>>>     COEFF.display("COEFF ");
>>>
>>>     MP_constraint vinc1;
>>>     MP_constraint vinc2;
>>>     vinc1 = sum(Sub, COEFF(Sub)*x(Sub))==8;//2x0+4x1+6x4==8
>>>     vinc2 = x(0) + x(4) <= 100;
>>>     modello.add(vinc1);
>>>     modello.add(vinc2);
>>>
>>>     modello.maximize( sum(Sub, x(Sub)) );//max(x(0)+x(1)+x(4))
>>>    x.display("Optimal solution per x:");
>>> }
>>>
>>> Which can be the reason(s) of this incorrect behaviour?
>>> Are there incompatibilities between the versions of FlopC++ 1.0.6 and
>>> GLPK
>>> 4.38? In this case, which version of GLPK should be used?
>>>
>>> Thanks for your help.
>>> Best regards,
>>> Renato Bruni
>>>
>>>
>>> _______________________________________________
>>> FlopCpp mailing list
>>> FlopCpp at list.coin-or.org
>>> http://list.coin-or.org/mailman/listinfo/flopcpp
>>>
>>> -------------------------------------------
>>> Modern Hosting PIPNI - http://www.pipni.cz/
>>
>> _______________________________________________
>> FlopCpp mailing list
>> FlopCpp at list.coin-or.org
>> http://list.coin-or.org/mailman/listinfo/flopcpp
> 
> 
> -------------------------------------------
> Modern Hosting PIPNI - http://www.pipni.cz/



More information about the FlopCpp mailing list