[557] | 1 | <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> |
---|
| 2 | <html xmlns="http://www.w3.org/1999/xhtml"><head><title>Advanced use of solver</title><meta name="generator" content="DocBook XSL Stylesheets V1.61.2"/><link rel="home" href="index.html" title="CBC User Guide"/><link rel="up" href="ch04.html" title="Chapter 4. Branching "/><link rel="previous" href="ch04.html" title="Chapter 4. Branching "/><link rel="next" href="ch05.html" title="Chapter 5. Building and Modifying a Model "/></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Advanced use of solver</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch04.html">Prev</a> </td><th width="60%" align="center">Chapter 4. |
---|
| 3 | Branching |
---|
| 4 | </th><td width="20%" align="right"> <a accesskey="n" href="ch05.html">Next</a></td></tr></table><hr/></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="solver"/>Advanced use of solver</h2></div></div><div/></div><p> |
---|
| 5 | Coin Branch and Cut uses a generic OsiSolverInterface and its <tt class="function">resolve</tt> capability. |
---|
| 6 | This does not give much flexibility so advanced users can inherit from the interface |
---|
| 7 | of choice. This describes such a solver for a long thin problem e.g. fast0507 again. |
---|
| 8 | As with all these examples it is not guaranteed that this is the fastest way to solve |
---|
| 9 | any of these problems - they are to illustrate techniques. |
---|
| 10 | The full code is in <tt class="filename">CbcSolver2.hpp</tt> and |
---|
| 11 | <tt class="filename">CbcSolver2.cpp</tt> |
---|
| 12 | (this code can be found in the CBC Samples directory, see |
---|
| 13 | <a href="ch06.html" title="Chapter 6. More Samples ">Chapter 6, <i> |
---|
| 14 | More Samples |
---|
| 15 | </i></a>). |
---|
| 16 | <tt class="function">initialSolve</tt> is called a few times so although we will not gain much |
---|
| 17 | this is a simpler place to start. The example derives from OsiClpSolverInterface and the code |
---|
| 18 | is: |
---|
| 19 | </p><div class="example"><a id="id2985361"/><p class="title"><b>Example 4.3. initialSolve</b></p><pre class="programlisting"> |
---|
| 20 | |
---|
| 21 | // modelPtr_ is of type ClpSimplex * |
---|
| 22 | modelPtr_->setLogLevel(1); // switch on a bit of printout |
---|
| 23 | modelPtr_->scaling(0); // We don't want scaling for fast0507 |
---|
| 24 | setBasis(basis_,modelPtr_); // Put basis into ClpSimplex |
---|
| 25 | // Do long thin by sprint |
---|
| 26 | ClpSolve options; |
---|
| 27 | options.setSolveType(ClpSolve::usePrimalorSprint); |
---|
| 28 | options.setPresolveType(ClpSolve::presolveOff); |
---|
| 29 | options.setSpecialOption(1,3,15); // Do 15 sprint iterations |
---|
| 30 | modelPtr_->initialSolve(options); // solve problem |
---|
| 31 | basis_ = getBasis(modelPtr_); // save basis |
---|
| 32 | modelPtr_->setLogLevel(0); // switch off printout |
---|
| 33 | |
---|
| 34 | </pre></div><p> |
---|
| 35 | The <tt class="function">resolve</tt> method is more complicated. The main pieces of data are |
---|
| 36 | a counter count_ which is incremented each solve and an int array node_ which stores the last time |
---|
| 37 | a variable was active in a solution. For the first few times normal dual is called and |
---|
| 38 | node_ array is updated. |
---|
| 39 | </p><div class="example"><a id="id2985410"/><p class="title"><b>Example 4.4. First few solves</b></p><pre class="programlisting"> |
---|
| 40 | |
---|
| 41 | if (count_<10) { |
---|
| 42 | OsiClpSolverInterface::resolve(); // Normal resolve |
---|
| 43 | if (modelPtr_->status()==0) { |
---|
| 44 | count_++; // feasible - save any nonzero or basic |
---|
| 45 | const double * solution = modelPtr_->primalColumnSolution(); |
---|
| 46 | for (int i=0;i<numberColumns;i++) { |
---|
| 47 | if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { |
---|
| 48 | node_[i]=CoinMax(count_,node_[i]); |
---|
| 49 | howMany_[i]++; |
---|
| 50 | } |
---|
| 51 | } |
---|
| 52 | } else { |
---|
| 53 | printf("infeasible early on\n"); |
---|
| 54 | } |
---|
| 55 | } |
---|
| 56 | |
---|
| 57 | </pre></div><p> |
---|
| 58 | After the first few solves we only use those which took part in a solution in the last so many |
---|
| 59 | solves. As fast0507 is a set covering problem we can also take out any rows which are |
---|
| 60 | already covered. |
---|
| 61 | </p><div class="example"><a id="id2985437"/><p class="title"><b>Example 4.5. Create small problem</b></p><pre class="programlisting"> |
---|
| 62 | |
---|
| 63 | int * whichRow = new int[numberRows]; // Array to say which rows used |
---|
| 64 | int * whichColumn = new int [numberColumns]; // Array to say which columns used |
---|
| 65 | int i; |
---|
| 66 | const double * lower = modelPtr_->columnLower(); |
---|
| 67 | const double * upper = modelPtr_->columnUpper(); |
---|
| 68 | setBasis(basis_,modelPtr_); // Set basis |
---|
| 69 | int nNewCol=0; // Number of columns in small model |
---|
| 70 | // Column copy of matrix |
---|
| 71 | const double * element = modelPtr_->matrix()->getElements(); |
---|
| 72 | const int * row = modelPtr_->matrix()->getIndices(); |
---|
| 73 | const CoinBigIndex * columnStart = modelPtr_->matrix()->getVectorStarts(); |
---|
| 74 | const int * columnLength = modelPtr_->matrix()->getVectorLengths(); |
---|
| 75 | |
---|
| 76 | int * rowActivity = new int[numberRows]; // Number of columns with entries in each row |
---|
| 77 | memset(rowActivity,0,numberRows*sizeof(int)); |
---|
| 78 | int * rowActivity2 = new int[numberRows]; // Lower bound on row activity for each row |
---|
| 79 | memset(rowActivity2,0,numberRows*sizeof(int)); |
---|
| 80 | char * mark = (char *) modelPtr_->dualColumnSolution(); // Get some space to mark columns |
---|
| 81 | memset(mark,0,numberColumns); |
---|
| 82 | for (i=0;i<numberColumns;i++) { |
---|
| 83 | bool choose = (node_[i]>count_-memory_&&node_[i]>0); // Choose if used recently |
---|
| 84 | // Take if used recently or active in some sense |
---|
| 85 | if ((choose&&upper[i]) |
---|
| 86 | ||(modelPtr_->getStatus(i)!=ClpSimplex::atLowerBound&& |
---|
| 87 | modelPtr_->getStatus(i)!=ClpSimplex::isFixed) |
---|
| 88 | ||lower[i]>0.0) { |
---|
| 89 | mark[i]=1; // mark as used |
---|
| 90 | whichColumn[nNewCol++]=i; // add to list |
---|
| 91 | CoinBigIndex j; |
---|
| 92 | double value = upper[i]; |
---|
| 93 | if (value) { |
---|
| 94 | for (j=columnStart[i]; |
---|
| 95 | j<columnStart[i]+columnLength[i];j++) { |
---|
| 96 | int iRow=row[j]; |
---|
| 97 | assert (element[j]==1.0); |
---|
| 98 | rowActivity[iRow] ++; // This variable can cover this row |
---|
| 99 | } |
---|
| 100 | if (lower[i]>0.0) { |
---|
| 101 | for (j=columnStart[i]; |
---|
| 102 | j<columnStart[i]+columnLength[i];j++) { |
---|
| 103 | int iRow=row[j]; |
---|
| 104 | rowActivity2[iRow] ++; // This row redundant |
---|
| 105 | } |
---|
| 106 | } |
---|
| 107 | } |
---|
| 108 | } |
---|
| 109 | } |
---|
| 110 | int nOK=0; // Use to count rows which can be covered |
---|
| 111 | int nNewRow=0; // Use to make list of rows needed |
---|
| 112 | for (i=0;i<numberRows;i++) { |
---|
| 113 | if (rowActivity[i]) |
---|
| 114 | nOK++; |
---|
| 115 | if (!rowActivity2[i]) |
---|
| 116 | whichRow[nNewRow++]=i; // not satisfied |
---|
| 117 | else |
---|
| 118 | modelPtr_->setRowStatus(i,ClpSimplex::basic); // make slack basic |
---|
| 119 | } |
---|
| 120 | if (nOK<numberRows) { |
---|
| 121 | // The variables we have do not cover rows - see if we can find any that do |
---|
| 122 | for (i=0;i<numberColumns;i++) { |
---|
| 123 | if (!mark[i]&&upper[i]) { |
---|
| 124 | CoinBigIndex j; |
---|
| 125 | int good=0; |
---|
| 126 | for (j=columnStart[i]; |
---|
| 127 | j<columnStart[i]+columnLength[i];j++) { |
---|
| 128 | int iRow=row[j]; |
---|
| 129 | if (!rowActivity[iRow]) { |
---|
| 130 | rowActivity[iRow] ++; |
---|
| 131 | good++; |
---|
| 132 | } |
---|
| 133 | } |
---|
| 134 | if (good) { |
---|
| 135 | nOK+=good; // This covers - put in list |
---|
| 136 | whichColumn[nNewCol++]=i; |
---|
| 137 | } |
---|
| 138 | } |
---|
| 139 | } |
---|
| 140 | } |
---|
| 141 | delete [] rowActivity; |
---|
| 142 | delete [] rowActivity2; |
---|
| 143 | if (nOK<numberRows) { |
---|
| 144 | // By inspection the problem is infeasible - no need to solve |
---|
| 145 | modelPtr_->setProblemStatus(1); |
---|
| 146 | delete [] whichRow; |
---|
| 147 | delete [] whichColumn; |
---|
| 148 | printf("infeasible by inspection\n"); |
---|
| 149 | return; |
---|
| 150 | } |
---|
| 151 | // Now make up a small model with the right rows and columns |
---|
| 152 | ClpSimplex * temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); |
---|
| 153 | |
---|
| 154 | </pre></div><p> |
---|
| 155 | If the variables cover the rows then we know that the problem is feasible (We are not using |
---|
| 156 | cuts). If the rows |
---|
| 157 | were E rows then this might not be the case and we would have to do more work. When we have solved |
---|
| 158 | then we see if there are any negative reduced costs and if there are then we have to go to the |
---|
| 159 | full problem and use primal to clean up. |
---|
| 160 | </p><div class="example"><a id="id2985478"/><p class="title"><b>Example 4.6. Check optimal solution</b></p><pre class="programlisting"> |
---|
| 161 | |
---|
| 162 | temp->setDualObjectiveLimit(1.0e50); // Switch off dual cutoff as problem is restricted |
---|
| 163 | temp->dual(); // solve |
---|
| 164 | double * solution = modelPtr_->primalColumnSolution(); // put back solution |
---|
| 165 | const double * solution2 = temp->primalColumnSolution(); |
---|
| 166 | memset(solution,0,numberColumns*sizeof(double)); |
---|
| 167 | for (i=0;i<nNewCol;i++) { |
---|
| 168 | int iColumn = whichColumn[i]; |
---|
| 169 | solution[iColumn]=solution2[i]; |
---|
| 170 | modelPtr_->setStatus(iColumn,temp->getStatus(i)); |
---|
| 171 | } |
---|
| 172 | double * rowSolution = modelPtr_->primalRowSolution(); |
---|
| 173 | const double * rowSolution2 = temp->primalRowSolution(); |
---|
| 174 | double * dual = modelPtr_->dualRowSolution(); |
---|
| 175 | const double * dual2 = temp->dualRowSolution(); |
---|
| 176 | memset(dual,0,numberRows*sizeof(double)); |
---|
| 177 | for (i=0;i<nNewRow;i++) { |
---|
| 178 | int iRow=whichRow[i]; |
---|
| 179 | modelPtr_->setRowStatus(iRow,temp->getRowStatus(i)); |
---|
| 180 | rowSolution[iRow]=rowSolution2[i]; |
---|
| 181 | dual[iRow]=dual2[i]; |
---|
| 182 | } |
---|
| 183 | // See if optimal |
---|
| 184 | double * dj = modelPtr_->dualColumnSolution(); |
---|
| 185 | // get reduced cost for large problem |
---|
| 186 | // this assumes minimization |
---|
| 187 | memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); |
---|
| 188 | modelPtr_->transposeTimes(-1.0,dual,dj); |
---|
| 189 | modelPtr_->setObjectiveValue(temp->objectiveValue()); |
---|
| 190 | modelPtr_->setProblemStatus(0); |
---|
| 191 | int nBad=0; |
---|
| 192 | |
---|
| 193 | for (i=0;i<numberColumns;i++) { |
---|
| 194 | if (modelPtr_->getStatus(i)==ClpSimplex::atLowerBound |
---|
| 195 | &&upper[i]>lower[i]&&dj[i]<-1.0e-5) |
---|
| 196 | nBad++; |
---|
| 197 | } |
---|
| 198 | // If necessary claen up with primal (and save some statistics) |
---|
| 199 | if (nBad) { |
---|
| 200 | timesBad_++; |
---|
| 201 | modelPtr_->primal(1); |
---|
| 202 | iterationsBad_ += modelPtr_->numberIterations(); |
---|
| 203 | } |
---|
| 204 | |
---|
| 205 | </pre></div><p> |
---|
| 206 | We then update node_ array as for the first few solves. To give some idea of the effect of this |
---|
| 207 | tactic fast0507 has 63,009 variables and the small problem never has more than 4,000 variables. |
---|
| 208 | In just over ten percent of solves did we have to resolve and then the average number of iterations |
---|
| 209 | on full problem was less than 20. |
---|
| 210 | To give another example - again only for illustrative purposes it is possible to do quadratic |
---|
| 211 | mip. In this case we make <tt class="function">resolve</tt> the same as |
---|
| 212 | <tt class="function">initialSolve</tt>. |
---|
| 213 | The full code is in <tt class="filename">ClpQuadInterface.hpp</tt> and |
---|
| 214 | <tt class="filename">ClpQuadInterface.cpp</tt> |
---|
| 215 | (this code can be found in the CBC Samples directory, see |
---|
| 216 | <a href="ch06.html" title="Chapter 6. More Samples ">Chapter 6, <i> |
---|
| 217 | More Samples |
---|
| 218 | </i></a>). |
---|
| 219 | </p><div class="example"><a id="id2985520"/><p class="title"><b>Example 4.7. Solve a quadratic mip</b></p><pre class="programlisting"> |
---|
| 220 | |
---|
| 221 | // save cutoff |
---|
| 222 | double cutoff = modelPtr_->dualObjectiveLimit(); |
---|
| 223 | modelPtr_->setDualObjectiveLimit(1.0e50); |
---|
| 224 | modelPtr_->scaling(0); |
---|
| 225 | modelPtr_->setLogLevel(0); |
---|
| 226 | // solve with no objective to get feasible solution |
---|
| 227 | setBasis(basis_,modelPtr_); |
---|
| 228 | modelPtr_->dual(); |
---|
| 229 | basis_ = getBasis(modelPtr_); |
---|
| 230 | modelPtr_->setDualObjectiveLimit(cutoff); |
---|
| 231 | if (modelPtr_->problemStatus()) |
---|
| 232 | return; // problem was infeasible |
---|
| 233 | // Now pass in quadratic objective |
---|
| 234 | ClpObjective * saveObjective = modelPtr_->objectiveAsObject(); |
---|
| 235 | modelPtr_->setObjectivePointer(quadraticObjective_); |
---|
| 236 | modelPtr_->primal(); |
---|
| 237 | modelPtr_->setDualObjectiveLimit(cutoff); |
---|
| 238 | if (modelPtr_->objectiveValue()>cutoff) |
---|
| 239 | modelPtr_->setProblemStatus(1); |
---|
| 240 | modelPtr_->setObjectivePointer(saveObjective); |
---|
| 241 | |
---|
| 242 | </pre></div></div><div class="navfooter"><hr/><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch04.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ch04.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch05.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 4. |
---|
| 243 | Branching |
---|
| 244 | </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 5. |
---|
| 245 | Building and Modifying a Model |
---|
| 246 | </td></tr></table></div></body></html> |
---|