<br><font size=2 face="sans-serif">Francois suggested I might modify the
cut generators for which I was responsible to use CglData classes, so I
looked more closely at the ideas put forward by Francois and Matt - and
I strongly dislike them - there must be a better way.</font>
<br>
<br><font size=2 face="sans-serif">Matt said he wanted to be independent
of any solver or solver interface. &nbsp;I have no problem with the first,
but I have with the second. &nbsp;Instead of a known interface OsiSolverInterface
it seems that a new CglData interface is being proposed which has less
functionality and a totally different interface. &nbsp;The idea of a simple
data object where there is no virtual overhead for getting arrays such
as bounds is a good idea. &nbsp;In fact Laci and I are using such a class
so that we can share coding between Cbc and BCP. &nbsp;Our attempt (OsiBranchingInformation
hidden in file OsiBranchingObject.hpp) has practically the same information
as CglData.</font>
<br>
<br><font size=2 face="sans-serif">I would suggest a new OsiXxxSolverInterface
class derived from OsiSolverInterface. &nbsp;It could be filled from an
OsiSolverInterface (either owning arrays or not as the user wanted) and
would throw an exception if you try and solve anything. &nbsp;It could
be extended to have data that is necessary for cuts and for using in a
branch and bound code. &nbsp;In that way the existing cut generators could
be used without re-writing which could lead to the introduction of bugs.</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>
<br><font size=1 face="sans-serif">Sent by: cgl-bounces@list.coin-or.org</font>
<p><font size=1 face="sans-serif">12/04/2006 09:38 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">Matthew Galati &lt;Matthew.Galati@sas.com&gt;</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 &lt;cgl@list.coin-or.org&gt;</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>
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>
 &nbsp; // Number of constraints<br>
 &nbsp; int nrow;<br>
<br>
 &nbsp; // Number of variables.<br>
 &nbsp; int ncol;<br>
<br>
 &nbsp; // Pointer on matrix of coefficients (ordered by columns).<br>
 &nbsp; CoinPackedMatrix const *matrixByCol;<br>
<br>
 &nbsp; // Pointer on matrix of coefficients (ordered by rows).<br>
 &nbsp; CoinPackedMatrix const *matrixByRow;<br>
<br>
 &nbsp; // Pointer on vector of objective coefficients.<br>
 &nbsp; const double *obj;<br>
<br>
 &nbsp; // Pointer on vector of lower bounds on variables.<br>
 &nbsp; const double *colLower;<br>
<br>
 &nbsp; // Pointer on vector of upper bounds for variables.<br>
 &nbsp; const double *colUpper;<br>
<br>
 &nbsp; // Pointer on vector of lower bounds for constraints.<br>
 &nbsp; const double *rowLower;<br>
<br>
 &nbsp; // Pointer on vector of upper bounds for constraints.<br>
 &nbsp; const double *rowUpper;<br>
<br>
 &nbsp; // Pointer on vector of upper bounds for constraints.<br>
 &nbsp; const double *rowRhs;<br>
<br>
 &nbsp; // Pointer on vector of activity of constraints (i.e. coefficient
matrix<br>
 &nbsp; // times separateThis)..<br>
 &nbsp; const double *rowActivity;<br>
<br>
 &nbsp; /** Pointer on vector of characters for columns types.<br>
 &nbsp; &nbsp; &nbsp; colType[i] can have values<br>
 &nbsp; &nbsp; &nbsp; &lt;UL&gt;<br>
 &nbsp; &nbsp; &nbsp; &lt;LI&gt; 'C' : continuous<br>
 &nbsp; &nbsp; &nbsp; &lt;LI&gt; 'B' : binary<br>
 &nbsp; &nbsp; &nbsp; &lt;LI&gt; 'I' : integer<br>
 &nbsp; &nbsp; &nbsp; &lt;/UL&gt;<br>
 &nbsp; */<br>
 &nbsp; const char *colType;<br>
<br>
 &nbsp; // Pointer on vector for point to separate.<br>
 &nbsp; const double *separateThis;<br>
<br>
 &nbsp; // Pointer on tree information.<br>
 &nbsp; const CglTreeInfo *treeInfo;<br>
<br>
 &nbsp; /// Pointer on vector for point that should not be cut; only for
debug.<br>
 &nbsp; 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>
 &nbsp; &nbsp;// Use the following for calling the cut generator where
rsdat is<br>
 &nbsp; &nbsp;// a CglRedSplitData object<br>
 &nbsp; &nbsp; cutGen.generateCuts(rsdat, cuts);<br>
<br>
 &nbsp; &nbsp; // Use the following for standard way to call the cut generator
where<br>
 &nbsp; &nbsp; // clp is an OsiSolverInterface<br>
 &nbsp; &nbsp; &nbsp;cutGen.generateCuts(*clp, cuts);<br>
<br>
What seemed simplest to me was to define private data members in CglRedSplit<br>
to store pointers on the data needed by the generator. Each time generateCuts<br>
is called, all these data members are set, using either the information
from<br>
the OsiSolverInterface or the information from the CglRedSplitData object.<br>
<br>
Then, there is a private method CglRedSplit::generateCuts(OsiCuts &amp;cs)
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 useful,<br>
I could not find an Osi method returning a pointer on that vector, 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>
&gt; At Informs, I spoke briefly with Francois Margot about the CGL design
that I had suggested a while back (see old thread: http://list.coin-or.org/pipermail/coin-discuss/2006-March/001875.html)<br>
&gt;<br>
&gt; Here is a little more about what I had in mind. I have not tried anything
like this, nor have I really worked out any details - just thinking out
loud. Let me know what you think.<br>
&gt;<br>
&gt; The main idea, is that I want to make CGL independent of any solver
or solver interface. In fact, a cut generator to me, is something that
solves a separation problem - that is, find a separating hyperplane that
cuts off a particular point, and is valid to the feasible region defined
by some model. Except for (simplex-based cuts, like Gomory and LiftandProject),
there is no need to assume anything about where the point is coming from.
I propose that CGL have a base class which is completely independent of
OSI. This would also allow the CGL library to be used by others, without
the burden of needing OSI.<br>
&gt;<br>
&gt; It would also be nice to have a &quot;raw&quot; version of generateCuts
that depends on no other COIN libs - but, given most cut implementations
will make use of CoinUtils anyway, it is probably fine to use CoinUtils
methods and objects. But, this forces Cgl dependence on Coin.<br>
&gt;<br>
&gt; Example prototype:<br>
&gt;<br>
&gt; class CglCutGenerator{<br>
&gt;<br>
&gt; &nbsp;//---<br>
&gt; &nbsp;//--- Input : (1) a description of the feasible region<br>
&gt; &nbsp;//--- &nbsp; &nbsp; &nbsp; &nbsp; (2) a point to separate<br>
&gt; &nbsp;//--- Output: (1) a list of separating hyperplanes<br>
&gt; &nbsp;//---<br>
&gt; &nbsp;virtual int generateCuts(const CoinPackedMatrix &amp; matrix,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const double &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *
collb,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const double &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *
colub,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const double &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *
obj,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const double &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *
rowlb,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const double &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *
rowub,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const char &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
* coltype,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const double &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *
currSol,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; vector&lt;CoinCut&gt; &nbsp; &nbsp; &nbsp; &nbsp;&amp;
cuts,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const CglTreeInfo &nbsp; &nbsp; &nbsp; &nbsp;info
= CglTreeInfo()) = 0;<br>
&gt; }<br>
&gt;<br>
&gt; For this, the only new thing we'd need is CoinCut - which can just
be a replacement for OsiCut - it should not be tied to Osi, since it has
nothing specific about any solver. A CoinModel could also help make this
cleaner.<br>
&gt;<br>
&gt; &nbsp;//or... force them to use something like CoinModel<br>
&gt; &nbsp;virtual int generateCuts(const CoinModel &nbsp; &nbsp; &nbsp;
&nbsp;&amp; model,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const double &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *
currSol,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; vector&lt;CoinCut&gt; &nbsp; &nbsp; &nbsp; &nbsp;&amp;
cuts,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; const CglTreeInfo &nbsp; &nbsp; &nbsp; &nbsp;info
= CglTreeInfo()) = 0;<br>
&gt;<br>
&gt; All the non-solver specific cuts will be derived from CglCutGenerator
(as before) - just remove any dependence on Osi. This includes clique,
knapsack, flowcover, etc.<br>
&gt;<br>
&gt; Then, for deriving solver specific cuts (like Gomory) - we can have
a separate library. One that does depend on Osi (and Cgl). Call it libCglOsi.
This can also include &quot;wrapper classes&quot; for the base cuts clique,
knapsack, etc - so that CglOsi users will have uniformity - as they did
before.<br>
&gt;<br>
&gt; //---<br>
&gt; //--- &nbsp; Cgl &nbsp; &nbsp;depends on Coin (NOT on Osi)<br>
&gt; //--- &nbsp; CglOsi depends on Coin, Cgl and Osi<br>
&gt; //---<br>
&gt; class CglOsiCutGenerator {<br>
&gt; private:<br>
&gt; &nbsp;OsiSolverInterface * si;<br>
&gt; ...<br>
&gt; &nbsp;virtual void generateCuts(const OsiSolverInterface &amp; si,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp;OsiCuts &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp;&amp; cuts,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp;const CglTreeInfo &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;info =
CglTreeInfo())=0;<br>
&gt; }<br>
&gt;<br>
&gt;<br>
&gt; So, an example derivation:<br>
&gt;<br>
&gt; class CglOsiGomory : public CglOsiCutGenerator {<br>
&gt; &nbsp;//this is exactly the same as before, it is dependent on Osi<br>
&gt; &nbsp;...<br>
&gt; };<br>
&gt;<br>
&gt;<br>
&gt; class CglClique : public CglCutGenerator {<br>
&gt; &nbsp;//this is exactly the same as before, but no dependence on Osi<br>
&gt; &nbsp;...<br>
&gt; };<br>
&gt;<br>
&gt;<br>
&gt; class CglOsiClique : public CglOsiCutGenerator {<br>
&gt; &nbsp;//CglOsiClique is just a wrapper class for CglClique.<br>
&gt; private:<br>
&gt; &nbsp;CglClique cglClique;<br>
&gt; ...<br>
&gt; &nbsp;virtual void generateCuts(const OsiSolverInterface &amp; si,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp;OsiCuts &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp;&amp; cuts,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp;const CglTreeInfo &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;info =
CglTreeInfo()){<br>
&gt;<br>
&gt; &nbsp; &nbsp;cglClique.generateCuts(si.getMatrixByRow(),<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; si.getColLowerBound(),<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; si.getColUpperBound(),<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; ...<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; ...<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; );<br>
&gt; &nbsp;}<br>
&gt; }<br>
&gt;<br>
&gt; In this way, the old users still can just &quot;add cut generators&quot;
- this time, they are CglOsiCutGenerator(s), but non-OSI users still have
access to cliques, knapsack, etc, via the base classes CglCutGenerator(s).<br>
&gt;<br>
&gt; Thanks,<br>
&gt; Matt<br>
&gt;<br>
&gt; Matthew Galati - Optimization Developer<br>
&gt; SAS Institute - Analytical Solutions<br>
&gt; Phone 919-531-0332, R5327<br>
&gt; Fax &nbsp; 919-677-4444<br>
&gt; http://coral.ie.lehigh.edu/~magh<br>
&gt; http://www.sas.com/technologies/analytics/optimization/<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
_______________________________________________<br>
Cgl mailing list<br>
Cgl@list.coin-or.org<br>
http://list.coin-or.org/mailman/listinfo/cgl<br>
</font></tt>
<br>