1 /* $Id$ */
2 // Copyright (C) 2006, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #include "CbcConfig.h"
7 
8 #include "CoinTime.hpp"
9 
10 #include "CoinHelperFunctions.hpp"
11 #include "CoinModel.hpp"
12 #include "ClpSimplex.hpp"
13 // returns jColumn (-2 if linear term, -1 if unknown) and coefficient
decodeBit(char * phrase,char * & nextPhrase,double & coefficient,bool ifFirst,const CoinModel & model)14 static int decodeBit(char *phrase, char *&nextPhrase, double &coefficient, bool ifFirst, const CoinModel &model)
15 {
16   char *pos = phrase;
17   // may be leading - (or +)
18   char *pos2 = pos;
19   double value = 1.0;
20   if (*pos2 == '-' || *pos2 == '+')
21     pos2++;
22   // next terminator * or + or -
23   while (*pos2) {
24     if (*pos2 == '*') {
25       break;
26     } else if (*pos2 == '-' || *pos2 == '+') {
27       if (pos2 == pos || *(pos2 - 1) != 'e')
28         break;
29     }
30     pos2++;
31   }
32   // if * must be number otherwise must be name
33   if (*pos2 == '*') {
34     char *pos3 = pos;
35     while (pos3 != pos2) {
36       pos3++;
37 #ifndef NDEBUG
38       char x = *(pos3 - 1);
39       assert((x >= '0' && x <= '9') || x == '.' || x == '+' || x == '-' || x == 'e');
40 #endif
41     }
42     char saved = *pos2;
43     *pos2 = '\0';
44     value = atof(pos);
45     *pos2 = saved;
46     // and down to next
47     pos2++;
48     pos = pos2;
49     while (*pos2) {
50       if (*pos2 == '-' || *pos2 == '+')
51         break;
52       pos2++;
53     }
54   }
55   char saved = *pos2;
56   *pos2 = '\0';
57   // now name
58   // might have + or -
59   if (*pos == '+') {
60     pos++;
61   } else if (*pos == '-') {
62     pos++;
63     assert(value == 1.0);
64     value = -value;
65   }
66   int jColumn = model.column(pos);
67   // must be column unless first when may be linear term
68   if (jColumn < 0) {
69     if (ifFirst) {
70       char *pos3 = pos;
71       while (pos3 != pos2) {
72         pos3++;
73 #ifndef NDEBUG
74         char x = *(pos3 - 1);
75         assert((x >= '0' && x <= '9') || x == '.' || x == '+' || x == '-' || x == 'e');
76 #endif
77       }
78       assert(*pos2 == '\0');
79       // keep possible -
80       value = value * atof(pos);
81       jColumn = -2;
82     } else {
83       // bad
84       *pos2 = saved;
85       printf("bad nonlinear term %s\n", phrase);
86       abort();
87     }
88   }
89   *pos2 = saved;
90   pos = pos2;
91   coefficient = value;
92   nextPhrase = pos;
93   return jColumn;
94 }
95 #include "ClpQuadraticObjective.hpp"
96 #include <cassert>
97 #if defined(_MSC_VER)
98 // Turn off compiler warning about long names
99 #pragma warning(disable : 4786)
100 #endif
101 #include "CbcLinked.hpp"
102 #include "CoinIndexedVector.hpp"
103 #include "CoinMpsIO.hpp"
104 //#include "OsiSolverLink.hpp"
105 //#include "OsiBranchLink.hpp"
106 #include "ClpPackedMatrix.hpp"
107 #include "CoinTime.hpp"
108 #include "CbcModel.hpp"
109 #include "CbcCutGenerator.hpp"
110 #include "CglStored.hpp"
111 #include "CglPreProcess.hpp"
112 #include "CglGomory.hpp"
113 #include "CglProbing.hpp"
114 #include "CglKnapsackCover.hpp"
115 #include "CglRedSplit.hpp"
116 #include "CglClique.hpp"
117 #include "CglFlowCover.hpp"
118 #include "CglMixedIntegerRounding2.hpp"
119 #include "CglTwomir.hpp"
120 #include "CglDuplicateRow.hpp"
121 #include "CbcHeuristicFPump.hpp"
122 #include "CbcHeuristic.hpp"
123 #include "CbcHeuristicLocal.hpp"
124 #include "CbcHeuristicGreedy.hpp"
125 #include "ClpLinearObjective.hpp"
126 #include "CbcBranchActual.hpp"
127 #include "CbcCompareActual.hpp"
128 //#############################################################################
129 // Solve methods
130 //#############################################################################
initialSolve()131 void OsiSolverLink::initialSolve()
132 {
133   //writeMps("yy");
134   //exit(77);
135   specialOptions_ = 0;
136   modelPtr_->setWhatsChanged(0);
137   if (numberVariables_) {
138     CoinPackedMatrix *temp = new CoinPackedMatrix(*matrix_);
139     // update all bounds before coefficients
140     for (int i = 0; i < numberVariables_; i++) {
141       info_[i].updateBounds(modelPtr_);
142     }
143     int updated = updateCoefficients(modelPtr_, temp);
144     //if (updated || 1) {
145       temp->removeGaps(1.0e-14);
146       ClpMatrixBase *save = modelPtr_->clpMatrix();
147       ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(save);
148       assert(clpMatrix);
149       if (save->getNumRows() > temp->getNumRows()) {
150         // add in cuts
151         int numberRows = temp->getNumRows();
152         int *which = new int[numberRows];
153         for (int i = 0; i < numberRows; i++)
154           which[i] = i;
155         save->deleteRows(numberRows, which);
156         delete[] which;
157         temp->bottomAppendPackedMatrix(*clpMatrix->matrix());
158       }
159       modelPtr_->replaceMatrix(temp, true);
160     //} else {
161     //  delete temp;
162     //}
163   }
164   if (0) {
165     const double *lower = getColLower();
166     const double *upper = getColUpper();
167     int n = 0;
168     for (int i = 84; i < 84 + 16; i++) {
169       if (lower[i] + 0.01 < upper[i]) {
170         n++;
171       }
172     }
173     if (!n)
174       writeMps("sol_query");
175   }
176   //static int iPass=0;
177   //char temp[50];
178   //iPass++;
179   //sprintf(temp,"cc%d",iPass);
180   //writeMps(temp);
181   //writeMps("tight");
182   //exit(33);
183   //printf("wrote cc%d\n",iPass);
184   OsiClpSolverInterface::initialSolve();
185   int secondaryStatus = modelPtr_->secondaryStatus();
186   if (modelPtr_->status() == 0 && (secondaryStatus == 2 || secondaryStatus == 4))
187     modelPtr_->cleanup(1);
188   //if (!isProvenOptimal())
189   //writeMps("yy");
190   if (isProvenOptimal() && quadraticModel_ && modelPtr_->numberColumns() == quadraticModel_->numberColumns()) {
191     // see if qp can get better solution
192     const double *solution = modelPtr_->primalColumnSolution();
193     int numberColumns = modelPtr_->numberColumns();
194     bool satisfied = true;
195     for (int i = 0; i < numberColumns; i++) {
196       if (isInteger(i)) {
197         double value = solution[i];
198         if (fabs(value - floor(value + 0.5)) > 1.0e-6) {
199           satisfied = false;
200           break;
201         }
202       }
203     }
204     if (satisfied) {
205       ClpSimplex qpTemp(*quadraticModel_);
206       double *lower = qpTemp.columnLower();
207       double *upper = qpTemp.columnUpper();
208       double *lower2 = modelPtr_->columnLower();
209       double *upper2 = modelPtr_->columnUpper();
210       for (int i = 0; i < numberColumns; i++) {
211         if (isInteger(i)) {
212           double value = floor(solution[i] + 0.5);
213           lower[i] = value;
214           upper[i] = value;
215         } else {
216           lower[i] = lower2[i];
217           upper[i] = upper2[i];
218         }
219       }
220       //qpTemp.writeMps("bad.mps");
221       //modelPtr_->writeMps("bad2.mps");
222       //qpTemp.objectiveAsObject()->setActivated(0);
223       //qpTemp.primal();
224       //qpTemp.objectiveAsObject()->setActivated(1);
225       qpTemp.primal();
226       //assert (!qpTemp.problemStatus());
227       if (qpTemp.objectiveValue() < bestObjectiveValue_ - 1.0e-3 && !qpTemp.problemStatus()) {
228         delete[] bestSolution_;
229         bestSolution_ = CoinCopyOfArray(qpTemp.primalColumnSolution(), numberColumns);
230         bestObjectiveValue_ = qpTemp.objectiveValue();
231         //printf("better qp objective of %g\n", bestObjectiveValue_);
232         // If model has stored then add cut (if convex)
233         if (cbcModel_ && (specialOptions2_ & 4) != 0) {
234           int numberGenerators = cbcModel_->numberCutGenerators();
235           int iGenerator;
236           cbcModel_->lockThread();
237           for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
238             CbcCutGenerator *generator = cbcModel_->cutGenerator(iGenerator);
239             CglCutGenerator *gen = generator->generator();
240             CglStored *gen2 = dynamic_cast< CglStored * >(gen);
241             if (gen2) {
242               // add OA cut
243               double offset;
244               double *gradient = new double[numberColumns + 1];
245               memcpy(gradient, qpTemp.objectiveAsObject()->gradient(&qpTemp, bestSolution_, offset, true, 2),
246                 numberColumns * sizeof(double));
247               // assume convex
248               double rhs = 0.0;
249               int *column = new int[numberColumns + 1];
250               int n = 0;
251               for (int i = 0; i < numberColumns; i++) {
252                 double value = gradient[i];
253                 if (fabs(value) > 1.0e-12) {
254                   gradient[n] = value;
255                   rhs += value * solution[i];
256                   column[n++] = i;
257                 }
258               }
259               gradient[n] = -1.0;
260               column[n++] = objectiveVariable_;
261               gen2->addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient);
262               delete[] gradient;
263               delete[] column;
264               break;
265             }
266           }
267           cbcModel_->unlockThread();
268         }
269       }
270     }
271   }
272 }
273 //#define WRITE_MATRIX
274 #ifdef WRITE_MATRIX
275 static int xxxxxx = 0;
276 #endif
277 //-----------------------------------------------------------------------------
resolve()278 void OsiSolverLink::resolve()
279 {
280   if (false) {
281     bool takeHint;
282     OsiHintStrength strength;
283     // Switch off printing if asked to
284     getHintParam(OsiDoReducePrint, takeHint, strength);
285     if (strength != OsiHintIgnore && takeHint) {
286       printf("no printing\n");
287     } else {
288       printf("printing\n");
289     }
290   }
291   int saveLogLevel=modelPtr_->logLevel();
292   if (saveLogLevel==1)
293     modelPtr_->setLogLevel(0);
294   specialOptions_ = 0;
295   modelPtr_->setWhatsChanged(0);
296   bool allFixed = numberFix_ > 0;
297   bool feasible = true;
298   if (numberVariables_) {
299     CoinPackedMatrix *temp = new CoinPackedMatrix(*matrix_);
300     //bool best=true;
301     const double *lower = modelPtr_->columnLower();
302     const double *upper = modelPtr_->columnUpper();
303     // update all bounds before coefficients
304     for (int i = 0; i < numberVariables_; i++) {
305       info_[i].updateBounds(modelPtr_);
306       int iColumn = info_[i].variable();
307       double lo = lower[iColumn];
308       double up = upper[iColumn];
309       if (up < lo)
310         feasible = false;
311     }
312     int updated = updateCoefficients(modelPtr_, temp);
313     if (updated) {
314       temp->removeGaps(1.0e-14);
315       ClpMatrixBase *save = modelPtr_->clpMatrix();
316       ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(save);
317       assert(clpMatrix);
318       if (save->getNumRows() > temp->getNumRows()) {
319         // add in cuts
320         int numberRows = temp->getNumRows();
321         int *which = new int[numberRows];
322         for (int i = 0; i < numberRows; i++)
323           which[i] = i;
324         CoinPackedMatrix *mat = clpMatrix->matrix();
325         // for debug
326         //mat = new CoinPackedMatrix(*mat);
327         mat->deleteRows(numberRows, which);
328         delete[] which;
329         temp->bottomAppendPackedMatrix(*mat);
330         temp->removeGaps(1.0e-14);
331       }
332       modelPtr_->replaceMatrix(temp, true);
333       modelPtr_->setNewRowCopy(NULL);
334       modelPtr_->setClpScaledMatrix(NULL);
335     } else {
336       delete temp;
337     }
338   }
339 #ifdef WRITE_MATRIX
340   {
341     xxxxxx++;
342     char temp[50];
343     sprintf(temp, "bb%d", xxxxxx);
344     writeMps(temp);
345     printf("wrote bb%d\n", xxxxxx);
346   }
347 #endif
348   if (0) {
349     const double *lower = getColLower();
350     const double *upper = getColUpper();
351     int n = 0;
352     for (int i = 60; i < 64; i++) {
353       if (lower[i]) {
354         printf("%d bounds %g %g\n", i, lower[i], upper[i]);
355         n++;
356       }
357     }
358     if (n == 1)
359       printf("just one?\n");
360   }
361   // check feasible
362   {
363     const double *lower = getColLower();
364     const double *upper = getColUpper();
365     int numberColumns = getNumCols();
366     for (int i = 0; i < numberColumns; i++) {
367       if (lower[i] > upper[i] + 1.0e-12) {
368         feasible = false;
369         break;
370       }
371     }
372   }
373   if (!feasible)
374     allFixed = false;
375   if ((specialOptions2_ & 1) == 0)
376     allFixed = false;
377   int returnCode = -1;
378   // See if in strong branching
379   int maxIts = modelPtr_->maximumIterations();
380   if (feasible) {
381     if (maxIts > 10000) {
382       // may do lots of work
383       if ((specialOptions2_ & 1) != 0) {
384         // see if fixed
385         const double *lower = modelPtr_->columnLower();
386         const double *upper = modelPtr_->columnUpper();
387         for (int i = 0; i < numberFix_; i++) {
388           int iColumn = fixVariables_[i];
389           double lo = lower[iColumn];
390           double up = upper[iColumn];
391           if (up > lo) {
392             allFixed = false;
393             break;
394           }
395         }
396         returnCode = allFixed ? fathom(allFixed) : 0;
397       } else {
398         returnCode = 0;
399       }
400     } else {
401       returnCode = 0;
402     }
403   }
404   if (returnCode >= 0) {
405     if (returnCode == 0)
406       OsiClpSolverInterface::resolve();
407     int satisfied = 2;
408     const double *solution = getColSolution();
409     const double *lower = getColLower();
410     const double *upper = getColUpper();
411     int numberColumns2 = coinModel_.numberColumns();
412     for (int i = 0; i < numberColumns2; i++) {
413       if (isInteger(i)) {
414         double value = solution[i];
415         if (fabs(value - floor(value + 0.5)) > 1.0e-6) {
416           satisfied = 0;
417           break;
418         } else if (upper[i] > lower[i]) {
419           satisfied = 1;
420         }
421       }
422     }
423     if (isProvenOptimal()) {
424       //if (satisfied==2)
425       //printf("satisfied %d\n",satisfied);
426       if (satisfied && (specialOptions2_ & 2) != 0) {
427         assert(quadraticModel_);
428         // look at true objective
429 #ifndef NDEBUG
430         double direction = modelPtr_->optimizationDirection();
431         assert(direction == 1.0);
432 #endif
433         double value = -quadraticModel_->objectiveOffset();
434         const double *objective = quadraticModel_->objective();
435         int i;
436         for (i = 0; i < numberColumns2; i++)
437           value += solution[i] * objective[i];
438         // and now rest
439         for (i = 0; i < numberObjects_; i++) {
440           OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
441           if (obj) {
442             value += obj->xyCoefficient(solution);
443           }
444         }
445         if (value < bestObjectiveValue_ - 1.0e-3) {
446           // printf("obj of %g\n", value);
447           //modelPtr_->setDualObjectiveLimit(value);
448           delete[] bestSolution_;
449           bestSolution_ = CoinCopyOfArray(modelPtr_->getColSolution(), modelPtr_->getNumCols());
450           bestObjectiveValue_ = value;
451           if (maxIts <= 10000 && cbcModel_) {
452             OsiSolverLink *solver2 = dynamic_cast< OsiSolverLink * >(cbcModel_->solver());
453             assert(solver2);
454             if (solver2 != this) {
455               // in strong branching - need to store in original solver
456               if (value < solver2->bestObjectiveValue_ - 1.0e-3) {
457                 delete[] solver2->bestSolution_;
458                 solver2->bestSolution_ = CoinCopyOfArray(bestSolution_, modelPtr_->getNumCols());
459                 solver2->bestObjectiveValue_ = value;
460               }
461             }
462           }
463           // If model has stored then add cut (if convex)
464           if (cbcModel_ && (specialOptions2_ & 4) != 0 && quadraticModel_) {
465             int numberGenerators = cbcModel_->numberCutGenerators();
466             int iGenerator;
467             for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
468               CbcCutGenerator *generator = cbcModel_->cutGenerator(iGenerator);
469               CglCutGenerator *gen = generator->generator();
470               CglStored *gen2 = dynamic_cast< CglStored * >(gen);
471               if (gen2) {
472                 cbcModel_->lockThread();
473                 // add OA cut
474                 double offset = 0.0;
475                 int numberColumns = quadraticModel_->numberColumns();
476                 double *gradient = new double[numberColumns + 1];
477                 // gradient from bilinear
478                 int i;
479                 CoinZeroN(gradient, numberColumns + 1);
480                 //const double * objective = modelPtr_->objective();
481                 assert(objectiveRow_ >= 0);
482                 const double *element = originalRowCopy_->getElements();
483                 const int *column2 = originalRowCopy_->getIndices();
484                 const CoinBigIndex *rowStart = originalRowCopy_->getVectorStarts();
485                 //const int * rowLength = originalRowCopy_->getVectorLengths();
486                 //int numberColumns2 = coinModel_.numberColumns();
487                 for (CoinBigIndex i = rowStart[objectiveRow_]; i < rowStart[objectiveRow_ + 1]; i++)
488                   gradient[column2[i]] = element[i];
489                 for (i = 0; i < numberObjects_; i++) {
490                   OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
491                   if (obj) {
492                     int xColumn = obj->xColumn();
493                     int yColumn = obj->yColumn();
494                     if (xColumn != yColumn) {
495                       double coefficient = /* 2.0* */ obj->coefficient();
496                       gradient[xColumn] += coefficient * solution[yColumn];
497                       gradient[yColumn] += coefficient * solution[xColumn];
498                       offset += coefficient * solution[xColumn] * solution[yColumn];
499                     } else {
500                       double coefficient = obj->coefficient();
501                       gradient[xColumn] += 2.0 * coefficient * solution[yColumn];
502                       offset += coefficient * solution[xColumn] * solution[yColumn];
503                     }
504                   }
505                 }
506                 // assume convex
507                 double rhs = 0.0;
508                 int *column = new int[numberColumns + 1];
509                 int n = 0;
510                 for (int i = 0; i < numberColumns; i++) {
511                   double value = gradient[i];
512                   if (fabs(value) > 1.0e-12) {
513                     gradient[n] = value;
514                     rhs += value * solution[i];
515                     column[n++] = i;
516                   }
517                 }
518                 gradient[n] = -1.0;
519                 column[n++] = objectiveVariable_;
520                 gen2->addCut(-COIN_DBL_MAX, offset + 1.0e-4, n, column, gradient);
521                 delete[] gradient;
522                 delete[] column;
523                 cbcModel_->unlockThread();
524                 break;
525               }
526             }
527           }
528         }
529       } else if (satisfied == 2) {
530         // is there anything left to do?
531         int i;
532         int numberContinuous = 0;
533         double gap = 0.0;
534         for (i = 0; i < numberObjects_; i++) {
535           OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
536           if (obj) {
537             if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0) {
538               numberContinuous++;
539               int xColumn = obj->xColumn();
540               double gapX = upper[xColumn] - lower[xColumn];
541               int yColumn = obj->yColumn();
542               double gapY = upper[yColumn] - lower[yColumn];
543               gap = CoinMax(gap, CoinMax(gapX, gapY));
544             }
545           }
546         }
547 #if 0
548         if (numberContinuous) {
549           // iterate to get solution and fathom node
550           int numberColumns2 = coinModel_.numberColumns();
551           double *lower2 = CoinCopyOfArray(getColLower(), numberColumns2);
552           double *upper2 = CoinCopyOfArray(getColUpper(), numberColumns2);
553           while (gap > defaultMeshSize_) {
554             gap *= 0.9;
555             const double *solution = getColSolution();
556             double newGap = 0.0;
557             for (i = 0; i < numberObjects_; i++) {
558               OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
559               if (obj && (obj->branchingStrategy() & 8) == 0) {
560                 if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0) {
561                   numberContinuous++;
562                   // need to make sure new xy value in range
563                   double xB[3];
564                   double yB[3];
565                   double xybar[4];
566                   obj->getCoefficients(this, xB, yB, xybar);
567                   //double xyTrue = obj->xyCoefficient(solution);
568                   double xyLambda = 0.0;
569                   int firstLambda = obj->firstLambda();
570                   for (int j = 0; j < 4; j++) {
571                     xyLambda += solution[firstLambda + j] * xybar[j];
572                   }
573                   //printf ("x %d, y %d - true %g lambda %g\n",obj->xColumn(),obj->yColumn(),
574                   //  xyTrue,xyLambda);
575                   int xColumn = obj->xColumn();
576                   double gapX = upper[xColumn] - lower[xColumn];
577                   int yColumn = obj->yColumn();
578                   if (gapX > gap) {
579                     double value = solution[xColumn];
580                     double newLower = CoinMax(lower2[xColumn], value - 0.5 * gap);
581                     double newUpper = CoinMin(upper2[xColumn], value + 0.5 * gap);
582                     if (newUpper - newLower < 0.99 * gap) {
583                       if (newLower == lower2[xColumn])
584                         newUpper = CoinMin(upper2[xColumn], newLower + gap);
585                       else if (newUpper == upper2[xColumn])
586                         newLower = CoinMax(lower2[xColumn], newUpper - gap);
587                     }
588                     // see if problem
589 #ifndef NDEBUG
590                     double lambda[4];
591 #endif
592                     xB[0] = newLower;
593                     xB[1] = newUpper;
594                     xB[2] = value;
595                     yB[2] = solution[yColumn];
596                     xybar[0] = xB[0] * yB[0];
597                     xybar[1] = xB[0] * yB[1];
598                     xybar[2] = xB[1] * yB[0];
599                     xybar[3] = xB[1] * yB[1];
600 #ifndef NDEBUG
601                     double infeasibility = obj->computeLambdas(xB, yB, xybar, lambda);
602                     assert(infeasibility < 1.0e-9);
603 #endif
604                     setColLower(xColumn, newLower);
605                     setColUpper(xColumn, newUpper);
606                   }
607                   double gapY = upper[yColumn] - lower[yColumn];
608                   if (gapY > gap) {
609                     double value = solution[yColumn];
610                     double newLower = CoinMax(lower2[yColumn], value - 0.5 * gap);
611                     double newUpper = CoinMin(upper2[yColumn], value + 0.5 * gap);
612                     if (newUpper - newLower < 0.99 * gap) {
613                       if (newLower == lower2[yColumn])
614                         newUpper = CoinMin(upper2[yColumn], newLower + gap);
615                       else if (newUpper == upper2[yColumn])
616                         newLower = CoinMax(lower2[yColumn], newUpper - gap);
617                     }
618                     // see if problem
619 #ifndef NDEBUG
620                     double lambda[4];
621 #endif
622                     yB[0] = newLower;
623                     yB[1] = newUpper;
624                     xybar[0] = xB[0] * yB[0];
625                     xybar[1] = xB[0] * yB[1];
626                     xybar[2] = xB[1] * yB[0];
627                     xybar[3] = xB[1] * yB[1];
628 #ifndef NDEBUG
629                     double infeasibility = obj->computeLambdas(xB, yB, xybar, lambda);
630                     assert(infeasibility < 1.0e-9);
631 #endif
632                     setColLower(yColumn, newLower);
633                     setColUpper(yColumn, newUpper);
634                   }
635                   newGap = CoinMax(newGap, CoinMax(gapX, gapY));
636                 }
637               }
638             }
639             printf("solving with gap of %g\n", gap);
640             //OsiClpSolverInterface::resolve();
641             initialSolve();
642             if (!isProvenOptimal())
643               break;
644           }
645           delete[] lower2;
646           delete[] upper2;
647           //if (isProvenOptimal())
648           //writeMps("zz");
649         }
650 #endif
651       }
652       // ???  - try
653       // But skip if strong branching
654       CbcModel *cbcModel = (modelPtr_->maximumIterations() > 10000) ? cbcModel_ : NULL;
655       if ((specialOptions2_ & 2) != 0) {
656         // If model has stored then add cut (if convex)
657         // off until I work out problem with ibell3a
658         if (cbcModel && (specialOptions2_ & 4) != 0 && quadraticModel_) {
659           int numberGenerators = cbcModel_->numberCutGenerators();
660           int iGenerator;
661           for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
662             CbcCutGenerator *generator = cbcModel_->cutGenerator(iGenerator);
663             CglCutGenerator *gen = generator->generator();
664             CglTemporary *gen2 = dynamic_cast< CglTemporary * >(gen);
665             if (gen2) {
666               double *solution2 = NULL;
667               int numberColumns = quadraticModel_->numberColumns();
668               int depth = cbcModel_->currentNode() ? cbcModel_->currentNode()->depth() : 0;
669               if (depth < 5) {
670                 ClpSimplex qpTemp(*quadraticModel_);
671                 double *lower = qpTemp.columnLower();
672                 double *upper = qpTemp.columnUpper();
673                 double *lower2 = modelPtr_->columnLower();
674                 double *upper2 = modelPtr_->columnUpper();
675                 for (int i = 0; i < numberColumns; i++) {
676                   lower[i] = lower2[i];
677                   upper[i] = upper2[i];
678                 }
679                 qpTemp.setLogLevel(modelPtr_->logLevel());
680                 qpTemp.primal();
681                 // assert(!qpTemp.problemStatus());
682                 if (qpTemp.objectiveValue() < bestObjectiveValue_ - 1.0e-3 && !qpTemp.problemStatus()) {
683                   solution2 = CoinCopyOfArray(qpTemp.primalColumnSolution(), numberColumns);
684                 } else {
685                   // printf("QP says expensive - kill\n");
686                   modelPtr_->setProblemStatus(1);
687                   modelPtr_->setObjectiveValue(COIN_DBL_MAX);
688                   break;
689                 }
690               }
691               const double *solution = getColSolution();
692               // add OA cut
693               doAOCuts(gen2, solution, solution);
694               if (solution2) {
695                 doAOCuts(gen2, solution, solution2);
696                 delete[] solution2;
697               }
698               break;
699             }
700           }
701         }
702       } else if (cbcModel && (specialOptions2_ & 8) == 8) {
703         // convex and nonlinear in constraints
704         int numberGenerators = cbcModel_->numberCutGenerators();
705         int iGenerator;
706         for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
707           CbcCutGenerator *generator = cbcModel_->cutGenerator(iGenerator);
708           CglCutGenerator *gen = generator->generator();
709           CglTemporary *gen2 = dynamic_cast< CglTemporary * >(gen);
710           if (gen2) {
711             const double *solution = getColSolution();
712             const double *rowUpper = getRowUpper();
713             const double *rowLower = getRowLower();
714             const double *element = originalRowCopy_->getElements();
715             const int *column2 = originalRowCopy_->getIndices();
716             const CoinBigIndex *rowStart = originalRowCopy_->getVectorStarts();
717             //const int * rowLength = originalRowCopy_->getVectorLengths();
718             int numberColumns2 = CoinMax(coinModel_.numberColumns(), objectiveVariable_ + 1);
719             double *gradient = new double[numberColumns2];
720             int *column = new int[numberColumns2];
721             //const double * columnLower = modelPtr_->columnLower();
722             //const double * columnUpper = modelPtr_->columnUpper();
723             cbcModel_->lockThread();
724             for (int iNon = 0; iNon < numberNonLinearRows_; iNon++) {
725               int iRow = rowNonLinear_[iNon];
726               bool convex = convex_[iNon] > 0;
727               if (!convex_[iNon])
728                 continue; // can't use this row
729               // add OA cuts
730               double offset = 0.0;
731               // gradient from bilinear
732               int i;
733               CoinZeroN(gradient, numberColumns2);
734               //const double * objective = modelPtr_->objective();
735               for (CoinBigIndex i = rowStart[iRow]; i < rowStart[iRow + 1]; i++)
736                 gradient[column2[i]] = element[i];
737               for (i = startNonLinear_[iNon]; i < startNonLinear_[iNon + 1]; i++) {
738                 OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[whichNonLinear_[i]]);
739                 assert(obj);
740                 int xColumn = obj->xColumn();
741                 int yColumn = obj->yColumn();
742                 if (xColumn != yColumn) {
743                   double coefficient = /* 2.0* */ obj->coefficient();
744                   gradient[xColumn] += coefficient * solution[yColumn];
745                   gradient[yColumn] += coefficient * solution[xColumn];
746                   offset += coefficient * solution[xColumn] * solution[yColumn];
747                 } else {
748                   double coefficient = obj->coefficient();
749                   gradient[xColumn] += 2.0 * coefficient * solution[yColumn];
750                   offset += coefficient * solution[xColumn] * solution[yColumn];
751                 }
752               }
753               // assume convex
754               double rhs = 0.0;
755               int n = 0;
756               for (int i = 0; i < numberColumns2; i++) {
757                 double value = gradient[i];
758                 if (fabs(value) > 1.0e-12) {
759                   gradient[n] = value;
760                   rhs += value * solution[i];
761                   column[n++] = i;
762                 }
763               }
764               if (iRow == objectiveRow_) {
765                 gradient[n] = -1.0;
766                 assert(objectiveVariable_ >= 0);
767                 rhs -= solution[objectiveVariable_];
768                 column[n++] = objectiveVariable_;
769                 assert(convex);
770               } else if (convex) {
771                 offset += rowUpper[iRow];
772               } else if (!convex) {
773                 offset += rowLower[iRow];
774               }
775               if (convex && rhs > offset + 1.0e-5)
776                 gen2->addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient);
777               else if (!convex && rhs < offset - 1.0e-5)
778                 gen2->addCut(offset - 1.0e-7, COIN_DBL_MAX, n, column, gradient);
779             }
780             cbcModel_->unlockThread();
781             delete[] gradient;
782             delete[] column;
783             break;
784           }
785         }
786       }
787     }
788   } else {
789     modelPtr_->setProblemStatus(1);
790     modelPtr_->setObjectiveValue(COIN_DBL_MAX);
791   }
792   modelPtr_->setLogLevel(saveLogLevel);
793 }
794 // Do OA cuts
doAOCuts(CglTemporary * cutGen,const double * solution,const double * solution2)795 int OsiSolverLink::doAOCuts(CglTemporary *cutGen, const double *solution, const double *solution2)
796 {
797   cbcModel_->lockThread();
798   // add OA cut
799   double offset = 0.0;
800   int numberColumns = quadraticModel_->numberColumns();
801   double *gradient = new double[numberColumns + 1];
802   // gradient from bilinear
803   int i;
804   CoinZeroN(gradient, numberColumns + 1);
805   //const double * objective = modelPtr_->objective();
806   assert(objectiveRow_ >= 0);
807   const double *element = originalRowCopy_->getElements();
808   const int *column2 = originalRowCopy_->getIndices();
809   const CoinBigIndex *rowStart = originalRowCopy_->getVectorStarts();
810   //const int * rowLength = originalRowCopy_->getVectorLengths();
811   //int numberColumns2 = coinModel_.numberColumns();
812   for (CoinBigIndex i = rowStart[objectiveRow_]; i < rowStart[objectiveRow_ + 1]; i++)
813     gradient[column2[i]] = element[i];
814   //const double * columnLower = modelPtr_->columnLower();
815   //const double * columnUpper = modelPtr_->columnUpper();
816   for (i = 0; i < numberObjects_; i++) {
817     OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
818     if (obj) {
819       int xColumn = obj->xColumn();
820       int yColumn = obj->yColumn();
821       if (xColumn != yColumn) {
822         double coefficient = /* 2.0* */ obj->coefficient();
823         gradient[xColumn] += coefficient * solution2[yColumn];
824         gradient[yColumn] += coefficient * solution2[xColumn];
825         offset += coefficient * solution2[xColumn] * solution2[yColumn];
826       } else {
827         double coefficient = obj->coefficient();
828         gradient[xColumn] += 2.0 * coefficient * solution2[yColumn];
829         offset += coefficient * solution2[xColumn] * solution2[yColumn];
830       }
831     }
832   }
833   // assume convex
834   double rhs = 0.0;
835   int *column = new int[numberColumns + 1];
836   int n = 0;
837   for (int i = 0; i < numberColumns; i++) {
838     double value = gradient[i];
839     if (fabs(value) > 1.0e-12) {
840       gradient[n] = value;
841       rhs += value * solution[i];
842       column[n++] = i;
843     }
844   }
845   gradient[n] = -1.0;
846   assert(objectiveVariable_ >= 0);
847   rhs -= solution[objectiveVariable_];
848   column[n++] = objectiveVariable_;
849   int returnCode = 0;
850   if (rhs > offset + 1.0e-5) {
851     cutGen->addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient);
852     //printf("added cut with %d elements\n",n);
853     returnCode = 1;
854   }
855   delete[] gradient;
856   delete[] column;
857   cbcModel_->unlockThread();
858   return returnCode;
859 }
860 
861 //#############################################################################
862 // Constructors, destructors clone and assignment
863 //#############################################################################
864 
865 //-------------------------------------------------------------------
866 // Default Constructor
867 //-------------------------------------------------------------------
OsiSolverLink()868 OsiSolverLink::OsiSolverLink()
869   : CbcOsiSolver()
870 {
871   gutsOfDestructor(true);
872 }
873 #ifdef JJF_ZERO
874 /* returns
875    sequence of nonlinear or
876    -1 numeric
877    -2 not found
878    -3 too many terms
879 */
getVariable(const CoinModel & model,char * expression,int & linear)880 static int getVariable(const CoinModel &model, char *expression,
881   int &linear)
882 {
883   int non = -1;
884   linear = -1;
885   if (strcmp(expression, "Numeric")) {
886     // function
887     char *first = strchr(expression, '*');
888     int numberColumns = model.numberColumns();
889     int j;
890     if (first) {
891       *first = '\0';
892       for (j = 0; j < numberColumns; j++) {
893         if (!strcmp(expression, model.columnName(j))) {
894           linear = j;
895           memmove(expression, first + 1, strlen(first + 1) + 1);
896           break;
897         }
898       }
899     }
900     // find nonlinear
901     for (j = 0; j < numberColumns; j++) {
902       const char *name = model.columnName(j);
903       first = strstr(expression, name);
904       if (first) {
905         if (first != expression && isalnum(*(first - 1)))
906           continue; // not real match
907         first += strlen(name);
908         if (!isalnum(*first)) {
909           // match
910           non = j;
911           // but check no others
912           j++;
913           for (; j < numberColumns; j++) {
914             const char *name = model.columnName(j);
915             first = strstr(expression, name);
916             if (first) {
917               if (isalnum(*(first - 1)))
918                 continue; // not real match
919               first += strlen(name);
920               if (!isalnum(*first)) {
921                 // match - ouch
922                 non = -3;
923                 break;
924               }
925             }
926           }
927           break;
928         }
929       }
930     }
931     if (non == -1)
932       non = -2;
933   }
934   return non;
935 }
936 #endif
937 /* This creates from a coinModel object
938 
939    if errors.then number of sets is -1
940 
941    This creates linked ordered sets information.  It assumes -
942 
943    for product terms syntax is yy*f(zz)
944    also just f(zz) is allowed
945    and even a constant
946 
947    modelObject not const as may be changed as part of process.
948 */
OsiSolverLink(CoinModel & coinModel)949 OsiSolverLink::OsiSolverLink(CoinModel &coinModel)
950   : CbcOsiSolver()
951 {
952   gutsOfDestructor(true);
953   load(coinModel);
954 }
955 // need bounds
fakeBounds(OsiSolverInterface * solver,int column,double maximumValue,CoinModel * model1,CoinModel * model2)956 static void fakeBounds(OsiSolverInterface *solver, int column, double maximumValue,
957   CoinModel *model1, CoinModel *model2)
958 {
959   double lo = solver->getColLower()[column];
960   if (lo < -maximumValue) {
961     solver->setColLower(column, -maximumValue);
962     if (model1)
963       model1->setColLower(column, -maximumValue);
964     if (model2)
965       model2->setColLower(column, -maximumValue);
966   }
967   double up = solver->getColUpper()[column];
968   if (up > maximumValue) {
969     solver->setColUpper(column, maximumValue);
970     if (model1)
971       model1->setColUpper(column, maximumValue);
972     if (model2)
973       model2->setColUpper(column, maximumValue);
974   }
975 }
load(CoinModel & coinModelOriginal,bool tightenBounds,int logLevel)976 void OsiSolverLink::load(CoinModel &coinModelOriginal, bool tightenBounds, int logLevel)
977 {
978   // first check and set up arrays
979   int numberColumns = coinModelOriginal.numberColumns();
980   int numberRows = coinModelOriginal.numberRows();
981   // List of nonlinear entries
982   int *which = new int[numberColumns];
983   numberVariables_ = 0;
984   //specialOptions2_=0;
985   int iColumn;
986   int numberErrors = 0;
987   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
988     CoinModelLink triple = coinModelOriginal.firstInColumn(iColumn);
989     bool linear = true;
990     int n = 0;
991     // See if quadratic objective
992     const char *expr = coinModelOriginal.getColumnObjectiveAsString(iColumn);
993     if (strcmp(expr, "Numeric")) {
994       linear = false;
995     }
996     while (triple.row() >= 0) {
997       int iRow = triple.row();
998       const char *expr = coinModelOriginal.getElementAsString(iRow, iColumn);
999       if (strcmp(expr, "Numeric")) {
1000         linear = false;
1001       }
1002       triple = coinModelOriginal.next(triple);
1003       n++;
1004     }
1005     if (!linear) {
1006       which[numberVariables_++] = iColumn;
1007     }
1008   }
1009   // return if nothing
1010   if (!numberVariables_) {
1011     delete[] which;
1012     coinModel_ = coinModelOriginal;
1013     int nInt = 0;
1014     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1015       if (coinModel_.isInteger(iColumn))
1016         nInt++;
1017     }
1018     printf("There are %d integers\n", nInt);
1019     loadFromCoinModel(coinModelOriginal, true);
1020     OsiObject **objects = new OsiObject *[nInt];
1021     nInt = 0;
1022     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1023       if (coinModel_.isInteger(iColumn)) {
1024         objects[nInt] = new OsiSimpleInteger(this, iColumn);
1025         objects[nInt]->setPriority(integerPriority_);
1026         nInt++;
1027       }
1028     }
1029     addObjects(nInt, objects);
1030     int i;
1031     for (i = 0; i < nInt; i++)
1032       delete objects[i];
1033     delete[] objects;
1034     return;
1035   } else {
1036     coinModel_ = coinModelOriginal;
1037     // arrays for tightening bounds
1038     int *freeRow = new int[numberRows];
1039     CoinZeroN(freeRow, numberRows);
1040     int *tryColumn = new int[numberColumns];
1041     CoinZeroN(tryColumn, numberColumns);
1042     int nBi = 0;
1043     int numberQuadratic = 0;
1044     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1045       // See if quadratic objective
1046       const char *expr = coinModel_.getColumnObjectiveAsString(iColumn);
1047       if (strcmp(expr, "Numeric")) {
1048         // check if value*x+-value*y....
1049         assert(strlen(expr) < 20000);
1050         tryColumn[iColumn] = 1;
1051         char temp[20000];
1052         strcpy(temp, expr);
1053         char *pos = temp;
1054         bool ifFirst = true;
1055         double linearTerm = 0.0;
1056         while (*pos) {
1057           double value;
1058           int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_);
1059           // must be column unless first when may be linear term
1060           if (jColumn >= 0) {
1061             tryColumn[jColumn] = 1;
1062             numberQuadratic++;
1063             nBi++;
1064           } else if (jColumn == -2) {
1065             linearTerm = value;
1066           } else {
1067             printf("bad nonlinear term %s\n", temp);
1068             abort();
1069           }
1070           ifFirst = false;
1071         }
1072         coinModelOriginal.setObjective(iColumn, linearTerm);
1073       }
1074     }
1075     int iRow;
1076     int saveNBi = nBi;
1077     for (iRow = 0; iRow < numberRows; iRow++) {
1078       CoinModelLink triple = coinModel_.firstInRow(iRow);
1079       while (triple.column() >= 0) {
1080         int iColumn = triple.column();
1081         const char *el = coinModel_.getElementAsString(iRow, iColumn);
1082         if (strcmp("Numeric", el)) {
1083           // check if value*x+-value*y....
1084           assert(strlen(el) < 20000);
1085           char temp[20000];
1086           strcpy(temp, el);
1087           char *pos = temp;
1088           bool ifFirst = true;
1089           double linearTerm = 0.0;
1090           tryColumn[iColumn] = 1;
1091           freeRow[iRow] = 1;
1092           while (*pos) {
1093             double value;
1094             int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_);
1095             // must be column unless first when may be linear term
1096             if (jColumn >= 0) {
1097               tryColumn[jColumn] = 1;
1098               nBi++;
1099             } else if (jColumn == -2) {
1100               linearTerm = value;
1101             } else {
1102               printf("bad nonlinear term %s\n", temp);
1103               abort();
1104             }
1105             ifFirst = false;
1106           }
1107           coinModelOriginal.setElement(iRow, iColumn, linearTerm);
1108         }
1109         triple = coinModel_.next(triple);
1110       }
1111     }
1112     if (!nBi)
1113       exit(1);
1114     bool quadraticObjective = false;
1115     int nInt = 0;
1116     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1117       if (coinModel_.isInteger(iColumn))
1118         nInt++;
1119     }
1120     printf("There are %d bilinear and %d integers\n", nBi, nInt);
1121     loadFromCoinModel(coinModelOriginal, true);
1122     CoinModel coinModel = coinModelOriginal;
1123     if (tightenBounds && numberColumns < 100) {
1124       // first fake bounds
1125       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1126         if (tryColumn[iColumn]) {
1127           fakeBounds(this, iColumn, defaultBound_, &coinModel, &coinModel_);
1128         }
1129       }
1130       ClpSimplex tempModel(*modelPtr_);
1131       int nDelete = 0;
1132       for (iRow = 0; iRow < numberRows; iRow++) {
1133         if (freeRow[iRow])
1134           freeRow[nDelete++] = iRow;
1135       }
1136       tempModel.deleteRows(nDelete, freeRow);
1137       tempModel.setOptimizationDirection(1.0);
1138       if (logLevel < 3) {
1139         tempModel.setLogLevel(0);
1140         tempModel.setSpecialOptions(32768);
1141       }
1142       double *objective = tempModel.objective();
1143       CoinZeroN(objective, numberColumns);
1144       // now up and down
1145       double *columnLower = modelPtr_->columnLower();
1146       double *columnUpper = modelPtr_->columnUpper();
1147       const double *solution = tempModel.primalColumnSolution();
1148       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1149         if (tryColumn[iColumn]) {
1150           objective[iColumn] = 1.0;
1151           tempModel.primal(1);
1152           if (solution[iColumn] > columnLower[iColumn] + 1.0e-3) {
1153             double value = solution[iColumn];
1154             if (coinModel_.isInteger(iColumn))
1155               value = ceil(value - 0.9e-3);
1156             if (logLevel > 1)
1157               printf("lower bound on %d changed from %g to %g\n", iColumn, columnLower[iColumn], value);
1158             columnLower[iColumn] = value;
1159             coinModel_.setColumnLower(iColumn, value);
1160             coinModel.setColumnLower(iColumn, value);
1161           }
1162           objective[iColumn] = -1.0;
1163           tempModel.primal(1);
1164           if (solution[iColumn] < columnUpper[iColumn] - 1.0e-3) {
1165             double value = solution[iColumn];
1166             if (coinModel_.isInteger(iColumn))
1167               value = floor(value + 0.9e-3);
1168             if (logLevel > 1)
1169               printf("upper bound on %d changed from %g to %g\n", iColumn, columnUpper[iColumn], value);
1170             columnUpper[iColumn] = value;
1171             coinModel_.setColumnUpper(iColumn, value);
1172             coinModel.setColumnUpper(iColumn, value);
1173           }
1174           objective[iColumn] = 0.0;
1175         }
1176       }
1177     }
1178     delete[] freeRow;
1179     delete[] tryColumn;
1180     CoinBigIndex *startQuadratic = NULL;
1181     int *columnQuadratic = NULL;
1182     double *elementQuadratic = NULL;
1183     if (saveNBi == nBi) {
1184       printf("all bilinearity in objective\n");
1185       specialOptions2_ |= 2;
1186       quadraticObjective = true;
1187       // save copy as quadratic model
1188       quadraticModel_ = new ClpSimplex(*modelPtr_);
1189       startQuadratic = new CoinBigIndex[numberColumns + 1];
1190       columnQuadratic = new int[numberQuadratic];
1191       elementQuadratic = new double[numberQuadratic];
1192       numberQuadratic = 0;
1193     }
1194     //if (quadraticObjective||((specialOptions2_&8)!=0&&saveNBi)) {
1195     if (saveNBi) {
1196       // add in objective as constraint
1197       objectiveVariable_ = numberColumns;
1198       objectiveRow_ = coinModel.numberRows();
1199       coinModel.addColumn(0, NULL, NULL, -COIN_DBL_MAX, COIN_DBL_MAX, 1.0);
1200       int *column = new int[numberColumns + 1];
1201       double *element = new double[numberColumns + 1];
1202       double *objective = coinModel.objectiveArray();
1203       int n = 0;
1204       for (int i = 0; i < numberColumns; i++) {
1205         if (objective[i]) {
1206           column[n] = i;
1207           element[n++] = objective[i];
1208           objective[i] = 0.0;
1209         }
1210       }
1211       column[n] = objectiveVariable_;
1212       element[n++] = -1.0;
1213       double offset = -coinModel.objectiveOffset();
1214       //assert (!offset); // get sign right if happens
1215       printf("***** offset %g\n", offset);
1216       coinModel.setObjectiveOffset(0.0);
1217       double lowerBound = -COIN_DBL_MAX;
1218       coinModel.addRow(n, column, element, lowerBound, offset);
1219       delete[] column;
1220       delete[] element;
1221     }
1222     OsiObject **objects = new OsiObject *[nBi + nInt];
1223     char *marked = new char[numberColumns];
1224     memset(marked, 0, numberColumns);
1225     // statistics I-I I-x x-x
1226     int stats[3] = { 0, 0, 0 };
1227     double *sort = new double[nBi];
1228     nBi = nInt;
1229     const OsiObject **justBi = const_cast< const OsiObject ** >(objects + nInt);
1230     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1231       if (quadraticObjective)
1232         startQuadratic[iColumn] = numberQuadratic;
1233       // See if quadratic objective
1234       const char *expr = coinModel_.getColumnObjectiveAsString(iColumn);
1235       if (strcmp(expr, "Numeric")) {
1236         // need bounds
1237         fakeBounds(this, iColumn, defaultBound_, &coinModel, &coinModel_);
1238         // value*x*y
1239         char temp[20000];
1240         strcpy(temp, expr);
1241         char *pos = temp;
1242         bool ifFirst = true;
1243         while (*pos) {
1244           double value;
1245           int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_);
1246           // must be column unless first when may be linear term
1247           if (jColumn >= 0) {
1248             if (quadraticObjective) {
1249               columnQuadratic[numberQuadratic] = jColumn;
1250               if (jColumn == iColumn)
1251                 elementQuadratic[numberQuadratic++] = 2.0 * value; // convention
1252               else
1253                 elementQuadratic[numberQuadratic++] = 1.0 * value; // convention
1254             }
1255             // need bounds
1256             fakeBounds(this, jColumn, defaultBound_, &coinModel, &coinModel_);
1257             double meshI = coinModel_.isInteger(iColumn) ? 1.0 : 0.0;
1258             if (meshI)
1259               marked[iColumn] = 1;
1260             double meshJ = coinModel_.isInteger(jColumn) ? 1.0 : 0.0;
1261             if (meshJ)
1262               marked[jColumn] = 1;
1263             // stats etc
1264             if (meshI) {
1265               if (meshJ)
1266                 stats[0]++;
1267               else
1268                 stats[1]++;
1269             } else {
1270               if (meshJ)
1271                 stats[1]++;
1272               else
1273                 stats[2]++;
1274             }
1275             if (iColumn <= jColumn)
1276               sort[nBi - nInt] = iColumn + numberColumns * jColumn;
1277             else
1278               sort[nBi - nInt] = jColumn + numberColumns * iColumn;
1279             if (!meshJ && !meshI) {
1280               meshI = defaultMeshSize_;
1281               meshJ = 0.0;
1282             }
1283             OsiBiLinear *newObj = new OsiBiLinear(&coinModel, iColumn, jColumn, objectiveRow_, value, meshI, meshJ,
1284               nBi - nInt, justBi);
1285             newObj->setPriority(biLinearPriority_);
1286             objects[nBi++] = newObj;
1287           } else if (jColumn == -2) {
1288           } else {
1289             printf("bad nonlinear term %s\n", temp);
1290             abort();
1291           }
1292           ifFirst = false;
1293         }
1294       }
1295     }
1296     // stats
1297     printf("There were %d I-I, %d I-x and %d x-x bilinear in objective\n",
1298       stats[0], stats[1], stats[2]);
1299     if (quadraticObjective) {
1300       startQuadratic[numberColumns] = numberQuadratic;
1301       quadraticModel_->loadQuadraticObjective(numberColumns, startQuadratic,
1302         columnQuadratic, elementQuadratic);
1303       delete[] startQuadratic;
1304       delete[] columnQuadratic;
1305       delete[] elementQuadratic;
1306     }
1307     for (iRow = 0; iRow < numberRows; iRow++) {
1308       CoinModelLink triple = coinModel_.firstInRow(iRow);
1309       while (triple.column() >= 0) {
1310         int iColumn = triple.column();
1311         const char *el = coinModel_.getElementAsString(iRow, iColumn);
1312         if (strcmp("Numeric", el)) {
1313           // need bounds
1314           fakeBounds(this, iColumn, defaultBound_, &coinModel, &coinModel_);
1315           // value*x*y
1316           char temp[20000];
1317           strcpy(temp, el);
1318           char *pos = temp;
1319           bool ifFirst = true;
1320           while (*pos) {
1321             double value;
1322             int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_);
1323             // must be column unless first when may be linear term
1324             if (jColumn >= 0) {
1325               // need bounds
1326               fakeBounds(this, jColumn, defaultBound_, &coinModel, &coinModel_);
1327               double meshI = coinModel_.isInteger(iColumn) ? 1.0 : 0.0;
1328               if (meshI)
1329                 marked[iColumn] = 1;
1330               double meshJ = coinModel_.isInteger(jColumn) ? 1.0 : 0.0;
1331               if (meshJ)
1332                 marked[jColumn] = 1;
1333               // stats etc
1334               if (meshI) {
1335                 if (meshJ)
1336                   stats[0]++;
1337                 else
1338                   stats[1]++;
1339               } else {
1340                 if (meshJ)
1341                   stats[1]++;
1342                 else
1343                   stats[2]++;
1344               }
1345               if (iColumn <= jColumn)
1346                 sort[nBi - nInt] = iColumn + numberColumns * jColumn;
1347               else
1348                 sort[nBi - nInt] = jColumn + numberColumns * iColumn;
1349               if (!meshJ && !meshI) {
1350                 meshI = defaultMeshSize_;
1351                 meshJ = 0.0;
1352               }
1353               OsiBiLinear *newObj = new OsiBiLinear(&coinModel, iColumn, jColumn, iRow, value, meshI, meshJ,
1354                 nBi - nInt, justBi);
1355               newObj->setPriority(biLinearPriority_);
1356               objects[nBi++] = newObj;
1357             } else if (jColumn == -2) {
1358             } else {
1359               printf("bad nonlinear term %s\n", temp);
1360               abort();
1361             }
1362             ifFirst = false;
1363           }
1364         }
1365         triple = coinModel_.next(triple);
1366       }
1367     }
1368     {
1369       // stats
1370       std::sort(sort, sort + nBi - nInt);
1371       int nDiff = 0;
1372       double last = -1.0;
1373       for (int i = 0; i < nBi - nInt; i++) {
1374         if (sort[i] != last)
1375           nDiff++;
1376         last = sort[i];
1377       }
1378       delete[] sort;
1379       printf("There were %d I-I, %d I-x and %d x-x bilinear in total of which %d were duplicates\n",
1380         stats[0], stats[1], stats[2], nBi - nInt - nDiff);
1381     }
1382     // reload with all bilinear stuff
1383     loadFromCoinModel(coinModel, true);
1384     //exit(77);
1385     nInt = 0;
1386     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1387       if (coinModel_.isInteger(iColumn)) {
1388         objects[nInt] = new OsiSimpleInteger(this, iColumn);
1389         if (marked[iColumn])
1390           objects[nInt]->setPriority(integerPriority_);
1391         else
1392           objects[nInt]->setPriority(integerPriority_);
1393         nInt++;
1394       }
1395     }
1396     nInt = nBi;
1397     delete[] marked;
1398     if (numberErrors) {
1399       // errors
1400       gutsOfDestructor();
1401       numberVariables_ = -1;
1402     } else {
1403       addObjects(nInt, objects);
1404       int i;
1405       for (i = 0; i < nInt; i++)
1406         delete objects[i];
1407       delete[] objects;
1408       // Now do dummy bound stuff
1409       matrix_ = new CoinPackedMatrix(*getMatrixByCol());
1410       info_ = new OsiLinkedBound[numberVariables_];
1411       for (i = 0; i < numberVariables_; i++) {
1412         info_[i] = OsiLinkedBound(this, which[i], 0, NULL, NULL, NULL);
1413       }
1414       // Do row copy but just part
1415       int numberRows2 = objectiveRow_ >= 0 ? numberRows + 1 : numberRows;
1416       int *whichRows = new int[numberRows2];
1417       int *whichColumns = new int[numberColumns];
1418       CoinIotaN(whichRows, numberRows2, 0);
1419       CoinIotaN(whichColumns, numberColumns, 0);
1420       originalRowCopy_ = new CoinPackedMatrix(*getMatrixByRow(),
1421         numberRows2, whichRows,
1422         numberColumns, whichColumns);
1423       delete[] whichColumns;
1424       numberNonLinearRows_ = 0;
1425       CoinZeroN(whichRows, numberRows2);
1426       for (i = 0; i < numberObjects_; i++) {
1427         OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
1428         if (obj) {
1429           int xyRow = obj->xyRow();
1430           assert(xyRow >= 0 && xyRow < numberRows2); // even if obj we should move
1431           whichRows[xyRow]++;
1432         }
1433       }
1434       int *pos = new int[numberRows2];
1435       int n = 0;
1436       for (i = 0; i < numberRows2; i++) {
1437         if (whichRows[i]) {
1438           pos[numberNonLinearRows_] = n;
1439           n += whichRows[i];
1440           whichRows[i] = numberNonLinearRows_;
1441           numberNonLinearRows_++;
1442         } else {
1443           whichRows[i] = -1;
1444         }
1445       }
1446       startNonLinear_ = new int[numberNonLinearRows_ + 1];
1447       memcpy(startNonLinear_, pos, numberNonLinearRows_ * sizeof(int));
1448       startNonLinear_[numberNonLinearRows_] = n;
1449       rowNonLinear_ = new int[numberNonLinearRows_];
1450       convex_ = new int[numberNonLinearRows_];
1451       // do row numbers now
1452       numberNonLinearRows_ = 0;
1453       for (i = 0; i < numberRows2; i++) {
1454         if (whichRows[i] >= 0) {
1455           rowNonLinear_[numberNonLinearRows_++] = i;
1456         }
1457       }
1458       whichNonLinear_ = new int[n];
1459       for (i = 0; i < numberObjects_; i++) {
1460         OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
1461         if (obj) {
1462           int xyRow = obj->xyRow();
1463           int k = whichRows[xyRow];
1464           int put = pos[k];
1465           pos[k]++;
1466           whichNonLinear_[put] = i;
1467         }
1468       }
1469       delete[] pos;
1470       delete[] whichRows;
1471       analyzeObjects();
1472     }
1473   }
1474   // See if there are any quadratic bounds
1475   int nQ = 0;
1476   const CoinPackedMatrix *rowCopy = getMatrixByRow();
1477   //const double * element = rowCopy->getElements();
1478   //const int * column = rowCopy->getIndices();
1479   //const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
1480   const int *rowLength = rowCopy->getVectorLengths();
1481   const double *rowLower = getRowLower();
1482   const double *rowUpper = getRowUpper();
1483   for (int iObject = 0; iObject < numberObjects_; iObject++) {
1484     OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[iObject]);
1485     if (obj) {
1486       int xyRow = obj->xyRow();
1487       if (rowLength[xyRow] == 4 && false) {
1488         // we have simple bound
1489         nQ++;
1490         double coefficient = obj->coefficient();
1491         double lo = rowLower[xyRow];
1492         double up = rowUpper[xyRow];
1493         if (coefficient != 1.0) {
1494           printf("*** double check code here\n");
1495           if (coefficient < 0.0) {
1496             double temp = lo;
1497             lo = -up;
1498             up = -temp;
1499             coefficient = -coefficient;
1500           }
1501           if (lo > -1.0e20)
1502             lo /= coefficient;
1503           if (up < 1.0e20)
1504             up /= coefficient;
1505           setRowLower(xyRow, lo);
1506           setRowUpper(xyRow, up);
1507           // we also need to change elements in matrix_
1508         }
1509         int type = 0;
1510         if (lo == up) {
1511           // good news
1512           type = 3;
1513           coefficient = lo;
1514         } else if (lo < -1.0e20) {
1515           assert(up < 1.0e20);
1516           coefficient = up;
1517           type = 1;
1518           // can we make equality?
1519         } else if (up > 1.0e20) {
1520           coefficient = lo;
1521           type = 2;
1522           // can we make equality?
1523         } else {
1524           // we would need extra code
1525           abort();
1526         }
1527         obj->setBoundType(type);
1528         obj->setCoefficient(coefficient);
1529         // can do better if integer?
1530         assert(!isInteger(obj->xColumn()));
1531         assert(!isInteger(obj->yColumn()));
1532       }
1533     }
1534   }
1535   delete[] which;
1536   if ((specialOptions2_ & 16) != 0)
1537     addTighterConstraints();
1538 }
1539 // Add reformulated bilinear constraints
addTighterConstraints()1540 void OsiSolverLink::addTighterConstraints()
1541 {
1542   // This is first attempt - for now get working on trimloss
1543   int numberW = 0;
1544   int *xW = new int[numberObjects_];
1545   int *yW = new int[numberObjects_];
1546   // Points to firstlambda
1547   int *wW = new int[numberObjects_];
1548   // Coefficient
1549   double *alphaW = new double[numberObjects_];
1550   // Objects
1551   OsiBiLinear **objW = new OsiBiLinear *[numberObjects_];
1552   int numberColumns = getNumCols();
1553   int firstLambda = numberColumns;
1554   // set up list (better to rethink and do properly as column ordered)
1555   int *list = new int[numberColumns];
1556   memset(list, 0, numberColumns * sizeof(int));
1557   int i;
1558   for (i = 0; i < numberObjects_; i++) {
1559     OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
1560     if (obj) {
1561       //obj->setBranchingStrategy(4); // ***** temp
1562       objW[numberW] = obj;
1563       xW[numberW] = obj->xColumn();
1564       yW[numberW] = obj->yColumn();
1565       list[xW[numberW]] = 1;
1566       list[yW[numberW]] = 1;
1567       wW[numberW] = obj->firstLambda();
1568       firstLambda = CoinMin(firstLambda, obj->firstLambda());
1569       alphaW[numberW] = obj->coefficient();
1570       //assert (alphaW[numberW]==1.0); // fix when occurs
1571       numberW++;
1572     }
1573   }
1574   int nList = 0;
1575   for (i = 0; i < numberColumns; i++) {
1576     if (list[i])
1577       list[nList++] = i;
1578   }
1579   // set up mark array
1580   char *mark = new char[firstLambda * firstLambda];
1581   memset(mark, 0, firstLambda * firstLambda);
1582   for (i = 0; i < numberW; i++) {
1583     int x = xW[i];
1584     int y = yW[i];
1585     mark[x * firstLambda + y] = 1;
1586     mark[y * firstLambda + x] = 1;
1587   }
1588   int numberRows2 = originalRowCopy_->getNumRows();
1589   int *addColumn = new int[numberColumns];
1590   double *addElement = new double[numberColumns];
1591   int *addW = new int[numberColumns];
1592   assert(objectiveRow_ < 0); // fix when occurs
1593   for (int iRow = 0; iRow < numberRows2; iRow++) {
1594     for (int iList = 0; iList < nList; iList++) {
1595       int kColumn = list[iList];
1596 #ifndef NDEBUG
1597       const double *columnLower = getColLower();
1598 #endif
1599       //const double * columnUpper = getColUpper();
1600       const double *rowLower = getRowLower();
1601       const double *rowUpper = getRowUpper();
1602       const CoinPackedMatrix *rowCopy = getMatrixByRow();
1603       const double *element = rowCopy->getElements();
1604       const int *column = rowCopy->getIndices();
1605       const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
1606       const int *rowLength = rowCopy->getVectorLengths();
1607       CoinBigIndex j;
1608       int numberElements = rowLength[iRow];
1609       int n = 0;
1610       for (j = rowStart[iRow]; j < rowStart[iRow] + numberElements; j++) {
1611         int iColumn = column[j];
1612         if (iColumn >= firstLambda) {
1613           // no good
1614           n = -1;
1615           break;
1616         }
1617         if (mark[iColumn * firstLambda + kColumn])
1618           n++;
1619       }
1620       if (n == numberElements) {
1621         printf("can add row %d\n", iRow);
1622         assert(columnLower[kColumn] >= 0); // might be able to fix
1623         n = 0;
1624         for (j = rowStart[iRow]; j < rowStart[iRow] + numberElements; j++) {
1625           int xColumn = kColumn;
1626           int yColumn = column[j];
1627           int k;
1628           for (k = 0; k < numberW; k++) {
1629             if ((xW[k] == yColumn && yW[k] == xColumn) || (yW[k] == yColumn && xW[k] == xColumn))
1630               break;
1631           }
1632           assert(k < numberW);
1633           if (xW[k] != xColumn) {
1634             int temp = xColumn;
1635             xColumn = yColumn;
1636             yColumn = temp;
1637           }
1638           addW[n / 4] = k;
1639           int start = wW[k];
1640           double value = element[j];
1641           for (int kk = 0; kk < 4; kk++) {
1642             // Dummy value
1643             addElement[n] = value;
1644             addColumn[n++] = start + kk;
1645           }
1646         }
1647         addColumn[n++] = kColumn;
1648         double lo = rowLower[iRow];
1649         double up = rowUpper[iRow];
1650         if (lo > -1.0e20) {
1651           // and tell object
1652           for (j = 0; j < n - 1; j += 4) {
1653             int iObject = addW[j / 4];
1654             objW[iObject]->addExtraRow(matrix_->getNumRows(), addElement[j]);
1655           }
1656           addElement[n - 1] = -lo;
1657           if (lo == up)
1658             addRow(n, addColumn, addElement, 0.0, 0.0);
1659           else
1660             addRow(n, addColumn, addElement, 0.0, COIN_DBL_MAX);
1661           matrix_->appendRow(n, addColumn, addElement);
1662         }
1663         if (up < 1.0e20 && up > lo) {
1664           // and tell object
1665           for (j = 0; j < n - 1; j += 4) {
1666             int iObject = addW[j / 4];
1667             objW[iObject]->addExtraRow(matrix_->getNumRows(), addElement[j]);
1668           }
1669           addElement[n - 1] = -up;
1670           addRow(n, addColumn, addElement, -COIN_DBL_MAX, 0.0);
1671           matrix_->appendRow(n, addColumn, addElement);
1672         }
1673       }
1674     }
1675   }
1676 #ifdef JJF_ZERO
1677   // possibly do bounds
1678   for (int iColumn = 0; iColumn < firstLambda; iColumn++) {
1679     for (int iList = 0; iList < nList; iList++) {
1680       int kColumn = list[iList];
1681       const double *columnLower = getColLower();
1682       const double *columnUpper = getColUpper();
1683       if (mark[iColumn * firstLambda + kColumn]) {
1684         printf("can add column %d\n", iColumn);
1685         assert(columnLower[kColumn] >= 0); // might be able to fix
1686         int xColumn = kColumn;
1687         int yColumn = iColumn;
1688         int k;
1689         for (k = 0; k < numberW; k++) {
1690           if ((xW[k] == yColumn && yW[k] == xColumn) || (yW[k] == yColumn && xW[k] == xColumn))
1691             break;
1692         }
1693         assert(k < numberW);
1694         if (xW[k] != xColumn) {
1695           int temp = xColumn;
1696           xColumn = yColumn;
1697           yColumn = temp;
1698         }
1699         int start = wW[k];
1700         int n = 0;
1701         for (int kk = 0; kk < 4; kk++) {
1702           // Dummy value
1703           addElement[n] = 1.0e-19;
1704           addColumn[n++] = start + kk;
1705         }
1706         // Tell object about this
1707         objW[k]->addExtraRow(matrix_->getNumRows(), 1.0);
1708         addColumn[n++] = kColumn;
1709         double lo = columnLower[iColumn];
1710         double up = columnUpper[iColumn];
1711         if (lo > -1.0e20) {
1712           addElement[n - 1] = -lo;
1713           if (lo == up)
1714             addRow(n, addColumn, addElement, 0.0, 0.0);
1715           else
1716             addRow(n, addColumn, addElement, 0.0, COIN_DBL_MAX);
1717           matrix_->appendRow(n, addColumn, addElement);
1718         }
1719         if (up < 1.0e20 && up > lo) {
1720           addElement[n - 1] = -up;
1721           addRow(n, addColumn, addElement, -COIN_DBL_MAX, 0.0);
1722           matrix_->appendRow(n, addColumn, addElement);
1723         }
1724       }
1725     }
1726   }
1727 #endif
1728   delete[] xW;
1729   delete[] yW;
1730   delete[] wW;
1731   delete[] alphaW;
1732   delete[] addColumn;
1733   delete[] addElement;
1734   delete[] addW;
1735   delete[] mark;
1736   delete[] list;
1737   delete[] objW;
1738 }
1739 // Set all biLinear priorities on x-x variables
setBiLinearPriorities(int value,double meshSize)1740 void OsiSolverLink::setBiLinearPriorities(int value, double meshSize)
1741 {
1742   OsiObject **newObject = new OsiObject *[numberObjects_];
1743   int numberOdd = 0;
1744   int i;
1745   for (i = 0; i < numberObjects_; i++) {
1746     OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
1747     if (obj) {
1748       if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0) {
1749         double oldSatisfied = CoinMax(obj->xSatisfied(),
1750           obj->ySatisfied());
1751         OsiBiLinear *objNew = new OsiBiLinear(*obj);
1752         newObject[numberOdd++] = objNew;
1753         objNew->setXSatisfied(0.5 * meshSize);
1754         obj->setXOtherSatisfied(0.5 * meshSize);
1755         objNew->setXOtherSatisfied(oldSatisfied);
1756         objNew->setXMeshSize(meshSize);
1757         objNew->setYSatisfied(0.5 * meshSize);
1758         obj->setYOtherSatisfied(0.5 * meshSize);
1759         objNew->setYOtherSatisfied(oldSatisfied);
1760         objNew->setYMeshSize(meshSize);
1761         objNew->setXYSatisfied(0.25 * meshSize);
1762         objNew->setPriority(value);
1763         objNew->setBranchingStrategy(8);
1764       }
1765     }
1766   }
1767   addObjects(numberOdd, newObject);
1768   for (i = 0; i < numberOdd; i++)
1769     delete newObject[i];
1770   delete[] newObject;
1771 }
1772 /* Set options and priority on all or some biLinear variables
1773    1 - on I-I
1774    2 - on I-x
1775    4 - on x-x
1776       or combinations.
1777       -1 means leave (for priority value and strategy value)
1778 */
setBranchingStrategyOnVariables(int strategyValue,int priorityValue,int mode)1779 void OsiSolverLink::setBranchingStrategyOnVariables(int strategyValue, int priorityValue,
1780   int mode)
1781 {
1782   int i;
1783   for (i = 0; i < numberObjects_; i++) {
1784     OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
1785     if (obj) {
1786       bool change = false;
1787       if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0 && (mode & 4) != 0)
1788         change = true;
1789       else if (((obj->xMeshSize() == 1.0 && obj->yMeshSize() < 1.0) || (obj->xMeshSize() < 1.0 && obj->yMeshSize() == 1.0)) && (mode & 2) != 0)
1790         change = true;
1791       else if (obj->xMeshSize() == 1.0 && obj->yMeshSize() == 1.0 && (mode & 1) != 0)
1792         change = true;
1793       else if (obj->xMeshSize() > 1.0 || obj->yMeshSize() > 1.0)
1794         abort();
1795       if (change) {
1796         if (strategyValue >= 0)
1797           obj->setBranchingStrategy(strategyValue);
1798         if (priorityValue >= 0)
1799           obj->setPriority(priorityValue);
1800       }
1801     }
1802   }
1803 }
1804 
1805 // Say convex (should work it out)
sayConvex(bool convex)1806 void OsiSolverLink::sayConvex(bool convex)
1807 {
1808   specialOptions2_ |= 4;
1809   if (convex_) {
1810     for (int iNon = 0; iNon < numberNonLinearRows_; iNon++) {
1811       convex_[iNon] = convex ? 1 : -1;
1812     }
1813   }
1814 }
1815 // Set all mesh sizes on x-x variables
setMeshSizes(double value)1816 void OsiSolverLink::setMeshSizes(double value)
1817 {
1818   int i;
1819   for (i = 0; i < numberObjects_; i++) {
1820     OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[i]);
1821     if (obj) {
1822       if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0) {
1823 #ifdef JJF_ZERO
1824         numberContinuous++;
1825         int xColumn = obj->xColumn();
1826         double gapX = upper[xColumn] - lower[xColumn];
1827         int yColumn = obj->yColumn();
1828         double gapY = upper[yColumn] - lower[yColumn];
1829         gap = CoinMax(gap, CoinMax(gapX, gapY));
1830 #endif
1831         obj->setMeshSizes(this, value, value);
1832       }
1833     }
1834   }
1835 }
1836 /* Solves nonlinear problem from CoinModel using SLP - may be used as crash
1837    for other algorithms when number of iterations small.
1838    Also exits if all problematical variables are changing
1839    less than deltaTolerance
1840    Returns solution array
1841 */
1842 double *
nonlinearSLP(int numberPasses,double deltaTolerance)1843 OsiSolverLink::nonlinearSLP(int numberPasses, double deltaTolerance)
1844 {
1845   if (!coinModel_.numberRows()) {
1846     printf("Model not set up or nonlinear arrays not created!\n");
1847     return NULL;
1848   }
1849   // first check and set up arrays
1850   int numberColumns = coinModel_.numberColumns();
1851   int numberRows = coinModel_.numberRows();
1852   char *markNonlinear = new char[numberColumns + numberRows];
1853   CoinZeroN(markNonlinear, numberColumns + numberRows);
1854   // List of nonlinear entries
1855   int *listNonLinearColumn = new int[numberColumns];
1856   // List of nonlinear constraints
1857   int *whichRow = new int[numberRows];
1858   CoinZeroN(whichRow, numberRows);
1859   int numberNonLinearColumns = 0;
1860   int iColumn;
1861   CoinModel coinModel = coinModel_;
1862   //const CoinModelHash * stringArray = coinModel.stringArray();
1863   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1864     CoinModelLink triple = coinModel.firstInColumn(iColumn);
1865     bool linear = true;
1866     int n = 0;
1867     // See if nonlinear objective
1868     const char *expr = coinModel.getColumnObjectiveAsString(iColumn);
1869     if (strcmp(expr, "Numeric")) {
1870       linear = false;
1871       // try and see which columns
1872       assert(strlen(expr) < 20000);
1873       char temp[20000];
1874       strcpy(temp, expr);
1875       char *pos = temp;
1876       bool ifFirst = true;
1877       while (*pos) {
1878         double value;
1879         int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_);
1880         // must be column unless first when may be linear term
1881         if (jColumn >= 0) {
1882           markNonlinear[jColumn] = 1;
1883         } else if (jColumn != -2) {
1884           printf("bad nonlinear term %s\n", temp);
1885           abort();
1886         }
1887         ifFirst = false;
1888       }
1889     }
1890     while (triple.row() >= 0) {
1891       int iRow = triple.row();
1892       const char *expr = coinModel.getElementAsString(iRow, iColumn);
1893       if (strcmp(expr, "Numeric")) {
1894         linear = false;
1895         whichRow[iRow]++;
1896         // try and see which columns
1897         assert(strlen(expr) < 20000);
1898         char temp[20000];
1899         strcpy(temp, expr);
1900         char *pos = temp;
1901         bool ifFirst = true;
1902         while (*pos) {
1903           double value;
1904           int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_);
1905           // must be column unless first when may be linear term
1906           if (jColumn >= 0) {
1907             markNonlinear[jColumn] = 1;
1908           } else if (jColumn != -2) {
1909             printf("bad nonlinear term %s\n", temp);
1910             abort();
1911           }
1912           ifFirst = false;
1913         }
1914       }
1915       triple = coinModel.next(triple);
1916       n++;
1917     }
1918     if (!linear) {
1919       markNonlinear[iColumn] = 1;
1920     }
1921   }
1922   //int xxxx[]={3,2,0,4,3,0};
1923   //double initialSolution[6];
1924   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1925     if (markNonlinear[iColumn]) {
1926       // put in something
1927       double lower = coinModel.columnLower(iColumn);
1928       double upper = CoinMin(coinModel.columnUpper(iColumn), lower + 1000.0);
1929       coinModel.associateElement(coinModel.columnName(iColumn), 0.5 * (lower + upper));
1930       //coinModel.associateElement(coinModel.columnName(iColumn),xxxx[iColumn]);
1931       listNonLinearColumn[numberNonLinearColumns++] = iColumn;
1932       //initialSolution[iColumn]=xxxx[iColumn];
1933     }
1934   }
1935   // if nothing just solve
1936   if (!numberNonLinearColumns) {
1937     delete[] listNonLinearColumn;
1938     delete[] whichRow;
1939     delete[] markNonlinear;
1940     ClpSimplex tempModel;
1941     tempModel.loadProblem(coinModel, true);
1942     tempModel.initialSolve();
1943     double *solution = CoinCopyOfArray(tempModel.getColSolution(), numberColumns);
1944     return solution;
1945   }
1946   // Create artificials
1947   ClpSimplex tempModel;
1948   tempModel.loadProblem(coinModel, true);
1949   const double *rowLower = tempModel.rowLower();
1950   const double *rowUpper = tempModel.rowUpper();
1951   bool takeAll = false;
1952   int iRow;
1953   int numberArtificials = 0;
1954   for (iRow = 0; iRow < numberRows; iRow++) {
1955     if (whichRow[iRow] || takeAll) {
1956       if (rowLower[iRow] > -1.0e30)
1957         numberArtificials++;
1958       if (rowUpper[iRow] < 1.0e30)
1959         numberArtificials++;
1960     }
1961   }
1962   CoinBigIndex *startArtificial = new CoinBigIndex[numberArtificials + 1];
1963   int *rowArtificial = new int[numberArtificials];
1964   double *elementArtificial = new double[numberArtificials];
1965   double *objectiveArtificial = new double[numberArtificials];
1966   numberArtificials = 0;
1967   startArtificial[0] = 0;
1968   double artificialCost = 1.0e9;
1969   for (iRow = 0; iRow < numberRows; iRow++) {
1970     if (whichRow[iRow] || takeAll) {
1971       if (rowLower[iRow] > -1.0e30) {
1972         rowArtificial[numberArtificials] = iRow;
1973         elementArtificial[numberArtificials] = 1.0;
1974         objectiveArtificial[numberArtificials] = artificialCost;
1975         numberArtificials++;
1976         startArtificial[numberArtificials] = numberArtificials;
1977       }
1978       if (rowUpper[iRow] < 1.0e30) {
1979         rowArtificial[numberArtificials] = iRow;
1980         elementArtificial[numberArtificials] = -1.0;
1981         objectiveArtificial[numberArtificials] = artificialCost;
1982         numberArtificials++;
1983         startArtificial[numberArtificials] = numberArtificials;
1984       }
1985     }
1986   }
1987   // Get first solution
1988   int numberColumnsSmall = numberColumns;
1989   ClpSimplex model;
1990   model.loadProblem(coinModel, true);
1991   model.addColumns(numberArtificials, NULL, NULL, objectiveArtificial,
1992     startArtificial, rowArtificial, elementArtificial);
1993   double *columnLower = model.columnLower();
1994   double *columnUpper = model.columnUpper();
1995   double *trueLower = new double[numberNonLinearColumns];
1996   double *trueUpper = new double[numberNonLinearColumns];
1997   int jNon;
1998   for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
1999     iColumn = listNonLinearColumn[jNon];
2000     trueLower[jNon] = columnLower[iColumn];
2001     trueUpper[jNon] = columnUpper[iColumn];
2002     //columnLower[iColumn]=initialSolution[iColumn];
2003     //columnUpper[iColumn]=initialSolution[iColumn];
2004   }
2005   model.initialSolve();
2006   //model.writeMps("bad.mps");
2007   // redo number of columns
2008   numberColumns = model.numberColumns();
2009   int *last[3];
2010   double *solution = model.primalColumnSolution();
2011 
2012   double *trust = new double[numberNonLinearColumns];
2013   for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2014     iColumn = listNonLinearColumn[jNon];
2015     trust[jNon] = 0.5;
2016     if (solution[iColumn] < trueLower[jNon])
2017       solution[iColumn] = trueLower[jNon];
2018     else if (solution[iColumn] > trueUpper[jNon])
2019       solution[iColumn] = trueUpper[jNon];
2020   }
2021   int iPass;
2022   double lastObjective = 1.0e31;
2023   double *saveSolution = new double[numberColumns];
2024   double *saveRowSolution = new double[numberRows];
2025   memset(saveRowSolution, 0, numberRows * sizeof(double));
2026   double *savePi = new double[numberRows];
2027   double *safeSolution = new double[numberColumns];
2028   unsigned char *saveStatus = new unsigned char[numberRows + numberColumns];
2029   double targetDrop = 1.0e31;
2030   //double objectiveOffset;
2031   //model.getDblParam(ClpObjOffset,objectiveOffset);
2032   // 1 bound up, 2 up, -1 bound down, -2 down, 0 no change
2033   for (iPass = 0; iPass < 3; iPass++) {
2034     last[iPass] = new int[numberNonLinearColumns];
2035     for (jNon = 0; jNon < numberNonLinearColumns; jNon++)
2036       last[iPass][jNon] = 0;
2037   }
2038   // goodMove +1 yes, 0 no, -1 last was bad - just halve gaps, -2 do nothing
2039   int goodMove = -2;
2040   char *statusCheck = new char[numberColumns];
2041   double *changeRegion = new double[numberColumns];
2042   int logLevel = 63;
2043   double dualTolerance = model.dualTolerance();
2044   double primalTolerance = model.primalTolerance();
2045   int lastGoodMove = 1;
2046   for (iPass = 0; iPass < numberPasses; iPass++) {
2047     lastGoodMove = goodMove;
2048     columnLower = model.columnLower();
2049     columnUpper = model.columnUpper();
2050     solution = model.primalColumnSolution();
2051     double *rowActivity = model.primalRowSolution();
2052     // redo objective
2053     ClpSimplex tempModel;
2054     // load new values
2055     for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2056       iColumn = listNonLinearColumn[jNon];
2057       coinModel.associateElement(coinModel.columnName(iColumn), solution[iColumn]);
2058     }
2059     tempModel.loadProblem(coinModel);
2060     double objectiveOffset;
2061     tempModel.getDblParam(ClpObjOffset, objectiveOffset);
2062     double objValue = -objectiveOffset;
2063     const double *objective = tempModel.objective();
2064     for (iColumn = 0; iColumn < numberColumnsSmall; iColumn++)
2065       objValue += solution[iColumn] * objective[iColumn];
2066     double *rowActivity2 = tempModel.primalRowSolution();
2067     const double *rowLower2 = tempModel.rowLower();
2068     const double *rowUpper2 = tempModel.rowUpper();
2069     memset(rowActivity2, 0, numberRows * sizeof(double));
2070     tempModel.times(1.0, solution, rowActivity2);
2071     for (iRow = 0; iRow < numberRows; iRow++) {
2072       if (rowActivity2[iRow] < rowLower2[iRow] - primalTolerance)
2073         objValue += (rowLower2[iRow] - rowActivity2[iRow] - primalTolerance) * artificialCost;
2074       else if (rowActivity2[iRow] > rowUpper2[iRow] + primalTolerance)
2075         objValue -= (rowUpper2[iRow] - rowActivity2[iRow] + primalTolerance) * artificialCost;
2076     }
2077     double theta = -1.0;
2078     double maxTheta = COIN_DBL_MAX;
2079     if (objValue <= lastObjective + 1.0e-15 * fabs(lastObjective) || !iPass)
2080       goodMove = 1;
2081     else
2082       goodMove = -1;
2083     //maxTheta=1.0;
2084     if (iPass) {
2085       int jNon = 0;
2086       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2087         changeRegion[iColumn] = solution[iColumn] - saveSolution[iColumn];
2088         double alpha = changeRegion[iColumn];
2089         double oldValue = saveSolution[iColumn];
2090         if (markNonlinear[iColumn] == 0) {
2091           // linear
2092           if (alpha < -1.0e-15) {
2093             // variable going towards lower bound
2094             double bound = columnLower[iColumn];
2095             oldValue -= bound;
2096             if (oldValue + maxTheta * alpha < 0.0) {
2097               maxTheta = CoinMax(0.0, oldValue / (-alpha));
2098             }
2099           } else if (alpha > 1.0e-15) {
2100             // variable going towards upper bound
2101             double bound = columnUpper[iColumn];
2102             oldValue = bound - oldValue;
2103             if (oldValue - maxTheta * alpha < 0.0) {
2104               maxTheta = CoinMax(0.0, oldValue / alpha);
2105             }
2106           }
2107         } else {
2108           // nonlinear
2109           if (alpha < -1.0e-15) {
2110             // variable going towards lower bound
2111             double bound = trueLower[jNon];
2112             oldValue -= bound;
2113             if (oldValue + maxTheta * alpha < 0.0) {
2114               maxTheta = CoinMax(0.0, oldValue / (-alpha));
2115             }
2116           } else if (alpha > 1.0e-15) {
2117             // variable going towards upper bound
2118             double bound = trueUpper[jNon];
2119             oldValue = bound - oldValue;
2120             if (oldValue - maxTheta * alpha < 0.0) {
2121               maxTheta = CoinMax(0.0, oldValue / alpha);
2122             }
2123           }
2124           jNon++;
2125         }
2126       }
2127       // make sure both accurate
2128       memset(rowActivity, 0, numberRows * sizeof(double));
2129       model.times(1.0, solution, rowActivity);
2130       memset(saveRowSolution, 0, numberRows * sizeof(double));
2131       model.times(1.0, saveSolution, saveRowSolution);
2132       for (int iRow = 0; iRow < numberRows; iRow++) {
2133         double alpha = rowActivity[iRow] - saveRowSolution[iRow];
2134         double oldValue = saveRowSolution[iRow];
2135         if (alpha < -1.0e-15) {
2136           // variable going towards lower bound
2137           double bound = rowLower[iRow];
2138           oldValue -= bound;
2139           if (oldValue + maxTheta * alpha < 0.0) {
2140             maxTheta = CoinMax(0.0, oldValue / (-alpha));
2141           }
2142         } else if (alpha > 1.0e-15) {
2143           // variable going towards upper bound
2144           double bound = rowUpper[iRow];
2145           oldValue = bound - oldValue;
2146           if (oldValue - maxTheta * alpha < 0.0) {
2147             maxTheta = CoinMax(0.0, oldValue / alpha);
2148           }
2149         }
2150       }
2151     } else {
2152       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2153         changeRegion[iColumn] = 0.0;
2154         saveSolution[iColumn] = solution[iColumn];
2155       }
2156       memcpy(saveRowSolution, rowActivity, numberRows * sizeof(double));
2157     }
2158     if (goodMove >= 0) {
2159       //theta = CoinMin(theta2,maxTheta);
2160       theta = maxTheta;
2161       if (theta > 0.0 && theta <= 1.0) {
2162         // update solution
2163         double lambda = 1.0 - theta;
2164         for (iColumn = 0; iColumn < numberColumns; iColumn++)
2165           solution[iColumn] = lambda * saveSolution[iColumn]
2166             + theta * solution[iColumn];
2167         memset(rowActivity, 0, numberRows * sizeof(double));
2168         model.times(1.0, solution, rowActivity);
2169         if (lambda > 0.999) {
2170           memcpy(model.dualRowSolution(), savePi, numberRows * sizeof(double));
2171           memcpy(model.statusArray(), saveStatus, numberRows + numberColumns);
2172         }
2173         // redo rowActivity
2174         memset(rowActivity, 0, numberRows * sizeof(double));
2175         model.times(1.0, solution, rowActivity);
2176       }
2177     }
2178     // load new values
2179     for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2180       iColumn = listNonLinearColumn[jNon];
2181       coinModel.associateElement(coinModel.columnName(iColumn), solution[iColumn]);
2182     }
2183     double *sol2 = CoinCopyOfArray(model.primalColumnSolution(), numberColumns);
2184     unsigned char *status2 = CoinCopyOfArray(model.statusArray(), numberColumns);
2185     model.loadProblem(coinModel);
2186     model.addColumns(numberArtificials, NULL, NULL, objectiveArtificial,
2187       startArtificial, rowArtificial, elementArtificial);
2188     memcpy(model.primalColumnSolution(), sol2, numberColumns * sizeof(double));
2189     memcpy(model.statusArray(), status2, numberColumns);
2190     delete[] sol2;
2191     delete[] status2;
2192     columnLower = model.columnLower();
2193     columnUpper = model.columnUpper();
2194     solution = model.primalColumnSolution();
2195     rowActivity = model.primalRowSolution();
2196     int *temp = last[2];
2197     last[2] = last[1];
2198     last[1] = last[0];
2199     last[0] = temp;
2200     for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2201       iColumn = listNonLinearColumn[jNon];
2202       double change = solution[iColumn] - saveSolution[iColumn];
2203       if (change < -1.0e-5) {
2204         if (fabs(change + trust[jNon]) < 1.0e-5)
2205           temp[jNon] = -1;
2206         else
2207           temp[jNon] = -2;
2208       } else if (change > 1.0e-5) {
2209         if (fabs(change - trust[jNon]) < 1.0e-5)
2210           temp[jNon] = 1;
2211         else
2212           temp[jNon] = 2;
2213       } else {
2214         temp[jNon] = 0;
2215       }
2216     }
2217     // goodMove +1 yes, 0 no, -1 last was bad - just halve gaps, -2 do nothing
2218     double maxDelta = 0.0;
2219     if (goodMove >= 0) {
2220       if (objValue <= lastObjective + 1.0e-15 * fabs(lastObjective))
2221         goodMove = 1;
2222       else
2223         goodMove = 0;
2224     } else {
2225       maxDelta = 1.0e10;
2226     }
2227     double maxGap = 0.0;
2228     int numberSmaller = 0;
2229     int numberSmaller2 = 0;
2230     int numberLarger = 0;
2231     for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2232       iColumn = listNonLinearColumn[jNon];
2233       maxDelta = CoinMax(maxDelta,
2234         fabs(solution[iColumn] - saveSolution[iColumn]));
2235       if (goodMove > 0) {
2236         if (last[0][jNon] * last[1][jNon] < 0) {
2237           // halve
2238           trust[jNon] *= 0.5;
2239           numberSmaller2++;
2240         } else {
2241           if (last[0][jNon] == last[1][jNon] && last[0][jNon] == last[2][jNon])
2242             trust[jNon] = CoinMin(1.5 * trust[jNon], 1.0e6);
2243           numberLarger++;
2244         }
2245       } else if (goodMove != -2 && trust[jNon] > 10.0 * deltaTolerance) {
2246         trust[jNon] *= 0.2;
2247         numberSmaller++;
2248       }
2249       maxGap = CoinMax(maxGap, trust[jNon]);
2250     }
2251 #ifdef CLP_DEBUG
2252     if (logLevel & 32)
2253       std::cout << "largest gap is " << maxGap << " "
2254                 << numberSmaller + numberSmaller2 << " reduced ("
2255                 << numberSmaller << " badMove ), "
2256                 << numberLarger << " increased" << std::endl;
2257 #endif
2258     if (iPass > 10000) {
2259       for (jNon = 0; jNon < numberNonLinearColumns; jNon++)
2260         trust[jNon] *= 0.0001;
2261     }
2262     printf("last good %d goodMove %d\n", lastGoodMove, goodMove);
2263     if (goodMove > 0) {
2264       double drop = lastObjective - objValue;
2265       printf("Pass %d, objective %g - drop %g maxDelta %g\n", iPass, objValue, drop, maxDelta);
2266       if (iPass > 20 && drop < 1.0e-12 * fabs(objValue) && lastGoodMove > 0)
2267         drop = 0.999e-4; // so will exit
2268       if (maxDelta < deltaTolerance && drop < 1.0e-4 && goodMove && theta < 0.99999 && lastGoodMove > 0) {
2269         if (logLevel > 1)
2270           std::cout << "Exiting as maxDelta < tolerance and small drop" << std::endl;
2271         break;
2272       }
2273     } else if (!numberSmaller && iPass > 1) {
2274       if (logLevel > 1)
2275         std::cout << "Exiting as all gaps small" << std::endl;
2276       break;
2277     }
2278     if (!iPass)
2279       goodMove = 1;
2280     targetDrop = 0.0;
2281     double *r = model.dualColumnSolution();
2282     for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2283       iColumn = listNonLinearColumn[jNon];
2284       columnLower[iColumn] = CoinMax(solution[iColumn]
2285           - trust[jNon],
2286         trueLower[jNon]);
2287       columnUpper[iColumn] = CoinMin(solution[iColumn]
2288           + trust[jNon],
2289         trueUpper[jNon]);
2290     }
2291     if (iPass) {
2292       // get reduced costs
2293       model.matrix()->transposeTimes(savePi,
2294         model.dualColumnSolution());
2295       const double *objective = model.objective();
2296       for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2297         iColumn = listNonLinearColumn[jNon];
2298         double dj = objective[iColumn] - r[iColumn];
2299         r[iColumn] = dj;
2300         if (dj < -dualTolerance)
2301           targetDrop -= dj * (columnUpper[iColumn] - solution[iColumn]);
2302         else if (dj > dualTolerance)
2303           targetDrop -= dj * (columnLower[iColumn] - solution[iColumn]);
2304       }
2305     } else {
2306       memset(r, 0, numberColumns * sizeof(double));
2307     }
2308 #ifdef JJF_ZERO
2309     for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2310       iColumn = listNonLinearColumn[jNon];
2311       if (statusCheck[iColumn] == 'L' && r[iColumn] < -1.0e-4) {
2312         columnLower[iColumn] = CoinMax(solution[iColumn],
2313           trueLower[jNon]);
2314         columnUpper[iColumn] = CoinMin(solution[iColumn]
2315             + trust[jNon],
2316           trueUpper[jNon]);
2317       } else if (statusCheck[iColumn] == 'U' && r[iColumn] > 1.0e-4) {
2318         columnLower[iColumn] = CoinMax(solution[iColumn]
2319             - trust[jNon],
2320           trueLower[jNon]);
2321         columnUpper[iColumn] = CoinMin(solution[iColumn],
2322           trueUpper[jNon]);
2323       } else {
2324         columnLower[iColumn] = CoinMax(solution[iColumn]
2325             - trust[jNon],
2326           trueLower[jNon]);
2327         columnUpper[iColumn] = CoinMin(solution[iColumn]
2328             + trust[jNon],
2329           trueUpper[jNon]);
2330       }
2331     }
2332 #endif
2333     if (goodMove > 0) {
2334       memcpy(saveSolution, solution, numberColumns * sizeof(double));
2335       memcpy(saveRowSolution, rowActivity, numberRows * sizeof(double));
2336       memcpy(savePi, model.dualRowSolution(), numberRows * sizeof(double));
2337       memcpy(saveStatus, model.statusArray(), numberRows + numberColumns);
2338 
2339 #ifdef CLP_DEBUG
2340       if (logLevel & 32)
2341         std::cout << "Pass - " << iPass
2342                   << ", target drop is " << targetDrop
2343                   << std::endl;
2344 #endif
2345       lastObjective = objValue;
2346       if (targetDrop < CoinMax(1.0e-8, CoinMin(1.0e-6, 1.0e-6 * fabs(objValue))) && lastGoodMove && iPass > 3) {
2347         if (logLevel > 1)
2348           printf("Exiting on target drop %g\n", targetDrop);
2349         break;
2350       }
2351 #ifdef CLP_DEBUG
2352       {
2353         double *r = model.dualColumnSolution();
2354         for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2355           iColumn = listNonLinearColumn[jNon];
2356           if (logLevel & 32)
2357             printf("Trust %d %g - solution %d %g obj %g dj %g state %c - bounds %g %g\n",
2358               jNon, trust[jNon], iColumn, solution[iColumn], objective[iColumn],
2359               r[iColumn], statusCheck[iColumn], columnLower[iColumn],
2360               columnUpper[iColumn]);
2361         }
2362       }
2363 #endif
2364       model.scaling(false);
2365       model.primal(1);
2366       for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2367         iColumn = listNonLinearColumn[jNon];
2368         printf("%d bounds etc %g %g %g\n", iColumn, columnLower[iColumn], solution[iColumn], columnUpper[iColumn]);
2369       }
2370       char temp[20];
2371       sprintf(temp, "pass%d.mps", iPass);
2372       //model.writeMps(temp);
2373 #ifdef CLP_DEBUG
2374       if (model.status()) {
2375         model.writeMps("xx.mps");
2376       }
2377 #endif
2378       if (model.status() == 1) {
2379         // not feasible ! - backtrack and exit
2380         // use safe solution
2381         memcpy(solution, safeSolution, numberColumns * sizeof(double));
2382         memcpy(saveSolution, solution, numberColumns * sizeof(double));
2383         memset(rowActivity, 0, numberRows * sizeof(double));
2384         model.times(1.0, solution, rowActivity);
2385         memcpy(saveRowSolution, rowActivity, numberRows * sizeof(double));
2386         memcpy(model.dualRowSolution(), savePi, numberRows * sizeof(double));
2387         memcpy(model.statusArray(), saveStatus, numberRows + numberColumns);
2388         for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2389           iColumn = listNonLinearColumn[jNon];
2390           columnLower[iColumn] = CoinMax(solution[iColumn]
2391               - trust[jNon],
2392             trueLower[jNon]);
2393           columnUpper[iColumn] = CoinMin(solution[iColumn]
2394               + trust[jNon],
2395             trueUpper[jNon]);
2396         }
2397         break;
2398       } else {
2399         // save in case problems
2400         memcpy(safeSolution, solution, numberColumns * sizeof(double));
2401       }
2402       goodMove = 1;
2403     } else {
2404       // bad pass - restore solution
2405 #ifdef CLP_DEBUG
2406       if (logLevel & 32)
2407         printf("Backtracking\n");
2408 #endif
2409       // load old values
2410       for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2411         iColumn = listNonLinearColumn[jNon];
2412         coinModel.associateElement(coinModel.columnName(iColumn), saveSolution[iColumn]);
2413       }
2414       model.loadProblem(coinModel);
2415       model.addColumns(numberArtificials, NULL, NULL, objectiveArtificial,
2416         startArtificial, rowArtificial, elementArtificial);
2417       solution = model.primalColumnSolution();
2418       rowActivity = model.primalRowSolution();
2419       memcpy(solution, saveSolution, numberColumns * sizeof(double));
2420       memcpy(rowActivity, saveRowSolution, numberRows * sizeof(double));
2421       memcpy(model.dualRowSolution(), savePi, numberRows * sizeof(double));
2422       memcpy(model.statusArray(), saveStatus, numberRows + numberColumns);
2423       columnLower = model.columnLower();
2424       columnUpper = model.columnUpper();
2425       for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2426         iColumn = listNonLinearColumn[jNon];
2427         columnLower[iColumn] = solution[iColumn];
2428         columnUpper[iColumn] = solution[iColumn];
2429       }
2430       model.primal(1);
2431       //model.writeMps("xx.mps");
2432       iPass--;
2433       goodMove = -1;
2434     }
2435   }
2436   // restore solution
2437   memcpy(solution, saveSolution, numberColumns * sizeof(double));
2438   delete[] statusCheck;
2439   delete[] savePi;
2440   delete[] saveStatus;
2441   // load new values
2442   for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2443     iColumn = listNonLinearColumn[jNon];
2444     coinModel.associateElement(coinModel.columnName(iColumn), solution[iColumn]);
2445   }
2446   double *sol2 = CoinCopyOfArray(model.primalColumnSolution(), numberColumns);
2447   unsigned char *status2 = CoinCopyOfArray(model.statusArray(), numberColumns);
2448   model.loadProblem(coinModel);
2449   model.addColumns(numberArtificials, NULL, NULL, objectiveArtificial,
2450     startArtificial, rowArtificial, elementArtificial);
2451   memcpy(model.primalColumnSolution(), sol2, numberColumns * sizeof(double));
2452   memcpy(model.statusArray(), status2, numberColumns);
2453   delete[] sol2;
2454   delete[] status2;
2455   columnLower = model.columnLower();
2456   columnUpper = model.columnUpper();
2457   solution = model.primalColumnSolution();
2458   for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2459     iColumn = listNonLinearColumn[jNon];
2460     columnLower[iColumn] = CoinMax(solution[iColumn],
2461       trueLower[jNon]);
2462     columnUpper[iColumn] = CoinMin(solution[iColumn],
2463       trueUpper[jNon]);
2464   }
2465   model.primal(1);
2466   for (jNon = 0; jNon < numberNonLinearColumns; jNon++) {
2467     iColumn = listNonLinearColumn[jNon];
2468     columnLower[iColumn] = trueLower[jNon];
2469     columnUpper[iColumn] = trueUpper[jNon];
2470   }
2471   delete[] saveSolution;
2472   delete[] safeSolution;
2473   delete[] saveRowSolution;
2474   for (iPass = 0; iPass < 3; iPass++)
2475     delete[] last[iPass];
2476   delete[] trust;
2477   delete[] trueUpper;
2478   delete[] trueLower;
2479   delete[] changeRegion;
2480   delete[] startArtificial;
2481   delete[] rowArtificial;
2482   delete[] elementArtificial;
2483   delete[] objectiveArtificial;
2484   delete[] listNonLinearColumn;
2485   delete[] whichRow;
2486   delete[] markNonlinear;
2487   return CoinCopyOfArray(solution, coinModel.numberColumns());
2488 }
2489 /* Solve linearized quadratic objective branch and bound.
2490    Return cutoff and OA cut
2491 */
2492 double
linearizedBAB(CglStored * cut)2493 OsiSolverLink::linearizedBAB(CglStored *cut)
2494 {
2495   double bestObjectiveValue = COIN_DBL_MAX;
2496   if (quadraticModel_) {
2497     ClpSimplex *qp = new ClpSimplex(*quadraticModel_);
2498     // bounds
2499     int numberColumns = qp->numberColumns();
2500     double *lower = qp->columnLower();
2501     double *upper = qp->columnUpper();
2502     const double *lower2 = getColLower();
2503     const double *upper2 = getColUpper();
2504     for (int i = 0; i < numberColumns; i++) {
2505       lower[i] = CoinMax(lower[i], lower2[i]);
2506       upper[i] = CoinMin(upper[i], upper2[i]);
2507     }
2508     qp->nonlinearSLP(20, 1.0e-5);
2509     qp->primal();
2510     OsiSolverLinearizedQuadratic solver2(qp);
2511     const double *solution = NULL;
2512     // Reduce printout
2513     solver2.setHintParam(OsiDoReducePrint, true, OsiHintTry);
2514     CbcModel model2(solver2);
2515     // Now do requested saves and modifications
2516     CbcModel *cbcModel = &model2;
2517     OsiSolverInterface *osiModel = model2.solver();
2518     OsiClpSolverInterface *osiclpModel = dynamic_cast< OsiClpSolverInterface * >(osiModel);
2519     ClpSimplex *clpModel = osiclpModel->getModelPtr();
2520 
2521     // Set changed values
2522 
2523     CglProbing probing;
2524     probing.setMaxProbe(10);
2525     probing.setMaxLook(10);
2526     probing.setMaxElements(200);
2527     probing.setMaxProbeRoot(50);
2528     probing.setMaxLookRoot(10);
2529     probing.setRowCuts(3);
2530     probing.setUsingObjective(true);
2531     cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1);
2532     cbcModel->cutGenerator(0)->setTiming(true);
2533 
2534     CglGomory gomory;
2535     gomory.setLimitAtRoot(512);
2536     cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1);
2537     cbcModel->cutGenerator(1)->setTiming(true);
2538 
2539     CglKnapsackCover knapsackCover;
2540     cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1);
2541     cbcModel->cutGenerator(2)->setTiming(true);
2542 
2543     CglClique clique;
2544     clique.setStarCliqueReport(false);
2545     clique.setRowCliqueReport(false);
2546     clique.setMinViolation(0.1);
2547     cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1);
2548     cbcModel->cutGenerator(3)->setTiming(true);
2549 
2550     CglMixedIntegerRounding2 mixedIntegerRounding2;
2551     cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1);
2552     cbcModel->cutGenerator(4)->setTiming(true);
2553 
2554     CglFlowCover flowCover;
2555     cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1);
2556     cbcModel->cutGenerator(5)->setTiming(true);
2557 
2558     CglTwomir twomir;
2559     twomir.setMaxElements(250);
2560     cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1);
2561     cbcModel->cutGenerator(6)->setTiming(true);
2562     // For now - switch off most heuristics (because CglPreProcess is bad with QP)
2563 #ifndef JJF_ONE
2564     CbcHeuristicFPump heuristicFPump(*cbcModel);
2565     heuristicFPump.setWhen(13);
2566     heuristicFPump.setMaximumPasses(20);
2567     heuristicFPump.setMaximumRetries(7);
2568     heuristicFPump.setAbsoluteIncrement(4332.64);
2569     cbcModel->addHeuristic(&heuristicFPump);
2570     heuristicFPump.setInitialWeight(1);
2571 
2572     CbcHeuristicLocal heuristicLocal(*cbcModel);
2573     heuristicLocal.setSearchType(1);
2574     cbcModel->addHeuristic(&heuristicLocal);
2575 
2576     CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel);
2577     cbcModel->addHeuristic(&heuristicGreedyCover);
2578 
2579     CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel);
2580     cbcModel->addHeuristic(&heuristicGreedyEquality);
2581 #endif
2582 
2583     CbcRounding rounding(*cbcModel);
2584     rounding.setHeuristicName("rounding");
2585     cbcModel->addHeuristic(&rounding);
2586 
2587     cbcModel->setNumberBeforeTrust(5);
2588     cbcModel->setSpecialOptions(2);
2589     cbcModel->messageHandler()->setLogLevel(1);
2590     cbcModel->setMaximumCutPassesAtRoot(-100);
2591     cbcModel->setMaximumCutPasses(1);
2592     cbcModel->setMinimumDrop(0.05);
2593     // For branchAndBound this may help
2594     clpModel->defaultFactorizationFrequency();
2595     clpModel->setDualBound(1.0001e+08);
2596     clpModel->setPerturbation(50);
2597     osiclpModel->setSpecialOptions(193);
2598     osiclpModel->messageHandler()->setLogLevel(0);
2599     osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100);
2600     osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry);
2601     // You can save some time by switching off message building
2602     // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);
2603 
2604     // Solve
2605 
2606     cbcModel->initialSolve();
2607     if (clpModel->tightenPrimalBounds() != 0) {
2608       std::cout << "Problem is infeasible - tightenPrimalBounds!" << std::endl;
2609       delete qp;
2610       return COIN_DBL_MAX;
2611     }
2612     clpModel->dual(); // clean up
2613     cbcModel->initialSolve();
2614     cbcModel->branchAndBound();
2615     OsiSolverLinearizedQuadratic *solver3 = dynamic_cast< OsiSolverLinearizedQuadratic * >(model2.solver());
2616     assert(solver3);
2617     solution = solver3->bestSolution();
2618     bestObjectiveValue = solver3->bestObjectiveValue();
2619     setBestObjectiveValue(bestObjectiveValue);
2620     setBestSolution(solution, solver3->getNumCols());
2621     // if convex
2622     if ((specialOptions2() & 4) != 0) {
2623       if (cbcModel_)
2624         cbcModel_->lockThread();
2625       // add OA cut
2626       double offset;
2627       double *gradient = new double[numberColumns + 1];
2628       memcpy(gradient, qp->objectiveAsObject()->gradient(qp, solution, offset, true, 2),
2629         numberColumns * sizeof(double));
2630       double rhs = 0.0;
2631       int *column = new int[numberColumns + 1];
2632       int n = 0;
2633       for (int i = 0; i < numberColumns; i++) {
2634         double value = gradient[i];
2635         if (fabs(value) > 1.0e-12) {
2636           gradient[n] = value;
2637           rhs += value * solution[i];
2638           column[n++] = i;
2639         }
2640       }
2641       gradient[n] = -1.0;
2642       column[n++] = numberColumns;
2643       cut->addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient);
2644       delete[] gradient;
2645       delete[] column;
2646       if (cbcModel_)
2647         cbcModel_->unlockThread();
2648     }
2649     delete qp;
2650     printf("obj %g\n", bestObjectiveValue);
2651   }
2652   return bestObjectiveValue;
2653 }
2654 /* Solves nonlinear problem from CoinModel using SLP - and then tries to get
2655    heuristic solution
2656    Returns solution array
2657 */
2658 double *
heuristicSolution(int numberPasses,double deltaTolerance,int mode)2659 OsiSolverLink::heuristicSolution(int numberPasses, double deltaTolerance, int mode)
2660 {
2661   // get a solution
2662   CoinModel tempModel = coinModel_;
2663   ClpSimplex *temp = approximateSolution(tempModel, numberPasses, deltaTolerance);
2664   int numberColumns = coinModel_.numberColumns();
2665   double *solution = CoinCopyOfArray(temp->primalColumnSolution(), numberColumns);
2666   delete temp;
2667   if (mode == 0) {
2668     return solution;
2669   } else if (mode == 2) {
2670     const double *lower = getColLower();
2671     const double *upper = getColUpper();
2672     for (int iObject = 0; iObject < numberObjects_; iObject++) {
2673       OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(object_[iObject]);
2674       if (obj && (obj->priority() < biLinearPriority_ || biLinearPriority_ <= 0)) {
2675         int iColumn = obj->columnNumber();
2676         double value = solution[iColumn];
2677         value = floor(value + 0.5);
2678         if (fabs(value - solution[iColumn]) > 0.01) {
2679           setColLower(iColumn, CoinMax(lower[iColumn], value - CoinMax(defaultBound_, 0.0)));
2680           setColUpper(iColumn, CoinMin(upper[iColumn], value + CoinMax(defaultBound_, 1.0)));
2681         } else {
2682           // could fix to integer
2683           setColLower(iColumn, CoinMax(lower[iColumn], value - CoinMax(defaultBound_, 0.0)));
2684           setColUpper(iColumn, CoinMin(upper[iColumn], value + CoinMax(defaultBound_, 0.0)));
2685         }
2686       }
2687     }
2688     return solution;
2689   }
2690   OsiClpSolverInterface newSolver;
2691   if (mode == 1) {
2692     // round all with priority < biLinearPriority_
2693     setFixedPriority(biLinearPriority_);
2694     // ? should we save and restore coin model
2695     tempModel = coinModel_;
2696     // solve modified problem
2697     char *mark = new char[numberColumns];
2698     memset(mark, 0, numberColumns);
2699     for (int iObject = 0; iObject < numberObjects_; iObject++) {
2700       OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(object_[iObject]);
2701       if (obj && obj->priority() < biLinearPriority_) {
2702         int iColumn = obj->columnNumber();
2703         double value = solution[iColumn];
2704         value = ceil(value - 1.0e-7);
2705         tempModel.associateElement(coinModel_.columnName(iColumn), value);
2706         mark[iColumn] = 1;
2707       }
2708       OsiBiLinear *objB = dynamic_cast< OsiBiLinear * >(object_[iObject]);
2709       if (objB) {
2710         // if one or both continuous then fix one
2711         if (objB->xMeshSize() < 1.0) {
2712           int xColumn = objB->xColumn();
2713           double value = solution[xColumn];
2714           tempModel.associateElement(coinModel_.columnName(xColumn), value);
2715           mark[xColumn] = 1;
2716         } else if (objB->yMeshSize() < 1.0) {
2717           int yColumn = objB->yColumn();
2718           double value = solution[yColumn];
2719           tempModel.associateElement(coinModel_.columnName(yColumn), value);
2720           mark[yColumn] = 1;
2721         }
2722       }
2723     }
2724     CoinModel *reOrdered = tempModel.reorder(mark);
2725     assert(reOrdered);
2726     tempModel = *reOrdered;
2727     delete reOrdered;
2728     delete[] mark;
2729     newSolver.loadFromCoinModel(tempModel, true);
2730     for (int iObject = 0; iObject < numberObjects_; iObject++) {
2731       OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(object_[iObject]);
2732       if (obj && obj->priority() < biLinearPriority_) {
2733         int iColumn = obj->columnNumber();
2734         double value = solution[iColumn];
2735         value = ceil(value - 1.0e-7);
2736         newSolver.setColLower(iColumn, value);
2737         newSolver.setColUpper(iColumn, value);
2738       }
2739       OsiBiLinear *objB = dynamic_cast< OsiBiLinear * >(object_[iObject]);
2740       if (objB) {
2741         // if one or both continuous then fix one
2742         if (objB->xMeshSize() < 1.0) {
2743           int xColumn = objB->xColumn();
2744           double value = solution[xColumn];
2745           newSolver.setColLower(xColumn, value);
2746           newSolver.setColUpper(xColumn, value);
2747         } else if (objB->yMeshSize() < 1.0) {
2748           int yColumn = objB->yColumn();
2749           double value = solution[yColumn];
2750           newSolver.setColLower(yColumn, value);
2751           newSolver.setColUpper(yColumn, value);
2752         }
2753       }
2754     }
2755   }
2756   CbcModel model(newSolver);
2757   // Now do requested saves and modifications
2758   CbcModel *cbcModel = &model;
2759   OsiSolverInterface *osiModel = model.solver();
2760   OsiClpSolverInterface *osiclpModel = dynamic_cast< OsiClpSolverInterface * >(osiModel);
2761   ClpSimplex *clpModel = osiclpModel->getModelPtr();
2762   CglProbing probing;
2763   probing.setMaxProbe(10);
2764   probing.setMaxLook(10);
2765   probing.setMaxElements(200);
2766   probing.setMaxProbeRoot(50);
2767   probing.setMaxLookRoot(10);
2768   probing.setRowCuts(3);
2769   probing.setRowCuts(0);
2770   probing.setUsingObjective(true);
2771   cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1);
2772 
2773   CglGomory gomory;
2774   gomory.setLimitAtRoot(512);
2775   cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1);
2776 
2777   CglKnapsackCover knapsackCover;
2778   cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1);
2779 
2780   CglClique clique;
2781   clique.setStarCliqueReport(false);
2782   clique.setRowCliqueReport(false);
2783   clique.setMinViolation(0.1);
2784   cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1);
2785   CglMixedIntegerRounding2 mixedIntegerRounding2;
2786   cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1);
2787 
2788   CglFlowCover flowCover;
2789   cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1);
2790 
2791   CglTwomir twomir;
2792   twomir.setMaxElements(250);
2793   cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1);
2794   cbcModel->cutGenerator(6)->setTiming(true);
2795 
2796   CbcHeuristicFPump heuristicFPump(*cbcModel);
2797   heuristicFPump.setWhen(1);
2798   heuristicFPump.setMaximumPasses(20);
2799   heuristicFPump.setDefaultRounding(0.5);
2800   cbcModel->addHeuristic(&heuristicFPump);
2801 
2802   CbcRounding rounding(*cbcModel);
2803   cbcModel->addHeuristic(&rounding);
2804 
2805   CbcHeuristicLocal heuristicLocal(*cbcModel);
2806   heuristicLocal.setSearchType(1);
2807   cbcModel->addHeuristic(&heuristicLocal);
2808 
2809   CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel);
2810   cbcModel->addHeuristic(&heuristicGreedyCover);
2811 
2812   CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel);
2813   cbcModel->addHeuristic(&heuristicGreedyEquality);
2814 
2815   CbcCompareDefault compare;
2816   cbcModel->setNodeComparison(compare);
2817   cbcModel->setNumberBeforeTrust(5);
2818   cbcModel->setSpecialOptions(2);
2819   cbcModel->messageHandler()->setLogLevel(1);
2820   cbcModel->setMaximumCutPassesAtRoot(-100);
2821   cbcModel->setMaximumCutPasses(1);
2822   cbcModel->setMinimumDrop(0.05);
2823   clpModel->setNumberIterations(1);
2824   // For branchAndBound this may help
2825   clpModel->defaultFactorizationFrequency();
2826   clpModel->setDualBound(6.71523e+07);
2827   clpModel->setPerturbation(50);
2828   osiclpModel->setSpecialOptions(193);
2829   osiclpModel->messageHandler()->setLogLevel(0);
2830   osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100);
2831   osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry);
2832   // You can save some time by switching off message building
2833   // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);
2834   // Solve
2835 
2836   cbcModel->initialSolve();
2837   //double cutoff = model_->getCutoff();
2838   if (!cbcModel_)
2839     cbcModel->setCutoff(1.0e50);
2840   else
2841     cbcModel->setCutoff(cbcModel_->getCutoff());
2842   int saveLogLevel = clpModel->logLevel();
2843   clpModel->setLogLevel(0);
2844 #ifndef NDEBUG
2845   int returnCode = 0;
2846 #endif
2847   if (clpModel->tightenPrimalBounds() != 0) {
2848     clpModel->setLogLevel(saveLogLevel);
2849 #ifndef NDEBUG
2850     returnCode = -1; // infeasible//std::cout<<"Problem is infeasible - tightenPrimalBounds!"<<std::endl;
2851 #endif
2852     //clpModel->writeMps("infeas2.mps");
2853   } else {
2854     clpModel->setLogLevel(saveLogLevel);
2855     clpModel->dual(); // clean up
2856     // compute some things using problem size
2857     cbcModel->setMinimumDrop(CoinMin(5.0e-2,
2858       fabs(cbcModel->getMinimizationObjValue()) * 1.0e-3 + 1.0e-4));
2859     if (cbcModel->getNumCols() < 500)
2860       cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible
2861     else if (cbcModel->getNumCols() < 5000)
2862       cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop
2863     else
2864       cbcModel->setMaximumCutPassesAtRoot(20);
2865     cbcModel->setMaximumCutPasses(1);
2866     // Hand coded preprocessing
2867     CglPreProcess process;
2868     OsiSolverInterface *saveSolver = cbcModel->solver()->clone();
2869     // Tell solver we are in Branch and Cut
2870     saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo);
2871     // Default set of cut generators
2872     CglProbing generator1;
2873     generator1.setUsingObjective(true);
2874     generator1.setMaxPass(3);
2875     generator1.setMaxProbeRoot(saveSolver->getNumCols());
2876     generator1.setMaxElements(100);
2877     generator1.setMaxLookRoot(50);
2878     generator1.setRowCuts(3);
2879     // Add in generators
2880     process.addCutGenerator(&generator1);
2881     process.messageHandler()->setLogLevel(cbcModel->logLevel());
2882     OsiSolverInterface *solver2 = process.preProcessNonDefault(*saveSolver, 0, 10);
2883     // Tell solver we are not in Branch and Cut
2884     saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
2885     if (solver2)
2886       solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
2887     if (!solver2) {
2888       std::cout << "Pre-processing says infeasible!" << std::endl;
2889       delete saveSolver;
2890 #ifndef NDEBUG
2891       returnCode = -1;
2892 #endif
2893     } else {
2894       std::cout << "processed model has " << solver2->getNumRows()
2895                 << " rows, " << solver2->getNumCols()
2896                 << " and " << solver2->getNumElements() << std::endl;
2897       // we have to keep solver2 so pass clone
2898       solver2 = solver2->clone();
2899       //solver2->writeMps("intmodel");
2900       cbcModel->assignSolver(solver2);
2901       cbcModel->initialSolve();
2902       cbcModel->branchAndBound();
2903       // For best solution
2904       int numberColumns = newSolver.getNumCols();
2905       if (cbcModel->getMinimizationObjValue() < 1.0e50) {
2906         // post process
2907         process.postProcess(*cbcModel->solver());
2908         // Solution now back in saveSolver
2909         cbcModel->assignSolver(saveSolver);
2910         memcpy(cbcModel->bestSolution(), cbcModel->solver()->getColSolution(),
2911           numberColumns * sizeof(double));
2912         // put back in original solver
2913         newSolver.setColSolution(cbcModel->bestSolution());
2914       } else {
2915         delete saveSolver;
2916       }
2917     }
2918   }
2919   assert(!returnCode);
2920   abort();
2921   return solution;
2922 }
2923 // Analyze constraints to see which are convex (quadratic)
analyzeObjects()2924 void OsiSolverLink::analyzeObjects()
2925 {
2926   // space for starts
2927   int numberColumns = coinModel_.numberColumns();
2928   int *start = new int[numberColumns + 1];
2929   const double *rowLower = getRowLower();
2930   const double *rowUpper = getRowUpper();
2931   for (int iNon = 0; iNon < numberNonLinearRows_; iNon++) {
2932     int iRow = rowNonLinear_[iNon];
2933     int numberElements = startNonLinear_[iNon + 1] - startNonLinear_[iNon];
2934     // triplet arrays
2935     int *iColumn = new int[2 * numberElements + 1];
2936     int *jColumn = new int[2 * numberElements];
2937     double *element = new double[2 * numberElements];
2938     int i;
2939     int n = 0;
2940     for (i = startNonLinear_[iNon]; i < startNonLinear_[iNon + 1]; i++) {
2941       OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[whichNonLinear_[i]]);
2942       assert(obj);
2943       int xColumn = obj->xColumn();
2944       int yColumn = obj->yColumn();
2945       double coefficient = obj->coefficient();
2946       if (xColumn != yColumn) {
2947         iColumn[n] = xColumn;
2948         jColumn[n] = yColumn;
2949         element[n++] = coefficient;
2950         iColumn[n] = yColumn;
2951         jColumn[n] = xColumn;
2952         element[n++] = coefficient;
2953       } else {
2954         iColumn[n] = xColumn;
2955         jColumn[n] = xColumn;
2956         element[n++] = coefficient;
2957       }
2958     }
2959     // First sort in column order
2960     CoinSort_3(iColumn, iColumn + n, jColumn, element);
2961     // marker at end
2962     iColumn[n] = numberColumns;
2963     int lastI = iColumn[0];
2964     // compute starts
2965     start[0] = 0;
2966     for (i = 1; i < n + 1; i++) {
2967       if (iColumn[i] != lastI) {
2968         while (lastI < iColumn[i]) {
2969           start[lastI + 1] = i;
2970           lastI++;
2971         }
2972         lastI = iColumn[i];
2973       }
2974     }
2975     // -1 unknown, 0 convex, 1 nonconvex
2976     int status = -1;
2977     int statusNegative = -1;
2978     int numberLong = 0; // number with >2 elements
2979     for (int k = 0; k < numberColumns; k++) {
2980       int first = start[k];
2981       int last = start[k + 1];
2982       if (last > first) {
2983         int j;
2984         double diagonal = 0.0;
2985         int whichK = -1;
2986         for (j = first; j < last; j++) {
2987           if (jColumn[j] == k) {
2988             diagonal = element[j];
2989             status = diagonal > 0 ? 0 : 1;
2990             statusNegative = diagonal < 0 ? 0 : 1;
2991             whichK = (j == first) ? j + 1 : j - 1;
2992             break;
2993           }
2994         }
2995         if (last == first + 1) {
2996           // just one entry
2997           if (!diagonal) {
2998             // one off diagonal - not positive semi definite
2999             status = 1;
3000             statusNegative = 1;
3001           }
3002         } else if (diagonal) {
3003           if (last == first + 2) {
3004             // other column and element
3005             double otherElement = element[whichK];
3006             ;
3007             int otherColumn = jColumn[whichK];
3008             double otherDiagonal = 0.0;
3009             // check 2x2 determinant - unless past and 2 long
3010             if (otherColumn > i || start[otherColumn + 1] > start[otherColumn] + 2) {
3011               for (j = start[otherColumn]; j < start[otherColumn + 1]; j++) {
3012                 if (jColumn[j] == otherColumn) {
3013                   otherDiagonal = element[j];
3014                   break;
3015                 }
3016               }
3017               // determinant
3018               double determinant = diagonal * otherDiagonal - otherElement * otherElement;
3019               if (determinant < -1.0e-12) {
3020                 // not positive semi definite
3021                 status = 1;
3022                 statusNegative = 1;
3023               } else if (start[otherColumn + 1] > start[otherColumn] + 2 && determinant < 1.0e-12) {
3024                 // not positive semi definite
3025                 status = 1;
3026                 statusNegative = 1;
3027               }
3028             }
3029           } else {
3030             numberLong++;
3031           }
3032         }
3033       }
3034     }
3035     if ((status == 0 || statusNegative == 0) && numberLong) {
3036       // need to do more work
3037       //printf("Needs more work\n");
3038     }
3039     assert(status > 0 || statusNegative > 0);
3040     if (!status) {
3041       convex_[iNon] = 1;
3042       // equality may be ok
3043       if (rowUpper[iRow] < 1.0e20)
3044         specialOptions2_ |= 8;
3045       else
3046         convex_[iNon] = 0;
3047     } else if (!statusNegative) {
3048       convex_[iNon] = -1;
3049       // equality may be ok
3050       if (rowLower[iRow] > -1.0e20)
3051         specialOptions2_ |= 8;
3052       else
3053         convex_[iNon] = 0;
3054     } else {
3055       convex_[iNon] = 0;
3056     }
3057     //printf("Convexity of row %d is %d\n",iRow,convex_[iNon]);
3058     delete[] iColumn;
3059     delete[] jColumn;
3060     delete[] element;
3061   }
3062   delete[] start;
3063 }
3064 //-------------------------------------------------------------------
3065 // Clone
3066 //-------------------------------------------------------------------
3067 OsiSolverInterface *
clone(bool) const3068 OsiSolverLink::clone(bool /*copyData*/) const
3069 {
3070   //assert (copyData);
3071   OsiSolverLink *newModel = new OsiSolverLink(*this);
3072   return newModel;
3073 }
3074 
3075 //-------------------------------------------------------------------
3076 // Copy constructor
3077 //-------------------------------------------------------------------
OsiSolverLink(const OsiSolverLink & rhs)3078 OsiSolverLink::OsiSolverLink(
3079   const OsiSolverLink &rhs)
3080   : OsiSolverInterface(rhs)
3081   , CbcOsiSolver(rhs)
3082 {
3083   gutsOfDestructor(true);
3084   gutsOfCopy(rhs);
3085   // something odd happens - try this
3086   OsiSolverInterface::operator=(rhs);
3087 }
3088 
3089 //-------------------------------------------------------------------
3090 // Destructor
3091 //-------------------------------------------------------------------
~OsiSolverLink()3092 OsiSolverLink::~OsiSolverLink()
3093 {
3094   gutsOfDestructor();
3095 }
3096 
3097 //-------------------------------------------------------------------
3098 // Assignment operator
3099 //-------------------------------------------------------------------
3100 OsiSolverLink &
operator =(const OsiSolverLink & rhs)3101 OsiSolverLink::operator=(const OsiSolverLink &rhs)
3102 {
3103   if (this != &rhs) {
3104     gutsOfDestructor();
3105     CbcOsiSolver::operator=(rhs);
3106     gutsOfCopy(rhs);
3107   }
3108   return *this;
3109 }
gutsOfDestructor(bool justNullify)3110 void OsiSolverLink::gutsOfDestructor(bool justNullify)
3111 {
3112   if (!justNullify) {
3113     delete matrix_;
3114     delete originalRowCopy_;
3115     delete[] info_;
3116     delete[] bestSolution_;
3117     delete quadraticModel_;
3118     delete[] startNonLinear_;
3119     delete[] rowNonLinear_;
3120     delete[] convex_;
3121     delete[] whichNonLinear_;
3122     delete[] fixVariables_;
3123   }
3124   matrix_ = NULL;
3125   originalRowCopy_ = NULL;
3126   quadraticModel_ = NULL;
3127   numberNonLinearRows_ = 0;
3128   startNonLinear_ = NULL;
3129   rowNonLinear_ = NULL;
3130   convex_ = NULL;
3131   whichNonLinear_ = NULL;
3132   info_ = NULL;
3133   fixVariables_ = NULL;
3134   numberVariables_ = 0;
3135   specialOptions2_ = 0;
3136   objectiveRow_ = -1;
3137   objectiveVariable_ = -1;
3138   bestSolution_ = NULL;
3139   bestObjectiveValue_ = 1.0e100;
3140   defaultMeshSize_ = 1.0e-4;
3141   defaultBound_ = 1.0e5;
3142   integerPriority_ = 1000;
3143   biLinearPriority_ = 10000;
3144   numberFix_ = 0;
3145 }
gutsOfCopy(const OsiSolverLink & rhs)3146 void OsiSolverLink::gutsOfCopy(const OsiSolverLink &rhs)
3147 {
3148   coinModel_ = rhs.coinModel_;
3149   numberVariables_ = rhs.numberVariables_;
3150   numberNonLinearRows_ = rhs.numberNonLinearRows_;
3151   specialOptions2_ = rhs.specialOptions2_;
3152   objectiveRow_ = rhs.objectiveRow_;
3153   objectiveVariable_ = rhs.objectiveVariable_;
3154   bestObjectiveValue_ = rhs.bestObjectiveValue_;
3155   defaultMeshSize_ = rhs.defaultMeshSize_;
3156   defaultBound_ = rhs.defaultBound_;
3157   integerPriority_ = rhs.integerPriority_;
3158   biLinearPriority_ = rhs.biLinearPriority_;
3159   numberFix_ = rhs.numberFix_;
3160   if (numberVariables_) {
3161     if (rhs.matrix_)
3162       matrix_ = new CoinPackedMatrix(*rhs.matrix_);
3163     else
3164       matrix_ = NULL;
3165     if (rhs.originalRowCopy_)
3166       originalRowCopy_ = new CoinPackedMatrix(*rhs.originalRowCopy_);
3167     else
3168       originalRowCopy_ = NULL;
3169     info_ = new OsiLinkedBound[numberVariables_];
3170     for (int i = 0; i < numberVariables_; i++) {
3171       info_[i] = OsiLinkedBound(rhs.info_[i]);
3172     }
3173     if (rhs.bestSolution_) {
3174       bestSolution_ = CoinCopyOfArray(rhs.bestSolution_, modelPtr_->getNumCols());
3175     } else {
3176       bestSolution_ = NULL;
3177     }
3178   }
3179   if (numberNonLinearRows_) {
3180     startNonLinear_ = CoinCopyOfArray(rhs.startNonLinear_, numberNonLinearRows_ + 1);
3181     rowNonLinear_ = CoinCopyOfArray(rhs.rowNonLinear_, numberNonLinearRows_);
3182     convex_ = CoinCopyOfArray(rhs.convex_, numberNonLinearRows_);
3183     int numberEntries = startNonLinear_[numberNonLinearRows_];
3184     whichNonLinear_ = CoinCopyOfArray(rhs.whichNonLinear_, numberEntries);
3185   }
3186   if (rhs.quadraticModel_) {
3187     quadraticModel_ = new ClpSimplex(*rhs.quadraticModel_);
3188   } else {
3189     quadraticModel_ = NULL;
3190   }
3191   fixVariables_ = CoinCopyOfArray(rhs.fixVariables_, numberFix_);
3192 }
3193 // Add a bound modifier
addBoundModifier(bool upperBoundAffected,bool useUpperBound,int whichVariable,int whichVariableAffected,double multiplier)3194 void OsiSolverLink::addBoundModifier(bool upperBoundAffected, bool useUpperBound, int whichVariable, int whichVariableAffected,
3195   double multiplier)
3196 {
3197   bool found = false;
3198   int i;
3199   for (i = 0; i < numberVariables_; i++) {
3200     if (info_[i].variable() == whichVariable) {
3201       found = true;
3202       break;
3203     }
3204   }
3205   if (!found) {
3206     // add in
3207     OsiLinkedBound *temp = new OsiLinkedBound[numberVariables_ + 1];
3208     for (int i = 0; i < numberVariables_; i++)
3209       temp[i] = info_[i];
3210     delete[] info_;
3211     info_ = temp;
3212     info_[numberVariables_++] = OsiLinkedBound(this, whichVariable, 0, NULL, NULL, NULL);
3213   }
3214   info_[i].addBoundModifier(upperBoundAffected, useUpperBound, whichVariableAffected, multiplier);
3215 }
3216 // Update coefficients
updateCoefficients(ClpSimplex * solver,CoinPackedMatrix * matrix)3217 int OsiSolverLink::updateCoefficients(ClpSimplex *solver, CoinPackedMatrix *matrix)
3218 {
3219   double *lower = solver->columnLower();
3220   double *upper = solver->columnUpper();
3221   double *objective = solver->objective();
3222   int numberChanged = 0;
3223   for (int iObject = 0; iObject < numberObjects_; iObject++) {
3224     OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(object_[iObject]);
3225     if (obj) {
3226       numberChanged += obj->updateCoefficients(lower, upper, objective, matrix, &basis_);
3227     }
3228   }
3229   return numberChanged;
3230 }
3231 // Set best solution found internally
setBestSolution(const double * solution,int numberColumns)3232 void OsiSolverLink::setBestSolution(const double *solution, int numberColumns)
3233 {
3234   delete[] bestSolution_;
3235   int numberColumnsThis = modelPtr_->numberColumns();
3236   bestSolution_ = new double[numberColumnsThis];
3237   CoinZeroN(bestSolution_, numberColumnsThis);
3238   memcpy(bestSolution_, solution, CoinMin(numberColumns, numberColumnsThis) * sizeof(double));
3239 }
3240 /* Two tier integer problem where when set of variables with priority
3241    less than this are fixed the problem becomes an easier integer problem
3242 */
setFixedPriority(int priorityValue)3243 void OsiSolverLink::setFixedPriority(int priorityValue)
3244 {
3245   delete[] fixVariables_;
3246   fixVariables_ = NULL;
3247   numberFix_ = 0;
3248   int i;
3249   for (i = 0; i < numberObjects_; i++) {
3250     OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(object_[i]);
3251     if (obj) {
3252 #ifndef NDEBUG
3253       int iColumn = obj->columnNumber();
3254       assert(iColumn >= 0);
3255 #endif
3256       if (obj->priority() < priorityValue)
3257         numberFix_++;
3258     }
3259   }
3260   if (numberFix_) {
3261     specialOptions2_ |= 1;
3262     fixVariables_ = new int[numberFix_];
3263     numberFix_ = 0;
3264     // need to make sure coinModel_ is correct
3265     int numberColumns = coinModel_.numberColumns();
3266     char *highPriority = new char[numberColumns];
3267     CoinZeroN(highPriority, numberColumns);
3268     for (i = 0; i < numberObjects_; i++) {
3269       OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(object_[i]);
3270       if (obj) {
3271         int iColumn = obj->columnNumber();
3272         assert(iColumn >= 0);
3273         if (iColumn < numberColumns) {
3274           if (obj->priority() < priorityValue) {
3275             object_[i] = new OsiSimpleFixedInteger(*obj);
3276             delete obj;
3277             fixVariables_[numberFix_++] = iColumn;
3278             highPriority[iColumn] = 1;
3279           }
3280         }
3281       }
3282     }
3283     CoinModel *newModel = coinModel_.reorder(highPriority);
3284     if (newModel) {
3285       coinModel_ = *newModel;
3286     } else {
3287       printf("Unable to use priorities\n");
3288       delete[] fixVariables_;
3289       fixVariables_ = NULL;
3290       numberFix_ = 0;
3291     }
3292     delete newModel;
3293     delete[] highPriority;
3294   }
3295 }
3296 // Gets correct form for a quadratic row - user to delete
3297 CoinPackedMatrix *
quadraticRow(int rowNumber,double * linearRow) const3298 OsiSolverLink::quadraticRow(int rowNumber, double *linearRow) const
3299 {
3300   int numberColumns = coinModel_.numberColumns();
3301   CoinZeroN(linearRow, numberColumns);
3302   int numberElements = 0;
3303 #ifndef NDEBUG
3304   int numberRows = coinModel_.numberRows();
3305   assert(rowNumber >= 0 && rowNumber < numberRows);
3306 #endif
3307   CoinModelLink triple = coinModel_.firstInRow(rowNumber);
3308   while (triple.column() >= 0) {
3309     int iColumn = triple.column();
3310     const char *expr = coinModel_.getElementAsString(rowNumber, iColumn);
3311     if (strcmp(expr, "Numeric")) {
3312       // try and see which columns
3313       assert(strlen(expr) < 20000);
3314       char temp[20000];
3315       strcpy(temp, expr);
3316       char *pos = temp;
3317       bool ifFirst = true;
3318       while (*pos) {
3319         double value;
3320         int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_);
3321         // must be column unless first when may be linear term
3322         if (jColumn >= 0) {
3323           numberElements++;
3324         } else if (jColumn == -2) {
3325           linearRow[iColumn] = value;
3326         } else {
3327           printf("bad nonlinear term %s\n", temp);
3328           abort();
3329         }
3330         ifFirst = false;
3331       }
3332     } else {
3333       linearRow[iColumn] = coinModel_.getElement(rowNumber, iColumn);
3334     }
3335     triple = coinModel_.next(triple);
3336   }
3337   if (!numberElements) {
3338     return NULL;
3339   } else {
3340     int *column = new int[numberElements];
3341     int *column2 = new int[numberElements];
3342     double *element = new double[numberElements];
3343     numberElements = 0;
3344     CoinModelLink triple = coinModel_.firstInRow(rowNumber);
3345     while (triple.column() >= 0) {
3346       int iColumn = triple.column();
3347       const char *expr = coinModel_.getElementAsString(rowNumber, iColumn);
3348       if (strcmp(expr, "Numeric")) {
3349         // try and see which columns
3350         assert(strlen(expr) < 20000);
3351         char temp[20000];
3352         strcpy(temp, expr);
3353         char *pos = temp;
3354         bool ifFirst = true;
3355         while (*pos) {
3356           double value;
3357           int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_);
3358           // must be column unless first when may be linear term
3359           if (jColumn >= 0) {
3360             column[numberElements] = iColumn;
3361             column2[numberElements] = jColumn;
3362             element[numberElements++] = value;
3363           } else if (jColumn != -2) {
3364             printf("bad nonlinear term %s\n", temp);
3365             abort();
3366           }
3367           ifFirst = false;
3368         }
3369       }
3370       triple = coinModel_.next(triple);
3371     }
3372     return new CoinPackedMatrix(true, column2, column, element, numberElements);
3373   }
3374 }
3375 /*
3376   Problem specific
3377   Returns -1 if node fathomed and no solution
3378   0 if did nothing
3379   1 if node fathomed and solution
3380   allFixed is true if all LinkedBound variables are fixed
3381 */
fathom(bool allFixed)3382 int OsiSolverLink::fathom(bool allFixed)
3383 {
3384   int returnCode = 0;
3385   if (allFixed) {
3386     // solve anyway
3387     OsiClpSolverInterface::resolve();
3388     if (!isProvenOptimal()) {
3389       printf("cutoff before fathoming\n");
3390       return -1;
3391     }
3392     // all fixed so we can reformulate
3393     OsiClpSolverInterface newSolver;
3394     // set values
3395     const double *lower = modelPtr_->columnLower();
3396     const double *upper = modelPtr_->columnUpper();
3397     int i;
3398     for (i = 0; i < numberFix_; i++) {
3399       int iColumn = fixVariables_[i];
3400       double lo = lower[iColumn];
3401 #ifndef NDEBUG
3402       double up = upper[iColumn];
3403       assert(lo == up);
3404 #endif
3405       //printf("column %d fixed to %g\n",iColumn,lo);
3406       coinModel_.associateElement(coinModel_.columnName(iColumn), lo);
3407     }
3408     newSolver.loadFromCoinModel(coinModel_, true);
3409     for (i = 0; i < numberFix_; i++) {
3410       int iColumn = fixVariables_[i];
3411       newSolver.setColLower(iColumn, lower[iColumn]);
3412       newSolver.setColUpper(iColumn, lower[iColumn]);
3413     }
3414     // see if everything with objective fixed
3415     const double *objective = modelPtr_->objective();
3416     int numberColumns = newSolver.getNumCols();
3417     bool zeroObjective = true;
3418     double sum = 0.0;
3419     for (i = 0; i < numberColumns; i++) {
3420       if (upper[i] > lower[i] && objective[i]) {
3421         zeroObjective = false;
3422         break;
3423       } else {
3424         sum += lower[i] * objective[i];
3425       }
3426     }
3427     int fake[] = { 5, 4, 3, 2, 0, 0, 0 };
3428     bool onOptimalPath = true;
3429     for (i = 0; i < 7; i++) {
3430       if (static_cast< int >(upper[i]) != fake[i])
3431         onOptimalPath = false;
3432     }
3433     if (onOptimalPath)
3434       printf("possible\n");
3435     if (zeroObjective) {
3436       // randomize objective
3437       ClpSimplex *clpModel = newSolver.getModelPtr();
3438       const double *element = clpModel->matrix()->getMutableElements();
3439       //const int * row = clpModel->matrix()->getIndices();
3440       const CoinBigIndex *columnStart = clpModel->matrix()->getVectorStarts();
3441       const int *columnLength = clpModel->matrix()->getVectorLengths();
3442       double *objective = clpModel->objective();
3443       for (i = 0; i < numberColumns; i++) {
3444         if (clpModel->isInteger(i)) {
3445           double value = 0.0;
3446           for (CoinBigIndex j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
3447             value += fabs(element[j]);
3448           }
3449           objective[i] = value;
3450         }
3451       }
3452     }
3453     //newSolver.writeMps("xx");
3454     CbcModel model(newSolver);
3455     // Now do requested saves and modifications
3456     CbcModel *cbcModel = &model;
3457     OsiSolverInterface *osiModel = model.solver();
3458     OsiClpSolverInterface *osiclpModel = dynamic_cast< OsiClpSolverInterface * >(osiModel);
3459     ClpSimplex *clpModel = osiclpModel->getModelPtr();
3460     CglProbing probing;
3461     probing.setMaxProbe(10);
3462     probing.setMaxLook(10);
3463     probing.setMaxElements(200);
3464     probing.setMaxProbeRoot(50);
3465     probing.setMaxLookRoot(10);
3466     probing.setRowCuts(3);
3467     probing.setRowCuts(0);
3468     probing.setUsingObjective(true);
3469     cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1);
3470 
3471     CglGomory gomory;
3472     gomory.setLimitAtRoot(512);
3473     cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1);
3474 
3475     CglKnapsackCover knapsackCover;
3476     cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1);
3477 
3478     CglClique clique;
3479     clique.setStarCliqueReport(false);
3480     clique.setRowCliqueReport(false);
3481     clique.setMinViolation(0.1);
3482     cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1);
3483     CglMixedIntegerRounding2 mixedIntegerRounding2;
3484     cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1);
3485 
3486     CglFlowCover flowCover;
3487     cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1);
3488 
3489     CglTwomir twomir;
3490     twomir.setMaxElements(250);
3491     cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1);
3492     cbcModel->cutGenerator(6)->setTiming(true);
3493 
3494     CbcHeuristicFPump heuristicFPump(*cbcModel);
3495     heuristicFPump.setWhen(1);
3496     heuristicFPump.setMaximumPasses(20);
3497     heuristicFPump.setDefaultRounding(0.5);
3498     cbcModel->addHeuristic(&heuristicFPump);
3499 
3500     CbcRounding rounding(*cbcModel);
3501     cbcModel->addHeuristic(&rounding);
3502 
3503     CbcHeuristicLocal heuristicLocal(*cbcModel);
3504     heuristicLocal.setSearchType(1);
3505     cbcModel->addHeuristic(&heuristicLocal);
3506 
3507     CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel);
3508     cbcModel->addHeuristic(&heuristicGreedyCover);
3509 
3510     CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel);
3511     cbcModel->addHeuristic(&heuristicGreedyEquality);
3512 
3513     CbcCompareDefault compare;
3514     cbcModel->setNodeComparison(compare);
3515     cbcModel->setNumberBeforeTrust(5);
3516     cbcModel->setSpecialOptions(2);
3517     cbcModel->messageHandler()->setLogLevel(1);
3518     cbcModel->setMaximumCutPassesAtRoot(-100);
3519     cbcModel->setMaximumCutPasses(1);
3520     cbcModel->setMinimumDrop(0.05);
3521     clpModel->setNumberIterations(1);
3522     // For branchAndBound this may help
3523     clpModel->defaultFactorizationFrequency();
3524     clpModel->setDualBound(6.71523e+07);
3525     clpModel->setPerturbation(50);
3526     osiclpModel->setSpecialOptions(193);
3527     osiclpModel->messageHandler()->setLogLevel(0);
3528     osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100);
3529     osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry);
3530     // You can save some time by switching off message building
3531     // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);
3532     // Solve
3533 
3534     cbcModel->initialSolve();
3535     //double cutoff = model_->getCutoff();
3536     if (zeroObjective || !cbcModel_)
3537       cbcModel->setCutoff(1.0e50);
3538     else
3539       cbcModel->setCutoff(cbcModel_->getCutoff());
3540     // to change exits
3541     bool isFeasible = false;
3542     int saveLogLevel = clpModel->logLevel();
3543     clpModel->setLogLevel(0);
3544     if (clpModel->tightenPrimalBounds() != 0) {
3545       clpModel->setLogLevel(saveLogLevel);
3546       returnCode = -1; // infeasible//std::cout<<"Problem is infeasible - tightenPrimalBounds!"<<std::endl;
3547     } else {
3548       clpModel->setLogLevel(saveLogLevel);
3549       clpModel->dual(); // clean up
3550       // compute some things using problem size
3551       cbcModel->setMinimumDrop(CoinMin(5.0e-2,
3552         fabs(cbcModel->getMinimizationObjValue()) * 1.0e-3 + 1.0e-4));
3553       if (cbcModel->getNumCols() < 500)
3554         cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible
3555       else if (cbcModel->getNumCols() < 5000)
3556         cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop
3557       else
3558         cbcModel->setMaximumCutPassesAtRoot(20);
3559       cbcModel->setMaximumCutPasses(1);
3560       // Hand coded preprocessing
3561       CglPreProcess process;
3562       OsiSolverInterface *saveSolver = cbcModel->solver()->clone();
3563       // Tell solver we are in Branch and Cut
3564       saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo);
3565       // Default set of cut generators
3566       CglProbing generator1;
3567       generator1.setUsingObjective(true);
3568       generator1.setMaxPass(3);
3569       generator1.setMaxProbeRoot(saveSolver->getNumCols());
3570       generator1.setMaxElements(100);
3571       generator1.setMaxLookRoot(50);
3572       generator1.setRowCuts(3);
3573       // Add in generators
3574       process.addCutGenerator(&generator1);
3575       process.messageHandler()->setLogLevel(cbcModel->logLevel());
3576       OsiSolverInterface *solver2 = process.preProcessNonDefault(*saveSolver, 0, 10);
3577       // Tell solver we are not in Branch and Cut
3578       saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
3579       if (solver2)
3580         solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
3581       if (!solver2) {
3582         std::cout << "Pre-processing says infeasible!" << std::endl;
3583         delete saveSolver;
3584         returnCode = -1;
3585       } else {
3586         std::cout << "processed model has " << solver2->getNumRows()
3587                   << " rows, " << solver2->getNumCols()
3588                   << " and " << solver2->getNumElements() << std::endl;
3589         // we have to keep solver2 so pass clone
3590         solver2 = solver2->clone();
3591         //solver2->writeMps("intmodel");
3592         cbcModel->assignSolver(solver2);
3593         cbcModel->initialSolve();
3594         if (zeroObjective) {
3595           cbcModel->setMaximumSolutions(1); // just getting a solution
3596 #ifdef JJF_ZERO
3597           OsiClpSolverInterface *osiclpModel = dynamic_cast< OsiClpSolverInterface * >(cbcModel->solver());
3598           ClpSimplex *clpModel = osiclpModel->getModelPtr();
3599           const double *element = clpModel->matrix()->getMutableElements();
3600           //const int * row = clpModel->matrix()->getIndices();
3601           const CoinBigIndex *columnStart = clpModel->matrix()->getVectorStarts();
3602           const int *columnLength = clpModel->matrix()->getVectorLengths();
3603           int n = clpModel->numberColumns();
3604           int *sort2 = new int[n];
3605           int *pri = new int[n];
3606           double *sort = new double[n];
3607           int i;
3608           int nint = 0;
3609           for (i = 0; i < n; i++) {
3610             if (clpModel->isInteger(i)) {
3611               double largest = 0.0;
3612               for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
3613                 largest = CoinMax(largest, fabs(element[j]));
3614               }
3615               sort2[nint] = nint;
3616               sort[nint++] = -largest;
3617             }
3618           }
3619           CoinSort_2(sort, sort + nint, sort2);
3620           int kpri = 1;
3621           double last = sort[0];
3622           for (i = 0; i < nint; i++) {
3623             if (sort[i] != last) {
3624               kpri++;
3625               last = sort[i];
3626             }
3627             pri[sort2[i]] = kpri;
3628           }
3629           cbcModel->passInPriorities(pri, false);
3630           delete[] sort;
3631           delete[] sort2;
3632           delete[] pri;
3633 #endif
3634         }
3635         cbcModel->branchAndBound();
3636         // For best solution
3637         int numberColumns = newSolver.getNumCols();
3638         if (cbcModel->getMinimizationObjValue() < 1.0e50) {
3639           // post process
3640           process.postProcess(*cbcModel->solver());
3641           // Solution now back in saveSolver
3642           cbcModel->assignSolver(saveSolver);
3643           memcpy(cbcModel->bestSolution(), cbcModel->solver()->getColSolution(),
3644             numberColumns * sizeof(double));
3645           // put back in original solver
3646           newSolver.setColSolution(cbcModel->bestSolution());
3647           isFeasible = true;
3648         } else {
3649           delete saveSolver;
3650         }
3651       }
3652       //const double * solution = newSolver.getColSolution();
3653       if (isFeasible && cbcModel->getMinimizationObjValue() < 1.0e50) {
3654         int numberColumns = this->getNumCols();
3655         int i;
3656         const double *solution = cbcModel->bestSolution();
3657         int numberColumns2 = newSolver.getNumCols();
3658         for (i = 0; i < numberColumns2; i++) {
3659           double value = solution[i];
3660           assert(fabs(value - floor(value + 0.5)) < 0.0001);
3661           value = floor(value + 0.5);
3662           this->setColLower(i, value);
3663           this->setColUpper(i, value);
3664         }
3665         for (; i < numberColumns; i++) {
3666           this->setColLower(i, 0.0);
3667           this->setColUpper(i, 1.1);
3668         }
3669         // but take off cuts
3670         int numberRows = getNumRows();
3671         int numberRows2 = cbcModel_->continuousSolver()->getNumRows();
3672 
3673         for (i = numberRows2; i < numberRows; i++)
3674           setRowBounds(i, -COIN_DBL_MAX, COIN_DBL_MAX);
3675         initialSolve();
3676         //if (!isProvenOptimal())
3677         //getModelPtr()->writeMps("bad.mps");
3678         if (isProvenOptimal()) {
3679           delete[] bestSolution_;
3680           bestSolution_ = CoinCopyOfArray(modelPtr_->getColSolution(), modelPtr_->getNumCols());
3681           bestObjectiveValue_ = modelPtr_->objectiveValue();
3682           printf("BB best value %g\n", bestObjectiveValue_);
3683           returnCode = 1;
3684         } else {
3685           printf("*** WHY BAD SOL\n");
3686           returnCode = -1;
3687         }
3688       } else {
3689         modelPtr_->setProblemStatus(1);
3690         modelPtr_->setObjectiveValue(COIN_DBL_MAX);
3691         returnCode = -1;
3692       }
3693     }
3694   }
3695   return returnCode;
3696 }
3697 //#############################################################################
3698 // Constructors, destructors  and assignment
3699 //#############################################################################
3700 
3701 //-------------------------------------------------------------------
3702 // Default Constructor
3703 //-------------------------------------------------------------------
OsiLinkedBound()3704 OsiLinkedBound::OsiLinkedBound()
3705 {
3706   model_ = NULL;
3707   variable_ = -1;
3708   numberAffected_ = 0;
3709   maximumAffected_ = numberAffected_;
3710   affected_ = NULL;
3711 }
3712 // Useful Constructor
OsiLinkedBound(OsiSolverInterface * model,int variable,int numberAffected,const int * positionL,const int * positionU,const double * multiplier)3713 OsiLinkedBound::OsiLinkedBound(OsiSolverInterface *model, int variable,
3714   int numberAffected, const int *positionL,
3715   const int *positionU, const double *multiplier)
3716 {
3717   model_ = model;
3718   variable_ = variable;
3719   numberAffected_ = 2 * numberAffected;
3720   maximumAffected_ = numberAffected_;
3721   if (numberAffected_) {
3722     affected_ = new boundElementAction[numberAffected_];
3723     int n = 0;
3724     for (int i = 0; i < numberAffected; i++) {
3725       // LB
3726       boundElementAction action;
3727       action.affect = 2;
3728       action.ubUsed = 0;
3729       action.type = 0;
3730       action.affected = positionL[i];
3731       action.multiplier = multiplier[i];
3732       affected_[n++] = action;
3733       // UB
3734       action.affect = 2;
3735       action.ubUsed = 1;
3736       action.type = 0;
3737       action.affected = positionU[i];
3738       action.multiplier = multiplier[i];
3739       affected_[n++] = action;
3740     }
3741   } else {
3742     affected_ = NULL;
3743   }
3744 }
3745 
3746 //-------------------------------------------------------------------
3747 // Copy constructor
3748 //-------------------------------------------------------------------
OsiLinkedBound(const OsiLinkedBound & rhs)3749 OsiLinkedBound::OsiLinkedBound(
3750   const OsiLinkedBound &rhs)
3751 {
3752   model_ = rhs.model_;
3753   variable_ = rhs.variable_;
3754   numberAffected_ = rhs.numberAffected_;
3755   maximumAffected_ = rhs.maximumAffected_;
3756   if (numberAffected_) {
3757     affected_ = new boundElementAction[maximumAffected_];
3758     memcpy(affected_, rhs.affected_, numberAffected_ * sizeof(boundElementAction));
3759   } else {
3760     affected_ = NULL;
3761   }
3762 }
3763 
3764 //-------------------------------------------------------------------
3765 // Destructor
3766 //-------------------------------------------------------------------
~OsiLinkedBound()3767 OsiLinkedBound::~OsiLinkedBound()
3768 {
3769   delete[] affected_;
3770 }
3771 
3772 //-------------------------------------------------------------------
3773 // Assignment operator
3774 //-------------------------------------------------------------------
3775 OsiLinkedBound &
operator =(const OsiLinkedBound & rhs)3776 OsiLinkedBound::operator=(const OsiLinkedBound &rhs)
3777 {
3778   if (this != &rhs) {
3779     delete[] affected_;
3780     model_ = rhs.model_;
3781     variable_ = rhs.variable_;
3782     numberAffected_ = rhs.numberAffected_;
3783     maximumAffected_ = rhs.maximumAffected_;
3784     if (numberAffected_) {
3785       affected_ = new boundElementAction[maximumAffected_];
3786       memcpy(affected_, rhs.affected_, numberAffected_ * sizeof(boundElementAction));
3787     } else {
3788       affected_ = NULL;
3789     }
3790   }
3791   return *this;
3792 }
3793 // Add a bound modifier
addBoundModifier(bool upperBoundAffected,bool useUpperBound,int whichVariable,double multiplier)3794 void OsiLinkedBound::addBoundModifier(bool upperBoundAffected, bool useUpperBound, int whichVariable,
3795   double multiplier)
3796 {
3797   if (numberAffected_ == maximumAffected_) {
3798     maximumAffected_ = maximumAffected_ + 10 + maximumAffected_ / 4;
3799     boundElementAction *temp = new boundElementAction[maximumAffected_];
3800     memcpy(temp, affected_, numberAffected_ * sizeof(boundElementAction));
3801     delete[] affected_;
3802     affected_ = temp;
3803   }
3804   boundElementAction action;
3805   action.affect = static_cast< unsigned char >(upperBoundAffected ? 1 : 0);
3806   action.ubUsed = static_cast< unsigned char >(useUpperBound ? 1 : 0);
3807   action.type = 2;
3808   action.affected = static_cast< short int >(whichVariable);
3809   action.multiplier = multiplier;
3810   affected_[numberAffected_++] = action;
3811 }
3812 // Update other bounds
updateBounds(ClpSimplex * solver)3813 void OsiLinkedBound::updateBounds(ClpSimplex *solver)
3814 {
3815   double *lower = solver->columnLower();
3816   double *upper = solver->columnUpper();
3817   double lo = lower[variable_];
3818   double up = upper[variable_];
3819   // printf("bounds for %d are %g and %g\n",variable_,lo,up);
3820   for (int j = 0; j < numberAffected_; j++) {
3821     if (affected_[j].affect < 2) {
3822       double multiplier = affected_[j].multiplier;
3823       assert(affected_[j].type == 2);
3824       int iColumn = affected_[j].affected;
3825       double useValue = (affected_[j].ubUsed) ? up : lo;
3826       if (affected_[j].affect == 0)
3827         lower[iColumn] = CoinMin(upper[iColumn], CoinMax(lower[iColumn], multiplier * useValue));
3828       else
3829         upper[iColumn] = CoinMax(lower[iColumn], CoinMin(upper[iColumn], multiplier * useValue));
3830     }
3831   }
3832 }
3833 #ifdef JJF_ZERO
3834 // Add an element modifier
addCoefficientModifier(bool useUpperBound,int position,double multiplier)3835 void OsiLinkedBound::addCoefficientModifier(bool useUpperBound, int position,
3836   double multiplier)
3837 {
3838   if (numberAffected_ == maximumAffected_) {
3839     maximumAffected_ = maximumAffected_ + 10 + maximumAffected_ / 4;
3840     boundElementAction *temp = new boundElementAction[maximumAffected_];
3841     memcpy(temp, affected_, numberAffected_ * sizeof(boundElementAction));
3842     delete[] affected_;
3843     affected_ = temp;
3844   }
3845   boundElementAction action;
3846   action.affect = 2;
3847   action.ubUsed = useUpperBound ? 1 : 0;
3848   action.type = 0;
3849   action.affected = position;
3850   action.multiplier = multiplier;
3851   affected_[numberAffected_++] = action;
3852 }
3853 // Update coefficients
updateCoefficients(ClpSimplex * solver,CoinPackedMatrix * matrix)3854 void OsiLinkedBound::updateCoefficients(ClpSimplex *solver, CoinPackedMatrix *matrix)
3855 {
3856   double *lower = solver->columnLower();
3857   double *upper = solver->columnUpper();
3858   double *element = matrix->getMutableElements();
3859   double lo = lower[variable_];
3860   double up = upper[variable_];
3861   // printf("bounds for %d are %g and %g\n",variable_,lo,up);
3862   for (int j = 0; j < numberAffected_; j++) {
3863     if (affected_[j].affect == 2) {
3864       double multiplier = affected_[j].multiplier;
3865       assert(affected_[j].type == 0);
3866       int position = affected_[j].affected;
3867       //double old = element[position];
3868       if (affected_[j].ubUsed)
3869         element[position] = multiplier * up;
3870       else
3871         element[position] = multiplier * lo;
3872       //if ( old != element[position])
3873       //printf("change at %d from %g to %g\n",position,old,element[position]);
3874     }
3875   }
3876 }
3877 #endif
3878 // Default Constructor
CbcHeuristicDynamic3()3879 CbcHeuristicDynamic3::CbcHeuristicDynamic3()
3880   : CbcHeuristic()
3881 {
3882 }
3883 
3884 // Constructor from model
CbcHeuristicDynamic3(CbcModel & model)3885 CbcHeuristicDynamic3::CbcHeuristicDynamic3(CbcModel &model)
3886   : CbcHeuristic(model)
3887 {
3888 }
3889 
3890 // Destructor
~CbcHeuristicDynamic3()3891 CbcHeuristicDynamic3::~CbcHeuristicDynamic3()
3892 {
3893 }
3894 
3895 // Clone
3896 CbcHeuristic *
clone() const3897 CbcHeuristicDynamic3::clone() const
3898 {
3899   return new CbcHeuristicDynamic3(*this);
3900 }
3901 
3902 // Copy constructor
CbcHeuristicDynamic3(const CbcHeuristicDynamic3 & rhs)3903 CbcHeuristicDynamic3::CbcHeuristicDynamic3(const CbcHeuristicDynamic3 &rhs)
3904   : CbcHeuristic(rhs)
3905 {
3906 }
3907 
3908 // Returns 1 if solution, 0 if not
solution(double & solutionValue,double * betterSolution)3909 int CbcHeuristicDynamic3::solution(double &solutionValue,
3910   double *betterSolution)
3911 {
3912   if (!model_)
3913     return 0;
3914   OsiSolverLink *clpSolver
3915     = dynamic_cast< OsiSolverLink * >(model_->solver());
3916   assert(clpSolver);
3917   double newSolutionValue = clpSolver->bestObjectiveValue();
3918   const double *solution = clpSolver->bestSolution();
3919   if (newSolutionValue < solutionValue && solution) {
3920     int numberColumns = clpSolver->getNumCols();
3921     // new solution
3922     memcpy(betterSolution, solution, numberColumns * sizeof(double));
3923     solutionValue = newSolutionValue;
3924     return 1;
3925   } else {
3926     return 0;
3927   }
3928 }
3929 // update model
setModel(CbcModel * model)3930 void CbcHeuristicDynamic3::setModel(CbcModel *model)
3931 {
3932   model_ = model;
3933 }
3934 // Resets stuff if model changes
resetModel(CbcModel * model)3935 void CbcHeuristicDynamic3::resetModel(CbcModel *model)
3936 {
3937   model_ = model;
3938 }
3939 #include <cassert>
3940 #include <cmath>
3941 #include <cfloat>
3942 //#define CBC_DEBUG
3943 
3944 #include "OsiSolverInterface.hpp"
3945 //#include "OsiBranchLink.hpp"
3946 #include "CoinError.hpp"
3947 #include "CoinHelperFunctions.hpp"
3948 #include "CoinPackedMatrix.hpp"
3949 #include "CoinWarmStartBasis.hpp"
3950 
3951 // Default Constructor
OsiOldLink()3952 OsiOldLink::OsiOldLink()
3953   : OsiSOS()
3954   , numberLinks_(0)
3955 {
3956 }
3957 
3958 // Useful constructor (which are indices)
OsiOldLink(const OsiSolverInterface *,int numberMembers,int numberLinks,int first,const double * weights,int)3959 OsiOldLink::OsiOldLink(const OsiSolverInterface * /*solver*/, int numberMembers,
3960   int numberLinks, int first, const double *weights, int /*identifier*/)
3961   : OsiSOS()
3962   , numberLinks_(numberLinks)
3963 {
3964   numberMembers_ = numberMembers;
3965   members_ = NULL;
3966   sosType_ = 1;
3967   if (numberMembers_) {
3968     weights_ = new double[numberMembers_];
3969     members_ = new int[numberMembers_ * numberLinks_];
3970     if (weights) {
3971       memcpy(weights_, weights, numberMembers_ * sizeof(double));
3972     } else {
3973       for (int i = 0; i < numberMembers_; i++)
3974         weights_[i] = i;
3975     }
3976     // weights must be increasing
3977     int i;
3978 #ifndef NDEBUG
3979     for (i = 1; i < numberMembers_; i++)
3980       assert(weights_[i] > weights_[i - 1] + 1.0e-12);
3981 #endif
3982     for (i = 0; i < numberMembers_ * numberLinks_; i++) {
3983       members_[i] = first + i;
3984     }
3985   } else {
3986     weights_ = NULL;
3987   }
3988 }
3989 
3990 // Useful constructor (which are indices)
OsiOldLink(const OsiSolverInterface *,int numberMembers,int numberLinks,int,const int * which,const double * weights,int)3991 OsiOldLink::OsiOldLink(const OsiSolverInterface * /*solver*/, int numberMembers,
3992   int numberLinks, int /*sosType*/, const int *which,
3993   const double *weights, int /*identifier*/)
3994   : OsiSOS()
3995   , numberLinks_(numberLinks)
3996 {
3997   numberMembers_ = numberMembers;
3998   members_ = NULL;
3999   sosType_ = 1;
4000   if (numberMembers_) {
4001     weights_ = new double[numberMembers_];
4002     members_ = new int[numberMembers_ * numberLinks_];
4003     if (weights) {
4004       memcpy(weights_, weights, numberMembers_ * sizeof(double));
4005     } else {
4006       for (int i = 0; i < numberMembers_; i++)
4007         weights_[i] = i;
4008     }
4009     // weights must be increasing
4010     int i;
4011 #ifndef NDEBUG
4012     for (i = 1; i < numberMembers_; i++)
4013       assert(weights_[i] > weights_[i - 1] + 1.0e-12);
4014 #endif
4015     for (i = 0; i < numberMembers_ * numberLinks_; i++) {
4016       members_[i] = which[i];
4017     }
4018   } else {
4019     weights_ = NULL;
4020   }
4021 }
4022 
4023 // Copy constructor
OsiOldLink(const OsiOldLink & rhs)4024 OsiOldLink::OsiOldLink(const OsiOldLink &rhs)
4025   : OsiSOS(rhs)
4026 {
4027   numberLinks_ = rhs.numberLinks_;
4028   if (numberMembers_) {
4029     delete[] members_;
4030     members_ = CoinCopyOfArray(rhs.members_, numberMembers_ * numberLinks_);
4031   }
4032 }
4033 
4034 // Clone
4035 OsiObject *
clone() const4036 OsiOldLink::clone() const
4037 {
4038   return new OsiOldLink(*this);
4039 }
4040 
4041 // Assignment operator
4042 OsiOldLink &
operator =(const OsiOldLink & rhs)4043 OsiOldLink::operator=(const OsiOldLink &rhs)
4044 {
4045   if (this != &rhs) {
4046     OsiSOS::operator=(rhs);
4047     delete[] members_;
4048     numberLinks_ = rhs.numberLinks_;
4049     if (numberMembers_) {
4050       members_ = CoinCopyOfArray(rhs.members_, numberMembers_ * numberLinks_);
4051     } else {
4052       members_ = NULL;
4053     }
4054   }
4055   return *this;
4056 }
4057 
4058 // Destructor
~OsiOldLink()4059 OsiOldLink::~OsiOldLink()
4060 {
4061 }
4062 
4063 // Infeasibility - large is 0.5
4064 double
infeasibility(const OsiBranchingInformation * info,int & whichWay) const4065 OsiOldLink::infeasibility(const OsiBranchingInformation *info, int &whichWay) const
4066 {
4067   int j;
4068   int firstNonZero = -1;
4069   int lastNonZero = -1;
4070   const double *solution = info->solution_;
4071   //const double * lower = info->lower_;
4072   const double *upper = info->upper_;
4073   double integerTolerance = info->integerTolerance_;
4074   double weight = 0.0;
4075   double sum = 0.0;
4076 
4077   // check bounds etc
4078   double lastWeight = -1.0e100;
4079   int base = 0;
4080   for (j = 0; j < numberMembers_; j++) {
4081     for (int k = 0; k < numberLinks_; k++) {
4082       int iColumn = members_[base + k];
4083       if (lastWeight >= weights_[j] - 1.0e-7)
4084         throw CoinError("Weights too close together in OsiLink", "infeasibility", "OsiLink");
4085       lastWeight = weights_[j];
4086       double value = CoinMax(0.0, solution[iColumn]);
4087       sum += value;
4088       if (value > integerTolerance && upper[iColumn]) {
4089         // Possibly due to scaling a fixed variable might slip through
4090         if (value > upper[iColumn] + 1.0e-8) {
4091 #ifdef OSI_DEBUG
4092           printf("** Variable %d (%d) has value %g and upper bound of %g\n",
4093             iColumn, j, value, upper[iColumn]);
4094 #endif
4095         }
4096         value = CoinMin(value, upper[iColumn]);
4097         weight += weights_[j] * value;
4098         if (firstNonZero < 0)
4099           firstNonZero = j;
4100         lastNonZero = j;
4101       }
4102     }
4103     base += numberLinks_;
4104   }
4105   double valueInfeasibility;
4106   whichWay = 1;
4107   whichWay_ = 1;
4108   if (lastNonZero - firstNonZero >= sosType_) {
4109     // find where to branch
4110     assert(sum > 0.0);
4111     weight /= sum;
4112     valueInfeasibility = lastNonZero - firstNonZero + 1;
4113     valueInfeasibility *= 0.5 / static_cast< double >(numberMembers_);
4114     //#define DISTANCE
4115 #ifdef DISTANCE
4116     assert(sosType_ == 1); // code up
4117     /* may still be satisfied.
4118            For LOS type 2 we might wish to move coding around
4119            and keep initial info in model_ for speed
4120         */
4121     int iWhere;
4122     bool possible = false;
4123     for (iWhere = firstNonZero; iWhere <= lastNonZero; iWhere++) {
4124       if (fabs(weight - weights_[iWhere]) < 1.0e-8) {
4125         possible = true;
4126         break;
4127       }
4128     }
4129     if (possible) {
4130       // One could move some of this (+ arrays) into model_
4131       const CoinPackedMatrix *matrix = solver->getMatrixByCol();
4132       const double *element = matrix->getMutableElements();
4133       const int *row = matrix->getIndices();
4134       const CoinBigIndex *columnStart = matrix->getVectorStarts();
4135       const int *columnLength = matrix->getVectorLengths();
4136       const double *rowSolution = solver->getRowActivity();
4137       const double *rowLower = solver->getRowLower();
4138       const double *rowUpper = solver->getRowUpper();
4139       int numberRows = matrix->getNumRows();
4140       double *array = new double[numberRows];
4141       CoinZeroN(array, numberRows);
4142       int *which = new int[numberRows];
4143       int n = 0;
4144       int base = numberLinks_ * firstNonZero;
4145       for (j = firstNonZero; j <= lastNonZero; j++) {
4146         for (int k = 0; k < numberLinks_; k++) {
4147           int iColumn = members_[base + k];
4148           double value = CoinMax(0.0, solution[iColumn]);
4149           if (value > integerTolerance && upper[iColumn]) {
4150             value = CoinMin(value, upper[iColumn]);
4151             for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4152               int iRow = row[j];
4153               double a = array[iRow];
4154               if (a) {
4155                 a += value * element[j];
4156                 if (!a)
4157                   a = 1.0e-100;
4158               } else {
4159                 which[n++] = iRow;
4160                 a = value * element[j];
4161                 assert(a);
4162               }
4163               array[iRow] = a;
4164             }
4165           }
4166         }
4167         base += numberLinks_;
4168       }
4169       base = numberLinks_ * iWhere;
4170       for (int k = 0; k < numberLinks_; k++) {
4171         int iColumn = members_[base + k];
4172         const double value = 1.0;
4173         for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4174           int iRow = row[j];
4175           double a = array[iRow];
4176           if (a) {
4177             a -= value * element[j];
4178             if (!a)
4179               a = 1.0e-100;
4180           } else {
4181             which[n++] = iRow;
4182             a = -value * element[j];
4183             assert(a);
4184           }
4185           array[iRow] = a;
4186         }
4187       }
4188       for (j = 0; j < n; j++) {
4189         int iRow = which[j];
4190         // moving to point will increase row solution by this
4191         double distance = array[iRow];
4192         if (distance > 1.0e-8) {
4193           if (distance + rowSolution[iRow] > rowUpper[iRow] + 1.0e-8) {
4194             possible = false;
4195             break;
4196           }
4197         } else if (distance < -1.0e-8) {
4198           if (distance + rowSolution[iRow] < rowLower[iRow] - 1.0e-8) {
4199             possible = false;
4200             break;
4201           }
4202         }
4203       }
4204       for (j = 0; j < n; j++)
4205         array[which[j]] = 0.0;
4206       delete[] array;
4207       delete[] which;
4208       if (possible) {
4209         valueInfeasibility = 0.0;
4210         printf("possible %d %d %d\n", firstNonZero, lastNonZero, iWhere);
4211       }
4212     }
4213 #endif
4214   } else {
4215     valueInfeasibility = 0.0; // satisfied
4216   }
4217   infeasibility_ = valueInfeasibility;
4218   otherInfeasibility_ = 1.0 - valueInfeasibility;
4219   return valueInfeasibility;
4220 }
4221 
4222 // This looks at solution and sets bounds to contain solution
4223 double
feasibleRegion(OsiSolverInterface * solver,const OsiBranchingInformation * info) const4224 OsiOldLink::feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const
4225 {
4226   int j;
4227   int firstNonZero = -1;
4228   int lastNonZero = -1;
4229   const double *solution = info->solution_;
4230   const double *upper = info->upper_;
4231   double integerTolerance = info->integerTolerance_;
4232   double weight = 0.0;
4233   double sum = 0.0;
4234 
4235   int base = 0;
4236   for (j = 0; j < numberMembers_; j++) {
4237     for (int k = 0; k < numberLinks_; k++) {
4238       int iColumn = members_[base + k];
4239       double value = CoinMax(0.0, solution[iColumn]);
4240       sum += value;
4241       if (value > integerTolerance && upper[iColumn]) {
4242         weight += weights_[j] * value;
4243         if (firstNonZero < 0)
4244           firstNonZero = j;
4245         lastNonZero = j;
4246       }
4247     }
4248     base += numberLinks_;
4249   }
4250 #ifdef DISTANCE
4251   if (lastNonZero - firstNonZero > sosType_ - 1) {
4252     /* may still be satisfied.
4253            For LOS type 2 we might wish to move coding around
4254            and keep initial info in model_ for speed
4255         */
4256     int iWhere;
4257     bool possible = false;
4258     for (iWhere = firstNonZero; iWhere <= lastNonZero; iWhere++) {
4259       if (fabs(weight - weights_[iWhere]) < 1.0e-8) {
4260         possible = true;
4261         break;
4262       }
4263     }
4264     if (possible) {
4265       // One could move some of this (+ arrays) into model_
4266       const CoinPackedMatrix *matrix = solver->getMatrixByCol();
4267       const double *element = matrix->getMutableElements();
4268       const int *row = matrix->getIndices();
4269       const CoinBigIndex *columnStart = matrix->getVectorStarts();
4270       const int *columnLength = matrix->getVectorLengths();
4271       const double *rowSolution = solver->getRowActivity();
4272       const double *rowLower = solver->getRowLower();
4273       const double *rowUpper = solver->getRowUpper();
4274       int numberRows = matrix->getNumRows();
4275       double *array = new double[numberRows];
4276       CoinZeroN(array, numberRows);
4277       int *which = new int[numberRows];
4278       int n = 0;
4279       int base = numberLinks_ * firstNonZero;
4280       for (j = firstNonZero; j <= lastNonZero; j++) {
4281         for (int k = 0; k < numberLinks_; k++) {
4282           int iColumn = members_[base + k];
4283           double value = CoinMax(0.0, solution[iColumn]);
4284           if (value > integerTolerance && upper[iColumn]) {
4285             value = CoinMin(value, upper[iColumn]);
4286             for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4287               int iRow = row[j];
4288               double a = array[iRow];
4289               if (a) {
4290                 a += value * element[j];
4291                 if (!a)
4292                   a = 1.0e-100;
4293               } else {
4294                 which[n++] = iRow;
4295                 a = value * element[j];
4296                 assert(a);
4297               }
4298               array[iRow] = a;
4299             }
4300           }
4301         }
4302         base += numberLinks_;
4303       }
4304       base = numberLinks_ * iWhere;
4305       for (int k = 0; k < numberLinks_; k++) {
4306         int iColumn = members_[base + k];
4307         const double value = 1.0;
4308         for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4309           int iRow = row[j];
4310           double a = array[iRow];
4311           if (a) {
4312             a -= value * element[j];
4313             if (!a)
4314               a = 1.0e-100;
4315           } else {
4316             which[n++] = iRow;
4317             a = -value * element[j];
4318             assert(a);
4319           }
4320           array[iRow] = a;
4321         }
4322       }
4323       for (j = 0; j < n; j++) {
4324         int iRow = which[j];
4325         // moving to point will increase row solution by this
4326         double distance = array[iRow];
4327         if (distance > 1.0e-8) {
4328           if (distance + rowSolution[iRow] > rowUpper[iRow] + 1.0e-8) {
4329             possible = false;
4330             break;
4331           }
4332         } else if (distance < -1.0e-8) {
4333           if (distance + rowSolution[iRow] < rowLower[iRow] - 1.0e-8) {
4334             possible = false;
4335             break;
4336           }
4337         }
4338       }
4339       for (j = 0; j < n; j++)
4340         array[which[j]] = 0.0;
4341       delete[] array;
4342       delete[] which;
4343       if (possible) {
4344         printf("possible feas region %d %d %d\n", firstNonZero, lastNonZero, iWhere);
4345         firstNonZero = iWhere;
4346         lastNonZero = iWhere;
4347       }
4348     }
4349   }
4350 #else
4351   assert(lastNonZero - firstNonZero < sosType_);
4352 #endif
4353   base = 0;
4354   for (j = 0; j < firstNonZero; j++) {
4355     for (int k = 0; k < numberLinks_; k++) {
4356       int iColumn = members_[base + k];
4357       solver->setColUpper(iColumn, 0.0);
4358     }
4359     base += numberLinks_;
4360   }
4361   // skip
4362   base += numberLinks_;
4363   for (j = lastNonZero + 1; j < numberMembers_; j++) {
4364     for (int k = 0; k < numberLinks_; k++) {
4365       int iColumn = members_[base + k];
4366       solver->setColUpper(iColumn, 0.0);
4367     }
4368     base += numberLinks_;
4369   }
4370   // go to coding as in OsiSOS
4371   abort();
4372   return -1.0;
4373 }
4374 
4375 // Redoes data when sequence numbers change
resetSequenceEtc(int numberColumns,const int * originalColumns)4376 void OsiOldLink::resetSequenceEtc(int numberColumns, const int *originalColumns)
4377 {
4378   int n2 = 0;
4379   for (int j = 0; j < numberMembers_ * numberLinks_; j++) {
4380     int iColumn = members_[j];
4381     int i;
4382 #ifdef JJF_ZERO
4383     for (i = 0; i < numberColumns; i++) {
4384       if (originalColumns[i] == iColumn)
4385         break;
4386     }
4387 #else
4388     i = originalColumns[iColumn];
4389 #endif
4390     if (i >= 0 && i < numberColumns) {
4391       members_[n2] = i;
4392       weights_[n2++] = weights_[j];
4393     }
4394   }
4395   if (n2 < numberMembers_) {
4396     printf("** SOS number of members reduced from %d to %d!\n", numberMembers_, n2 / numberLinks_);
4397     numberMembers_ = n2 / numberLinks_;
4398   }
4399 }
4400 
4401 // Creates a branching object
4402 OsiBranchingObject *
createBranch(OsiSolverInterface * solver,const OsiBranchingInformation * info,int way) const4403 OsiOldLink::createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const
4404 {
4405   int j;
4406   const double *solution = info->solution_;
4407   double tolerance = info->primalTolerance_;
4408   const double *upper = info->upper_;
4409   int firstNonFixed = -1;
4410   int lastNonFixed = -1;
4411   int firstNonZero = -1;
4412   int lastNonZero = -1;
4413   double weight = 0.0;
4414   double sum = 0.0;
4415   int base = 0;
4416   for (j = 0; j < numberMembers_; j++) {
4417     for (int k = 0; k < numberLinks_; k++) {
4418       int iColumn = members_[base + k];
4419       if (upper[iColumn]) {
4420         double value = CoinMax(0.0, solution[iColumn]);
4421         sum += value;
4422         if (firstNonFixed < 0)
4423           firstNonFixed = j;
4424         lastNonFixed = j;
4425         if (value > tolerance) {
4426           weight += weights_[j] * value;
4427           if (firstNonZero < 0)
4428             firstNonZero = j;
4429           lastNonZero = j;
4430         }
4431       }
4432     }
4433     base += numberLinks_;
4434   }
4435   assert(lastNonZero - firstNonZero >= sosType_);
4436   // find where to branch
4437   assert(sum > 0.0);
4438   weight /= sum;
4439   int iWhere;
4440   double separator = 0.0;
4441   for (iWhere = firstNonZero; iWhere < lastNonZero; iWhere++)
4442     if (weight < weights_[iWhere + 1])
4443       break;
4444   if (sosType_ == 1) {
4445     // SOS 1
4446     separator = 0.5 * (weights_[iWhere] + weights_[iWhere + 1]);
4447   } else {
4448     // SOS 2
4449     if (iWhere == firstNonFixed)
4450       iWhere++;
4451     ;
4452     if (iWhere == lastNonFixed - 1)
4453       iWhere = lastNonFixed - 2;
4454     separator = weights_[iWhere + 1];
4455   }
4456   // create object
4457   OsiBranchingObject *branch;
4458   branch = new OsiOldLinkBranchingObject(solver, this, way, separator);
4459   return branch;
4460 }
OsiOldLinkBranchingObject()4461 OsiOldLinkBranchingObject::OsiOldLinkBranchingObject()
4462   : OsiSOSBranchingObject()
4463 {
4464 }
4465 
4466 // Useful constructor
OsiOldLinkBranchingObject(OsiSolverInterface * solver,const OsiOldLink * set,int way,double separator)4467 OsiOldLinkBranchingObject::OsiOldLinkBranchingObject(OsiSolverInterface *solver,
4468   const OsiOldLink *set,
4469   int way,
4470   double separator)
4471   : OsiSOSBranchingObject(solver, set, way, separator)
4472 {
4473 }
4474 
4475 // Copy constructor
OsiOldLinkBranchingObject(const OsiOldLinkBranchingObject & rhs)4476 OsiOldLinkBranchingObject::OsiOldLinkBranchingObject(const OsiOldLinkBranchingObject &rhs)
4477   : OsiSOSBranchingObject(rhs)
4478 {
4479 }
4480 
4481 // Assignment operator
4482 OsiOldLinkBranchingObject &
operator =(const OsiOldLinkBranchingObject & rhs)4483 OsiOldLinkBranchingObject::operator=(const OsiOldLinkBranchingObject &rhs)
4484 {
4485   if (this != &rhs) {
4486     OsiSOSBranchingObject::operator=(rhs);
4487   }
4488   return *this;
4489 }
4490 OsiBranchingObject *
clone() const4491 OsiOldLinkBranchingObject::clone() const
4492 {
4493   return (new OsiOldLinkBranchingObject(*this));
4494 }
4495 
4496 // Destructor
~OsiOldLinkBranchingObject()4497 OsiOldLinkBranchingObject::~OsiOldLinkBranchingObject()
4498 {
4499 }
4500 double
branch(OsiSolverInterface * solver)4501 OsiOldLinkBranchingObject::branch(OsiSolverInterface *solver)
4502 {
4503   const OsiOldLink *set = dynamic_cast< const OsiOldLink * >(originalObject_);
4504   assert(set);
4505   int way = (!branchIndex_) ? (2 * firstBranch_ - 1) : -(2 * firstBranch_ - 1);
4506   branchIndex_++;
4507   int numberMembers = set->numberMembers();
4508   const int *which = set->members();
4509   const double *weights = set->weights();
4510   int numberLinks = set->numberLinks();
4511   //const double * lower = info->lower_;
4512   //const double * upper = solver->getColUpper();
4513   // *** for way - up means fix all those in down section
4514   if (way < 0) {
4515     int i;
4516     for (i = 0; i < numberMembers; i++) {
4517       if (weights[i] > value_)
4518         break;
4519     }
4520     assert(i < numberMembers);
4521     int base = i * numberLinks;
4522     ;
4523     for (; i < numberMembers; i++) {
4524       for (int k = 0; k < numberLinks; k++) {
4525         int iColumn = which[base + k];
4526         solver->setColUpper(iColumn, 0.0);
4527       }
4528       base += numberLinks;
4529     }
4530   } else {
4531     int i;
4532     int base = 0;
4533     for (i = 0; i < numberMembers; i++) {
4534       if (weights[i] >= value_) {
4535         break;
4536       } else {
4537         for (int k = 0; k < numberLinks; k++) {
4538           int iColumn = which[base + k];
4539           solver->setColUpper(iColumn, 0.0);
4540         }
4541         base += numberLinks;
4542       }
4543     }
4544     assert(i < numberMembers);
4545   }
4546   return 0.0;
4547 }
4548 // Print what would happen
print(const OsiSolverInterface * solver)4549 void OsiOldLinkBranchingObject::print(const OsiSolverInterface *solver)
4550 {
4551   const OsiOldLink *set = dynamic_cast< const OsiOldLink * >(originalObject_);
4552   assert(set);
4553   int way = (!branchIndex_) ? (2 * firstBranch_ - 1) : -(2 * firstBranch_ - 1);
4554   int numberMembers = set->numberMembers();
4555   int numberLinks = set->numberLinks();
4556   const double *weights = set->weights();
4557   const int *which = set->members();
4558   const double *upper = solver->getColUpper();
4559   int first = numberMembers;
4560   int last = -1;
4561   int numberFixed = 0;
4562   int numberOther = 0;
4563   int i;
4564   int base = 0;
4565   for (i = 0; i < numberMembers; i++) {
4566     for (int k = 0; k < numberLinks; k++) {
4567       int iColumn = which[base + k];
4568       double bound = upper[iColumn];
4569       if (bound) {
4570         first = CoinMin(first, i);
4571         last = CoinMax(last, i);
4572       }
4573     }
4574     base += numberLinks;
4575   }
4576   // *** for way - up means fix all those in down section
4577   base = 0;
4578   if (way < 0) {
4579     printf("SOS Down");
4580     for (i = 0; i < numberMembers; i++) {
4581       if (weights[i] > value_)
4582         break;
4583       for (int k = 0; k < numberLinks; k++) {
4584         int iColumn = which[base + k];
4585         double bound = upper[iColumn];
4586         if (bound)
4587           numberOther++;
4588       }
4589       base += numberLinks;
4590     }
4591     assert(i < numberMembers);
4592     for (; i < numberMembers; i++) {
4593       for (int k = 0; k < numberLinks; k++) {
4594         int iColumn = which[base + k];
4595         double bound = upper[iColumn];
4596         if (bound)
4597           numberFixed++;
4598       }
4599       base += numberLinks;
4600     }
4601   } else {
4602     printf("SOS Up");
4603     for (i = 0; i < numberMembers; i++) {
4604       if (weights[i] >= value_)
4605         break;
4606       for (int k = 0; k < numberLinks; k++) {
4607         int iColumn = which[base + k];
4608         double bound = upper[iColumn];
4609         if (bound)
4610           numberFixed++;
4611       }
4612       base += numberLinks;
4613     }
4614     assert(i < numberMembers);
4615     for (; i < numberMembers; i++) {
4616       for (int k = 0; k < numberLinks; k++) {
4617         int iColumn = which[base + k];
4618         double bound = upper[iColumn];
4619         if (bound)
4620           numberOther++;
4621       }
4622       base += numberLinks;
4623     }
4624   }
4625   assert((numberFixed % numberLinks) == 0);
4626   assert((numberOther % numberLinks) == 0);
4627   printf(" - at %g, free range %d (%g) => %d (%g), %d would be fixed, %d other way\n",
4628     value_, first, weights[first], last, weights[last], numberFixed / numberLinks,
4629     numberOther / numberLinks);
4630 }
4631 // Default Constructor
OsiBiLinear()4632 OsiBiLinear::OsiBiLinear()
4633   : OsiObject2()
4634   , coefficient_(0.0)
4635   , xMeshSize_(0.0)
4636   , yMeshSize_(0.0)
4637   , xSatisfied_(1.0e-6)
4638   , ySatisfied_(1.0e-6)
4639   , xOtherSatisfied_(0.0)
4640   , yOtherSatisfied_(0.0)
4641   , xySatisfied_(1.0e-6)
4642   , xyBranchValue_(0.0)
4643   , xColumn_(-1)
4644   , yColumn_(-1)
4645   , firstLambda_(-1)
4646   , branchingStrategy_(0)
4647   , boundType_(0)
4648   , xRow_(-1)
4649   , yRow_(-1)
4650   , xyRow_(-1)
4651   , convexity_(-1)
4652   , numberExtraRows_(0)
4653   , multiplier_(NULL)
4654   , extraRow_(NULL)
4655   , chosen_(-1)
4656 {
4657 }
4658 
4659 // Useful constructor
OsiBiLinear(OsiSolverInterface * solver,int xColumn,int yColumn,int xyRow,double coefficient,double xMesh,double yMesh,int numberExistingObjects,const OsiObject ** objects)4660 OsiBiLinear::OsiBiLinear(OsiSolverInterface *solver, int xColumn,
4661   int yColumn, int xyRow, double coefficient,
4662   double xMesh, double yMesh,
4663   int numberExistingObjects, const OsiObject **objects)
4664   : OsiObject2()
4665   , coefficient_(coefficient)
4666   , xMeshSize_(xMesh)
4667   , yMeshSize_(yMesh)
4668   , xSatisfied_(1.0e-6)
4669   , ySatisfied_(1.0e-6)
4670   , xOtherSatisfied_(0.0)
4671   , yOtherSatisfied_(0.0)
4672   , xySatisfied_(1.0e-6)
4673   , xyBranchValue_(0.0)
4674   , xColumn_(xColumn)
4675   , yColumn_(yColumn)
4676   , firstLambda_(-1)
4677   , branchingStrategy_(0)
4678   , boundType_(0)
4679   , xRow_(-1)
4680   , yRow_(-1)
4681   , xyRow_(xyRow)
4682   , convexity_(-1)
4683   , numberExtraRows_(0)
4684   , multiplier_(NULL)
4685   , extraRow_(NULL)
4686   , chosen_(-1)
4687 {
4688   double columnLower[4];
4689   double columnUpper[4];
4690   double objective[4];
4691   double rowLower[3];
4692   double rowUpper[3];
4693   CoinBigIndex starts[5];
4694   int index[16];
4695   double element[16];
4696   int i;
4697   starts[0] = 0;
4698   // rows
4699   int numberRows = solver->getNumRows();
4700   // convexity
4701   rowLower[0] = 1.0;
4702   rowUpper[0] = 1.0;
4703   convexity_ = numberRows;
4704   starts[1] = 0;
4705   // x
4706   rowLower[1] = 0.0;
4707   rowUpper[1] = 0.0;
4708   index[0] = xColumn_;
4709   element[0] = -1.0;
4710   xRow_ = numberRows + 1;
4711   starts[2] = 1;
4712   int nAdd = 2;
4713   if (xColumn_ != yColumn_) {
4714     rowLower[2] = 0.0;
4715     rowUpper[2] = 0.0;
4716     index[1] = yColumn;
4717     element[1] = -1.0;
4718     nAdd = 3;
4719     yRow_ = numberRows + 2;
4720     starts[3] = 2;
4721   } else {
4722     yRow_ = -1;
4723     branchingStrategy_ = 1;
4724   }
4725   // may be objective
4726   assert(xyRow_ >= -1);
4727   solver->addRows(nAdd, starts, index, element, rowLower, rowUpper);
4728   int n = 0;
4729   // order is LxLy, LxUy, UxLy and UxUy
4730   firstLambda_ = solver->getNumCols();
4731   // bit sloppy as theoretically could be infeasible but otherwise need to do more work
4732   double xB[2];
4733   double yB[2];
4734   const double *lower = solver->getColLower();
4735   const double *upper = solver->getColUpper();
4736   xB[0] = lower[xColumn_];
4737   xB[1] = upper[xColumn_];
4738   yB[0] = lower[yColumn_];
4739   yB[1] = upper[yColumn_];
4740   if (xMeshSize_ != floor(xMeshSize_)) {
4741     // not integral
4742     xSatisfied_ = CoinMax(xSatisfied_, 0.51 * xMeshSize_);
4743     if (!yMeshSize_) {
4744       xySatisfied_ = CoinMax(xySatisfied_, xSatisfied_ * CoinMax(fabs(yB[0]), fabs(yB[1])));
4745     }
4746   }
4747   if (yMeshSize_ != floor(yMeshSize_)) {
4748     // not integral
4749     ySatisfied_ = CoinMax(ySatisfied_, 0.51 * yMeshSize_);
4750     if (!xMeshSize_) {
4751       xySatisfied_ = CoinMax(xySatisfied_, ySatisfied_ * CoinMax(fabs(xB[0]), fabs(xB[1])));
4752     }
4753   }
4754   // adjust
4755   double distance;
4756   double steps;
4757   if (xMeshSize_) {
4758     distance = xB[1] - xB[0];
4759     steps = floor((distance + 0.5 * xMeshSize_) / xMeshSize_);
4760     distance = xB[0] + xMeshSize_ * steps;
4761     if (fabs(xB[1] - distance) > xSatisfied_) {
4762       printf("bad x mesh %g %g %g -> %g\n", xB[0], xMeshSize_, xB[1], distance);
4763       //double newValue = CoinMax(fabs(xB[1]-distance),xMeshSize_);
4764       //printf("xSatisfied increased to %g\n",newValue);
4765       //xSatisfied_ = newValue;
4766       //xB[1]=distance;
4767       //solver->setColUpper(xColumn_,distance);
4768     }
4769   }
4770   if (yMeshSize_) {
4771     distance = yB[1] - yB[0];
4772     steps = floor((distance + 0.5 * yMeshSize_) / yMeshSize_);
4773     distance = yB[0] + yMeshSize_ * steps;
4774     if (fabs(yB[1] - distance) > ySatisfied_) {
4775       printf("bad y mesh %g %g %g -> %g\n", yB[0], yMeshSize_, yB[1], distance);
4776       //double newValue = CoinMax(fabs(yB[1]-distance),yMeshSize_);
4777       //printf("ySatisfied increased to %g\n",newValue);
4778       //ySatisfied_ = newValue;
4779       //yB[1]=distance;
4780       //solver->setColUpper(yColumn_,distance);
4781     }
4782   }
4783   for (i = 0; i < 4; i++) {
4784     double x = (i < 2) ? xB[0] : xB[1];
4785     double y = ((i & 1) == 0) ? yB[0] : yB[1];
4786     columnLower[i] = 0.0;
4787     columnUpper[i] = 2.0;
4788     objective[i] = 0.0;
4789     double value;
4790     // xy
4791     value = coefficient_ * x * y;
4792     if (xyRow_ >= 0) {
4793       if (fabs(value) < 1.0e-19)
4794         value = 1.0e-19;
4795       element[n] = value;
4796       index[n++] = xyRow_;
4797     } else {
4798       objective[i] = value;
4799     }
4800     // convexity
4801     value = 1.0;
4802     element[n] = value;
4803     index[n++] = 0 + numberRows;
4804     // x
4805     value = x;
4806     if (fabs(value) < 1.0e-19)
4807       value = 1.0e-19;
4808     element[n] = value;
4809     index[n++] = 1 + numberRows;
4810     if (xColumn_ != yColumn_) {
4811       // y
4812       value = y;
4813       if (fabs(value) < 1.0e-19)
4814         value = 1.0e-19;
4815       element[n] = value;
4816       index[n++] = 2 + numberRows;
4817     }
4818     starts[i + 1] = n;
4819   }
4820   solver->addCols(4, starts, index, element, columnLower, columnUpper, objective);
4821   // At least one has to have a mesh
4822   if (!xMeshSize_ && (!yMeshSize_ || yRow_ < 0)) {
4823     printf("one of x and y must have a mesh size\n");
4824     abort();
4825   } else if (yRow_ >= 0) {
4826     if (!xMeshSize_)
4827       branchingStrategy_ = 2;
4828     else if (!yMeshSize_)
4829       branchingStrategy_ = 1;
4830   }
4831   // Now add constraints to link in x and or y to existing ones.
4832   bool xDone = false;
4833   bool yDone = false;
4834   // order is LxLy, LxUy, UxLy and UxUy
4835   for (i = numberExistingObjects - 1; i >= 0; i--) {
4836     const OsiObject *obj = objects[i];
4837     const OsiBiLinear *obj2 = dynamic_cast< const OsiBiLinear * >(obj);
4838     if (obj2) {
4839       if (xColumn_ == obj2->xColumn_ && !xDone) {
4840         // make sure y equal
4841         double rhs = 0.0;
4842         CoinBigIndex starts[2];
4843         int index[4];
4844         double element[4] = { 1.0, 1.0, -1.0, -1.0 };
4845         starts[0] = 0;
4846         starts[1] = 4;
4847         index[0] = firstLambda_ + 0;
4848         index[1] = firstLambda_ + 1;
4849         index[2] = obj2->firstLambda_ + 0;
4850         index[3] = obj2->firstLambda_ + 1;
4851         solver->addRows(1, starts, index, element, &rhs, &rhs);
4852         xDone = true;
4853       }
4854       if (yColumn_ == obj2->yColumn_ && yRow_ >= 0 && !yDone) {
4855         // make sure x equal
4856         double rhs = 0.0;
4857         CoinBigIndex starts[2];
4858         int index[4];
4859         double element[4] = { 1.0, 1.0, -1.0, -1.0 };
4860         starts[0] = 0;
4861         starts[1] = 4;
4862         index[0] = firstLambda_ + 0;
4863         index[1] = firstLambda_ + 2;
4864         index[2] = obj2->firstLambda_ + 0;
4865         index[3] = obj2->firstLambda_ + 2;
4866         solver->addRows(1, starts, index, element, &rhs, &rhs);
4867         yDone = true;
4868       }
4869     }
4870   }
4871 }
4872 // Set sizes and other stuff
setMeshSizes(const OsiSolverInterface * solver,double x,double y)4873 void OsiBiLinear::setMeshSizes(const OsiSolverInterface *solver, double x, double y)
4874 {
4875   xMeshSize_ = x;
4876   yMeshSize_ = y;
4877   double xB[2];
4878   double yB[2];
4879   const double *lower = solver->getColLower();
4880   const double *upper = solver->getColUpper();
4881   xB[0] = lower[xColumn_];
4882   xB[1] = upper[xColumn_];
4883   yB[0] = lower[yColumn_];
4884   yB[1] = upper[yColumn_];
4885   if (xMeshSize_ != floor(xMeshSize_)) {
4886     // not integral
4887     xSatisfied_ = CoinMax(xSatisfied_, 0.51 * xMeshSize_);
4888     if (!yMeshSize_) {
4889       xySatisfied_ = CoinMax(xySatisfied_, xSatisfied_ * CoinMax(fabs(yB[0]), fabs(yB[1])));
4890     }
4891   }
4892   if (yMeshSize_ != floor(yMeshSize_)) {
4893     // not integral
4894     ySatisfied_ = CoinMax(ySatisfied_, 0.51 * yMeshSize_);
4895     if (!xMeshSize_) {
4896       xySatisfied_ = CoinMax(xySatisfied_, ySatisfied_ * CoinMax(fabs(xB[0]), fabs(xB[1])));
4897     }
4898   }
4899 }
4900 // Useful constructor
OsiBiLinear(CoinModel * coinModel,int xColumn,int yColumn,int xyRow,double coefficient,double xMesh,double yMesh,int numberExistingObjects,const OsiObject ** objects)4901 OsiBiLinear::OsiBiLinear(CoinModel *coinModel, int xColumn,
4902   int yColumn, int xyRow, double coefficient,
4903   double xMesh, double yMesh,
4904   int numberExistingObjects, const OsiObject **objects)
4905   : OsiObject2()
4906   , coefficient_(coefficient)
4907   , xMeshSize_(xMesh)
4908   , yMeshSize_(yMesh)
4909   , xSatisfied_(1.0e-6)
4910   , ySatisfied_(1.0e-6)
4911   , xOtherSatisfied_(0.0)
4912   , yOtherSatisfied_(0.0)
4913   , xySatisfied_(1.0e-6)
4914   , xyBranchValue_(0.0)
4915   , xColumn_(xColumn)
4916   , yColumn_(yColumn)
4917   , firstLambda_(-1)
4918   , branchingStrategy_(0)
4919   , boundType_(0)
4920   , xRow_(-1)
4921   , yRow_(-1)
4922   , xyRow_(xyRow)
4923   , convexity_(-1)
4924   , numberExtraRows_(0)
4925   , multiplier_(NULL)
4926   , extraRow_(NULL)
4927   , chosen_(-1)
4928 {
4929   double columnLower[4];
4930   double columnUpper[4];
4931   double objective[4];
4932   double rowLower[3];
4933   double rowUpper[3];
4934   CoinBigIndex starts[5];
4935   int index[16];
4936   double element[16];
4937   int i;
4938   starts[0] = 0;
4939   // rows
4940   int numberRows = coinModel->numberRows();
4941   // convexity
4942   rowLower[0] = 1.0;
4943   rowUpper[0] = 1.0;
4944   convexity_ = numberRows;
4945   starts[1] = 0;
4946   // x
4947   rowLower[1] = 0.0;
4948   rowUpper[1] = 0.0;
4949   index[0] = xColumn_;
4950   element[0] = -1.0;
4951   xRow_ = numberRows + 1;
4952   starts[2] = 1;
4953   int nAdd = 2;
4954   if (xColumn_ != yColumn_) {
4955     rowLower[2] = 0.0;
4956     rowUpper[2] = 0.0;
4957     index[1] = yColumn;
4958     element[1] = -1.0;
4959     nAdd = 3;
4960     yRow_ = numberRows + 2;
4961     starts[3] = 2;
4962   } else {
4963     yRow_ = -1;
4964     branchingStrategy_ = 1;
4965   }
4966   // may be objective
4967   assert(xyRow_ >= -1);
4968   for (i = 0; i < nAdd; i++) {
4969     CoinBigIndex iStart = starts[i];
4970     coinModel->addRow(static_cast< int >(starts[i + 1] - iStart),
4971       index + iStart, element + iStart,
4972       rowLower[i], rowUpper[i]);
4973   }
4974   int n = 0;
4975   // order is LxLy, LxUy, UxLy and UxUy
4976   firstLambda_ = coinModel->numberColumns();
4977   // bit sloppy as theoretically could be infeasible but otherwise need to do more work
4978   double xB[2];
4979   double yB[2];
4980   const double *lower = coinModel->columnLowerArray();
4981   const double *upper = coinModel->columnUpperArray();
4982   xB[0] = lower[xColumn_];
4983   xB[1] = upper[xColumn_];
4984   yB[0] = lower[yColumn_];
4985   yB[1] = upper[yColumn_];
4986   if (xMeshSize_ != floor(xMeshSize_)) {
4987     // not integral
4988     xSatisfied_ = CoinMax(xSatisfied_, 0.51 * xMeshSize_);
4989     if (!yMeshSize_) {
4990       xySatisfied_ = CoinMax(xySatisfied_, xSatisfied_ * CoinMax(fabs(yB[0]), fabs(yB[1])));
4991     }
4992   }
4993   if (yMeshSize_ != floor(yMeshSize_)) {
4994     // not integral
4995     ySatisfied_ = CoinMax(ySatisfied_, 0.51 * yMeshSize_);
4996     if (!xMeshSize_) {
4997       xySatisfied_ = CoinMax(xySatisfied_, ySatisfied_ * CoinMax(fabs(xB[0]), fabs(xB[1])));
4998     }
4999   }
5000   // adjust
5001   double distance;
5002   double steps;
5003   if (xMeshSize_) {
5004     distance = xB[1] - xB[0];
5005     steps = floor((distance + 0.5 * xMeshSize_) / xMeshSize_);
5006     distance = xB[0] + xMeshSize_ * steps;
5007     if (fabs(xB[1] - distance) > xSatisfied_) {
5008       printf("bad x mesh %g %g %g -> %g\n", xB[0], xMeshSize_, xB[1], distance);
5009       //double newValue = CoinMax(fabs(xB[1]-distance),xMeshSize_);
5010       //printf("xSatisfied increased to %g\n",newValue);
5011       //xSatisfied_ = newValue;
5012       //xB[1]=distance;
5013       //coinModel->setColUpper(xColumn_,distance);
5014     }
5015   }
5016   if (yMeshSize_) {
5017     distance = yB[1] - yB[0];
5018     steps = floor((distance + 0.5 * yMeshSize_) / yMeshSize_);
5019     distance = yB[0] + yMeshSize_ * steps;
5020     if (fabs(yB[1] - distance) > ySatisfied_) {
5021       printf("bad y mesh %g %g %g -> %g\n", yB[0], yMeshSize_, yB[1], distance);
5022       //double newValue = CoinMax(fabs(yB[1]-distance),yMeshSize_);
5023       //printf("ySatisfied increased to %g\n",newValue);
5024       //ySatisfied_ = newValue;
5025       //yB[1]=distance;
5026       //coinModel->setColUpper(yColumn_,distance);
5027     }
5028   }
5029   for (i = 0; i < 4; i++) {
5030     double x = (i < 2) ? xB[0] : xB[1];
5031     double y = ((i & 1) == 0) ? yB[0] : yB[1];
5032     columnLower[i] = 0.0;
5033     columnUpper[i] = 2.0;
5034     objective[i] = 0.0;
5035     double value;
5036     // xy
5037     value = coefficient_ * x * y;
5038     if (xyRow_ >= 0) {
5039       if (fabs(value) < 1.0e-19)
5040         value = 1.0e-19;
5041       element[n] = value;
5042       index[n++] = xyRow_;
5043     } else {
5044       objective[i] = value;
5045     }
5046     // convexity
5047     value = 1.0;
5048     element[n] = value;
5049     index[n++] = 0 + numberRows;
5050     // x
5051     value = x;
5052     if (fabs(value) < 1.0e-19)
5053       value = 1.0e-19;
5054     element[n] = value;
5055     index[n++] = 1 + numberRows;
5056     if (xColumn_ != yColumn_) {
5057       // y
5058       value = y;
5059       if (fabs(value) < 1.0e-19)
5060         value = 1.0e-19;
5061       element[n] = value;
5062       index[n++] = 2 + numberRows;
5063     }
5064     starts[i + 1] = n;
5065   }
5066   for (i = 0; i < 4; i++) {
5067     CoinBigIndex iStart = starts[i];
5068     coinModel->addColumn(static_cast< int >(starts[i + 1] - iStart),
5069       index + iStart, element + iStart, columnLower[i],
5070       columnUpper[i], objective[i]);
5071   }
5072   // At least one has to have a mesh
5073   if (!xMeshSize_ && (!yMeshSize_ || yRow_ < 0)) {
5074     printf("one of x and y must have a mesh size\n");
5075     abort();
5076   } else if (yRow_ >= 0) {
5077     if (!xMeshSize_)
5078       branchingStrategy_ = 2;
5079     else if (!yMeshSize_)
5080       branchingStrategy_ = 1;
5081   }
5082   // Now add constraints to link in x and or y to existing ones.
5083   bool xDone = false;
5084   bool yDone = false;
5085   // order is LxLy, LxUy, UxLy and UxUy
5086   for (i = numberExistingObjects - 1; i >= 0; i--) {
5087     const OsiObject *obj = objects[i];
5088     const OsiBiLinear *obj2 = dynamic_cast< const OsiBiLinear * >(obj);
5089     if (obj2) {
5090       if (xColumn_ == obj2->xColumn_ && !xDone) {
5091         // make sure y equal
5092         double rhs = 0.0;
5093         int index[4];
5094         double element[4] = { 1.0, 1.0, -1.0, -1.0 };
5095         index[0] = firstLambda_ + 0;
5096         index[1] = firstLambda_ + 1;
5097         index[2] = obj2->firstLambda_ + 0;
5098         index[3] = obj2->firstLambda_ + 1;
5099         coinModel->addRow(4, index, element, rhs, rhs);
5100         xDone = true;
5101       }
5102       if (yColumn_ == obj2->yColumn_ && yRow_ >= 0 && !yDone) {
5103         // make sure x equal
5104         double rhs = 0.0;
5105         int index[4];
5106         double element[4] = { 1.0, 1.0, -1.0, -1.0 };
5107         index[0] = firstLambda_ + 0;
5108         index[1] = firstLambda_ + 2;
5109         index[2] = obj2->firstLambda_ + 0;
5110         index[3] = obj2->firstLambda_ + 2;
5111         coinModel->addRow(4, index, element, rhs, rhs);
5112         yDone = true;
5113       }
5114     }
5115   }
5116 }
5117 
5118 // Copy constructor
OsiBiLinear(const OsiBiLinear & rhs)5119 OsiBiLinear::OsiBiLinear(const OsiBiLinear &rhs)
5120   : OsiObject2(rhs)
5121   , coefficient_(rhs.coefficient_)
5122   , xMeshSize_(rhs.xMeshSize_)
5123   , yMeshSize_(rhs.yMeshSize_)
5124   , xSatisfied_(rhs.xSatisfied_)
5125   , ySatisfied_(rhs.ySatisfied_)
5126   , xOtherSatisfied_(rhs.xOtherSatisfied_)
5127   , yOtherSatisfied_(rhs.yOtherSatisfied_)
5128   , xySatisfied_(rhs.xySatisfied_)
5129   , xyBranchValue_(rhs.xyBranchValue_)
5130   , xColumn_(rhs.xColumn_)
5131   , yColumn_(rhs.yColumn_)
5132   , firstLambda_(rhs.firstLambda_)
5133   , branchingStrategy_(rhs.branchingStrategy_)
5134   , boundType_(rhs.boundType_)
5135   , xRow_(rhs.xRow_)
5136   , yRow_(rhs.yRow_)
5137   , xyRow_(rhs.xyRow_)
5138   , convexity_(rhs.convexity_)
5139   , numberExtraRows_(rhs.numberExtraRows_)
5140   , multiplier_(NULL)
5141   , extraRow_(NULL)
5142   , chosen_(rhs.chosen_)
5143 {
5144   if (numberExtraRows_) {
5145     multiplier_ = CoinCopyOfArray(rhs.multiplier_, numberExtraRows_);
5146     extraRow_ = CoinCopyOfArray(rhs.extraRow_, numberExtraRows_);
5147   }
5148 }
5149 
5150 // Clone
5151 OsiObject *
clone() const5152 OsiBiLinear::clone() const
5153 {
5154   return new OsiBiLinear(*this);
5155 }
5156 
5157 // Assignment operator
5158 OsiBiLinear &
operator =(const OsiBiLinear & rhs)5159 OsiBiLinear::operator=(const OsiBiLinear &rhs)
5160 {
5161   if (this != &rhs) {
5162     OsiObject2::operator=(rhs);
5163     coefficient_ = rhs.coefficient_;
5164     xMeshSize_ = rhs.xMeshSize_;
5165     yMeshSize_ = rhs.yMeshSize_;
5166     xSatisfied_ = rhs.xSatisfied_;
5167     ySatisfied_ = rhs.ySatisfied_;
5168     xOtherSatisfied_ = rhs.xOtherSatisfied_;
5169     yOtherSatisfied_ = rhs.yOtherSatisfied_;
5170     xySatisfied_ = rhs.xySatisfied_;
5171     xyBranchValue_ = rhs.xyBranchValue_;
5172     xColumn_ = rhs.xColumn_;
5173     yColumn_ = rhs.yColumn_;
5174     firstLambda_ = rhs.firstLambda_;
5175     branchingStrategy_ = rhs.branchingStrategy_;
5176     boundType_ = rhs.boundType_;
5177     xRow_ = rhs.xRow_;
5178     yRow_ = rhs.yRow_;
5179     xyRow_ = rhs.xyRow_;
5180     convexity_ = rhs.convexity_;
5181     numberExtraRows_ = rhs.numberExtraRows_;
5182     delete[] multiplier_;
5183     delete[] extraRow_;
5184     if (numberExtraRows_) {
5185       multiplier_ = CoinCopyOfArray(rhs.multiplier_, numberExtraRows_);
5186       extraRow_ = CoinCopyOfArray(rhs.extraRow_, numberExtraRows_);
5187     } else {
5188       multiplier_ = NULL;
5189       extraRow_ = NULL;
5190     }
5191     chosen_ = rhs.chosen_;
5192   }
5193   return *this;
5194 }
5195 
5196 // Destructor
~OsiBiLinear()5197 OsiBiLinear::~OsiBiLinear()
5198 {
5199   delete[] multiplier_;
5200   delete[] extraRow_;
5201 }
5202 // Adds in data for extra row with variable coefficients
addExtraRow(int row,double multiplier)5203 void OsiBiLinear::addExtraRow(int row, double multiplier)
5204 {
5205   int *tempI = new int[numberExtraRows_ + 1];
5206   double *tempD = new double[numberExtraRows_ + 1];
5207   memcpy(tempI, extraRow_, numberExtraRows_ * sizeof(int));
5208   memcpy(tempD, multiplier_, numberExtraRows_ * sizeof(double));
5209   tempI[numberExtraRows_] = row;
5210   tempD[numberExtraRows_] = multiplier;
5211   if (numberExtraRows_)
5212     assert(row > tempI[numberExtraRows_ - 1]);
5213   numberExtraRows_++;
5214   delete[] extraRow_;
5215   extraRow_ = tempI;
5216   delete[] multiplier_;
5217   multiplier_ = tempD;
5218 }
5219 static bool testCoarse = true;
5220 // Infeasibility - large is 0.5
5221 double
infeasibility(const OsiBranchingInformation * info,int & whichWay) const5222 OsiBiLinear::infeasibility(const OsiBranchingInformation *info, int &whichWay) const
5223 {
5224   // order is LxLy, LxUy, UxLy and UxUy
5225   double xB[2];
5226   double yB[2];
5227   xB[0] = info->lower_[xColumn_];
5228   xB[1] = info->upper_[xColumn_];
5229   yB[0] = info->lower_[yColumn_];
5230   yB[1] = info->upper_[yColumn_];
5231 #ifdef JJF_ZERO
5232   if (info->lower_[1] <= 43.0 && info->upper_[1] >= 43.0) {
5233     if (info->lower_[4] <= 49.0 && info->upper_[4] >= 49.0) {
5234       if (info->lower_[2] <= 16.0 && info->upper_[2] >= 16.0) {
5235         if (info->lower_[3] <= 19.0 && info->upper_[3] >= 19.0) {
5236           printf("feas %g %g %g %g  p %g t %g\n",
5237             info->solution_[1],
5238             info->solution_[2],
5239             info->solution_[3],
5240             info->solution_[4],
5241             info->solution_[0],
5242             info->solution_[5]);
5243         }
5244       }
5245     }
5246   }
5247 #endif
5248   double x = info->solution_[xColumn_];
5249   x = CoinMax(x, xB[0]);
5250   x = CoinMin(x, xB[1]);
5251   double y = info->solution_[yColumn_];
5252   y = CoinMax(y, yB[0]);
5253   y = CoinMin(y, yB[1]);
5254   int j;
5255   // seems something wrong here
5256 #if 0 //ndef NDEBUG
5257     double xLambda = 0.0;
5258     double yLambda = 0.0;
5259     if ((branchingStrategy_&4) == 0) {
5260         for (j = 0; j < 4; j++) {
5261             int iX = j >> 1;
5262             int iY = j & 1;
5263             xLambda += xB[iX] * info->solution_[firstLambda_+j];
5264             if (yRow_ >= 0)
5265                 yLambda += yB[iY] * info->solution_[firstLambda_+j];
5266         }
5267     } else {
5268         const double * element = info->elementByColumn_;
5269         const int * row = info->row_;
5270         const CoinBigIndex * columnStart = info->columnStart_;
5271         const int * columnLength = info->columnLength_;
5272         for (j = 0; j < 4; j++) {
5273             int iColumn = firstLambda_ + j;
5274             CoinBigIndex iStart = columnStart[iColumn];
5275             CoinBigIndex iEnd = iStart + columnLength[iColumn];
5276             CoinBigIndex k = iStart;
5277             double sol = info->solution_[iColumn];
5278             for (; k < iEnd; k++) {
5279                 if (xRow_ == row[k])
5280                     xLambda += element[k] * sol;
5281                 if (yRow_ == row[k])
5282                     yLambda += element[k] * sol;
5283             }
5284         }
5285     }
5286     assert (fabs(x - xLambda) < 1.0e-1);
5287     if (yRow_ >= 0)
5288         assert (fabs(y - yLambda) < 1.0e-1);
5289 #endif
5290   // If x or y not satisfied then branch on that
5291   double distance;
5292   double steps;
5293   bool xSatisfied;
5294   double xNew = xB[0];
5295   if (xMeshSize_) {
5296     if (x < 0.5 * (xB[0] + xB[1])) {
5297       distance = x - xB[0];
5298       steps = floor((distance + 0.5 * xMeshSize_) / xMeshSize_);
5299       xNew = xB[0] + steps * xMeshSize_;
5300       assert(xNew <= xB[1] + xSatisfied_);
5301       xSatisfied = (fabs(xNew - x) < xSatisfied_);
5302     } else {
5303       distance = xB[1] - x;
5304       steps = floor((distance + 0.5 * xMeshSize_) / xMeshSize_);
5305       xNew = xB[1] - steps * xMeshSize_;
5306       assert(xNew >= xB[0] - xSatisfied_);
5307       xSatisfied = (fabs(xNew - x) < xSatisfied_);
5308     }
5309     // but if first coarse grid then only if gap small
5310     if (testCoarse && (branchingStrategy_ & 8) != 0 && xSatisfied && xB[1] - xB[0] >= xMeshSize_) {
5311       // but allow if fine grid would allow
5312       if (fabs(xNew - x) >= xOtherSatisfied_ && fabs(yB[0] - y) > yOtherSatisfied_
5313         && fabs(yB[1] - y) > yOtherSatisfied_) {
5314         xNew = 0.5 * (xB[0] + xB[1]);
5315         x = xNew;
5316         xSatisfied = false;
5317       }
5318     }
5319   } else {
5320     xSatisfied = true;
5321   }
5322   bool ySatisfied;
5323   double yNew = yB[0];
5324   if (yMeshSize_) {
5325     if (y < 0.5 * (yB[0] + yB[1])) {
5326       distance = y - yB[0];
5327       steps = floor((distance + 0.5 * yMeshSize_) / yMeshSize_);
5328       yNew = yB[0] + steps * yMeshSize_;
5329       assert(yNew <= yB[1] + ySatisfied_);
5330       ySatisfied = (fabs(yNew - y) < ySatisfied_);
5331     } else {
5332       distance = yB[1] - y;
5333       steps = floor((distance + 0.5 * yMeshSize_) / yMeshSize_);
5334       yNew = yB[1] - steps * yMeshSize_;
5335       assert(yNew >= yB[0] - ySatisfied_);
5336       ySatisfied = (fabs(yNew - y) < ySatisfied_);
5337     }
5338     // but if first coarse grid then only if gap small
5339     if (testCoarse && (branchingStrategy_ & 8) != 0 && ySatisfied && yB[1] - yB[0] >= yMeshSize_) {
5340       // but allow if fine grid would allow
5341       if (fabs(yNew - y) >= yOtherSatisfied_ && fabs(xB[0] - x) > xOtherSatisfied_
5342         && fabs(xB[1] - x) > xOtherSatisfied_) {
5343         yNew = 0.5 * (yB[0] + yB[1]);
5344         y = yNew;
5345         ySatisfied = false;
5346       }
5347     }
5348   } else {
5349     ySatisfied = true;
5350   }
5351   /* There are several possibilities
5352        1 - one or both are unsatisfied and branching strategy tells us what to do
5353        2 - both are unsatisfied and branching strategy is 0
5354        3 - both are satisfied but xy is not
5355            3a one has bounds within satisfied_ - other does not
5356        (or neither have but branching strategy tells us what to do)
5357        3b neither do - and branching strategy does not tell us
5358        3c both do - treat as feasible knowing another copy of object will fix
5359        4 - both are satisfied and xy is satisfied - as 3c
5360     */
5361   chosen_ = -1;
5362   xyBranchValue_ = COIN_DBL_MAX;
5363   whichWay_ = 0;
5364   double xyTrue = x * y;
5365   double xyLambda = 0.0;
5366   if ((branchingStrategy_ & 4) == 0) {
5367     for (j = 0; j < 4; j++) {
5368       int iX = j >> 1;
5369       int iY = j & 1;
5370       xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda_ + j];
5371     }
5372   } else {
5373     if (xyRow_ >= 0) {
5374       const double *element = info->elementByColumn_;
5375       const int *row = info->row_;
5376       const CoinBigIndex *columnStart = info->columnStart_;
5377       const int *columnLength = info->columnLength_;
5378       for (j = 0; j < 4; j++) {
5379         int iColumn = firstLambda_ + j;
5380         CoinBigIndex iStart = columnStart[iColumn];
5381         CoinBigIndex iEnd = iStart + columnLength[iColumn];
5382         CoinBigIndex k = iStart;
5383         double sol = info->solution_[iColumn];
5384         for (; k < iEnd; k++) {
5385           if (xyRow_ == row[k])
5386             xyLambda += element[k] * sol;
5387         }
5388       }
5389     } else {
5390       // objective
5391       const double *objective = info->objective_;
5392       for (j = 0; j < 4; j++) {
5393         int iColumn = firstLambda_ + j;
5394         double sol = info->solution_[iColumn];
5395         xyLambda += objective[iColumn] * sol;
5396       }
5397     }
5398     xyLambda /= coefficient_;
5399   }
5400   if (0) {
5401     // only true with positive values
5402     // see if all convexification constraints OK with true
5403     assert(xyTrue + 1.0e-5 > xB[0] * y + yB[0] * x - xB[0] * yB[0]);
5404     assert(xyTrue + 1.0e-5 > xB[1] * y + yB[1] * x - xB[1] * yB[1]);
5405     assert(xyTrue - 1.0e-5 < xB[1] * y + yB[0] * x - xB[1] * yB[0]);
5406     assert(xyTrue - 1.0e-5 < xB[0] * y + yB[1] * x - xB[0] * yB[1]);
5407     // see if all convexification constraints OK with lambda version
5408 #ifndef JJF_ONE
5409     assert(xyLambda + 1.0e-5 > xB[0] * y + yB[0] * x - xB[0] * yB[0]);
5410     assert(xyLambda + 1.0e-5 > xB[1] * y + yB[1] * x - xB[1] * yB[1]);
5411     assert(xyLambda - 1.0e-5 < xB[1] * y + yB[0] * x - xB[1] * yB[0]);
5412     assert(xyLambda - 1.0e-5 < xB[0] * y + yB[1] * x - xB[0] * yB[1]);
5413 #endif
5414     // see if other bound stuff true
5415     assert(xyLambda + 1.0e-5 > xB[0] * y);
5416     assert(xyLambda + 1.0e-5 > yB[0] * x);
5417     assert(xyLambda - 1.0e-5 < xB[1] * y);
5418     assert(xyLambda - 1.0e-5 < yB[1] * x);
5419 #define SIZE 2
5420     if (yColumn_ == xColumn_ + SIZE) {
5421 #if SIZE == 6
5422       double bMax = 2200.0;
5423       double bMin = bMax - 100.0;
5424       double b[] = { 330.0, 360.0, 380.0, 430.0, 490.0, 530.0 };
5425 #elif SIZE == 2
5426       double bMax = 1900.0;
5427       double bMin = bMax - 200.0;
5428       double b[] = { 460.0, 570.0 };
5429 #else
5430       abort();
5431 #endif
5432       double sum = 0.0;
5433       double sum2 = 0.0;
5434       int m = xColumn_;
5435       double x = info->solution_[m];
5436       double xB[2];
5437       double yB[2];
5438       xB[0] = info->lower_[m];
5439       xB[1] = info->upper_[m];
5440       for (int i = 0; i < SIZE * SIZE; i += SIZE) {
5441         int n = i + SIZE + m;
5442         double y = info->solution_[n];
5443         yB[0] = info->lower_[n];
5444         yB[1] = info->upper_[n];
5445         int firstLambda = SIZE * SIZE + 2 * SIZE + 4 * i + 4 * m;
5446         double xyLambda = 0.0;
5447         for (int j = 0; j < 4; j++) {
5448           int iX = j >> 1;
5449           int iY = j & 1;
5450           xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda + j];
5451         }
5452         sum += xyLambda * b[i / SIZE];
5453         double xyTrue = x * y;
5454         sum2 += xyTrue * b[i / SIZE];
5455       }
5456       if (sum > bMax * x + 1.0e-5 || sum < bMin * x - 1.0e-5) {
5457         //if (sum<bMax*x+1.0e-5&&sum>bMin*x-1.0e-5) {
5458         printf("bmin*x %g b*w %g bmax*x %g (true) %g\n", bMin * x, sum, bMax * x, sum2);
5459         printf("m %d lb %g value %g up %g\n",
5460           m, xB[0], x, xB[1]);
5461         sum = 0.0;
5462         for (int i = 0; i < SIZE * SIZE; i += SIZE) {
5463           int n = i + SIZE + m;
5464           double y = info->solution_[n];
5465           yB[0] = info->lower_[n];
5466           yB[1] = info->upper_[n];
5467           printf("n %d lb %g value %g up %g\n",
5468             n, yB[0], y, yB[1]);
5469           int firstLambda = SIZE * SIZE + 2 * SIZE + 4 * i + m * 4;
5470           double xyLambda = 0.0;
5471           for (int j = 0; j < 4; j++) {
5472             int iX = j >> 1;
5473             int iY = j & 1;
5474             xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda + j];
5475             printf("j %d l %d new xylambda %g ", j, firstLambda + j, xyLambda);
5476           }
5477           sum += xyLambda * b[i / SIZE];
5478           printf(" - sum now %g\n", sum);
5479         }
5480       }
5481       if (sum2 > bMax * x + 1.0e-5 || sum2 < bMin * x - 1.0e-5) {
5482         printf("bmin*x %g b*x*y %g bmax*x %g (estimate) %g\n", bMin * x, sum2, bMax * x, sum);
5483         printf("m %d lb %g value %g up %g\n",
5484           m, xB[0], x, xB[1]);
5485         sum2 = 0.0;
5486         for (int i = 0; i < SIZE * SIZE; i += SIZE) {
5487           int n = i + SIZE + m;
5488           double y = info->solution_[n];
5489           yB[0] = info->lower_[n];
5490           yB[1] = info->upper_[n];
5491           printf("n %d lb %g value %g up %g\n",
5492             n, yB[0], y, yB[1]);
5493           double xyTrue = x * y;
5494           sum2 += xyTrue * b[i / SIZE];
5495           printf("xyTrue %g - sum now %g\n", xyTrue, sum2);
5496         }
5497       }
5498     }
5499   }
5500   // If pseudo shadow prices then see what would happen
5501   //double pseudoEstimate = 0.0;
5502   if (info->defaultDual_ >= 0.0) {
5503     // If we move to xy then we move by coefficient * (xyTrue-xyLambda) on row xyRow_
5504     double move = xyTrue - xyLambda;
5505     assert(xyRow_ >= 0);
5506     if (boundType_ == 0) {
5507       move *= coefficient_;
5508       move *= info->pi_[xyRow_];
5509       move = CoinMax(move, 0.0);
5510     } else if (boundType_ == 1) {
5511       // if OK then say satisfied
5512     } else if (boundType_ == 2) {
5513     } else {
5514       // == row so move x and y not xy
5515     }
5516   }
5517   if ((branchingStrategy_ & 16) != 0) {
5518     // always treat as satisfied!!
5519     xSatisfied = true;
5520     ySatisfied = true;
5521     xyTrue = xyLambda;
5522   }
5523   if (!xSatisfied) {
5524     if (!ySatisfied) {
5525       if ((branchingStrategy_ & 3) == 0) {
5526         // If pseudo shadow prices then see what would happen
5527         if (info->defaultDual_ >= 0.0) {
5528           // need coding here
5529           if (fabs(x - xNew) > fabs(y - yNew)) {
5530             chosen_ = 0;
5531             xyBranchValue_ = x;
5532           } else {
5533             chosen_ = 1;
5534             xyBranchValue_ = y;
5535           }
5536         } else {
5537           if (fabs(x - xNew) > fabs(y - yNew)) {
5538             chosen_ = 0;
5539             xyBranchValue_ = x;
5540           } else {
5541             chosen_ = 1;
5542             xyBranchValue_ = y;
5543           }
5544         }
5545       } else if ((branchingStrategy_ & 3) == 1) {
5546         chosen_ = 0;
5547         xyBranchValue_ = x;
5548       } else {
5549         chosen_ = 1;
5550         xyBranchValue_ = y;
5551       }
5552     } else {
5553       // y satisfied
5554       chosen_ = 0;
5555       xyBranchValue_ = x;
5556     }
5557   } else {
5558     // x satisfied
5559     if (!ySatisfied) {
5560       chosen_ = 1;
5561       xyBranchValue_ = y;
5562     } else {
5563       /*
5564             3 - both are satisfied but xy is not
5565             3a one has bounds within satisfied_ - other does not
5566             (or neither have but branching strategy tells us what to do)
5567             3b neither do - and branching strategy does not tell us
5568             3c both do - treat as feasible knowing another copy of object will fix
5569               4 - both are satisfied and xy is satisfied - as 3c
5570             */
5571       if (fabs(xyLambda - xyTrue) < xySatisfied_ || (xB[0] == xB[1] && yB[0] == yB[1])) {
5572         // satisfied
5573 #ifdef JJF_ZERO
5574         printf("all satisfied true %g lambda %g\n",
5575           xyTrue, xyLambda);
5576         printf("x %d (%g,%g,%g) y %d (%g,%g,%g)\n",
5577           xColumn_, xB[0], x, xB[1],
5578           yColumn_, yB[0], y, yB[1]);
5579 #endif
5580       } else {
5581         // May be infeasible - check
5582         bool feasible = true;
5583         if (xB[0] == xB[1] && yB[0] == yB[1]) {
5584           double lambda[4];
5585           computeLambdas(info->solver_, lambda);
5586           for (int j = 0; j < 4; j++) {
5587             int iColumn = firstLambda_ + j;
5588             if (info->lower_[iColumn] > lambda[j] + 1.0e-5 || info->upper_[iColumn] < lambda[j] - 1.0e-5)
5589               feasible = false;
5590           }
5591         }
5592         if (testCoarse && (branchingStrategy_ & 8) != 0 && xB[1] - xB[0] < 1.0001 * xSatisfied_ && yB[1] - yB[0] < 1.0001 * ySatisfied_)
5593           feasible = true;
5594         if (feasible) {
5595           if (xB[1] - xB[0] >= xSatisfied_ && xMeshSize_) {
5596             if (yB[1] - yB[0] >= ySatisfied_ && yMeshSize_) {
5597               if ((branchingStrategy_ & 3) == 0) {
5598                 // If pseudo shadow prices then see what would happen
5599                 if (info->defaultDual_ >= 0.0) {
5600                   // need coding here
5601                   if (xB[1] - xB[0] > yB[1] - yB[0]) {
5602                     chosen_ = 0;
5603                     xyBranchValue_ = 0.5 * (xB[0] + xB[1]);
5604                   } else {
5605                     chosen_ = 1;
5606                     xyBranchValue_ = 0.5 * (yB[0] + yB[1]);
5607                   }
5608                 } else {
5609                   if (xB[1] - xB[0] > yB[1] - yB[0]) {
5610                     chosen_ = 0;
5611                     xyBranchValue_ = 0.5 * (xB[0] + xB[1]);
5612                   } else {
5613                     chosen_ = 1;
5614                     xyBranchValue_ = 0.5 * (yB[0] + yB[1]);
5615                   }
5616                 }
5617               } else if ((branchingStrategy_ & 3) == 1) {
5618                 chosen_ = 0;
5619                 xyBranchValue_ = 0.5 * (xB[0] + xB[1]);
5620               } else {
5621                 chosen_ = 1;
5622                 xyBranchValue_ = 0.5 * (yB[0] + yB[1]);
5623               }
5624             } else {
5625               // y satisfied
5626               chosen_ = 0;
5627               xyBranchValue_ = 0.5 * (xB[0] + xB[1]);
5628             }
5629           } else if (yB[1] - yB[0] >= ySatisfied_ && yMeshSize_) {
5630             chosen_ = 1;
5631             xyBranchValue_ = 0.5 * (yB[0] + yB[1]);
5632           } else {
5633             // treat as satisfied unless no coefficient tightening
5634             if ((branchingStrategy_ & 4) != 0) {
5635               chosen_ = 0; // fix up in branch
5636               xyBranchValue_ = x;
5637             }
5638           }
5639         } else {
5640           // node not feasible!!!
5641           chosen_ = 0;
5642           infeasibility_ = COIN_DBL_MAX;
5643           otherInfeasibility_ = COIN_DBL_MAX;
5644           whichWay = whichWay_;
5645           return infeasibility_;
5646         }
5647       }
5648     }
5649   }
5650   if (chosen_ == -1) {
5651     infeasibility_ = 0.0;
5652   } else if (chosen_ == 0) {
5653     infeasibility_ = CoinMax(fabs(xyBranchValue_ - x), 1.0e-12);
5654     //assert (xyBranchValue_>=info->lower_[xColumn_]&&xyBranchValue_<=info->upper_[xColumn_]);
5655   } else {
5656     infeasibility_ = CoinMax(fabs(xyBranchValue_ - y), 1.0e-12);
5657     //assert (xyBranchValue_>=info->lower_[yColumn_]&&xyBranchValue_<=info->upper_[yColumn_]);
5658   }
5659   if (info->defaultDual_ < 0.0) {
5660     // not using pseudo shadow prices
5661     otherInfeasibility_ = 1.0 - infeasibility_;
5662   } else {
5663     abort();
5664   }
5665   if (infeasibility_) {
5666     bool fixed = true;
5667     for (int j = 0; j < 4; j++) {
5668       int iColumn = firstLambda_ + j;
5669       //if (info->lower_[iColumn]) printf("lower of %g on %d\n",info->lower_[iColumn],iColumn);
5670       if (info->lower_[iColumn] < info->upper_[iColumn])
5671         fixed = false;
5672     }
5673     if (fixed) {
5674       //printf("must be tolerance problem - xy true %g lambda %g\n",xyTrue,xyLambda);
5675       chosen_ = -1;
5676       infeasibility_ = 0.0;
5677     }
5678   }
5679   whichWay = whichWay_;
5680   //if (infeasibility_&&priority_==10)
5681   //printf("x %d %g %g %g, y %d %g %g %g\n",xColumn_,xB[0],x,xB[1],yColumn_,yB[0],y,yB[1]);
5682   return infeasibility_;
5683 }
5684 // Sets infeasibility and other when pseudo shadow prices
getPseudoShadow(const OsiBranchingInformation * info)5685 void OsiBiLinear::getPseudoShadow(const OsiBranchingInformation *info)
5686 {
5687   // order is LxLy, LxUy, UxLy and UxUy
5688   double xB[2];
5689   double yB[2];
5690   xB[0] = info->lower_[xColumn_];
5691   xB[1] = info->upper_[xColumn_];
5692   yB[0] = info->lower_[yColumn_];
5693   yB[1] = info->upper_[yColumn_];
5694   double x = info->solution_[xColumn_];
5695   x = CoinMax(x, xB[0]);
5696   x = CoinMin(x, xB[1]);
5697   double y = info->solution_[yColumn_];
5698   y = CoinMax(y, yB[0]);
5699   y = CoinMin(y, yB[1]);
5700   int j;
5701   double xyTrue = x * y;
5702   double xyLambda = 0.0;
5703   if ((branchingStrategy_ & 4) == 0) {
5704     for (j = 0; j < 4; j++) {
5705       int iX = j >> 1;
5706       int iY = j & 1;
5707       xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda_ + j];
5708     }
5709   } else {
5710     if (xyRow_ >= 0) {
5711       const double *element = info->elementByColumn_;
5712       const int *row = info->row_;
5713       const CoinBigIndex *columnStart = info->columnStart_;
5714       const int *columnLength = info->columnLength_;
5715       for (j = 0; j < 4; j++) {
5716         int iColumn = firstLambda_ + j;
5717         CoinBigIndex iStart = columnStart[iColumn];
5718         CoinBigIndex iEnd = iStart + columnLength[iColumn];
5719         CoinBigIndex k = iStart;
5720         double sol = info->solution_[iColumn];
5721         for (; k < iEnd; k++) {
5722           if (xyRow_ == row[k])
5723             xyLambda += element[k] * sol;
5724         }
5725       }
5726     } else {
5727       // objective
5728       const double *objective = info->objective_;
5729       for (j = 0; j < 4; j++) {
5730         int iColumn = firstLambda_ + j;
5731         double sol = info->solution_[iColumn];
5732         xyLambda += objective[iColumn] * sol;
5733       }
5734     }
5735     xyLambda /= coefficient_;
5736   }
5737   assert(info->defaultDual_ >= 0.0);
5738   // If we move to xy then we move by coefficient * (xyTrue-xyLambda) on row xyRow_
5739   double movement = xyTrue - xyLambda;
5740   infeasibility_ = 0.0;
5741   const double *pi = info->pi_;
5742   const double *activity = info->rowActivity_;
5743   const double *lower = info->rowLower_;
5744   const double *upper = info->rowUpper_;
5745   double tolerance = info->primalTolerance_;
5746   double direction = info->direction_;
5747   bool infeasible = false;
5748   if (xyRow_ >= 0) {
5749     assert(!boundType_);
5750     if (lower[xyRow_] < -1.0e20)
5751       assert(pi[xyRow_] <= 1.0e-3);
5752     if (upper[xyRow_] > 1.0e20)
5753       assert(pi[xyRow_] >= -1.0e-3);
5754     double valueP = pi[xyRow_] * direction;
5755     // if move makes infeasible then make at least default
5756     double newValue = activity[xyRow_] + movement * coefficient_;
5757     if (newValue > upper[xyRow_] + tolerance || newValue < lower[xyRow_] - tolerance) {
5758       infeasibility_ += fabs(movement * coefficient_) * CoinMax(fabs(valueP), info->defaultDual_);
5759       infeasible = true;
5760     }
5761   } else {
5762     // objective
5763     assert(movement > -1.0e-7);
5764     infeasibility_ += movement;
5765   }
5766   for (int i = 0; i < numberExtraRows_; i++) {
5767     int iRow = extraRow_[i];
5768     if (lower[iRow] < -1.0e20)
5769       assert(pi[iRow] <= 1.0e-3);
5770     if (upper[iRow] > 1.0e20)
5771       assert(pi[iRow] >= -1.0e-3);
5772     double valueP = pi[iRow] * direction;
5773     // if move makes infeasible then make at least default
5774     double newValue = activity[iRow] + movement * multiplier_[i];
5775     if (newValue > upper[iRow] + tolerance || newValue < lower[iRow] - tolerance) {
5776       infeasibility_ += fabs(movement * multiplier_[i]) * CoinMax(fabs(valueP), info->defaultDual_);
5777       infeasible = true;
5778     }
5779   }
5780   if (infeasibility_ < info->integerTolerance_) {
5781     if (!infeasible)
5782       infeasibility_ = 0.0;
5783     else
5784       infeasibility_ = info->integerTolerance_;
5785   }
5786   otherInfeasibility_ = CoinMax(1.0e-12, infeasibility_ * 10.0);
5787 }
5788 // Gets sum of movements to correct value
5789 double
getMovement(const OsiBranchingInformation * info)5790 OsiBiLinear::getMovement(const OsiBranchingInformation *info)
5791 {
5792   // order is LxLy, LxUy, UxLy and UxUy
5793   double xB[2];
5794   double yB[2];
5795   xB[0] = info->lower_[xColumn_];
5796   xB[1] = info->upper_[xColumn_];
5797   yB[0] = info->lower_[yColumn_];
5798   yB[1] = info->upper_[yColumn_];
5799   double x = info->solution_[xColumn_];
5800   x = CoinMax(x, xB[0]);
5801   x = CoinMin(x, xB[1]);
5802   double y = info->solution_[yColumn_];
5803   y = CoinMax(y, yB[0]);
5804   y = CoinMin(y, yB[1]);
5805   int j;
5806   double xyTrue = x * y;
5807   double xyLambda = 0.0;
5808   if ((branchingStrategy_ & 4) == 0) {
5809     for (j = 0; j < 4; j++) {
5810       int iX = j >> 1;
5811       int iY = j & 1;
5812       xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda_ + j];
5813     }
5814   } else {
5815     if (xyRow_ >= 0) {
5816       const double *element = info->elementByColumn_;
5817       const int *row = info->row_;
5818       const CoinBigIndex *columnStart = info->columnStart_;
5819       const int *columnLength = info->columnLength_;
5820       for (j = 0; j < 4; j++) {
5821         int iColumn = firstLambda_ + j;
5822         CoinBigIndex iStart = columnStart[iColumn];
5823         CoinBigIndex iEnd = iStart + columnLength[iColumn];
5824         CoinBigIndex k = iStart;
5825         double sol = info->solution_[iColumn];
5826         for (; k < iEnd; k++) {
5827           if (xyRow_ == row[k])
5828             xyLambda += element[k] * sol;
5829         }
5830       }
5831     } else {
5832       // objective
5833       const double *objective = info->objective_;
5834       for (j = 0; j < 4; j++) {
5835         int iColumn = firstLambda_ + j;
5836         double sol = info->solution_[iColumn];
5837         xyLambda += objective[iColumn] * sol;
5838       }
5839     }
5840     xyLambda /= coefficient_;
5841   }
5842   // If we move to xy then we move by coefficient * (xyTrue-xyLambda) on row xyRow_
5843   double movement = xyTrue - xyLambda;
5844   double mesh = CoinMax(xMeshSize_, yMeshSize_);
5845   if (fabs(movement) < xySatisfied_ && (xB[1] - xB[0] < mesh || yB[1] - yB[0] < mesh))
5846     return 0.0; // say feasible
5847   const double *activity = info->rowActivity_;
5848   const double *lower = info->rowLower_;
5849   const double *upper = info->rowUpper_;
5850   double tolerance = info->primalTolerance_;
5851   double infeasibility = 0.0;
5852   if (xyRow_ >= 0) {
5853     assert(!boundType_);
5854     // if move makes infeasible
5855     double newValue = activity[xyRow_] + movement * coefficient_;
5856     if (newValue > upper[xyRow_] + tolerance)
5857       infeasibility += newValue - upper[xyRow_];
5858     else if (newValue < lower[xyRow_] - tolerance)
5859       infeasibility += lower[xyRow_] - newValue;
5860   } else {
5861     // objective
5862     assert(movement > -1.0e-7);
5863     infeasibility += movement;
5864   }
5865   for (int i = 0; i < numberExtraRows_; i++) {
5866     int iRow = extraRow_[i];
5867     // if move makes infeasible
5868     double newValue = activity[iRow] + movement * multiplier_[i];
5869     if (newValue > upper[iRow] + tolerance)
5870       infeasibility += newValue - upper[iRow];
5871     else if (newValue < lower[iRow] - tolerance)
5872       infeasibility += lower[iRow] - newValue;
5873   }
5874   return infeasibility;
5875 }
5876 // This looks at solution and sets bounds to contain solution
5877 double
feasibleRegion(OsiSolverInterface * solver,const OsiBranchingInformation * info) const5878 OsiBiLinear::feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const
5879 {
5880   // If another object has finer mesh ignore this
5881   if ((branchingStrategy_ & 8) != 0)
5882     return 0.0;
5883   // order is LxLy, LxUy, UxLy and UxUy
5884   double xB[2];
5885   double yB[2];
5886   xB[0] = info->lower_[xColumn_];
5887   xB[1] = info->upper_[xColumn_];
5888   yB[0] = info->lower_[yColumn_];
5889   yB[1] = info->upper_[yColumn_];
5890   double x = info->solution_[xColumn_];
5891   double y = info->solution_[yColumn_];
5892   int j;
5893 #ifndef NDEBUG
5894   double xLambda = 0.0;
5895   double yLambda = 0.0;
5896   if ((branchingStrategy_ & 4) == 0) {
5897     for (j = 0; j < 4; j++) {
5898       int iX = j >> 1;
5899       int iY = j & 1;
5900       xLambda += xB[iX] * info->solution_[firstLambda_ + j];
5901       if (yRow_ >= 0)
5902         yLambda += yB[iY] * info->solution_[firstLambda_ + j];
5903     }
5904   } else {
5905     const double *element = info->elementByColumn_;
5906     const int *row = info->row_;
5907     const CoinBigIndex *columnStart = info->columnStart_;
5908     const int *columnLength = info->columnLength_;
5909     for (j = 0; j < 4; j++) {
5910       int iColumn = firstLambda_ + j;
5911       CoinBigIndex iStart = columnStart[iColumn];
5912       CoinBigIndex iEnd = iStart + columnLength[iColumn];
5913       CoinBigIndex k = iStart;
5914       double sol = info->solution_[iColumn];
5915       for (; k < iEnd; k++) {
5916         if (xRow_ == row[k])
5917           xLambda += element[k] * sol;
5918         if (yRow_ == row[k])
5919           yLambda += element[k] * sol;
5920       }
5921     }
5922   }
5923   if (yRow_ < 0)
5924     yLambda = xLambda;
5925 #ifdef JJF_ZERO
5926   if (fabs(x - xLambda) > 1.0e-4 || fabs(y - yLambda) > 1.0e-4)
5927     printf("feasibleregion x %d given %g lambda %g y %d given %g lambda %g\n",
5928       xColumn_, x, xLambda,
5929       yColumn_, y, yLambda);
5930 #endif
5931 #endif
5932   double infeasibility = 0.0;
5933   double distance;
5934   double steps;
5935   double xNew = x;
5936   if (xMeshSize_) {
5937     distance = x - xB[0];
5938     if (x < 0.5 * (xB[0] + xB[1])) {
5939       distance = x - xB[0];
5940       steps = floor((distance + 0.5 * xMeshSize_) / xMeshSize_);
5941       xNew = xB[0] + steps * xMeshSize_;
5942       assert(xNew <= xB[1] + xSatisfied_);
5943     } else {
5944       distance = xB[1] - x;
5945       steps = floor((distance + 0.5 * xMeshSize_) / xMeshSize_);
5946       xNew = xB[1] - steps * xMeshSize_;
5947       assert(xNew >= xB[0] - xSatisfied_);
5948     }
5949     if (xMeshSize_ < 1.0 && fabs(xNew - x) <= xSatisfied_) {
5950       double lo = CoinMax(xB[0], x - 0.5 * xSatisfied_);
5951       double up = CoinMin(xB[1], x + 0.5 * xSatisfied_);
5952       solver->setColLower(xColumn_, lo);
5953       solver->setColUpper(xColumn_, up);
5954     } else {
5955       infeasibility += fabs(xNew - x);
5956       solver->setColLower(xColumn_, xNew);
5957       solver->setColUpper(xColumn_, xNew);
5958     }
5959   }
5960   double yNew = y;
5961   if (yMeshSize_) {
5962     distance = y - yB[0];
5963     if (y < 0.5 * (yB[0] + yB[1])) {
5964       distance = y - yB[0];
5965       steps = floor((distance + 0.5 * yMeshSize_) / yMeshSize_);
5966       yNew = yB[0] + steps * yMeshSize_;
5967       assert(yNew <= yB[1] + ySatisfied_);
5968     } else {
5969       distance = yB[1] - y;
5970       steps = floor((distance + 0.5 * yMeshSize_) / yMeshSize_);
5971       yNew = yB[1] - steps * yMeshSize_;
5972       assert(yNew >= yB[0] - ySatisfied_);
5973     }
5974     if (yMeshSize_ < 1.0 && fabs(yNew - y) <= ySatisfied_) {
5975       double lo = CoinMax(yB[0], y - 0.5 * ySatisfied_);
5976       double up = CoinMin(yB[1], y + 0.5 * ySatisfied_);
5977       solver->setColLower(yColumn_, lo);
5978       solver->setColUpper(yColumn_, up);
5979     } else {
5980       infeasibility += fabs(yNew - y);
5981       solver->setColLower(yColumn_, yNew);
5982       solver->setColUpper(yColumn_, yNew);
5983     }
5984   }
5985   if (0) {
5986     // temp
5987     solver->setColLower(xColumn_, x);
5988     solver->setColUpper(xColumn_, x);
5989     solver->setColLower(yColumn_, y);
5990     solver->setColUpper(yColumn_, y);
5991   }
5992   if ((branchingStrategy_ & 4)) {
5993     // fake to make correct
5994     double lambda[4];
5995     computeLambdas(solver, lambda);
5996     for (int j = 0; j < 4; j++) {
5997       int iColumn = firstLambda_ + j;
5998       double value = lambda[j];
5999       solver->setColLower(iColumn, value);
6000       solver->setColUpper(iColumn, value);
6001     }
6002   }
6003   double xyTrue = xNew * yNew;
6004   double xyLambda = 0.0;
6005   for (j = 0; j < 4; j++) {
6006     int iX = j >> 1;
6007     int iY = j & 1;
6008     xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda_ + j];
6009   }
6010   infeasibility += fabs(xyTrue - xyLambda);
6011   return infeasibility;
6012 }
6013 // Returns true value of single xyRow coefficient
6014 double
xyCoefficient(const double * solution) const6015 OsiBiLinear::xyCoefficient(const double *solution) const
6016 {
6017   // If another object has finer mesh ignore this
6018   if ((branchingStrategy_ & 8) != 0)
6019     return 0.0;
6020   double x = solution[xColumn_];
6021   double y = solution[yColumn_];
6022   //printf("x (%d,%g) y (%d,%g) x*y*coefficient %g\n",
6023   // xColumn_,x,yColumn_,y,x*y*coefficient_);
6024   return x * y * coefficient_;
6025 }
6026 
6027 // Redoes data when sequence numbers change
resetSequenceEtc(int numberColumns,const int * originalColumns)6028 void OsiBiLinear::resetSequenceEtc(int numberColumns, const int *originalColumns)
6029 {
6030   int i;
6031 #ifdef JJF_ZERO
6032   for (i = 0; i < numberColumns; i++) {
6033     if (originalColumns[i] == firstLambda_)
6034       break;
6035   }
6036 #else
6037   i = originalColumns[firstLambda_];
6038 #endif
6039   if (i >= 0 && i < numberColumns) {
6040     firstLambda_ = i;
6041     for (int j = 0; j < 4; j++) {
6042       assert(originalColumns[j + i] - firstLambda_ == j);
6043     }
6044   } else {
6045     printf("lost set\n");
6046     abort();
6047   }
6048   // rows will be out anyway
6049   abort();
6050 }
6051 
6052 // Creates a branching object
6053 OsiBranchingObject *
createBranch(OsiSolverInterface * solver,const OsiBranchingInformation *,int way) const6054 OsiBiLinear::createBranch(OsiSolverInterface *solver, const OsiBranchingInformation * /*info*/, int way) const
6055 {
6056   // create object
6057   OsiBranchingObject *branch;
6058   assert(chosen_ == 0 || chosen_ == 1);
6059   //if (chosen_==0)
6060   //assert (xyBranchValue_>=info->lower_[xColumn_]&&xyBranchValue_<=info->upper_[xColumn_]);
6061   //else
6062   //assert (xyBranchValue_>=info->lower_[yColumn_]&&xyBranchValue_<=info->upper_[yColumn_]);
6063   branch = new OsiBiLinearBranchingObject(solver, this, way, xyBranchValue_, chosen_);
6064   return branch;
6065 }
6066 // Does work of branching
newBounds(OsiSolverInterface * solver,int way,short xOrY,double separator) const6067 void OsiBiLinear::newBounds(OsiSolverInterface *solver, int way, short xOrY, double separator) const
6068 {
6069   int iColumn;
6070   double mesh;
6071   double satisfied;
6072   if (xOrY == 0) {
6073     iColumn = xColumn_;
6074     mesh = xMeshSize_;
6075     satisfied = xSatisfied_;
6076   } else {
6077     iColumn = yColumn_;
6078     mesh = yMeshSize_;
6079     satisfied = ySatisfied_;
6080   }
6081   const double *columnLower = solver->getColLower();
6082   const double *columnUpper = solver->getColUpper();
6083   double lower = columnLower[iColumn];
6084   double distance;
6085   double steps;
6086   double zNew = separator;
6087   distance = separator - lower;
6088   assert(mesh);
6089   steps = floor((distance + 0.5 * mesh) / mesh);
6090   if (mesh < 1.0)
6091     zNew = lower + steps * mesh;
6092   if (zNew > columnUpper[iColumn] - satisfied)
6093     zNew = 0.5 * (columnUpper[iColumn] - lower);
6094   double oldUpper = columnUpper[iColumn];
6095   double oldLower = columnLower[iColumn];
6096 #ifndef NDEBUG
6097   int nullChange = 0;
6098 #endif
6099   if (way < 0) {
6100     if (zNew > separator && mesh < 1.0)
6101       zNew -= mesh;
6102     double oldUpper = columnUpper[iColumn];
6103     if (zNew + satisfied >= oldUpper)
6104       zNew = 0.5 * (oldUpper + oldLower);
6105     if (mesh == 1.0)
6106       zNew = floor(separator);
6107 #ifndef NDEBUG
6108     if (oldUpper < zNew + 1.0e-8)
6109       nullChange = -1;
6110 #endif
6111     solver->setColUpper(iColumn, zNew);
6112   } else {
6113     if (zNew < separator && mesh < 1.0)
6114       zNew += mesh;
6115     if (zNew - satisfied <= oldLower)
6116       zNew = 0.5 * (oldUpper + oldLower);
6117     if (mesh == 1.0)
6118       zNew = ceil(separator);
6119 #ifndef NDEBUG
6120     if (oldLower > zNew - 1.0e-8)
6121       nullChange = 1;
6122 #endif
6123     solver->setColLower(iColumn, zNew);
6124   }
6125   if ((branchingStrategy_ & 4) != 0
6126     && columnLower[xColumn_] == columnUpper[xColumn_]
6127     && columnLower[yColumn_] == columnUpper[yColumn_]) {
6128     // fake to make correct
6129     double lambda[4];
6130     computeLambdas(solver, lambda);
6131     for (int j = 0; j < 4; j++) {
6132       int iColumn = firstLambda_ + j;
6133       double value = lambda[j];
6134 #ifndef NDEBUG
6135       if (fabs(value - columnLower[iColumn]) > 1.0e-5 || fabs(value - columnUpper[iColumn]) > 1.0e-5)
6136         nullChange = 0;
6137 #endif
6138       solver->setColLower(iColumn, value);
6139       solver->setColUpper(iColumn, value);
6140     }
6141   }
6142 #ifndef NDEBUG
6143   if (nullChange)
6144     printf("null change on column%s %d - bounds %g,%g\n", nullChange > 0 ? "Lower" : "Upper",
6145       iColumn, oldLower, oldUpper);
6146 #endif
6147 #ifdef JJF_ZERO
6148   // always free up lambda
6149   for (int i = firstLambda_; i < firstLambda_ + 4; i++) {
6150     solver->setColLower(i, 0.0);
6151     solver->setColUpper(i, 2.0);
6152   }
6153 #endif
6154   double xB[3];
6155   xB[0] = columnLower[xColumn_];
6156   xB[1] = columnUpper[xColumn_];
6157   double yB[3];
6158   yB[0] = columnLower[yColumn_];
6159   yB[1] = columnUpper[yColumn_];
6160   if (false && (branchingStrategy_ & 4) != 0 && yRow_ >= 0 && xMeshSize_ == 1.0 && yMeshSize_ == 1.0) {
6161     if ((xB[1] - xB[0]) * (yB[1] - yB[0]) < 40) {
6162       // try looking at all solutions
6163       double lower[4];
6164       double upper[4];
6165       double lambda[4];
6166       int i;
6167       double lowerLambda[4];
6168       double upperLambda[4];
6169       for (i = 0; i < 4; i++) {
6170         lower[i] = CoinMax(0.0, columnLower[firstLambda_ + i]);
6171         upper[i] = CoinMin(1.0, columnUpper[firstLambda_ + i]);
6172         lowerLambda[i] = 1.0;
6173         upperLambda[i] = 0.0;
6174       }
6175       // get coefficients
6176       double xybar[4];
6177       getCoefficients(solver, xB, yB, xybar);
6178       double x, y;
6179       for (x = xB[0]; x <= xB[1]; x++) {
6180         xB[2] = x;
6181         for (y = yB[0]; y <= yB[1]; y++) {
6182           yB[2] = y;
6183           computeLambdas(xB, yB, xybar, lambda);
6184           for (i = 0; i < 4; i++) {
6185             lowerLambda[i] = CoinMin(lowerLambda[i], lambda[i]);
6186             upperLambda[i] = CoinMax(upperLambda[i], lambda[i]);
6187           }
6188         }
6189       }
6190       double change = 0.0;
6191       ;
6192       for (i = 0; i < 4; i++) {
6193         if (lowerLambda[i] > lower[i] + 1.0e-12) {
6194           solver->setColLower(firstLambda_ + i, lowerLambda[i]);
6195           change += lowerLambda[i] - lower[i];
6196         }
6197         if (upperLambda[i] < upper[i] - 1.0e-12) {
6198           solver->setColUpper(firstLambda_ + i, upperLambda[i]);
6199           change -= upperLambda[i] - upper[i];
6200         }
6201       }
6202       if (change > 1.0e-5)
6203         printf("change of %g\n", change);
6204     }
6205   }
6206   if (boundType_) {
6207     assert(!xMeshSize_ || !yMeshSize_);
6208     if (xMeshSize_) {
6209       // can tighten bounds on y
6210       if ((boundType_ & 1) != 0) {
6211         if (xB[0] * yB[1] > coefficient_) {
6212           // tighten upper bound on y
6213           solver->setColUpper(yColumn_, coefficient_ / xB[0]);
6214         }
6215       }
6216       if ((boundType_ & 2) != 0) {
6217         if (xB[1] * yB[0] < coefficient_) {
6218           // tighten lower bound on y
6219           solver->setColLower(yColumn_, coefficient_ / xB[1]);
6220         }
6221       }
6222     } else {
6223       // can tighten bounds on x
6224       if ((boundType_ & 1) != 0) {
6225         if (yB[0] * xB[1] > coefficient_) {
6226           // tighten upper bound on x
6227           solver->setColUpper(xColumn_, coefficient_ / yB[0]);
6228         }
6229       }
6230       if ((boundType_ & 2) != 0) {
6231         if (yB[1] * xB[0] < coefficient_) {
6232           // tighten lower bound on x
6233           solver->setColLower(xColumn_, coefficient_ / yB[1]);
6234         }
6235       }
6236     }
6237   }
6238 }
6239 // Compute lambdas if coefficients not changing
computeLambdas(const OsiSolverInterface * solver,double lambda[4]) const6240 void OsiBiLinear::computeLambdas(const OsiSolverInterface *solver, double lambda[4]) const
6241 {
6242   // fix so correct
6243   double xB[3], yB[3];
6244   double xybar[4];
6245   getCoefficients(solver, xB, yB, xybar);
6246   double x, y;
6247   x = solver->getColLower()[xColumn_];
6248   assert(x == solver->getColUpper()[xColumn_]);
6249   xB[2] = x;
6250   y = solver->getColLower()[yColumn_];
6251   assert(y == solver->getColUpper()[yColumn_]);
6252   yB[2] = y;
6253   computeLambdas(xB, yB, xybar, lambda);
6254   assert(xyRow_ >= 0);
6255 }
6256 // Get LU coefficients from matrix
getCoefficients(const OsiSolverInterface * solver,double xB[2],double yB[2],double xybar[4]) const6257 void OsiBiLinear::getCoefficients(const OsiSolverInterface *solver, double xB[2], double yB[2],
6258   double xybar[4]) const
6259 {
6260   const CoinPackedMatrix *matrix = solver->getMatrixByCol();
6261   const double *element = matrix->getElements();
6262   const double *objective = solver->getObjCoefficients();
6263   const int *row = matrix->getIndices();
6264   const CoinBigIndex *columnStart = matrix->getVectorStarts();
6265   const int *columnLength = matrix->getVectorLengths();
6266   // order is LxLy, LxUy, UxLy and UxUy
6267   int j;
6268   double multiplier = (boundType_ == 0) ? 1.0 / coefficient_ : 1.0;
6269   if (yRow_ >= 0) {
6270     for (j = 0; j < 4; j++) {
6271       int iColumn = firstLambda_ + j;
6272       CoinBigIndex iStart = columnStart[iColumn];
6273       CoinBigIndex iEnd = iStart + columnLength[iColumn];
6274       CoinBigIndex k = iStart;
6275       double x = 0.0;
6276       double y = 0.0;
6277       xybar[j] = 0.0;
6278       for (; k < iEnd; k++) {
6279         if (xRow_ == row[k])
6280           x = element[k];
6281         if (yRow_ == row[k])
6282           y = element[k];
6283         if (xyRow_ == row[k])
6284           xybar[j] = element[k] * multiplier;
6285       }
6286       if (xyRow_ < 0)
6287         xybar[j] = objective[iColumn] * multiplier;
6288       if (j == 0)
6289         xB[0] = x;
6290       else if (j == 1)
6291         yB[1] = y;
6292       else if (j == 2)
6293         yB[0] = y;
6294       else if (j == 3)
6295         xB[1] = x;
6296       assert(fabs(xybar[j] - x * y) < 1.0e-4);
6297     }
6298   } else {
6299     // x==y
6300     for (j = 0; j < 4; j++) {
6301       int iColumn = firstLambda_ + j;
6302       CoinBigIndex iStart = columnStart[iColumn];
6303       CoinBigIndex iEnd = iStart + columnLength[iColumn];
6304       CoinBigIndex k = iStart;
6305       double x = 0.0;
6306       xybar[j] = 0.0;
6307       for (; k < iEnd; k++) {
6308         if (xRow_ == row[k])
6309           x = element[k];
6310         if (xyRow_ == row[k])
6311           xybar[j] = element[k] * multiplier;
6312       }
6313       if (xyRow_ < 0)
6314         xybar[j] = objective[iColumn] * multiplier;
6315       if (j == 0) {
6316         xB[0] = x;
6317         yB[0] = x;
6318       } else if (j == 2) {
6319         xB[1] = x;
6320         yB[1] = x;
6321       }
6322     }
6323     assert(fabs(xybar[0] - xB[0] * yB[0]) < 1.0e-4);
6324     assert(fabs(xybar[1] - xB[0] * yB[1]) < 1.0e-4);
6325     assert(fabs(xybar[2] - xB[1] * yB[0]) < 1.0e-4);
6326     assert(fabs(xybar[3] - xB[1] * yB[1]) < 1.0e-4);
6327   }
6328 }
6329 // Compute lambdas (third entry in each .B is current value)
6330 double
computeLambdas(const double xB[3],const double yB[3],const double xybar[4],double lambda[4]) const6331 OsiBiLinear::computeLambdas(const double xB[3], const double yB[3], const double xybar[4], double lambda[4]) const
6332 {
6333   // fake to make correct
6334   double x = xB[2];
6335   double y = yB[2];
6336   // order is LxLy, LxUy, UxLy and UxUy
6337   // l0 + l1 = this
6338   double rhs1 = (xB[1] - x) / (xB[1] - xB[0]);
6339   // l0 + l2 = this
6340   double rhs2 = (yB[1] - y) / (yB[1] - yB[0]);
6341   // For xy (taking out l3)
6342   double rhs3 = xB[1] * yB[1] - x * y;
6343   double a0 = xB[1] * yB[1] - xB[0] * yB[0];
6344   double a1 = xB[1] * yB[1] - xB[0] * yB[1];
6345   double a2 = xB[1] * yB[1] - xB[1] * yB[0];
6346   // divide through to get l0 coefficient
6347   rhs3 /= a0;
6348   a1 /= a0;
6349   a2 /= a0;
6350   // subtract out l0
6351   double b[2][2];
6352   double rhs[2];
6353   // first for l1 and l2
6354   b[0][0] = 1.0 - a1;
6355   b[0][1] = -a2;
6356   rhs[0] = rhs1 - rhs3;
6357   // second
6358   b[1][0] = -a1;
6359   b[1][1] = 1.0 - a2;
6360   rhs[1] = rhs2 - rhs3;
6361   if (fabs(b[0][0]) > fabs(b[0][1])) {
6362     double sub = b[1][0] / b[0][0];
6363     b[1][1] -= sub * b[0][1];
6364     rhs[1] -= sub * rhs[0];
6365     assert(fabs(b[1][1]) > 1.0e-12);
6366     lambda[2] = rhs[1] / b[1][1];
6367     lambda[0] = rhs2 - lambda[2];
6368     lambda[1] = rhs1 - lambda[0];
6369   } else {
6370     double sub = b[1][1] / b[0][1];
6371     b[1][0] -= sub * b[0][0];
6372     rhs[1] -= sub * rhs[0];
6373     assert(fabs(b[1][0]) > 1.0e-12);
6374     lambda[1] = rhs[1] / b[1][0];
6375     lambda[0] = rhs1 - lambda[1];
6376     lambda[2] = rhs2 - lambda[0];
6377   }
6378   lambda[3] = 1.0 - (lambda[0] + lambda[1] + lambda[2]);
6379   double infeasibility = 0.0;
6380   double xy = 0.0;
6381   for (int j = 0; j < 4; j++) {
6382     double value = lambda[j];
6383     if (value > 1.0) {
6384       infeasibility += value - 1.0;
6385       value = 1.0;
6386     }
6387     if (value < 0.0) {
6388       infeasibility -= value;
6389       value = 0.0;
6390     }
6391     lambda[j] = value;
6392     xy += xybar[j] * value;
6393   }
6394   assert(fabs(xy - x * y) < 1.0e-4);
6395   return infeasibility;
6396 }
6397 // Updates coefficients
updateCoefficients(const double * lower,const double * upper,double * objective,CoinPackedMatrix * matrix,CoinWarmStartBasis * basis) const6398 int OsiBiLinear::updateCoefficients(const double *lower, const double *upper, double *objective,
6399   CoinPackedMatrix *matrix, CoinWarmStartBasis *basis) const
6400 {
6401   // Return if no updates
6402   if ((branchingStrategy_ & 4) != 0)
6403     return 0;
6404   int numberUpdated = 0;
6405   double *element = matrix->getMutableElements();
6406   const int *row = matrix->getIndices();
6407   const CoinBigIndex *columnStart = matrix->getVectorStarts();
6408   const int *columnLength = matrix->getVectorLengths();
6409   // order is LxLy, LxUy, UxLy and UxUy
6410   double xB[2];
6411   double yB[2];
6412   xB[0] = lower[xColumn_];
6413   xB[1] = upper[xColumn_];
6414   yB[0] = lower[yColumn_];
6415   yB[1] = upper[yColumn_];
6416   //printf("x %d (%g,%g) y %d (%g,%g)\n",
6417   // xColumn_,xB[0],xB[1],
6418   // yColumn_,yB[0],yB[1]);
6419   CoinWarmStartBasis::Status status[4];
6420   int numStruct = basis ? basis->getNumStructural() - firstLambda_ : 0;
6421   double coefficient = (boundType_ == 0) ? coefficient_ : 1.0;
6422   for (int j = 0; j < 4; j++) {
6423     status[j] = (j < numStruct) ? basis->getStructStatus(j + firstLambda_) : CoinWarmStartBasis::atLowerBound;
6424     int iX = j >> 1;
6425     double x = xB[iX];
6426     int iY = j & 1;
6427     double y = yB[iY];
6428     CoinBigIndex k = columnStart[j + firstLambda_];
6429     CoinBigIndex last = k + columnLength[j + firstLambda_];
6430     double value;
6431     // xy
6432     value = coefficient * x * y;
6433     if (xyRow_ >= 0) {
6434       assert(row[k] == xyRow_);
6435 #if BI_PRINT > 1
6436       printf("j %d xy (%d,%d) coeff from %g to %g\n", j, xColumn_, yColumn_, element[k], value);
6437 #endif
6438       element[k++] = value;
6439     } else {
6440       // objective
6441       objective[j + firstLambda_] = value;
6442     }
6443     numberUpdated++;
6444     // convexity
6445     assert(row[k] == convexity_);
6446     k++;
6447     // x
6448     value = x;
6449 #if BI_PRINT > 1
6450     printf("j %d x (%d) coeff from %g to %g\n", j, xColumn_, element[k], value);
6451 #endif
6452     assert(row[k] == xRow_);
6453     element[k++] = value;
6454     numberUpdated++;
6455     if (yRow_ >= 0) {
6456       // y
6457       value = y;
6458 #if BI_PRINT > 1
6459       printf("j %d y (%d) coeff from %g to %g\n", j, yColumn_, element[k], value);
6460 #endif
6461       assert(row[k] == yRow_);
6462       element[k++] = value;
6463       numberUpdated++;
6464     }
6465     // Do extra rows
6466     for (int i = 0; i < numberExtraRows_; i++) {
6467       int iRow = extraRow_[i];
6468       for (; k < last; k++) {
6469         if (row[k] == iRow)
6470           break;
6471       }
6472       assert(k < last);
6473       element[k++] = x * y * multiplier_[i];
6474     }
6475   }
6476 
6477   if (xB[0] == xB[1]) {
6478     if (yB[0] == yB[1]) {
6479       // only one basic
6480       bool first = true;
6481       for (int j = 0; j < 4; j++) {
6482         if (status[j] == CoinWarmStartBasis::basic) {
6483           if (first) {
6484             first = false;
6485           } else {
6486             basis->setStructStatus(j + firstLambda_, CoinWarmStartBasis::atLowerBound);
6487 #if BI_PRINT
6488             printf("zapping %d (x=%d,y=%d)\n", j, xColumn_, yColumn_);
6489 #endif
6490           }
6491         }
6492       }
6493     } else {
6494       if (status[0] == CoinWarmStartBasis::basic && status[2] == CoinWarmStartBasis::basic) {
6495         basis->setStructStatus(2 + firstLambda_, CoinWarmStartBasis::atLowerBound);
6496 #if BI_PRINT
6497         printf("zapping %d (x=%d,y=%d)\n", 2, xColumn_, yColumn_);
6498 #endif
6499       }
6500       if (status[1] == CoinWarmStartBasis::basic && status[3] == CoinWarmStartBasis::basic) {
6501         basis->setStructStatus(3 + firstLambda_, CoinWarmStartBasis::atLowerBound);
6502 #if BI_PRINT
6503         printf("zapping %d (x=%d,y=%d)\n", 3, xColumn_, yColumn_);
6504 #endif
6505       }
6506     }
6507   } else if (yB[0] == yB[1]) {
6508     if (status[0] == CoinWarmStartBasis::basic && status[1] == CoinWarmStartBasis::basic) {
6509       basis->setStructStatus(1 + firstLambda_, CoinWarmStartBasis::atLowerBound);
6510 #if BI_PRINT
6511       printf("zapping %d (x=%d,y=%d)\n", 1, xColumn_, yColumn_);
6512 #endif
6513     }
6514     if (status[2] == CoinWarmStartBasis::basic && status[3] == CoinWarmStartBasis::basic) {
6515       basis->setStructStatus(3 + firstLambda_, CoinWarmStartBasis::atLowerBound);
6516 #if BI_PRINT
6517       printf("zapping %d (x=%d,y=%d)\n", 3, xColumn_, yColumn_);
6518 #endif
6519     }
6520   }
6521   return numberUpdated;
6522 }
6523 // This does NOT set mutable stuff
6524 double
checkInfeasibility(const OsiBranchingInformation * info) const6525 OsiBiLinear::checkInfeasibility(const OsiBranchingInformation *info) const
6526 {
6527   // If another object has finer mesh ignore this
6528   if ((branchingStrategy_ & 8) != 0)
6529     return 0.0;
6530   int way;
6531   double saveInfeasibility = infeasibility_;
6532   short int saveWhichWay = whichWay_;
6533   double saveXyBranchValue = xyBranchValue_;
6534   short saveChosen = chosen_;
6535   double value = infeasibility(info, way);
6536   infeasibility_ = saveInfeasibility;
6537   whichWay_ = saveWhichWay;
6538   xyBranchValue_ = saveXyBranchValue;
6539   chosen_ = saveChosen;
6540   return value;
6541 }
OsiBiLinearBranchingObject()6542 OsiBiLinearBranchingObject::OsiBiLinearBranchingObject()
6543   : OsiTwoWayBranchingObject()
6544   , chosen_(0)
6545 {
6546 }
6547 
6548 // Useful constructor
OsiBiLinearBranchingObject(OsiSolverInterface * solver,const OsiBiLinear * set,int way,double separator,int chosen)6549 OsiBiLinearBranchingObject::OsiBiLinearBranchingObject(OsiSolverInterface *solver,
6550   const OsiBiLinear *set,
6551   int way,
6552   double separator,
6553   int chosen)
6554   : OsiTwoWayBranchingObject(solver, set, way, separator)
6555   , chosen_(static_cast< short int >(chosen))
6556 {
6557   assert(chosen_ >= 0 && chosen_ < 2);
6558 }
6559 
6560 // Copy constructor
OsiBiLinearBranchingObject(const OsiBiLinearBranchingObject & rhs)6561 OsiBiLinearBranchingObject::OsiBiLinearBranchingObject(const OsiBiLinearBranchingObject &rhs)
6562   : OsiTwoWayBranchingObject(rhs)
6563   , chosen_(rhs.chosen_)
6564 {
6565 }
6566 
6567 // Assignment operator
6568 OsiBiLinearBranchingObject &
operator =(const OsiBiLinearBranchingObject & rhs)6569 OsiBiLinearBranchingObject::operator=(const OsiBiLinearBranchingObject &rhs)
6570 {
6571   if (this != &rhs) {
6572     OsiTwoWayBranchingObject::operator=(rhs);
6573     chosen_ = rhs.chosen_;
6574   }
6575   return *this;
6576 }
6577 OsiBranchingObject *
clone() const6578 OsiBiLinearBranchingObject::clone() const
6579 {
6580   return (new OsiBiLinearBranchingObject(*this));
6581 }
6582 
6583 // Destructor
~OsiBiLinearBranchingObject()6584 OsiBiLinearBranchingObject::~OsiBiLinearBranchingObject()
6585 {
6586 }
6587 double
branch(OsiSolverInterface * solver)6588 OsiBiLinearBranchingObject::branch(OsiSolverInterface *solver)
6589 {
6590   const OsiBiLinear *set = dynamic_cast< const OsiBiLinear * >(originalObject_);
6591   assert(set);
6592   int way = (!branchIndex_) ? (2 * firstBranch_ - 1) : -(2 * firstBranch_ - 1);
6593   branchIndex_++;
6594   set->newBounds(solver, way, chosen_, value_);
6595   return 0.0;
6596 }
6597 /* Return true if branch should only bound variables
6598  */
boundBranch() const6599 bool OsiBiLinearBranchingObject::boundBranch() const
6600 {
6601   const OsiBiLinear *set = dynamic_cast< const OsiBiLinear * >(originalObject_);
6602   assert(set);
6603   return (set->branchingStrategy() & 4) != 0;
6604 }
6605 // Print what would happen
print(const OsiSolverInterface *)6606 void OsiBiLinearBranchingObject::print(const OsiSolverInterface * /*solver*/)
6607 {
6608   const OsiBiLinear *set = dynamic_cast< const OsiBiLinear * >(originalObject_);
6609   assert(set);
6610   int way = (!branchIndex_) ? (2 * firstBranch_ - 1) : -(2 * firstBranch_ - 1);
6611   int iColumn = (chosen_ == 1) ? set->xColumn() : set->yColumn();
6612   printf("OsiBiLinear would branch %s on %c variable %d from value %g\n",
6613     (way < 0) ? "down" : "up",
6614     (chosen_ == 0) ? 'X' : 'Y', iColumn, value_);
6615 }
6616 // Default Constructor
OsiBiLinearEquality()6617 OsiBiLinearEquality::OsiBiLinearEquality()
6618   : OsiBiLinear()
6619   , numberPoints_(0)
6620 {
6621 }
6622 
6623 // Useful constructor
OsiBiLinearEquality(OsiSolverInterface * solver,int xColumn,int yColumn,int xyRow,double rhs,double xMesh)6624 OsiBiLinearEquality::OsiBiLinearEquality(OsiSolverInterface *solver, int xColumn,
6625   int yColumn, int xyRow, double rhs,
6626   double xMesh)
6627   : OsiBiLinear()
6628   , numberPoints_(0)
6629 {
6630   double xB[2];
6631   double yB[2];
6632   const double *lower = solver->getColLower();
6633   const double *upper = solver->getColUpper();
6634   xColumn_ = xColumn;
6635   yColumn_ = yColumn;
6636   xyRow_ = xyRow;
6637   coefficient_ = rhs;
6638   xB[0] = lower[xColumn_];
6639   xB[1] = upper[xColumn_];
6640   yB[0] = lower[yColumn_];
6641   yB[1] = upper[yColumn_];
6642   if (xB[1] * yB[1] < coefficient_ + 1.0e-12 || xB[0] * yB[0] > coefficient_ - 1.0e-12) {
6643     printf("infeasible row - reformulate\n");
6644     abort();
6645   }
6646   // reduce range of x if possible
6647   if (yB[0] * xB[1] > coefficient_ + 1.0e12) {
6648     xB[1] = coefficient_ / yB[0];
6649     solver->setColUpper(xColumn_, xB[1]);
6650   }
6651   if (yB[1] * xB[0] < coefficient_ - 1.0e12) {
6652     xB[0] = coefficient_ / yB[1];
6653     solver->setColLower(xColumn_, xB[0]);
6654   }
6655   // See how many points
6656   numberPoints_ = static_cast< int >((xB[1] - xB[0] + 0.5 * xMesh) / xMesh);
6657   // redo exactly
6658   xMeshSize_ = (xB[1] - xB[0]) / static_cast< double >(numberPoints_);
6659   numberPoints_++;
6660   //#define KEEPXY
6661 #ifndef KEEPXY
6662   // Take out xyRow
6663   solver->setRowLower(xyRow_, 0.0);
6664   solver->setRowUpper(xyRow_, 0.0);
6665 #else
6666   // make >=
6667   solver->setRowLower(xyRow_, coefficient_ - 0.05);
6668   solver->setRowUpper(xyRow_, COIN_DBL_MAX);
6669 #endif
6670   double rowLower[3];
6671   double rowUpper[3];
6672 #ifndef KEEPXY
6673   double *columnLower = new double[numberPoints_];
6674   double *columnUpper = new double[numberPoints_];
6675   double *objective = new double[numberPoints_];
6676   CoinBigIndex *starts = new CoinBigIndex[numberPoints_ + 1];
6677   int *index = new int[3 * numberPoints_];
6678   double *element = new double[3 * numberPoints_];
6679 #else
6680   double *columnLower = new double[numberPoints_ + 2];
6681   double *columnUpper = new double[numberPoints_ + 2];
6682   double *objective = new double[numberPoints_ + 2];
6683   CoinBigIndex *starts = new CoinBigIndex[numberPoints_ + 3];
6684   int *index = new int[4 * numberPoints_ + 2];
6685   double *element = new double[4 * numberPoints_ + 2];
6686 #endif
6687   int i;
6688   starts[0] = 0;
6689   // rows
6690   int numberRows = solver->getNumRows();
6691   // convexity
6692   rowLower[0] = 1.0;
6693   rowUpper[0] = 1.0;
6694   convexity_ = numberRows;
6695   starts[1] = 0;
6696   // x
6697   rowLower[1] = 0.0;
6698   rowUpper[1] = 0.0;
6699   index[0] = xColumn_;
6700   element[0] = -1.0;
6701   xRow_ = numberRows + 1;
6702   starts[2] = 1;
6703   rowLower[2] = 0.0;
6704   rowUpper[2] = 0.0;
6705   index[1] = yColumn;
6706   element[1] = -1.0;
6707   yRow_ = numberRows + 2;
6708   starts[3] = 2;
6709   solver->addRows(3, starts, index, element, rowLower, rowUpper);
6710   int n = 0;
6711   firstLambda_ = solver->getNumCols();
6712   double x = xB[0];
6713   assert(xColumn_ != yColumn_);
6714   for (i = 0; i < numberPoints_; i++) {
6715     double y = coefficient_ / x;
6716     columnLower[i] = 0.0;
6717     columnUpper[i] = 2.0;
6718     objective[i] = 0.0;
6719     double value;
6720 #ifdef KEEPXY
6721     // xy
6722     value = coefficient_;
6723     element[n] = value;
6724     index[n++] = xyRow_;
6725 #endif
6726     // convexity
6727     value = 1.0;
6728     element[n] = value;
6729     index[n++] = 0 + numberRows;
6730     // x
6731     value = x;
6732     if (fabs(value) < 1.0e-19)
6733       value = 1.0e-19;
6734     element[n] = value;
6735     index[n++] = 1 + numberRows;
6736     // y
6737     value = y;
6738     if (fabs(value) < 1.0e-19)
6739       value = 1.0e-19;
6740     element[n] = value;
6741     index[n++] = 2 + numberRows;
6742     starts[i + 1] = n;
6743     x += xMeshSize_;
6744   }
6745 #ifdef KEEPXY
6746   // costed slacks
6747   columnLower[numberPoints_] = 0.0;
6748   columnUpper[numberPoints_] = xMeshSize_;
6749   objective[numberPoints_] = 1.0e3;
6750   ;
6751   // convexity
6752   element[n] = 1.0;
6753   index[n++] = 0 + numberRows;
6754   starts[numberPoints_ + 1] = n;
6755   columnLower[numberPoints_ + 1] = 0.0;
6756   columnUpper[numberPoints_ + 1] = xMeshSize_;
6757   objective[numberPoints_ + 1] = 1.0e3;
6758   ;
6759   // convexity
6760   element[n] = -1.0;
6761   index[n++] = 0 + numberRows;
6762   starts[numberPoints_ + 2] = n;
6763   solver->addCols(numberPoints_ + 2, starts, index, element, columnLower, columnUpper, objective);
6764 #else
6765   solver->addCols(numberPoints_, starts, index, element, columnLower, columnUpper, objective);
6766 #endif
6767   delete[] columnLower;
6768   delete[] columnUpper;
6769   delete[] objective;
6770   delete[] starts;
6771   delete[] index;
6772   delete[] element;
6773 }
6774 
6775 // Copy constructor
OsiBiLinearEquality(const OsiBiLinearEquality & rhs)6776 OsiBiLinearEquality::OsiBiLinearEquality(const OsiBiLinearEquality &rhs)
6777   : OsiBiLinear(rhs)
6778   , numberPoints_(rhs.numberPoints_)
6779 {
6780 }
6781 
6782 // Clone
6783 OsiObject *
clone() const6784 OsiBiLinearEquality::clone() const
6785 {
6786   return new OsiBiLinearEquality(*this);
6787 }
6788 
6789 // Assignment operator
6790 OsiBiLinearEquality &
operator =(const OsiBiLinearEquality & rhs)6791 OsiBiLinearEquality::operator=(const OsiBiLinearEquality &rhs)
6792 {
6793   if (this != &rhs) {
6794     OsiBiLinear::operator=(rhs);
6795     numberPoints_ = rhs.numberPoints_;
6796   }
6797   return *this;
6798 }
6799 
6800 // Destructor
~OsiBiLinearEquality()6801 OsiBiLinearEquality::~OsiBiLinearEquality()
6802 {
6803 }
6804 // Possible improvement
6805 double
improvement(const OsiSolverInterface * solver) const6806 OsiBiLinearEquality::improvement(const OsiSolverInterface *solver) const
6807 {
6808   const double *pi = solver->getRowPrice();
6809   int i;
6810   const double *solution = solver->getColSolution();
6811   printf(" for x %d y %d - pi %g %g\n", xColumn_, yColumn_, pi[xRow_], pi[yRow_]);
6812   for (i = 0; i < numberPoints_; i++) {
6813     if (fabs(solution[i + firstLambda_]) > 1.0e-7)
6814       printf("(%d %g) ", i, solution[i + firstLambda_]);
6815   }
6816   printf("\n");
6817   return 0.0;
6818 }
6819 /* change grid
6820    if type 0 then use solution and make finer
6821    if 1 then back to original
6822 */
6823 double
newGrid(OsiSolverInterface * solver,int type) const6824 OsiBiLinearEquality::newGrid(OsiSolverInterface *solver, int type) const
6825 {
6826   CoinPackedMatrix *matrix = solver->getMutableMatrixByCol();
6827   if (!matrix) {
6828     printf("Unable to modify matrix\n");
6829     abort();
6830   }
6831   double *element = matrix->getMutableElements();
6832 #ifndef NDEBUG
6833   const int *row = matrix->getIndices();
6834 #endif
6835   const CoinBigIndex *columnStart = matrix->getVectorStarts();
6836   //const int * columnLength = matrix->getVectorLengths();
6837   // get original bounds
6838   double xB[2];
6839   const double *lower = solver->getColLower();
6840   const double *upper = solver->getColUpper();
6841   xB[0] = lower[xColumn_];
6842   xB[1] = upper[xColumn_];
6843   assert(fabs((xB[1] - xB[0]) - xMeshSize_ * (numberPoints_ - 1)) < 1.0e-7);
6844   double mesh = 0.0;
6845   int i;
6846   if (type == 0) {
6847     const double *solution = solver->getColSolution();
6848     int first = -1;
6849     int last = -1;
6850     double xValue = 0.0;
6851     double step = 0.0;
6852     for (i = 0; i < numberPoints_; i++) {
6853       int iColumn = i + firstLambda_;
6854       if (fabs(solution[iColumn]) > 1.0e-7) {
6855         CoinBigIndex k = columnStart[iColumn] + 1;
6856         xValue += element[k] * solution[iColumn];
6857         if (first == -1) {
6858           first = i;
6859           step = -element[k];
6860         } else {
6861           step += element[k];
6862         }
6863         last = i;
6864       }
6865     }
6866     if (last > first + 1) {
6867       printf("not adjacent - presuming small djs\n");
6868     }
6869     // new step size
6870     assert(numberPoints_ > 2);
6871     step = CoinMax((1.5 * step) / static_cast< double >(numberPoints_ - 1), 0.5 * step);
6872     xB[0] = CoinMax(xB[0], xValue - 0.5 * step);
6873     xB[1] = CoinMin(xB[1], xValue + 0.5 * step);
6874     // and now divide these
6875     mesh = (xB[1] - xB[0]) / static_cast< double >(numberPoints_ - 1);
6876   } else {
6877     // back to original
6878     mesh = xMeshSize_;
6879   }
6880   double x = xB[0];
6881   for (i = 0; i < numberPoints_; i++) {
6882     int iColumn = i + firstLambda_;
6883     double y = coefficient_ / x;
6884     //assert (columnLength[iColumn]==3); - could have cuts
6885     CoinBigIndex k = columnStart[iColumn];
6886 #ifdef KEEPXY
6887     // xy
6888     assert(row[k] == xyRow_);
6889     k++;
6890 #endif
6891     assert(row[k] == convexity_);
6892     k++;
6893     double value;
6894     // x
6895     value = x;
6896     assert(row[k] == xRow_);
6897     assert(fabs(value) > 1.0e-10);
6898     element[k++] = value;
6899     // y
6900     value = y;
6901     assert(row[k] == yRow_);
6902     assert(fabs(value) > 1.0e-10);
6903     element[k++] = value;
6904     x += mesh;
6905   }
6906   return mesh;
6907 }
6908 /** Default Constructor
6909 
6910   Equivalent to an unspecified binary variable.
6911 */
OsiSimpleFixedInteger()6912 OsiSimpleFixedInteger::OsiSimpleFixedInteger()
6913   : OsiSimpleInteger()
6914 {
6915 }
6916 
6917 /** Useful constructor
6918 
6919   Loads actual upper & lower bounds for the specified variable.
6920 */
OsiSimpleFixedInteger(const OsiSolverInterface * solver,int iColumn)6921 OsiSimpleFixedInteger::OsiSimpleFixedInteger(const OsiSolverInterface *solver, int iColumn)
6922   : OsiSimpleInteger(solver, iColumn)
6923 {
6924 }
6925 
6926 // Useful constructor - passed solver index and original bounds
OsiSimpleFixedInteger(int iColumn,double lower,double upper)6927 OsiSimpleFixedInteger::OsiSimpleFixedInteger(int iColumn, double lower, double upper)
6928   : OsiSimpleInteger(iColumn, lower, upper)
6929 {
6930 }
6931 
6932 // Useful constructor - passed simple integer
OsiSimpleFixedInteger(const OsiSimpleInteger & rhs)6933 OsiSimpleFixedInteger::OsiSimpleFixedInteger(const OsiSimpleInteger &rhs)
6934   : OsiSimpleInteger(rhs)
6935 {
6936 }
6937 
6938 // Copy constructor
OsiSimpleFixedInteger(const OsiSimpleFixedInteger & rhs)6939 OsiSimpleFixedInteger::OsiSimpleFixedInteger(const OsiSimpleFixedInteger &rhs)
6940   : OsiSimpleInteger(rhs)
6941 
6942 {
6943 }
6944 
6945 // Clone
6946 OsiObject *
clone() const6947 OsiSimpleFixedInteger::clone() const
6948 {
6949   return new OsiSimpleFixedInteger(*this);
6950 }
6951 
6952 // Assignment operator
6953 OsiSimpleFixedInteger &
operator =(const OsiSimpleFixedInteger & rhs)6954 OsiSimpleFixedInteger::operator=(const OsiSimpleFixedInteger &rhs)
6955 {
6956   if (this != &rhs) {
6957     OsiSimpleInteger::operator=(rhs);
6958   }
6959   return *this;
6960 }
6961 
6962 // Destructor
~OsiSimpleFixedInteger()6963 OsiSimpleFixedInteger::~OsiSimpleFixedInteger()
6964 {
6965 }
6966 // Infeasibility - large is 0.5
6967 double
infeasibility(const OsiBranchingInformation * info,int & whichWay) const6968 OsiSimpleFixedInteger::infeasibility(const OsiBranchingInformation *info, int &whichWay) const
6969 {
6970   double value = info->solution_[columnNumber_];
6971   value = CoinMax(value, info->lower_[columnNumber_]);
6972   value = CoinMin(value, info->upper_[columnNumber_]);
6973   double nearest = floor(value + (1.0 - 0.5));
6974   if (nearest > value) {
6975     whichWay = 1;
6976   } else {
6977     whichWay = 0;
6978   }
6979   infeasibility_ = fabs(value - nearest);
6980   bool satisfied = false;
6981   if (infeasibility_ <= info->integerTolerance_) {
6982     otherInfeasibility_ = 1.0;
6983     satisfied = true;
6984     if (info->lower_[columnNumber_] != info->upper_[columnNumber_])
6985       infeasibility_ = 1.0e-5;
6986     else
6987       infeasibility_ = 0.0;
6988   } else if (info->defaultDual_ < 0.0) {
6989     otherInfeasibility_ = 1.0 - infeasibility_;
6990   } else {
6991     const double *pi = info->pi_;
6992     const double *activity = info->rowActivity_;
6993     const double *lower = info->rowLower_;
6994     const double *upper = info->rowUpper_;
6995     const double *element = info->elementByColumn_;
6996     const int *row = info->row_;
6997     const CoinBigIndex *columnStart = info->columnStart_;
6998     const int *columnLength = info->columnLength_;
6999     double direction = info->direction_;
7000     double downMovement = value - floor(value);
7001     double upMovement = 1.0 - downMovement;
7002     double valueP = info->objective_[columnNumber_] * direction;
7003     CoinBigIndex start = columnStart[columnNumber_];
7004     CoinBigIndex end = start + columnLength[columnNumber_];
7005     double upEstimate = 0.0;
7006     double downEstimate = 0.0;
7007     if (valueP > 0.0)
7008       upEstimate = valueP * upMovement;
7009     else
7010       downEstimate -= valueP * downMovement;
7011     double tolerance = info->primalTolerance_;
7012     for (CoinBigIndex j = start; j < end; j++) {
7013       int iRow = row[j];
7014       if (lower[iRow] < -1.0e20)
7015         assert(pi[iRow] <= 1.0e-3);
7016       if (upper[iRow] > 1.0e20)
7017         assert(pi[iRow] >= -1.0e-3);
7018       valueP = pi[iRow] * direction;
7019       double el2 = element[j];
7020       double value2 = valueP * el2;
7021       double u = 0.0;
7022       double d = 0.0;
7023       if (value2 > 0.0)
7024         u = value2;
7025       else
7026         d = -value2;
7027       // if up makes infeasible then make at least default
7028       double newUp = activity[iRow] + upMovement * el2;
7029       if (newUp > upper[iRow] + tolerance || newUp < lower[iRow] - tolerance)
7030         u = CoinMax(u, info->defaultDual_);
7031       upEstimate += u * upMovement * fabs(el2);
7032       // if down makes infeasible then make at least default
7033       double newDown = activity[iRow] - downMovement * el2;
7034       if (newDown > upper[iRow] + tolerance || newDown < lower[iRow] - tolerance)
7035         d = CoinMax(d, info->defaultDual_);
7036       downEstimate += d * downMovement * fabs(el2);
7037     }
7038     if (downEstimate >= upEstimate) {
7039       infeasibility_ = CoinMax(1.0e-12, upEstimate);
7040       otherInfeasibility_ = CoinMax(1.0e-12, downEstimate);
7041       whichWay = 1;
7042     } else {
7043       infeasibility_ = CoinMax(1.0e-12, downEstimate);
7044       otherInfeasibility_ = CoinMax(1.0e-12, upEstimate);
7045       whichWay = 0;
7046     }
7047   }
7048   if (preferredWay_ >= 0 && !satisfied)
7049     whichWay = preferredWay_;
7050   whichWay_ = static_cast< short int >(whichWay);
7051   return infeasibility_;
7052 }
7053 // Creates a branching object
7054 OsiBranchingObject *
createBranch(OsiSolverInterface * solver,const OsiBranchingInformation * info,int way) const7055 OsiSimpleFixedInteger::createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const
7056 {
7057   double value = info->solution_[columnNumber_];
7058   value = CoinMax(value, info->lower_[columnNumber_]);
7059   value = CoinMin(value, info->upper_[columnNumber_]);
7060   assert(info->upper_[columnNumber_] > info->lower_[columnNumber_]);
7061   double nearest = floor(value + 0.5);
7062   double integerTolerance = info->integerTolerance_;
7063   if (fabs(value - nearest) < integerTolerance) {
7064     // adjust value
7065     if (nearest != info->upper_[columnNumber_])
7066       value = nearest + 2.0 * integerTolerance;
7067     else
7068       value = nearest - 2.0 * integerTolerance;
7069   }
7070   OsiBranchingObject *branch = new OsiIntegerBranchingObject(solver, this, way,
7071     value);
7072   return branch;
7073 }
7074 
7075 #include <cstdlib>
7076 #include <cstdio>
7077 #include <cmath>
7078 #include <cfloat>
7079 #include <cassert>
7080 #include <iostream>
7081 //#define CGL_DEBUG 2
7082 #include "CoinHelperFunctions.hpp"
7083 #include "CoinPackedVector.hpp"
7084 #include "OsiRowCutDebugger.hpp"
7085 #include "CoinWarmStartBasis.hpp"
7086 //#include "CglTemporary.hpp"
7087 #include "CoinFinite.hpp"
7088 //-------------------------------------------------------------------
7089 // Generate Stored cuts
7090 //-------------------------------------------------------------------
generateCuts(const OsiSolverInterface & si,OsiCuts & cs,const CglTreeInfo)7091 void CglTemporary::generateCuts(const OsiSolverInterface &si, OsiCuts &cs,
7092   const CglTreeInfo /*info*/)
7093 {
7094   // Get basic problem information
7095   const double *solution = si.getColSolution();
7096   int numberRowCuts = cuts_.sizeRowCuts();
7097   for (int i = 0; i < numberRowCuts; i++) {
7098     const OsiRowCut *rowCutPointer = cuts_.rowCutPtr(i);
7099     double violation = rowCutPointer->violated(solution);
7100     if (violation >= requiredViolation_)
7101       cs.insert(*rowCutPointer);
7102   }
7103   // delete
7104   cuts_ = OsiCuts();
7105 }
7106 
7107 //-------------------------------------------------------------------
7108 // Default Constructor
7109 //-------------------------------------------------------------------
CglTemporary()7110 CglTemporary::CglTemporary()
7111   : CglStored()
7112 {
7113 }
7114 
7115 //-------------------------------------------------------------------
7116 // Copy constructor
7117 //-------------------------------------------------------------------
CglTemporary(const CglTemporary & source)7118 CglTemporary::CglTemporary(const CglTemporary &source)
7119   : CglStored(source)
7120 {
7121 }
7122 
7123 //-------------------------------------------------------------------
7124 // Clone
7125 //-------------------------------------------------------------------
7126 CglCutGenerator *
clone() const7127 CglTemporary::clone() const
7128 {
7129   return new CglTemporary(*this);
7130 }
7131 
7132 //-------------------------------------------------------------------
7133 // Destructor
7134 //-------------------------------------------------------------------
~CglTemporary()7135 CglTemporary::~CglTemporary()
7136 {
7137 }
7138 
7139 //----------------------------------------------------------------
7140 // Assignment operator
7141 //-------------------------------------------------------------------
7142 CglTemporary &
operator =(const CglTemporary & rhs)7143 CglTemporary::operator=(const CglTemporary &rhs)
7144 {
7145   if (this != &rhs) {
7146     CglStored::operator=(rhs);
7147   }
7148   return *this;
7149 }
checkQP(ClpSimplex *)7150 void checkQP(ClpSimplex * /*model*/)
7151 {
7152 #ifdef JJF_ZERO
7153   printf("Checking quadratic model %x\n", model);
7154   if (model) {
7155     ClpQuadraticObjective *quadraticObj = (dynamic_cast< ClpQuadraticObjective * >(model->objectiveAsObject()));
7156     assert(quadraticObj);
7157     CoinPackedMatrix *quadraticObjective = quadraticObj->quadraticObjective();
7158     int numberColumns = quadraticObj->numberColumns();
7159     const int *columnQuadratic = quadraticObjective->getIndices();
7160     const CoinBigIndex *columnQuadraticStart = quadraticObjective->getVectorStarts();
7161     const int *columnQuadraticLength = quadraticObjective->getVectorLengths();
7162     //const double * quadraticElement = quadraticObjective->getElements();
7163     for (int i = 0; i < numberColumns; i++) {
7164       for (int j = columnQuadraticStart[i]; j < columnQuadraticStart[i] + columnQuadraticLength[i]; j++)
7165         assert(columnQuadratic[j] >= 0 && columnQuadratic[j] < 1000);
7166     }
7167   }
7168 #endif
7169 }
7170 //#############################################################################
7171 // Solve methods
7172 //#############################################################################
initialSolve()7173 void OsiSolverLinearizedQuadratic::initialSolve()
7174 {
7175   OsiClpSolverInterface::initialSolve();
7176   int secondaryStatus = modelPtr_->secondaryStatus();
7177   if (modelPtr_->status() == 0 && (secondaryStatus == 2 || secondaryStatus == 4))
7178     modelPtr_->cleanup(1);
7179   if (isProvenOptimal() && modelPtr_->numberColumns() == quadraticModel_->numberColumns()) {
7180     // see if qp can get better solution
7181     const double *solution = modelPtr_->primalColumnSolution();
7182     int numberColumns = modelPtr_->numberColumns();
7183     bool satisfied = true;
7184     for (int i = 0; i < numberColumns; i++) {
7185       if (isInteger(i)) {
7186         double value = solution[i];
7187         if (fabs(value - floor(value + 0.5)) > 1.0e-6) {
7188           satisfied = false;
7189           break;
7190         }
7191       }
7192     }
7193     if (satisfied) {
7194       checkQP(quadraticModel_);
7195       ClpSimplex qpTemp(*quadraticModel_);
7196       checkQP(&qpTemp);
7197       double *lower = qpTemp.columnLower();
7198       double *upper = qpTemp.columnUpper();
7199       double *lower2 = modelPtr_->columnLower();
7200       double *upper2 = modelPtr_->columnUpper();
7201       for (int i = 0; i < numberColumns; i++) {
7202         if (isInteger(i)) {
7203           double value = floor(solution[i] + 0.5);
7204           lower[i] = value;
7205           upper[i] = value;
7206         } else {
7207           lower[i] = lower2[i];
7208           upper[i] = upper2[i];
7209         }
7210       }
7211       //qpTemp.writeMps("bad.mps");
7212       //modelPtr_->writeMps("bad2.mps");
7213       //qpTemp.objectiveAsObject()->setActivated(0);
7214       //qpTemp.primal();
7215       //qpTemp.objectiveAsObject()->setActivated(1);
7216       qpTemp.primal();
7217       //assert (!qpTemp.problemStatus());
7218       if (qpTemp.objectiveValue() < bestObjectiveValue_ && !qpTemp.problemStatus()) {
7219         delete[] bestSolution_;
7220         bestSolution_ = CoinCopyOfArray(qpTemp.primalColumnSolution(), numberColumns);
7221         bestObjectiveValue_ = qpTemp.objectiveValue();
7222         //printf("better qp objective of %g\n", bestObjectiveValue_);
7223       }
7224     }
7225   }
7226 }
7227 //#############################################################################
7228 // Constructors, destructors clone and assignment
7229 //#############################################################################
7230 //-------------------------------------------------------------------
7231 // Default Constructor
7232 //-------------------------------------------------------------------
OsiSolverLinearizedQuadratic()7233 OsiSolverLinearizedQuadratic::OsiSolverLinearizedQuadratic()
7234   : OsiClpSolverInterface()
7235 {
7236   bestObjectiveValue_ = COIN_DBL_MAX;
7237   bestSolution_ = NULL;
7238   specialOptions3_ = 0;
7239   quadraticModel_ = NULL;
7240 }
OsiSolverLinearizedQuadratic(ClpSimplex * quadraticModel)7241 OsiSolverLinearizedQuadratic::OsiSolverLinearizedQuadratic(ClpSimplex *quadraticModel)
7242   : OsiClpSolverInterface(new ClpSimplex(*quadraticModel), true)
7243 {
7244   bestObjectiveValue_ = COIN_DBL_MAX;
7245   bestSolution_ = NULL;
7246   specialOptions3_ = 0;
7247   quadraticModel_ = new ClpSimplex(*quadraticModel);
7248   // linearize
7249   int numberColumns = modelPtr_->numberColumns();
7250   const double *solution = modelPtr_->primalColumnSolution();
7251   // Replace objective
7252   ClpObjective *trueObjective = modelPtr_->objectiveAsObject();
7253   ClpObjective *objective = new ClpLinearObjective(NULL, numberColumns);
7254   modelPtr_->setObjectivePointer(objective);
7255   double offset;
7256   double saveOffset = modelPtr_->objectiveOffset();
7257   memcpy(modelPtr_->objective(), trueObjective->gradient(modelPtr_, solution, offset, true, 2),
7258     numberColumns * sizeof(double));
7259   modelPtr_->setObjectiveOffset(saveOffset + offset);
7260   delete trueObjective;
7261   checkQP(quadraticModel_);
7262 }
7263 //-------------------------------------------------------------------
7264 // Clone
7265 //-------------------------------------------------------------------
7266 OsiSolverInterface *
clone(bool) const7267 OsiSolverLinearizedQuadratic::clone(bool /*copyData*/) const
7268 {
7269   //assert (copyData);
7270   return new OsiSolverLinearizedQuadratic(*this);
7271 }
7272 
7273 //-------------------------------------------------------------------
7274 // Copy constructor
7275 //-------------------------------------------------------------------
OsiSolverLinearizedQuadratic(const OsiSolverLinearizedQuadratic & rhs)7276 OsiSolverLinearizedQuadratic::OsiSolverLinearizedQuadratic(
7277   const OsiSolverLinearizedQuadratic &rhs)
7278   : OsiSolverInterface(rhs)
7279   , OsiClpSolverInterface(rhs)
7280 {
7281   bestObjectiveValue_ = rhs.bestObjectiveValue_;
7282   if (rhs.bestSolution_) {
7283     bestSolution_ = CoinCopyOfArray(rhs.bestSolution_, modelPtr_->numberColumns());
7284   } else {
7285     bestSolution_ = NULL;
7286   }
7287   specialOptions3_ = rhs.specialOptions3_;
7288   if (rhs.quadraticModel_) {
7289     quadraticModel_ = new ClpSimplex(*rhs.quadraticModel_);
7290   } else {
7291     quadraticModel_ = NULL;
7292   }
7293   checkQP(rhs.quadraticModel_);
7294   checkQP(quadraticModel_);
7295 }
7296 
7297 //-------------------------------------------------------------------
7298 // Destructor
7299 //-------------------------------------------------------------------
~OsiSolverLinearizedQuadratic()7300 OsiSolverLinearizedQuadratic::~OsiSolverLinearizedQuadratic()
7301 {
7302   delete[] bestSolution_;
7303   delete quadraticModel_;
7304 }
7305 
7306 //-------------------------------------------------------------------
7307 // Assignment operator
7308 //-------------------------------------------------------------------
7309 OsiSolverLinearizedQuadratic &
operator =(const OsiSolverLinearizedQuadratic & rhs)7310 OsiSolverLinearizedQuadratic::operator=(const OsiSolverLinearizedQuadratic &rhs)
7311 {
7312   if (this != &rhs) {
7313     delete[] bestSolution_;
7314     delete quadraticModel_;
7315     OsiClpSolverInterface::operator=(rhs);
7316     bestObjectiveValue_ = rhs.bestObjectiveValue_;
7317     if (rhs.bestSolution_) {
7318       bestSolution_ = CoinCopyOfArray(rhs.bestSolution_, modelPtr_->numberColumns());
7319     } else {
7320       bestSolution_ = NULL;
7321     }
7322     specialOptions3_ = rhs.specialOptions3_;
7323     if (rhs.quadraticModel_) {
7324       quadraticModel_ = new ClpSimplex(*rhs.quadraticModel_);
7325     } else {
7326       quadraticModel_ = NULL;
7327     }
7328     checkQP(rhs.quadraticModel_);
7329     checkQP(quadraticModel_);
7330   }
7331   return *this;
7332 }
7333 /* Expands out all possible combinations for a knapsack
7334    If buildObj NULL then just computes space needed - returns number elements
7335    On entry numberOutput is maximum allowed, on exit it is number needed or
7336    -1 (as will be number elements) if maximum exceeded.  numberOutput will have at
7337    least space to return values which reconstruct input.
7338    Rows returned will be original rows but no entries will be returned for
7339    any rows all of whose entries are in knapsack.  So up to user to allow for this.
7340    If reConstruct >=0 then returns number of entrie which make up item "reConstruct"
7341    in expanded knapsack.  Values in buildRow and buildElement;
7342 */
expandKnapsack(int knapsackRow,int & numberOutput,double * buildObj,CoinBigIndex * buildStart,int * buildRow,double * buildElement,int reConstruct) const7343 int CoinModel::expandKnapsack(int knapsackRow, int &numberOutput, double *buildObj, CoinBigIndex *buildStart,
7344   int *buildRow, double *buildElement, int reConstruct) const
7345 {
7346   /* mark rows
7347        -2 in knapsack and other variables
7348        -1 not involved
7349        0 only in knapsack
7350     */
7351   int *markRow = new int[numberRows_];
7352   int iRow;
7353   int iColumn;
7354   int *whichColumn = new int[numberColumns_];
7355   for (iColumn = 0; iColumn < numberColumns_; iColumn++)
7356     whichColumn[iColumn] = -1;
7357   int numJ = 0;
7358   for (iRow = 0; iRow < numberRows_; iRow++)
7359     markRow[iRow] = -1;
7360   CoinModelLink triple;
7361   triple = firstInRow(knapsackRow);
7362   while (triple.column() >= 0) {
7363     int iColumn = triple.column();
7364 #ifndef NDEBUG
7365     const char *el = getElementAsString(knapsackRow, iColumn);
7366     assert(!strcmp("Numeric", el));
7367 #endif
7368     whichColumn[iColumn] = numJ;
7369     numJ++;
7370     triple = next(triple);
7371   }
7372   for (iRow = 0; iRow < numberRows_; iRow++) {
7373     triple = firstInRow(iRow);
7374     int type = -3;
7375     while (triple.column() >= 0) {
7376       int iColumn = triple.column();
7377       if (whichColumn[iColumn] >= 0) {
7378         if (type == -3)
7379           type = 0;
7380         else if (type != 0)
7381           type = -2;
7382       } else {
7383         if (type == -3)
7384           type = -1;
7385         else if (type == 0)
7386           type = -2;
7387       }
7388       triple = next(triple);
7389     }
7390     if (type == -3)
7391       type = -1;
7392     markRow[iRow] = type;
7393   }
7394   int *bound = new int[numberColumns_ + 1];
7395   int *whichRow = new int[numberRows_];
7396   ClpSimplex tempModel;
7397   CoinModel tempModel2(*this);
7398   tempModel.loadProblem(tempModel2);
7399   int *stack = new int[numberColumns_ + 1];
7400   double *size = new double[numberColumns_ + 1];
7401   double *rhsOffset = new double[numberRows_];
7402   int *build = new int[numberColumns_];
7403   int maxNumber = numberOutput;
7404   numJ = 0;
7405   double minSize = getRowLower(knapsackRow);
7406   double maxSize = getRowUpper(knapsackRow);
7407   double offset = 0.0;
7408   triple = firstInRow(knapsackRow);
7409   while (triple.column() >= 0) {
7410     iColumn = triple.column();
7411     double lowerColumn = columnLower(iColumn);
7412     double upperColumn = columnUpper(iColumn);
7413     double gap = upperColumn - lowerColumn;
7414     if (gap > 1.0e8)
7415       gap = 1.0e8;
7416     assert(fabs(floor(gap + 0.5) - gap) < 1.0e-5);
7417     whichColumn[numJ] = iColumn;
7418     bound[numJ] = static_cast< int >(gap);
7419     size[numJ++] = triple.value();
7420     offset += triple.value() * lowerColumn;
7421     triple = next(triple);
7422   }
7423   int jRow;
7424   for (iRow = 0; iRow < numberRows_; iRow++)
7425     whichRow[iRow] = iRow;
7426   ClpSimplex smallModel(&tempModel, numberRows_, whichRow, numJ, whichColumn, true, true, true);
7427   // modify rhs to allow for nonzero lower bounds
7428   double *rowLower = smallModel.rowLower();
7429   double *rowUpper = smallModel.rowUpper();
7430   const double *columnLower = smallModel.columnLower();
7431   //const double * columnUpper = smallModel.columnUpper();
7432   const CoinPackedMatrix *matrix = smallModel.matrix();
7433   const double *element = matrix->getElements();
7434   const int *row = matrix->getIndices();
7435   const CoinBigIndex *columnStart = matrix->getVectorStarts();
7436   const int *columnLength = matrix->getVectorLengths();
7437   const double *objective = smallModel.objective();
7438   double objectiveOffset = 0.0;
7439   CoinZeroN(rhsOffset, numberRows_);
7440   for (iColumn = 0; iColumn < numJ; iColumn++) {
7441     double lower = columnLower[iColumn];
7442     if (lower) {
7443       objectiveOffset += objective[iColumn];
7444       for (CoinBigIndex j = columnStart[iColumn];
7445            j < columnStart[iColumn] + columnLength[iColumn]; j++) {
7446         double value = element[j] * lower;
7447         int kRow = row[j];
7448         rhsOffset[kRow] += value;
7449         if (rowLower[kRow] > -1.0e20)
7450           rowLower[kRow] -= value;
7451         if (rowUpper[kRow] < 1.0e20)
7452           rowUpper[kRow] -= value;
7453       }
7454     }
7455   }
7456   // relax
7457   for (jRow = 0; jRow < numberRows_; jRow++) {
7458     if (markRow[jRow] == 0 && knapsackRow != jRow) {
7459       if (rowLower[jRow] > -1.0e20)
7460         rowLower[jRow] -= 1.0e-7;
7461       if (rowUpper[jRow] < 1.0e20)
7462         rowUpper[jRow] += 1.0e-7;
7463     } else {
7464       rowLower[jRow] = -COIN_DBL_MAX;
7465       rowUpper[jRow] = COIN_DBL_MAX;
7466     }
7467   }
7468   double *rowActivity = smallModel.primalRowSolution();
7469   CoinZeroN(rowActivity, numberRows_);
7470   maxSize -= offset;
7471   minSize -= offset;
7472   // now generate
7473   int i;
7474   int iStack = numJ;
7475   for (i = 0; i < numJ; i++) {
7476     stack[i] = 0;
7477   }
7478   double tooMuch = 10.0 * maxSize;
7479   stack[numJ] = 1;
7480   size[numJ] = tooMuch;
7481   bound[numJ] = 0;
7482   double sum = tooMuch;
7483   numberOutput = 0;
7484   int nelCreate = 0;
7485   /* typeRun is - 0 for initial sizes
7486                     1 for build
7487       	  2 for reconstruct
7488     */
7489   int typeRun = buildObj ? 1 : 0;
7490   if (reConstruct >= 0) {
7491     assert(buildRow && buildElement);
7492     typeRun = 2;
7493   }
7494   if (typeRun == 1)
7495     buildStart[0] = 0;
7496   while (iStack >= 0) {
7497     if (sum >= minSize && sum <= maxSize) {
7498       double checkSize = 0.0;
7499       bool good = true;
7500       int nRow = 0;
7501       double obj = objectiveOffset;
7502       // nRow is zero? CoinZeroN(rowActivity,nRow);
7503       for (iColumn = 0; iColumn < numJ; iColumn++) {
7504         int iValue = stack[iColumn];
7505         if (iValue > bound[iColumn]) {
7506           good = false;
7507           break;
7508         } else if (iValue) {
7509           obj += objective[iColumn] * iValue;
7510           for (CoinBigIndex j = columnStart[iColumn];
7511                j < columnStart[iColumn] + columnLength[iColumn]; j++) {
7512             double value = element[j] * iValue;
7513             int kRow = row[j];
7514             if (rowActivity[kRow]) {
7515               rowActivity[kRow] += value;
7516               if (!rowActivity[kRow])
7517                 rowActivity[kRow] = 1.0e-100;
7518             } else {
7519               build[nRow++] = kRow;
7520               rowActivity[kRow] = value;
7521             }
7522           }
7523         }
7524       }
7525       if (good) {
7526         for (jRow = 0; jRow < nRow; jRow++) {
7527           int kRow = build[jRow];
7528           double value = rowActivity[kRow];
7529           if (value > rowUpper[kRow] || value < rowLower[kRow]) {
7530             good = false;
7531             break;
7532           }
7533         }
7534       }
7535       if (good) {
7536         if (typeRun == 1) {
7537           buildObj[numberOutput] = obj;
7538           for (jRow = 0; jRow < nRow; jRow++) {
7539             int kRow = build[jRow];
7540             double value = rowActivity[kRow];
7541             if (markRow[kRow] < 0 && fabs(value) > 1.0e-13) {
7542               buildElement[nelCreate] = value;
7543               buildRow[nelCreate++] = kRow;
7544             }
7545           }
7546           buildStart[numberOutput + 1] = nelCreate;
7547         } else if (!typeRun) {
7548           for (jRow = 0; jRow < nRow; jRow++) {
7549             int kRow = build[jRow];
7550             double value = rowActivity[kRow];
7551             if (markRow[kRow] < 0 && fabs(value) > 1.0e-13) {
7552               nelCreate++;
7553             }
7554           }
7555         }
7556         if (typeRun == 2 && reConstruct == numberOutput) {
7557           // build and exit
7558           nelCreate = 0;
7559           for (iColumn = 0; iColumn < numJ; iColumn++) {
7560             int iValue = stack[iColumn];
7561             if (iValue) {
7562               buildRow[nelCreate] = whichColumn[iColumn];
7563               buildElement[nelCreate++] = iValue;
7564             }
7565           }
7566           numberOutput = 1;
7567           for (i = 0; i < numJ; i++) {
7568             bound[i] = 0;
7569           }
7570           break;
7571         }
7572         numberOutput++;
7573         if (numberOutput > maxNumber) {
7574           nelCreate = -1;
7575           numberOutput = -1;
7576           for (i = 0; i < numJ; i++) {
7577             bound[i] = 0;
7578           }
7579           break;
7580         } else if (typeRun == 1 && numberOutput == maxNumber) {
7581           // On second run
7582           for (i = 0; i < numJ; i++) {
7583             bound[i] = 0;
7584           }
7585           break;
7586         }
7587         for (int j = 0; j < numJ; j++) {
7588           checkSize += stack[j] * size[j];
7589         }
7590         assert(fabs(sum - checkSize) < 1.0e-3);
7591       }
7592       for (jRow = 0; jRow < nRow; jRow++) {
7593         int kRow = build[jRow];
7594         rowActivity[kRow] = 0.0;
7595       }
7596     }
7597     if (sum > maxSize || stack[iStack] > bound[iStack]) {
7598       sum -= size[iStack] * stack[iStack];
7599       stack[iStack--] = 0;
7600       if (iStack >= 0) {
7601         stack[iStack]++;
7602         sum += size[iStack];
7603       }
7604     } else {
7605       // must be less
7606       // add to last possible
7607       iStack = numJ - 1;
7608       sum += size[iStack];
7609       stack[iStack]++;
7610     }
7611   }
7612   //printf("%d will be created\n",numberOutput);
7613   delete[] whichColumn;
7614   delete[] whichRow;
7615   delete[] bound;
7616   delete[] stack;
7617   delete[] size;
7618   delete[] rhsOffset;
7619   delete[] build;
7620   delete[] markRow;
7621   return nelCreate;
7622 }
7623 #include "ClpConstraint.hpp"
7624 #include "ClpConstraintLinear.hpp"
7625 #include "ClpConstraintQuadratic.hpp"
7626 #ifdef COIN_HAS_ASL
7627 //#include "ClpAmplObjective.hpp"
7628 #endif
7629 /* Return an approximate solution to a CoinModel.
7630     Lots of bounds may be odd to force a solution.
7631     mode = 0 just tries to get a continuous solution
7632 */
7633 ClpSimplex *
approximateSolution(CoinModel & coinModel,int numberPasses,double deltaTolerance,int)7634 approximateSolution(CoinModel &coinModel,
7635   int numberPasses, double deltaTolerance,
7636   int /*mode*/)
7637 {
7638 #ifndef JJF_ONE
7639   //#ifdef COIN_HAS_ASL
7640   // matrix etc will be changed
7641   CoinModel coinModel2 = coinModel;
7642   if (coinModel2.moreInfo()) {
7643     // for now just ampl objective
7644     ClpSimplex *model = new ClpSimplex();
7645     model->loadProblem(coinModel2);
7646     int numberConstraints;
7647     ClpConstraint **constraints = NULL;
7648     int type = model->loadNonLinear(coinModel2.moreInfo(),
7649       numberConstraints, constraints);
7650     if (type == 1 || type == 3) {
7651       model->nonlinearSLP(numberPasses, deltaTolerance);
7652     } else if (type == 2 || type == 4) {
7653       model->nonlinearSLP(numberConstraints, constraints,
7654         numberPasses, deltaTolerance);
7655     } else {
7656       printf("error or linear - fix %d\n", type);
7657     }
7658     //exit(66);
7659     return model;
7660   }
7661   // first check and set up arrays
7662   int numberColumns = coinModel.numberColumns();
7663   int numberRows = coinModel.numberRows();
7664   // List of nonlinear rows
7665   int *which = new int[numberRows];
7666   bool testLinear = false;
7667   int numberConstraints = 0;
7668   int iColumn;
7669   bool linearObjective = true;
7670   int maximumQuadraticElements = 0;
7671   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
7672     // See if quadratic objective
7673     const char *expr = coinModel.getColumnObjectiveAsString(iColumn);
7674     if (strcmp(expr, "Numeric")) {
7675       linearObjective = false;
7676       // check if value*x+-value*y....
7677       assert(strlen(expr) < 20000);
7678       char temp[20000];
7679       strcpy(temp, expr);
7680       char *pos = temp;
7681       bool ifFirst = true;
7682       while (*pos) {
7683         double value;
7684         int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel);
7685         // must be column unless first when may be linear term
7686         if (jColumn >= 0) {
7687           maximumQuadraticElements++;
7688         } else if (jColumn != -2) {
7689           printf("bad nonlinear term %s\n", temp);
7690           abort();
7691         }
7692         ifFirst = false;
7693       }
7694     }
7695   }
7696   if (!linearObjective) {
7697     // zero objective
7698     for (iColumn = 0; iColumn < numberColumns; iColumn++)
7699       coinModel2.setObjective(iColumn, 0.0);
7700   }
7701   int iRow;
7702   for (iRow = 0; iRow < numberRows; iRow++) {
7703     int numberQuadratic = 0;
7704     bool linear = true;
7705     CoinModelLink triple = coinModel.firstInRow(iRow);
7706     while (triple.column() >= 0) {
7707       int iColumn = triple.column();
7708       const char *expr = coinModel.getElementAsString(iRow, iColumn);
7709       if (strcmp("Numeric", expr)) {
7710         linear = false;
7711         // check if value*x+-value*y....
7712         assert(strlen(expr) < 20000);
7713         char temp[20000];
7714         strcpy(temp, expr);
7715         char *pos = temp;
7716         bool ifFirst = true;
7717         while (*pos) {
7718           double value;
7719           int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel);
7720           // must be column unless first when may be linear term
7721           if (jColumn >= 0) {
7722             numberQuadratic++;
7723           } else if (jColumn != -2) {
7724             printf("bad nonlinear term %s\n", temp);
7725             abort();
7726           }
7727           ifFirst = false;
7728         }
7729       }
7730       triple = coinModel.next(triple);
7731     }
7732     if (!linear || testLinear) {
7733       CoinModelLink triple = coinModel.firstInRow(iRow);
7734       while (triple.column() >= 0) {
7735         int iColumn = triple.column();
7736         coinModel2.setElement(iRow, iColumn, 0.0);
7737         triple = coinModel.next(triple);
7738       }
7739       which[numberConstraints++] = iRow;
7740       maximumQuadraticElements = CoinMax(maximumQuadraticElements, numberQuadratic);
7741     }
7742   }
7743   ClpSimplex *model = new ClpSimplex();
7744   // return if nothing
7745   if (!numberConstraints && linearObjective) {
7746     delete[] which;
7747     model->loadProblem(coinModel);
7748     model->dual();
7749     return model;
7750   }
7751   // space for quadratic
7752   // allow for linear term
7753   maximumQuadraticElements += numberColumns;
7754   CoinBigIndex *startQuadratic = new CoinBigIndex[numberColumns + 1];
7755   int *columnQuadratic = new int[maximumQuadraticElements];
7756   double *elementQuadratic = new double[maximumQuadraticElements];
7757   ClpConstraint **constraints = new ClpConstraint *[numberConstraints];
7758   double *linearTerm = new double[numberColumns];
7759   int saveNumber = numberConstraints;
7760   numberConstraints = 0;
7761   ClpQuadraticObjective *quadObj = NULL;
7762   if (!linearObjective) {
7763     int numberQuadratic = 0;
7764     CoinZeroN(linearTerm, numberColumns);
7765     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
7766       startQuadratic[iColumn] = numberQuadratic;
7767       // See if quadratic objective
7768       const char *expr = coinModel.getColumnObjectiveAsString(iColumn);
7769       if (strcmp(expr, "Numeric")) {
7770         // value*x*y
7771         char temp[20000];
7772         strcpy(temp, expr);
7773         char *pos = temp;
7774         bool ifFirst = true;
7775         while (*pos) {
7776           double value;
7777           int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel);
7778           // must be column unless first when may be linear term
7779           if (jColumn >= 0) {
7780             columnQuadratic[numberQuadratic] = jColumn;
7781             if (jColumn != iColumn)
7782               elementQuadratic[numberQuadratic++] = 1.0 * value; // convention
7783             else if (jColumn == iColumn)
7784               elementQuadratic[numberQuadratic++] = 2.0 * value; // convention
7785           } else if (jColumn == -2) {
7786             linearTerm[iColumn] = value;
7787           } else {
7788             printf("bad nonlinear term %s\n", temp);
7789             abort();
7790           }
7791           ifFirst = false;
7792         }
7793       } else {
7794         // linear part
7795         linearTerm[iColumn] = coinModel.getColumnObjective(iColumn);
7796       }
7797     }
7798     startQuadratic[numberColumns] = numberQuadratic;
7799     quadObj = new ClpQuadraticObjective(linearTerm, numberColumns,
7800       startQuadratic, columnQuadratic, elementQuadratic);
7801   }
7802   int iConstraint;
7803   for (iConstraint = 0; iConstraint < saveNumber; iConstraint++) {
7804     iRow = which[iConstraint];
7805     if (iRow >= 0) {
7806       int numberQuadratic = 0;
7807       int lastColumn = -1;
7808       int largestColumn = -1;
7809       CoinZeroN(linearTerm, numberColumns);
7810       CoinModelLink triple = coinModel.firstInRow(iRow);
7811       while (triple.column() >= 0) {
7812         int iColumn = triple.column();
7813         while (lastColumn < iColumn) {
7814           startQuadratic[lastColumn + 1] = numberQuadratic;
7815           lastColumn++;
7816         }
7817         const char *expr = coinModel.getElementAsString(iRow, iColumn);
7818         if (strcmp("Numeric", expr)) {
7819           largestColumn = CoinMax(largestColumn, iColumn);
7820           // value*x*y
7821           char temp[20000];
7822           strcpy(temp, expr);
7823           char *pos = temp;
7824           bool ifFirst = true;
7825           while (*pos) {
7826             double value;
7827             int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel);
7828             // must be column unless first when may be linear term
7829             if (jColumn >= 0) {
7830               columnQuadratic[numberQuadratic] = jColumn;
7831               if (jColumn == iColumn)
7832                 elementQuadratic[numberQuadratic++] = 2.0 * value; // convention
7833               else
7834                 elementQuadratic[numberQuadratic++] = 1.0 * value; // convention
7835               largestColumn = CoinMax(largestColumn, jColumn);
7836             } else if (jColumn == -2) {
7837               linearTerm[iColumn] = value;
7838               // and put in as row -1
7839               columnQuadratic[numberQuadratic] = -1;
7840               if (jColumn == iColumn)
7841                 elementQuadratic[numberQuadratic++] = 2.0 * value; // convention
7842               else
7843                 elementQuadratic[numberQuadratic++] = 1.0 * value; // convention
7844               largestColumn = CoinMax(largestColumn, iColumn);
7845             } else {
7846               printf("bad nonlinear term %s\n", temp);
7847               abort();
7848             }
7849             ifFirst = false;
7850           }
7851         } else {
7852           // linear part
7853           linearTerm[iColumn] = coinModel.getElement(iRow, iColumn);
7854           // and put in as row -1
7855           columnQuadratic[numberQuadratic] = -1;
7856           elementQuadratic[numberQuadratic++] = linearTerm[iColumn];
7857           if (linearTerm[iColumn])
7858             largestColumn = CoinMax(largestColumn, iColumn);
7859         }
7860         triple = coinModel.next(triple);
7861       }
7862       while (lastColumn < numberColumns) {
7863         startQuadratic[lastColumn + 1] = numberQuadratic;
7864         lastColumn++;
7865       }
7866       // here we create ClpConstraint
7867       if (testLinear) {
7868         int n = 0;
7869         int *indices = new int[numberColumns];
7870         for (int j = 0; j < numberColumns; j++) {
7871           if (linearTerm[j]) {
7872             linearTerm[n] = linearTerm[j];
7873             indices[n++] = j;
7874           }
7875         }
7876         /// Constructor from constraint
7877         constraints[numberConstraints++] = new ClpConstraintLinear(iRow, n, numberColumns,
7878           indices, linearTerm);
7879         delete[] indices;
7880       } else {
7881         constraints[numberConstraints++] = new ClpConstraintQuadratic(iRow, largestColumn + 1, numberColumns,
7882           startQuadratic, columnQuadratic, elementQuadratic);
7883       }
7884     }
7885   }
7886   delete[] startQuadratic;
7887   delete[] columnQuadratic;
7888   delete[] elementQuadratic;
7889   delete[] linearTerm;
7890   delete[] which;
7891   model->loadProblem(coinModel2);
7892   if (quadObj)
7893     model->setObjective(quadObj);
7894   delete quadObj;
7895 #ifndef NDEBUG
7896   int returnCode;
7897   if (numberConstraints) {
7898     returnCode = model->nonlinearSLP(numberConstraints, constraints,
7899       numberPasses, deltaTolerance);
7900     for (iConstraint = 0; iConstraint < saveNumber; iConstraint++)
7901       delete constraints[iConstraint];
7902   } else {
7903     returnCode = model->nonlinearSLP(numberPasses, deltaTolerance);
7904   }
7905   assert(!returnCode);
7906 #else
7907   if (numberConstraints) {
7908     model->nonlinearSLP(numberConstraints, constraints, numberPasses, deltaTolerance);
7909     for (iConstraint = 0; iConstraint < saveNumber; iConstraint++)
7910       delete constraints[iConstraint];
7911   } else {
7912     model->nonlinearSLP(numberPasses, deltaTolerance);
7913   }
7914 #endif
7915   delete[] constraints;
7916   return model;
7917 #else
7918   printf("loadNonLinear needs ampl\n");
7919   abort();
7920   return NULL;
7921 #endif
7922 }
OsiChooseStrongSubset()7923 OsiChooseStrongSubset::OsiChooseStrongSubset()
7924   : OsiChooseStrong()
7925   , numberObjectsToUse_(0)
7926 {
7927 }
7928 
OsiChooseStrongSubset(const OsiSolverInterface * solver)7929 OsiChooseStrongSubset::OsiChooseStrongSubset(const OsiSolverInterface *solver)
7930   : OsiChooseStrong(solver)
7931   , numberObjectsToUse_(-1)
7932 {
7933 }
7934 
OsiChooseStrongSubset(const OsiChooseStrongSubset & rhs)7935 OsiChooseStrongSubset::OsiChooseStrongSubset(const OsiChooseStrongSubset &rhs)
7936   : OsiChooseStrong(rhs)
7937 {
7938   numberObjectsToUse_ = -1;
7939 }
7940 
7941 OsiChooseStrongSubset &
operator =(const OsiChooseStrongSubset & rhs)7942 OsiChooseStrongSubset::operator=(const OsiChooseStrongSubset &rhs)
7943 {
7944   if (this != &rhs) {
7945     OsiChooseStrong::operator=(rhs);
7946     numberObjectsToUse_ = -1;
7947   }
7948   return *this;
7949 }
7950 
~OsiChooseStrongSubset()7951 OsiChooseStrongSubset::~OsiChooseStrongSubset()
7952 {
7953 }
7954 
7955 // Clone
7956 OsiChooseVariable *
clone() const7957 OsiChooseStrongSubset::clone() const
7958 {
7959   return new OsiChooseStrongSubset(*this);
7960 }
7961 // Initialize
setupList(OsiBranchingInformation * info,bool initialize)7962 int OsiChooseStrongSubset::setupList(OsiBranchingInformation *info, bool initialize)
7963 {
7964   assert(solver_ == info->solver_);
7965   // Only has to work with Clp
7966   OsiSolverInterface *solverA = const_cast< OsiSolverInterface * >(solver_);
7967   OsiSolverLink *solver = dynamic_cast< OsiSolverLink * >(solverA);
7968   assert(solver);
7969   int numberObjects = solver->numberObjects();
7970   if (numberObjects > pseudoCosts_.numberObjects()) {
7971     // redo useful arrays
7972     pseudoCosts_.initialize(numberObjects);
7973   }
7974   int numObj = numberObjects;
7975   if (numberObjectsToUse_ < 0) {
7976     // Sort objects so bilinear at end
7977     OsiObject **sorted = new OsiObject *[numberObjects];
7978     OsiObject **objects = solver->objects();
7979     numObj = 0;
7980     int numberBiLinear = 0;
7981     int i;
7982     for (i = 0; i < numberObjects; i++) {
7983       OsiObject *obj = objects[i];
7984       OsiBiLinear *objB = dynamic_cast< OsiBiLinear * >(obj);
7985       if (!objB)
7986         objects[numObj++] = obj;
7987       else
7988         sorted[numberBiLinear++] = obj;
7989     }
7990     numberObjectsToUse_ = numObj;
7991     for (i = 0; i < numberBiLinear; i++)
7992       objects[numObj++] = sorted[i];
7993     delete[] sorted;
7994     // See if any master objects
7995     for (i = 0; i < numberObjectsToUse_; i++) {
7996       OsiUsesBiLinear *obj = dynamic_cast< OsiUsesBiLinear * >(objects[i]);
7997       if (obj)
7998         obj->addBiLinearObjects(solver);
7999     }
8000   }
8001   solver->setNumberObjects(numberObjectsToUse_);
8002   numObj = numberObjectsToUse_;
8003   // Use shadow prices
8004   //info->defaultDual_=0.0;
8005   int numberUnsatisfied = OsiChooseStrong::setupList(info, initialize);
8006   solver->setNumberObjects(numberObjects);
8007   numObj = numberObjects;
8008   return numberUnsatisfied;
8009 }
8010 /* Choose a variable
8011    Returns -
8012    -1 Node is infeasible
8013    0  Normal termination - we have a candidate
8014    1  All looks satisfied - no candidate
8015    2  We can change the bound on a variable - but we also have a strong branching candidate
8016    3  We can change the bound on a variable - but we have a non-strong branching candidate
8017    4  We can change the bound on a variable - no other candidates
8018    We can pick up branch from whichObject() and whichWay()
8019    We can pick up a forced branch (can change bound) from whichForcedObject() and whichForcedWay()
8020    If we have a solution then we can pick up from goodObjectiveValue() and goodSolution()
8021 */
chooseVariable(OsiSolverInterface * solver,OsiBranchingInformation * info,bool fixVariables)8022 int OsiChooseStrongSubset::chooseVariable(OsiSolverInterface *solver, OsiBranchingInformation *info, bool fixVariables)
8023 {
8024   //int numberObjects = solver->numberObjects();
8025   //solver->setNumberObjects(numberObjectsToUse_);
8026   //numberObjects_=numberObjectsToUse_;
8027   // Use shadow prices
8028   //info->defaultDual_=0.0;
8029   int returnCode = OsiChooseStrong::chooseVariable(solver, info, fixVariables);
8030   //solver->setNumberObjects(numberObjects);
8031   //numberObjects_=numberObjects;
8032   return returnCode;
8033 }
8034 /** Default Constructor
8035 
8036   Equivalent to an unspecified binary variable.
8037 */
OsiUsesBiLinear()8038 OsiUsesBiLinear::OsiUsesBiLinear()
8039   : OsiSimpleInteger()
8040   , numberBiLinear_(0)
8041   , type_(0)
8042   , objects_(NULL)
8043 {
8044 }
8045 
8046 /** Useful constructor
8047 
8048   Loads actual upper & lower bounds for the specified variable.
8049 */
OsiUsesBiLinear(const OsiSolverInterface * solver,int iColumn,int type)8050 OsiUsesBiLinear::OsiUsesBiLinear(const OsiSolverInterface *solver, int iColumn, int type)
8051   : OsiSimpleInteger(solver, iColumn)
8052   , numberBiLinear_(0)
8053   , type_(type)
8054   , objects_(NULL)
8055 {
8056   if (type_) {
8057     assert(originalLower_ == floor(originalLower_ + 0.5));
8058     assert(originalUpper_ == floor(originalUpper_ + 0.5));
8059   }
8060 }
8061 
8062 // Useful constructor - passed solver index and original bounds
OsiUsesBiLinear(int iColumn,double lower,double upper,int type)8063 OsiUsesBiLinear::OsiUsesBiLinear(int iColumn, double lower, double upper, int type)
8064   : OsiSimpleInteger(iColumn, lower, upper)
8065   , numberBiLinear_(0)
8066   , type_(type)
8067   , objects_(NULL)
8068 {
8069   if (type_) {
8070     assert(originalLower_ == floor(originalLower_ + 0.5));
8071     assert(originalUpper_ == floor(originalUpper_ + 0.5));
8072   }
8073 }
8074 
8075 // Useful constructor - passed simple integer
OsiUsesBiLinear(const OsiSimpleInteger & rhs,int type)8076 OsiUsesBiLinear::OsiUsesBiLinear(const OsiSimpleInteger &rhs, int type)
8077   : OsiSimpleInteger(rhs)
8078   , numberBiLinear_(0)
8079   , type_(type)
8080   , objects_(NULL)
8081 {
8082   if (type_) {
8083     assert(originalLower_ == floor(originalLower_ + 0.5));
8084     assert(originalUpper_ == floor(originalUpper_ + 0.5));
8085   }
8086 }
8087 
8088 // Copy constructor
OsiUsesBiLinear(const OsiUsesBiLinear & rhs)8089 OsiUsesBiLinear::OsiUsesBiLinear(const OsiUsesBiLinear &rhs)
8090   : OsiSimpleInteger(rhs)
8091   , numberBiLinear_(0)
8092   , type_(rhs.type_)
8093   , objects_(NULL)
8094 
8095 {
8096 }
8097 
8098 // Clone
8099 OsiObject *
clone() const8100 OsiUsesBiLinear::clone() const
8101 {
8102   return new OsiUsesBiLinear(*this);
8103 }
8104 
8105 // Assignment operator
8106 OsiUsesBiLinear &
operator =(const OsiUsesBiLinear & rhs)8107 OsiUsesBiLinear::operator=(const OsiUsesBiLinear &rhs)
8108 {
8109   if (this != &rhs) {
8110     OsiSimpleInteger::operator=(rhs);
8111     delete[] objects_;
8112     numberBiLinear_ = 0;
8113     type_ = rhs.type_;
8114     objects_ = NULL;
8115   }
8116   return *this;
8117 }
8118 
8119 // Destructor
~OsiUsesBiLinear()8120 OsiUsesBiLinear::~OsiUsesBiLinear()
8121 {
8122   delete[] objects_;
8123 }
8124 // Infeasibility - large is 0.5
8125 double
infeasibility(const OsiBranchingInformation * info,int & whichWay) const8126 OsiUsesBiLinear::infeasibility(const OsiBranchingInformation *info, int &whichWay) const
8127 {
8128   assert(type_ == 0); // just continuous for now
8129   double value = info->solution_[columnNumber_];
8130   value = CoinMax(value, info->lower_[columnNumber_]);
8131   value = CoinMin(value, info->upper_[columnNumber_]);
8132   infeasibility_ = 0.0;
8133   for (int i = 0; i < numberBiLinear_; i++) {
8134     OsiBiLinear *obj = dynamic_cast< OsiBiLinear * >(objects_[i]);
8135     assert(obj);
8136     //obj->getPseudoShadow(info);
8137     //infeasibility_ += objects_[i]->infeasibility(info,whichWay);
8138     infeasibility_ += obj->getMovement(info);
8139   }
8140   bool satisfied = false;
8141   whichWay = -1;
8142   if (!infeasibility_) {
8143     otherInfeasibility_ = 1.0;
8144     satisfied = true;
8145     infeasibility_ = 0.0;
8146   } else {
8147     otherInfeasibility_ = 10.0 * infeasibility_;
8148     if (value - info->lower_[columnNumber_] > info->upper_[columnNumber_] - value)
8149       whichWay = 1;
8150     else
8151       whichWay = -1;
8152   }
8153   if (preferredWay_ >= 0 && !satisfied)
8154     whichWay = preferredWay_;
8155   whichWay_ = static_cast< short int >(whichWay);
8156   return infeasibility_;
8157 }
8158 // Creates a branching object
8159 OsiBranchingObject *
createBranch(OsiSolverInterface * solver,const OsiBranchingInformation * info,int way) const8160 OsiUsesBiLinear::createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const
8161 {
8162   double value = info->solution_[columnNumber_];
8163   value = CoinMax(value, info->lower_[columnNumber_]);
8164   value = CoinMin(value, info->upper_[columnNumber_]);
8165   assert(info->upper_[columnNumber_] > info->lower_[columnNumber_]);
8166   double nearest = floor(value + 0.5);
8167   double integerTolerance = info->integerTolerance_;
8168   if (fabs(value - nearest) < integerTolerance) {
8169     // adjust value
8170     if (nearest != info->upper_[columnNumber_])
8171       value = nearest + 2.0 * integerTolerance;
8172     else
8173       value = nearest - 2.0 * integerTolerance;
8174   }
8175   OsiBranchingObject *branch = new OsiIntegerBranchingObject(solver, this, way,
8176     value, value, value);
8177   return branch;
8178 }
8179 // This looks at solution and sets bounds to contain solution
8180 /** More precisely: it first forces the variable within the existing
8181     bounds, and then tightens the bounds to fix the variable at the
8182     nearest integer value.
8183 */
8184 double
feasibleRegion(OsiSolverInterface * solver,const OsiBranchingInformation * info) const8185 OsiUsesBiLinear::feasibleRegion(OsiSolverInterface *solver,
8186   const OsiBranchingInformation *info) const
8187 {
8188   double value = info->solution_[columnNumber_];
8189   double newValue = CoinMax(value, info->lower_[columnNumber_]);
8190   newValue = CoinMin(newValue, info->upper_[columnNumber_]);
8191   solver->setColLower(columnNumber_, newValue);
8192   solver->setColUpper(columnNumber_, newValue);
8193   return fabs(value - newValue);
8194 }
8195 // Add all bi-linear objects
addBiLinearObjects(OsiSolverLink * solver)8196 void OsiUsesBiLinear::addBiLinearObjects(OsiSolverLink *solver)
8197 {
8198   delete[] objects_;
8199   numberBiLinear_ = 0;
8200   OsiObject **objects = solver->objects();
8201   int i;
8202   int numberObjects = solver->numberObjects();
8203   for (i = 0; i < numberObjects; i++) {
8204     OsiObject *obj = objects[i];
8205     OsiBiLinear *objB = dynamic_cast< OsiBiLinear * >(obj);
8206     if (objB) {
8207       if (objB->xColumn() == columnNumber_ || objB->yColumn() == columnNumber_)
8208         numberBiLinear_++;
8209     }
8210   }
8211   if (numberBiLinear_) {
8212     objects_ = new OsiObject *[numberBiLinear_];
8213     numberBiLinear_ = 0;
8214     for (i = 0; i < numberObjects; i++) {
8215       OsiObject *obj = objects[i];
8216       OsiBiLinear *objB = dynamic_cast< OsiBiLinear * >(obj);
8217       if (objB) {
8218         if (objB->xColumn() == columnNumber_ || objB->yColumn() == columnNumber_)
8219           objects_[numberBiLinear_++] = obj;
8220         ;
8221       }
8222     }
8223   } else {
8224     objects_ = NULL;
8225   }
8226 }
8227 
8228 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
8229 */
8230