source: trunk/Docs/otherclasses.xml @ 113

Last change on this file since 113 was 113, checked in by rlh, 15 years ago

* empty log message *

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.8 KB
Line 
1<?xml version="1.0" encoding="ISO-8859-1"?>
2  <chapter id="otherclasses">
3  <title>
4  Other Classes and Examples
5  </title>
6  <section id="comparison">
7  <title>CbcCompare - Comparison Methods</title>
8  <para>
9  The order in which the nodes of the tree are explored is not predetermined and can be influenced by the user.
10  CBC provides a abstract base class <classname>CbcCompareBase</classname>
11  and several instances which are described in Table Compare Classes Provided.
12  </para>
13    <table frame="none">
14  <title>Compare Classes Provided</title>
15    <tgroup cols="2">
16    <thead>
17    <row>
18    <entry>
19    Class name
20    </entry>
21    <entry>
22    Description
23    </entry>
24    </row>
25    </thead>
26    <tbody>
27    <row>
28      <entry align="left" valign="top">
29      <classname>CbcCompareDepth</classname>
30      </entry>
31      <entry align="left" valign="top">
32      This will always choose the node deepest in tree.  It gives minimum
33      tree size but may take a long time to find best solution.
34      </entry>
35    </row>
36    <row>
37      <entry align="left" valign="top">
38      <classname>CbcCompareObjective</classname>
39      </entry>
40      <entry align="left" valign="top">
41      This will always choose the node with the best objective value.  This may
42      give a very large tree.  It is likely that the first solution found
43      will be the best and the search should finish soon after the first solution
44      is found.
45      </entry>
46    </row>
47    <row>
48      <entry align="left" valign="top">
49      <classname>CbcCompareDefault</classname>
50      </entry>
51      <entry align="left" valign="top">
52      This is designed to do a mostly depth first search until a solution has
53      been found and then use estimates designed to give a slightly better solution.
54      If a reasonable number of nodes have been done or a reasonable number of
55      solutions found then it will go breadth first (i.e. on objective) unless
56      the tree is very large when it will revert to depth first.  Probably
57      <classname>CbcCompareUser</classname> described below is better.
58      </entry>
59    </row>
60    <row>
61      <entry align="left" valign="top">
62      <classname>CbcCompareEstimate</classname>
63      </entry>
64      <entry align="left" valign="top">
65      If pseudocosts are being used then they can be used to guess a solution.
66      This just uses guessed solution.
67      </entry>
68    </row>
69    </tbody>
70  </tgroup>
71  </table>
72  <para>
73  It is relatively simple for an advanced user to create new compare class instances.  This describes how to build a new comparison class and the reasoning behind it. This is <filename>CbcCompareUser.hpp</filename> and <filename>CbcCompareUser.cpp</filename> (this code can be found in the CBC Samples directory, see
74  <xref linkend="moreexamples"/>).  The key <classname>CbcCompare</classname> method is <function>bool test(CbcNode* x, CbcNode* y))</function> which returns true if node <parameter>y</parameter> is better than node <parameter>x</parameter>. In this method the user can easily use the following information available from <classname>CbcModel</classname>.
75  <table frame="none">
76  <title>Information Available from <classname>CbcNode</classname></title>
77    <tgroup cols="2">
78    <tbody>
79    <row>
80      <entry align="left" valign="top">
81      <function>double objectiveValue() const</function>
82      </entry>
83      <entry align="left" valign="top">
84      Value of objective at that node.
85      </entry>
86    </row>
87    <row>
88      <entry align="left" valign="top">
89      <function>int numberUnsatisfied() const</function>
90      </entry>
91      <entry align="left" valign="top">
92      Number of unsatisfied integers (assuming branching
93      object is an integer - otherwise might be number of unsatsified sets).
94      </entry>
95    </row>
96    <row>
97      <entry align="left" valign="top">
98      <function>int depth() const</function>
99      </entry>
100      <entry align="left" valign="top">
101       Depth of the node in the search tree.
102      </entry>
103    </row>
104    <row>
105      <entry align="left" valign="top">
106      <function>double guessedObjectiveValue() const</function>
107      </entry>
108     <entry align="left" valign="top"> 
109     If user was setting this (e.g., if using pseudo costs).
110      </entry>
111    </row>
112    <row>
113      <entry align="left" valign="top">
114      <function>int way() const</function>
115      </entry>
116      <entry align="left" valign="top">
117       The way which branching would next occur from this node
118       (for more advanced use).
119      </entry>
120    </row>
121    <row>
122      <entry align="left" valign="top">
123      <function>int variable() const</function>
124      </entry>
125      <entry align="left" valign="top">
126       The branching "variable" (associated with the <classname>CbcBranchingObject</classname> -- for more advanced use).
127      </entry>
128    </row>
129    </tbody>
130  </tgroup>
131  </table>
132</para>
133
134<para>
135  There is no information on the state of the tree. If you wanted you could
136  keep a pointer to the <classname>CbcModel</classname> but the way it is meant to work is that
137  <function>newSolution()</function> is called whenever a solution is found and <function>every1000Nodes()</function> is called every 1000 nodes.  When these are called the user can modify the
138  behavior of <function>test()</function>.  Because <classname>CbcNode</classname> has a pointer to the model, the user can also do other things such as changing the maximum time of CBC once a solution has been found (e.g., <function>CbcModel::setMaximumSeconds(double value)</function>). In <filename>CbcCompareUser.cpp</filename> in <filename>COIN/Cbc/Samples</filename> four items of data are used.
139</para>
140<itemizedlist>
141  <listitem>
142  <para>
1431) The number of solutions found so far
144  </para>
145  </listitem>
146  <listitem>
147  <para>
1482) The size of the tree (defined to be the number of active nodes)
149  </para>
150  </listitem>
151  <listitem>
152  <para>
1533) A weight which is initialized to -1.0
154  </para>
155  </listitem>
156  <listitem>
157  <para>
1584) A saved value of weight (for when we set weight back to -1.0 for special reason)
159  </para>
160  </listitem>
161</itemizedlist>
162<para>
163The full code for <function>CbcCompareUser::test()</function> is given below.
164</para>
165  <example>
166  <title>test</title>
167  <programlisting>
168  <![CDATA[ 
169// Returns true if y better than x
170bool
171CbcCompareUser::test (CbcNode * x, CbcNode * y)
172{
173  if (weight_==-1.0) {
174    // before solution
175    if (x->numberUnsatisfied() > y->numberUnsatisfied())
176      return true;
177    else if (x->numberUnsatisfied() < y->numberUnsatisfied())
178      return false;
179    else
180      return x->depth() < y->depth();
181  } else {
182    // after solution
183    double weight = CoinMax(weight_,0.0);
184    return x->objectiveValue()+ weight*x->numberUnsatisfied() >
185      y->objectiveValue() + weight*y->numberUnsatisfied();
186  }
187}
188  ]]>   
189  </programlisting>
190  </example>
191<para>
192Initially, <varname>weight</varname>_ is &lt; 0.0 and we are biased towards depth first.  In
193fact, the method prefers <parameter>y</parameter> if <parameter>y</parameter> has fewer unsatisfied variables. In the case of a tie, the method prefers the node with the greater depth in tree.
194
195Once we get a solution <function>newSolution()</function> is called.  If it was a solution
196achieved by branching, <!-- how do can you determine that? --> we work out how much it cost per unsatisfied integer
197variable to go from continuous solution to integer solution.  We then set the weight to aim at a slightly better solution.  From then on the method <function>test()</function> returns true if it looks as if <parameter>y</parameter> will lead to a better solution than <parameter>x</parameter>. This is done by <function>newSolution()</function>.
198</para>
199  <example>
200  <title>newSolution</title>
201  <programlisting>
202  <![CDATA[ 
203// This allows method to change behavior as it is called
204// after each solution
205void
206CbcCompareUser::newSolution(CbcModel * model,
207                               double objectiveAtContinuous,
208                               int numberInfeasibilitiesAtContinuous)
209{
210  if (model->getSolutionCount()==model->getNumberHeuristicSolutions())
211    return; // solution was got by rounding so we ignore
212  // set to get close to this solution
213  double costPerInteger =
214    (model->getObjValue()-objectiveAtContinuous)/
215    ((double) numberInfeasibilitiesAtContinuous);
216  weight_ = 0.98*costPerInteger;
217  saveWeight_=weight_;
218  numberSolutions_++;
219  if (numberSolutions_>5)
220    weight_ =0.0; // this searches on objective
221}
222  ]]>   
223  </programlisting>
224  </example>
225<para>
226
227But as the search goes on this <!-- what? is "this"? --> may be modified. If a lot of nodes or got a lot of solutions have been genereated, then <varname>weight_</varname> is set to 0.0 so we are doing breadth-first search.  Breadth-first search can lead to an enormous tree. If the tree size is exceeds 10000, then we may desire to go back to a search biased towards depth first. Changing the behaviour done by the method <function>every1000Nodes</function>.
228  </para>
229  <example>
230  <title>newSolution</title>
231  <programlisting>
232  <![CDATA[ 
233// This allows method to change behavior
234bool
235CbcCompareUser::every1000Nodes(CbcModel * model, int numberNodes)
236{
237  if (numberNodes>10000)
238    weight_ =0.0; // this searches on objective
239  else if (numberNodes==1000&&weight_==-2.0)
240    weight_=-1.0; // Go to depth first
241  // get size of tree
242  treeSize_ = model->tree()->size();
243  if (treeSize_>10000) {
244    // set weight to reduce size most of time
245    if (treeSize_>20000)
246      weight_=-1.0;
247    else if ((numberNodes%4000)!=0)
248      weight_=-1.0;
249    else
250      weight_=saveWeight_;
251  }
252  return numberNodes==11000; // resort if first time
253}
254  ]]>   
255  </programlisting>
256  </example>
257  </section>
258  <section id="heuristics">
259  <title>CbcHeuristic - Heuristic Methods</title>
260  <para>
261  In practice, it is very useful to get a good solution reasonably fast.
262  A good bound will greatly reduce the run time and good solutions can satisfy the user
263  on very large problems where a complete search is impossible.  Obviously, heuristics are
264  problem dependent although some have more general use.
265  At present there is only one in CBC itself. Hopefully, the number of heuristics will grow.
266  Other hueristics are in the <filename>COIN/Cbc/Samples</filename>
267  directory.  A heuristic tries to obtain a solution to the original
268  problem so it only needs to consider the original rows and does not have to use the
269  current bounds.
270  One to use a greedy heuristic designed for use in the miplib problem
271  fast0507 will be developed later in this section. <!-- huh? -->
272  CBC provides an abstract base class <classname>CbcHeuristic</classname> and a rounding heuristic in CBC.
273  </para>
274  <para>
275  This describes how to build a greedy heuristic for a set covering problem.
276   A more general version is in <filename>CbcHeuristicGreedy.hpp</filename> and
277   <filename>CbcHeuristicGreedy.cpp</filename> which can be found in the <filename>COIN/Cbc/Samples</filename> directory, see <xref linkend="moreexamples"/>.
278
279  The heuristic we will code will leave all variables which are at one at this node of the
280  tree to that value and will
281  initially set all others to zero.  We then sort all variables in order of their cost
282  divided by the number of entries in rows which are not yet covered.  We may randomize that
283  value a bit so that ties will be broken in different ways on different runs of the heuristic.
284  We then choose the best one and set it to one and repeat the exercise. Because this is
285  a set covering problem &ge; we are guaranteed to find a solution (not necessarily a
286  better one though).  We could
287  improve the speed by just redoing those affected but in this text we will keep it simple.
288  Also if all elements are 1.0 then we could do faster.
289  The key CbcHeuristic method is <function>int&nbsp;solution(double &amp; solutionValue,
290                                              double&nbsp;*&nbsp;betterSolution)</function>
291  which returns 0 if no solution found and 1 if found when it fills in the objective value
292  and primal solution.  The actual code in <filename>CbcHeuristicGreedy.cpp</filename> is
293  a little more complicated but this will work and gives the basic idea.  For instance
294  the code here assumes all variables are integer.
295  The important bit of data is a copy of the matrix (stored by column)
296  before any cuts have been made.  The data used are bounds, objective and the matrix
297  plus two work arrays.
298  </para>
299  <example>
300  <title>Data</title>
301  <programlisting>
302  <![CDATA[ 
303  OsiSolverInterface * solver = model_->solver(); // Get solver from CbcModel
304  const double * columnLower = solver->getColLower(); // Column Bounds
305  const double * columnUpper = solver->getColUpper();
306  const double * rowLower = solver->getRowLower(); // We know we only need lower bounds
307  const double * solution = solver->getColSolution();
308  const double * objective = solver->getObjCoefficients(); // In code we also use min/max
309  double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
310  double primalTolerance;
311  solver->getDblParam(OsiPrimalTolerance,primalTolerance);
312  int numberRows = originalNumberRows_; // This is number of rows when matrix was passed in
313  // Column copy of matrix (before cuts)
314  const double * element = matrix_.getElements();
315  const int * row = matrix_.getIndices();
316  const CoinBigIndex * columnStart = matrix_.getVectorStarts();
317  const int * columnLength = matrix_.getVectorLengths();
318
319  // Get solution array for heuristic solution
320  int numberColumns = solver->getNumCols();
321  double * newSolution = new double [numberColumns];
322  // And to sum row activities
323  double * rowActivity = new double[numberRows];
324  ]]>   
325  </programlisting>
326  </example>
327<para>
328Then we initialize newSolution as rounded down solution.
329</para>
330  <example>
331  <title>initialize newSolution</title>
332  <programlisting>
333  <![CDATA[ 
334  for (iColumn=0;iColumn<numberColumns;iColumn++) {
335    CoinBigIndex j;
336    double value = solution[iColumn];
337    // Round down integer
338    if (fabs(floor(value+0.5)-value)<integerTolerance)
339      value=floor(CoinMax(value+1.0e-3,columnLower[iColumn]));
340    // make sure clean
341    value = CoinMin(value,columnUpper[iColumn]);
342    value = CoinMax(value,columnLower[iColumn]);
343    newSolution[iColumn]=value;
344    if (value) {
345      double cost = direction * objective[iColumn];
346      newSolutionValue += value*cost;
347      for (j=columnStart[iColumn];
348           j<columnStart[iColumn]+columnLength[iColumn];j++) {
349        int iRow=row[j];
350        rowActivity[iRow] += value*element[j];
351      }
352    }
353  }
354  ]]>   
355  </programlisting>
356  </example>
357<para>
358Now some row activities will be below their lower bound so
359we then find the variable which is cheapest in reducing the sum of
360infeasibilities.  We then repeat.  This is a finite process and could be coded
361to be faster but this is simplest.
362  </para>
363  <example>
364  <title>Create feasible new solution</title>
365  <programlisting>
366  <![CDATA[ 
367  while (true) {
368    // Get column with best ratio
369    int bestColumn=-1;
370    double bestRatio=COIN_DBL_MAX;
371    for (int iColumn=0;iColumn<numberColumns;iColumn++) {
372      CoinBigIndex j;
373      double value = newSolution[iColumn];
374      double cost = direction * objective[iColumn];
375      // we could use original upper rather than current
376      if (value+0.99<columnUpper[iColumn]) {
377        double sum=0.0; // Compute how much we will reduce infeasibility by
378        for (j=columnStart[iColumn];
379             j<columnStart[iColumn]+columnLength[iColumn];j++) {
380          int iRow=row[j];
381          double gap = rowLower[iRow]-rowActivity[iRow];
382          if (gap>1.0e-7) {
383            sum += CoinMin(element[j],gap);
384          if (element[j]+rowActivity[iRow]<rowLower[iRow]+1.0e-7) {
385            sum += element[j];
386          }
387        }
388        if (sum>0.0) {
389          double ratio = (cost/sum)*(1.0+0.1*CoinDrand48());
390          if (ratio<bestRatio) {
391            bestRatio=ratio;
392            bestColumn=iColumn;
393          }
394        }
395      }
396    }
397    if (bestColumn<0)
398      break; // we have finished
399    // Increase chosen column
400    newSolution[bestColumn] += 1.0;
401    double cost = direction * objective[bestColumn];
402    newSolutionValue += cost;
403    for (CoinBigIndex j=columnStart[bestColumn];
404         j<columnStart[bestColumn]+columnLength[bestColumn];j++) {
405      int iRow = row[j];
406      rowActivity[iRow] += element[j];
407    }
408  }
409  ]]>   
410  </programlisting>
411  </example>
412<para>
413We have finished so now we need to see if solution is better and doublecheck
414we are feasible.
415  </para>
416  <example>
417  <title>Check good solution</title>
418  <programlisting>
419  <![CDATA[ 
420  returnCode=0; // 0 means no good solution
421  if (newSolutionValue<solutionValue) {
422    // check feasible
423    memset(rowActivity,0,numberRows*sizeof(double));
424    for (iColumn=0;iColumn<numberColumns;iColumn++) {
425      CoinBigIndex j;
426      double value = newSolution[iColumn];
427      if (value) {
428        for (j=columnStart[iColumn];
429             j<columnStart[iColumn]+columnLength[iColumn];j++) {
430          int iRow=row[j];
431          rowActivity[iRow] += value*element[j];
432        }
433      }
434    }
435    // check was approximately feasible
436    bool feasible=true;
437    for (iRow=0;iRow<numberRows;iRow++) {
438      if(rowActivity[iRow]<rowLower[iRow]) {
439        if (rowActivity[iRow]<rowLower[iRow]-10.0*primalTolerance)
440          feasible = false;
441      }
442    }
443    if (feasible) {
444      // new solution
445      memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
446      solutionValue = newSolutionValue;
447      // We have good solution
448      returnCode=1;
449    }
450  }
451  ]]>   
452  </programlisting>
453  </example>
454  </section>
455  <section id="branching">
456  <title>Branching</title>
457  <para>
458If the user declares variables as integer but does no more, then Cbc will treat them
459as simple integer variables.  In many cases the user would like to do some more fine tuning.  This shows how to create integer variables with pseudo costs.  When pseudo costs are given then
460it is assumed that if a variable is at 1.3 then the cost of branching that variable down will be 0.3 times the down pseudo cost and the cost of branching up would be 0.7 times the up pseudo cost.  This can be used both for branching and for choosing a node.
461   The full code is in <filename>longthin.cpp</filename>
462  (this code can be found in the CBC Samples directory, see
463  <xref linkend="moreexamples"/>). 
464  The idea is simple for set covering problems.
465  Branching up gets us much closer to an integer solution so we want
466  to encourage up - so we will branch up if variable value > 0.333333.
467  The expected cost of going up obviously depends on the cost of the
468  variable so we just choose pseudo costs to reflect that.
469  </para>
470  <example>
471  <title>Pseudo costs</title>
472  <programlisting>
473  <![CDATA[ 
474  int iColumn;
475  int numberColumns = solver3->getNumCols();
476  // do pseudo costs
477  CbcObject ** objects = new CbcObject * [numberColumns];
478  // Point to objective
479  const double * objective = model.getObjCoefficients();
480  int numberIntegers=0;
481  for (iColumn=0;iColumn<numberColumns;iColumn++) {
482    if (solver3->isInteger(iColumn)) {
483      double cost = objective[iColumn];
484      CbcSimpleIntegerPseudoCost * newObject =
485        new CbcSimpleIntegerPseudoCost(&model,numberIntegers,iColumn,
486                                       2.0*cost,cost);
487      newObject->setMethod(3);
488      objects[numberIntegers++]= newObject;
489    }
490  }
491  // Now add in objects (they will replace simple integers)
492  model.addObjects(numberIntegers,objects);
493  for (iColumn=0;iColumn<numberIntegers;iColumn++)
494    delete objects[iColumn];
495  delete [] objects;
496  ]]>   
497  </programlisting>
498  </example>
499<para>
500The actual coding in the example also tries to give more importance to variables with more
501coefficients.  Whether this sort of thing is worthwhile should be the subject of experimentation.
502Here is another example which is for crew scheduling problems.  In this case the problem has
503few rows but many thousands of variables.  Branching a variable to 1 is very powerful as it
504fixes many other variables to zero, but branching to zero is very weak as thousands of variables
505can increase from zero.  But in crew scheduling each constraint is a flight leg e.g. JFK to DFW.
506From DFW (Dallas) there may be several flights the crew could take next - suppose one flight is
507the 9:30 flight from DFW to LAX (Los Angeles).  Then a binary branch is that the crew arriving
508at DFW either take the 9:30 flight to LAX or they don't.  This follow-on branching does not
509fix individual variables but instead divides all the variables with entries in the JFK-DFW
510constraint into two groups - those with entries in the DFW-LAX constraint and those without
511entries.
512   The full code is in <filename>crew.cpp</filename>
513  (this code can be found in the CBC Samples directory, see
514  <xref linkend="moreexamples"/>).  In this case we may as well leave the simple integer
515variables and we may have to if there are other sorts of constraints.  But we want to
516branch on the follow-on rules first so we use priorities to say that those are the
517important ones.
518</para>
519  <example>
520  <title>Follow-on branching</title>
521  <programlisting>
522  <![CDATA[ 
523  int iColumn;
524  int numberColumns = solver3->getNumCols();
525  /* We are going to add a single follow on object but we
526     want to give low priority to existing integers
527     As the default priority is 1000 we don't actually need to give
528     integer priorities but it is here to show how.
529  */
530  // Normal integer priorities
531  int * priority = new int [numberColumns];
532  int numberIntegers=0;
533  for (iColumn=0;iColumn<numberColumns;iColumn++) {
534    if (solver3->isInteger(iColumn)) {
535      priority[numberIntegers++]= 100; // low priority
536    }
537  }
538  /* Second parameter is true if we are adding objects,
539     false if integers.  So this does integers */
540  model.passInPriorities(priority,false);
541  delete [] priority;
542  /* Add in objects before we can give priority.
543     In this case just one - but this shows general method
544  */
545  CbcObject ** objects = new CbcObject * [1];
546  objects[0]=new CbcFollowOn(&model);
547  model.addObjects(1,objects);
548  delete objects[0];
549  delete [] objects;
550  // High priority
551  int followPriority=1;
552  model.passInPriorities(&followPriority,true);
553  ]]>   
554  </programlisting>
555  </example>
556  </section>
557  <section id="solver">
558  <title>Advanced use of solver</title>
559  <para>
560  Coin Branch and Cut uses a generic OsiSolverInterface and its <function>resolve</function> capability.
561  This does not give much flexibility so advanced users can inherit from the interface
562  of choice.  This describes such a solver for a long thin problem e.g. fast0507 again.
563  As with all these examples it is not guaranteed that this is the fastest way to solve
564  any of these problems - they are to illustrate techniques.
565   The full code is in <filename>CbcSolver2.hpp</filename> and
566   <filename>CbcSolver2.cpp</filename>
567  (this code can be found in the CBC Samples directory, see
568  <xref linkend="moreexamples"/>).
569  <function>initialSolve</function> is called a few times so although we will not gain much
570  this is a simpler place to start.  The example derives from OsiClpSolverInterface and the code
571  is:
572  </para>
573  <example>
574  <title>initialSolve</title>
575  <programlisting>
576  <![CDATA[ 
577  // modelPtr_ is of type ClpSimplex *
578  modelPtr_->setLogLevel(1); // switch on a bit of printout
579  modelPtr_->scaling(0); // We don't want scaling for fast0507
580  setBasis(basis_,modelPtr_); // Put basis into ClpSimplex
581  // Do long thin by sprint
582  ClpSolve options;
583  options.setSolveType(ClpSolve::usePrimalorSprint);
584  options.setPresolveType(ClpSolve::presolveOff);
585  options.setSpecialOption(1,3,15); // Do 15 sprint iterations
586  modelPtr_->initialSolve(options); // solve problem
587  basis_ = getBasis(modelPtr_); // save basis
588  modelPtr_->setLogLevel(0); // switch off printout
589  ]]>   
590  </programlisting>
591  </example>
592<para>
593The <function>resolve</function> method is more complicated.  The main pieces of data are
594a counter count_ which is incremented each solve and an int array node_ which stores the last time
595a variable was active in a solution.  For the first few times normal dual is called and
596node_ array is updated.
597</para>
598  <example>
599  <title>First few solves</title>
600  <programlisting>
601  <![CDATA[ 
602  if (count_<10) {
603    OsiClpSolverInterface::resolve(); // Normal resolve
604    if (modelPtr_->status()==0) {
605      count_++; // feasible - save any nonzero or basic
606      const double * solution = modelPtr_->primalColumnSolution();
607      for (int i=0;i<numberColumns;i++) {
608        if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) {
609          node_[i]=CoinMax(count_,node_[i]);
610          howMany_[i]++;
611        }
612      }
613    } else {
614      printf("infeasible early on\n");
615    }
616  }
617  ]]>   
618  </programlisting>
619  </example>
620<para>
621After the first few solves we only use those which took part in a solution in the last so many
622solves.  As fast0507 is a set covering problem we can also take out any rows which are
623already covered.
624  </para>
625  <example>
626  <title>Create small problem</title>
627  <programlisting>
628  <![CDATA[ 
629    int * whichRow = new int[numberRows]; // Array to say which rows used
630    int * whichColumn = new int [numberColumns]; // Array to say which columns used
631    int i;
632    const double * lower = modelPtr_->columnLower();
633    const double * upper = modelPtr_->columnUpper();
634    setBasis(basis_,modelPtr_); // Set basis
635    int nNewCol=0; // Number of columns in small model
636    // Column copy of matrix
637    const double * element = modelPtr_->matrix()->getElements();
638    const int * row = modelPtr_->matrix()->getIndices();
639    const CoinBigIndex * columnStart = modelPtr_->matrix()->getVectorStarts();
640    const int * columnLength = modelPtr_->matrix()->getVectorLengths();
641   
642    int * rowActivity = new int[numberRows]; // Number of columns with entries in each row
643    memset(rowActivity,0,numberRows*sizeof(int));
644    int * rowActivity2 = new int[numberRows]; // Lower bound on row activity for each row
645    memset(rowActivity2,0,numberRows*sizeof(int));
646    char * mark = (char *) modelPtr_->dualColumnSolution(); // Get some space to mark columns
647    memset(mark,0,numberColumns);
648    for (i=0;i<numberColumns;i++) {
649      bool choose = (node_[i]>count_-memory_&&node_[i]>0); // Choose if used recently
650      // Take if used recently or active in some sense
651      if ((choose&&upper[i])
652          ||(modelPtr_->getStatus(i)!=ClpSimplex::atLowerBound&&
653             modelPtr_->getStatus(i)!=ClpSimplex::isFixed)
654          ||lower[i]>0.0) {
655        mark[i]=1; // mark as used
656        whichColumn[nNewCol++]=i; // add to list
657        CoinBigIndex j;
658        double value = upper[i];
659        if (value) {
660          for (j=columnStart[i];
661               j<columnStart[i]+columnLength[i];j++) {
662            int iRow=row[j];
663            assert (element[j]==1.0);
664            rowActivity[iRow] ++; // This variable can cover this row
665          }
666          if (lower[i]>0.0) {
667            for (j=columnStart[i];
668                 j<columnStart[i]+columnLength[i];j++) {
669              int iRow=row[j];
670              rowActivity2[iRow] ++; // This row redundant
671            }
672          }
673        }
674      }
675    }
676    int nOK=0; // Use to count rows which can be covered
677    int nNewRow=0; // Use to make list of rows needed
678    for (i=0;i<numberRows;i++) {
679      if (rowActivity[i])
680        nOK++;
681      if (!rowActivity2[i])
682        whichRow[nNewRow++]=i; // not satisfied
683      else
684        modelPtr_->setRowStatus(i,ClpSimplex::basic); // make slack basic
685    }
686    if (nOK<numberRows) {
687      // The variables we have do not cover rows - see if we can find any that do
688      for (i=0;i<numberColumns;i++) {
689        if (!mark[i]&&upper[i]) {
690          CoinBigIndex j;
691          int good=0;
692          for (j=columnStart[i];
693               j<columnStart[i]+columnLength[i];j++) {
694            int iRow=row[j];
695            if (!rowActivity[iRow]) {
696              rowActivity[iRow] ++;
697              good++;
698            }
699          }
700          if (good) {
701            nOK+=good; // This covers - put in list
702            whichColumn[nNewCol++]=i;
703          }
704        }
705      }
706    }
707    delete [] rowActivity;
708    delete [] rowActivity2;
709    if (nOK<numberRows) {
710      // By inspection the problem is infeasible - no need to solve
711      modelPtr_->setProblemStatus(1);
712      delete [] whichRow;
713      delete [] whichColumn;
714      printf("infeasible by inspection\n");
715      return;
716    }
717    // Now make up a small model with the right rows and columns
718    ClpSimplex *  temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn);
719  ]]>   
720  </programlisting>
721  </example>
722<para>
723If the variables cover the rows then we know that the problem is feasible (We are not using
724cuts).  If the rows
725were E rows then this might not be the case and we would have to do more work.  When we have solved
726then we see if there are any negative reduced costs and if there are then we have to go to the
727full problem and use primal to clean up.
728  </para>
729  <example>
730  <title>Check optimal solution</title>
731  <programlisting>
732  <![CDATA[ 
733    temp->setDualObjectiveLimit(1.0e50); // Switch off dual cutoff as problem is restricted
734    temp->dual(); // solve
735    double * solution = modelPtr_->primalColumnSolution(); // put back solution
736    const double * solution2 = temp->primalColumnSolution();
737    memset(solution,0,numberColumns*sizeof(double));
738    for (i=0;i<nNewCol;i++) {
739      int iColumn = whichColumn[i];
740      solution[iColumn]=solution2[i];
741      modelPtr_->setStatus(iColumn,temp->getStatus(i));
742    }
743    double * rowSolution = modelPtr_->primalRowSolution();
744    const double * rowSolution2 = temp->primalRowSolution();
745    double * dual = modelPtr_->dualRowSolution();
746    const double * dual2 = temp->dualRowSolution();
747    memset(dual,0,numberRows*sizeof(double));
748    for (i=0;i<nNewRow;i++) {
749      int iRow=whichRow[i];
750      modelPtr_->setRowStatus(iRow,temp->getRowStatus(i));
751      rowSolution[iRow]=rowSolution2[i];
752      dual[iRow]=dual2[i];
753    }
754    // See if optimal
755    double * dj = modelPtr_->dualColumnSolution();
756    // get reduced cost for large problem
757    // this assumes minimization
758    memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double));
759    modelPtr_->transposeTimes(-1.0,dual,dj);
760    modelPtr_->setObjectiveValue(temp->objectiveValue());
761    modelPtr_->setProblemStatus(0);
762    int nBad=0;
763     
764    for (i=0;i<numberColumns;i++) {
765      if (modelPtr_->getStatus(i)==ClpSimplex::atLowerBound
766          &&upper[i]>lower[i]&&dj[i]<-1.0e-5)
767        nBad++;
768    }
769    // If necessary claen up with primal (and save some statistics)
770    if (nBad) {
771      timesBad_++;
772      modelPtr_->primal(1);
773      iterationsBad_ += modelPtr_->numberIterations();
774    }
775  ]]>   
776  </programlisting>
777  </example>
778<para>
779We then update node_ array as for the first few solves.  To give some idea of the effect of this
780tactic fast0507 has 63,009 variables and the small problem never has more than 4,000 variables.
781In just over ten percent of solves did we have to resolve and then the average number of iterations
782on full problem was less than 20.
783To give another example - again only for illustrative purposes it is possible to do quadratic
784mip.  In this case we make <function>resolve</function> the same as
785<function>initialSolve</function>.
786   The full code is in <filename>ClpQuadInterface.hpp</filename> and
787   <filename>ClpQuadInterface.cpp</filename>
788  (this code can be found in the CBC Samples directory, see
789  <xref linkend="moreexamples"/>).
790  </para>
791  <example>
792  <title>Solve a quadratic mip</title>
793  <programlisting>
794  <![CDATA[ 
795  // save cutoff
796  double cutoff = modelPtr_->dualObjectiveLimit();
797  modelPtr_->setDualObjectiveLimit(1.0e50);
798  modelPtr_->scaling(0);
799  modelPtr_->setLogLevel(0);
800  // solve with no objective to get feasible solution
801  setBasis(basis_,modelPtr_);
802  modelPtr_->dual();
803  basis_ = getBasis(modelPtr_);
804  modelPtr_->setDualObjectiveLimit(cutoff);
805  if (modelPtr_->problemStatus())
806    return; // problem was infeasible
807  // Now pass in quadratic objective
808  ClpObjective * saveObjective  = modelPtr_->objectiveAsObject();
809  modelPtr_->setObjectivePointer(quadraticObjective_);
810  modelPtr_->primal();
811  modelPtr_->setDualObjectiveLimit(cutoff);
812  if (modelPtr_->objectiveValue()>cutoff)
813    modelPtr_->setProblemStatus(1);
814  modelPtr_->setObjectivePointer(saveObjective);
815  ]]>   
816  </programlisting>
817  </example>
818  </section>
819  </chapter>
Note: See TracBrowser for help on using the repository browser.