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