<br><font size=2 face="sans-serif">Francois,</font>
<br>
<br><font size=2 face="sans-serif">I don't like things becoming more complicated
than they are already and I don't think it is going to help 99% of users,
so I would like to mitigate the damage I think this will cause.</font>
<br>
<br><font size=2 face="sans-serif">1) I don't think CglParam is really
necessary. Different cut generators would need different values e.g.
getMAX_SUPPORT() so I don't think a user would pass a common CglParam into
different generators. Therefore I think it would be much easier to
put common scalars into CglCutGenerator.</font>
<br>
<br><font size=2 face="sans-serif">2) I don't like CglData being in Cgl.
Osi does not know about Cgl and I think it would be useful to have
Osi methods to populate this new data structure. </font>
<br>
<br><font size=2 face="sans-serif">I suggest something in CoinUtils. As
a straw man I have added (and will probably delete in a few days) CoinSnapshot.hpp
and CoinSnapshot.cpp to CoinUtils branches/devel for people to look at.
It has all the same method names as OsiSolverInterface to make it
easier to modify cut generators. It can either own arrays and matrices
or just point to them. If a solution along these lines is adopted
then it would be trivial to put fillSnapshot into OsiSolverInterface to
populate CoinSnapshot from a solver.</font>
<br>
<br><font size=2 face="sans-serif">John Forrest </font>
<br>
<br>
<br>
<table width=100%>
<tr valign=top>
<td width=40%><font size=1 face="sans-serif"><b>fmargot@andrew.cmu.edu</b>
</font>
<p><font size=1 face="sans-serif">12/14/2006 08:44 AM</font>
<td width=59%>
<table width=100%>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">To</font></div>
<td><font size=1 face="sans-serif">John J Forrest/Watson/IBM@IBMUS</font>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">cc</font></div>
<td><font size=1 face="sans-serif">cgl <cgl@list.coin-or.org></font>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">Subject</font></div>
<td><font size=1 face="sans-serif">Re: [Cgl] CGL Design</font></table>
<br>
<table>
<tr valign=top>
<td>
<td></table>
<br></table>
<br>
<br>
<br><tt><font size=2><br>
John:<br>
<br>
I agree that the solution of using an OsiCglSolverInterface instead of
<br>
CglData has the big advantage of not requiring modifications of the<br>
cut generators. However, as Lou pointed out, it creates an ugly<br>
Osi class with most of the functionalities of a OsiSolverInterface<br>
disabled and keeps users in the dark about what data each cut generator<br>
needs.<br>
<br>
The modifications required for using CglData are not that difficult<br>
or dangerous to implement. This can be done by replacing the existing method<br>
<br>
generateCuts(const OsiSolverInterface & si, OsiCuts & cs,<br>
const CglTreeInfo info)<br>
<br>
by three methods:<br>
<br>
A) generateCuts(const OsiSolverInterface & si, OsiCuts & cs,<br>
const CglTreeInfo info)<br>
<br>
B) generateCuts(const CglData data, OsiCuts &cs, const CglTreeInfo
info)<br>
<br>
C) generateCuts(OsiCuts &cs, const CglTreeInfo info)<br>
<br>
The first two are just wrappers that call the third one, which contains<br>
the code currently in generateCuts(). The modifications to be done<br>
is to scan the code for reference to the OsiSolverInterface si.<br>
Each line in C) (or other existing methods) of the form<br>
<br>
some = si.getSomething();<br>
<br>
is replaced by<br>
<br>
some = something;<br>
<br>
where something is a new member in the generator class and<br>
putting in method A):<br>
<br>
something = si.getSomething();<br>
<br>
and in method B):<br>
<br>
something = data.getSomething();<br>
<br>
While mistakes can of course be introduced by doing this, this does<br>
not require a major rewriting of the code. For generators that have<br>
a const OsiSolverInterface si as parameter (and keep it that way),<br>
I do not see how serious mistakes can be introduced. For generators<br>
that are tightly related to the optimal simplex tableau (Gomory, <br>
Lift-and-Project and others) keeping access to the OsiSolver is an option.<br>
<br>
Francois<br>
<br>
<br>
On Tue, 12 Dec 2006, John J Forrest wrote:<br>
<br>
> Francois suggested I might modify the cut generators for which I was<br>
> responsible to use CglData classes, so I looked more closely at the
ideas<br>
> put forward by Francois and Matt - and I strongly dislike them - there<br>
> must be a better way.<br>
><br>
> Matt said he wanted to be independent of any solver or solver interface.
I<br>
> have no problem with the first, but I have with the second. Instead
of a<br>
> known interface OsiSolverInterface it seems that a new CglData interface<br>
> is being proposed which has less functionality and a totally different<br>
> interface. The idea of a simple data object where there is no
virtual<br>
> overhead for getting arrays such as bounds is a good idea. In
fact Laci<br>
> and I are using such a class so that we can share coding between Cbc
and<br>
> BCP. Our attempt (OsiBranchingInformation hidden in file<br>
> OsiBranchingObject.hpp) has practically the same information as CglData.<br>
><br>
> I would suggest a new OsiXxxSolverInterface class derived from<br>
> OsiSolverInterface. It could be filled from an OsiSolverInterface
(either<br>
> owning arrays or not as the user wanted) and would throw an exception
if<br>
> you try and solve anything. It could be extended to have data
that is<br>
> necessary for cuts and for using in a branch and bound code. In
that way<br>
> the existing cut generators could be used without re-writing which
could<br>
> lead to the introduction of bugs.<br>
><br>
> John Forrest<br>
><br>
><br>
><br>
> fmargot@andrew.cmu.edu<br>
> Sent by: cgl-bounces@list.coin-or.org<br>
> 12/04/2006 09:38 AM<br>
><br>
> To<br>
> Matthew Galati <Matthew.Galati@sas.com><br>
> cc<br>
> cgl <cgl@list.coin-or.org><br>
> Subject<br>
> Re: [Cgl] CGL Design<br>
><br>
><br>
><br>
><br>
><br>
><br>
><br>
> I have implemented something similar to what Matt suggested below
for<br>
> getting rid of the dependence on the solver. Currently<br>
> it applies only to the CglRedSplit generator. What I suggest is to<br>
> have a class CglData containing the following members:<br>
><br>
> // Number of constraints<br>
> int nrow;<br>
><br>
> // Number of variables.<br>
> int ncol;<br>
><br>
> // Pointer on matrix of coefficients (ordered by columns).<br>
> CoinPackedMatrix const *matrixByCol;<br>
><br>
> // Pointer on matrix of coefficients (ordered by rows).<br>
> CoinPackedMatrix const *matrixByRow;<br>
><br>
> // Pointer on vector of objective coefficients.<br>
> const double *obj;<br>
><br>
> // Pointer on vector of lower bounds on variables.<br>
> const double *colLower;<br>
><br>
> // Pointer on vector of upper bounds for variables.<br>
> const double *colUpper;<br>
><br>
> // Pointer on vector of lower bounds for constraints.<br>
> const double *rowLower;<br>
><br>
> // Pointer on vector of upper bounds for constraints.<br>
> const double *rowUpper;<br>
><br>
> // Pointer on vector of upper bounds for constraints.<br>
> const double *rowRhs;<br>
><br>
> // Pointer on vector of activity of constraints (i.e. coefficient<br>
> matrix<br>
> // times separateThis)..<br>
> const double *rowActivity;<br>
><br>
> /** Pointer on vector of characters for columns types.<br>
> colType[i] can have values<br>
> <UL><br>
> <LI> 'C' : continuous<br>
> <LI> 'B' : binary<br>
> <LI> 'I' : integer<br>
> </UL><br>
> */<br>
> const char *colType;<br>
><br>
> // Pointer on vector for point to separate.<br>
> const double *separateThis;<br>
><br>
> // Pointer on tree information.<br>
> const CglTreeInfo *treeInfo;<br>
><br>
> /// Pointer on vector for point that should not be cut; only
for debug.<br>
> const double *doNotSeparateThis;<br>
><br>
> Each generator may derive a class (as I did with CglRedSplitData)
to add<br>
> additional data needed by the generator. If a generator does not require<br>
> one of the members, the corresponding pointer may be NULL.<br>
><br>
> Then there are two ways to call the generator:<br>
><br>
> // Use the following for calling the cut generator where
rsdat is<br>
> // a CglRedSplitData object<br>
> cutGen.generateCuts(rsdat, cuts);<br>
><br>
> // Use the following for standard way to call the cut
generator where<br>
> // clp is an OsiSolverInterface<br>
> cutGen.generateCuts(*clp, cuts);<br>
><br>
> What seemed simplest to me was to define private data members in<br>
> CglRedSplit<br>
> to store pointers on the data needed by the generator. Each time<br>
> generateCuts<br>
> is called, all these data members are set, using either the information<br>
> from<br>
> the OsiSolverInterface or the information from the CglRedSplitData
object.<br>
><br>
> Then, there is a private method CglRedSplit::generateCuts(OsiCuts
&cs)<br>
> that<br>
> does the actual cut generation based on the data members in CglRedSplit.<br>
> This seem quite easy to implement and will not disturb any existing
code.<br>
><br>
> I have also put a driver in trunk/Cgl/example/cgl_data_test.cpp that<br>
> can be compiled from build/Cgl/examples/ using<br>
><br>
> make DRIVER=cgl_data_test<br>
><br>
> and run from that directory for example on p0033.mps as<br>
><br>
> ./cgl_data_test ../../Data/Sample/p0033.mps<br>
><br>
> The code shows how to use either methods to call generateCuts().<br>
> Comments are welcome.<br>
><br>
> One thing I do not like is the colType member in CglData. While it
is<br>
> useful,<br>
> I could not find an Osi method returning a pointer on that vector,<br>
> implying<br>
> that it must be constructed by the calling method. If we could replace
it<br>
> with something equivalent existing in Osi, that would be better.<br>
><br>
> Francois<br>
><br>
><br>
><br>
> On Sat, 11 Nov 2006, Matthew Galati wrote:<br>
><br>
>> At Informs, I spoke briefly with Francois Margot about the CGL
design<br>
> that I had suggested a while back (see old thread:<br>
> http://list.coin-or.org/pipermail/coin-discuss/2006-March/001875.html)<br>
>><br>
>> Here is a little more about what I had in mind. I have not tried<br>
> anything like this, nor have I really worked out any details - just<br>
> thinking out loud. Let me know what you think.<br>
>><br>
>> The main idea, is that I want to make CGL independent of any solver
or<br>
> solver interface. In fact, a cut generator to me, is something that
solves<br>
> a separation problem - that is, find a separating hyperplane that
cuts off<br>
> a particular point, and is valid to the feasible region defined by
some<br>
> model. Except for (simplex-based cuts, like Gomory and LiftandProject),<br>
> there is no need to assume anything about where the point is coming
from.<br>
> I propose that CGL have a base class which is completely independent
of<br>
> OSI. This would also allow the CGL library to be used by others, without<br>
> the burden of needing OSI.<br>
>><br>
>> It would also be nice to have a "raw" version of generateCuts
that<br>
> depends on no other COIN libs - but, given most cut implementations
will<br>
> make use of CoinUtils anyway, it is probably fine to use CoinUtils
methods<br>
> and objects. But, this forces Cgl dependence on Coin.<br>
>><br>
>> Example prototype:<br>
>><br>
>> class CglCutGenerator{<br>
>><br>
>> //---<br>
>> //--- Input : (1) a description of the feasible region<br>
>> //--- (2) a point to separate<br>
>> //--- Output: (1) a list of separating hyperplanes<br>
>> //---<br>
>> virtual int generateCuts(const CoinPackedMatrix & matrix,<br>
>>
const double
* collb,<br>
>>
const double
* colub,<br>
>>
const double
* obj,<br>
>>
const double
* rowlb,<br>
>>
const double
* rowub,<br>
>>
const char
* coltype,<br>
>>
const double
* currSol,<br>
>>
vector<CoinCut>
& cuts,<br>
>>
const CglTreeInfo info
= CglTreeInfo())<br>
> = 0;<br>
>> }<br>
>><br>
>> For this, the only new thing we'd need is CoinCut - which can
just be a<br>
> replacement for OsiCut - it should not be tied to Osi, since it has<br>
> nothing specific about any solver. A CoinModel could also help make
this<br>
> cleaner.<br>
>><br>
>> //or... force them to use something like CoinModel<br>
>> virtual int generateCuts(const CoinModel
& model,<br>
>>
const double
* currSol,<br>
>>
vector<CoinCut>
& cuts,<br>
>>
const CglTreeInfo info
= CglTreeInfo())<br>
> = 0;<br>
>><br>
>> All the non-solver specific cuts will be derived from CglCutGenerator<br>
> (as before) - just remove any dependence on Osi. This includes clique,<br>
> knapsack, flowcover, etc.<br>
>><br>
>> Then, for deriving solver specific cuts (like Gomory) - we can
have a<br>
> separate library. One that does depend on Osi (and Cgl). Call it<br>
> libCglOsi. This can also include "wrapper classes" for the
base cuts<br>
> clique, knapsack, etc - so that CglOsi users will have uniformity
- as<br>
> they did before.<br>
>><br>
>> //---<br>
>> //--- Cgl depends on Coin (NOT on Osi)<br>
>> //--- CglOsi depends on Coin, Cgl and Osi<br>
>> //---<br>
>> class CglOsiCutGenerator {<br>
>> private:<br>
>> OsiSolverInterface * si;<br>
>> ...<br>
>> virtual void generateCuts(const OsiSolverInterface &
si,<br>
>>
OsiCuts
& cuts,<br>
>>
const CglTreeInfo<br>
> info = CglTreeInfo())=0;<br>
>> }<br>
>><br>
>><br>
>> So, an example derivation:<br>
>><br>
>> class CglOsiGomory : public CglOsiCutGenerator {<br>
>> //this is exactly the same as before, it is dependent on
Osi<br>
>> ...<br>
>> };<br>
>><br>
>><br>
>> class CglClique : public CglCutGenerator {<br>
>> //this is exactly the same as before, but no dependence
on Osi<br>
>> ...<br>
>> };<br>
>><br>
>><br>
>> class CglOsiClique : public CglOsiCutGenerator {<br>
>> //CglOsiClique is just a wrapper class for CglClique.<br>
>> private:<br>
>> CglClique cglClique;<br>
>> ...<br>
>> virtual void generateCuts(const OsiSolverInterface &
si,<br>
>>
OsiCuts
& cuts,<br>
>>
const CglTreeInfo<br>
> info = CglTreeInfo()){<br>
>><br>
>> cglClique.generateCuts(si.getMatrixByRow(),<br>
>>
si.getColLowerBound(),<br>
>>
si.getColUpperBound(),<br>
>>
...<br>
>>
...<br>
>>
);<br>
>> }<br>
>> }<br>
>><br>
>> In this way, the old users still can just "add cut generators"
- this<br>
> time, they are CglOsiCutGenerator(s), but non-OSI users still have
access<br>
> to cliques, knapsack, etc, via the base classes CglCutGenerator(s).<br>
>><br>
>> Thanks,<br>
>> Matt<br>
>><br>
>> Matthew Galati - Optimization Developer<br>
>> SAS Institute - Analytical Solutions<br>
>> Phone 919-531-0332, R5327<br>
>> Fax 919-677-4444<br>
>> http://coral.ie.lehigh.edu/~magh<br>
>> http://www.sas.com/technologies/analytics/optimization/<br>
>><br>
>><br>
>><br>
>><br>
>><br>
> _______________________________________________<br>
> Cgl mailing list<br>
> Cgl@list.coin-or.org<br>
> http://list.coin-or.org/mailman/listinfo/cgl<br>
><br>
><br>
</font></tt>
<br>