1// $Id$
2// Copyright (C) 2002, 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 <cassert>
7#ifdef CBC_STATISTICS
8extern int osi_crunch;
9extern int osi_primal;
10extern int osi_dual;
11extern int osi_hot;
12#endif
13#include "CoinTime.hpp"
14#include "CoinHelperFunctions.hpp"
15#include "CoinIndexedVector.hpp"
16#include "CoinModel.hpp"
17#include "CoinMpsIO.hpp"
18#include "CoinSort.hpp"
19#include "ClpDualRowSteepest.hpp"
20#include "ClpPrimalColumnSteepest.hpp"
21#include "ClpPackedMatrix.hpp"
22#include "ClpDualRowDantzig.hpp"
23#include "ClpPrimalColumnDantzig.hpp"
24#include "ClpFactorization.hpp"
25#include "ClpObjective.hpp"
26#include "ClpSimplex.hpp"
27#include "ClpSimplexOther.hpp"
28#include "ClpSimplexPrimal.hpp"
29#include "ClpSimplexDual.hpp"
30#include "ClpNonLinearCost.hpp"
31#include "OsiClpSolverInterface.hpp"
32#include "OsiBranchingObject.hpp"
33#include "OsiCuts.hpp"
34#include "OsiRowCut.hpp"
35#include "OsiColCut.hpp"
36#include "ClpPresolve.hpp"
37#include "CoinLpIO.hpp"
38static double totalTime=0.0;
39//#define SAVE_MODEL 1
40#ifdef SAVE_MODEL
41static int resolveTry=0;
42static int loResolveTry=0;
43static int hiResolveTry=9999999;
44#endif
45//#############################################################################
46// Solve methods
47//#############################################################################
48void OsiClpSolverInterface::initialSolve()
49{
50#define KEEP_SMALL
51#ifdef KEEP_SMALL
52 if (smallModel_) {
53 delete [] spareArrays_;
54 spareArrays_ = NULL;
55 delete smallModel_;
56 smallModel_=NULL;
57 }
58#endif
59 if ((specialOptions_&2097152)!=0||(specialOptions_&4194304)!=0) {
60 bool takeHint;
61 OsiHintStrength strength;
62 int algorithm = 0;
63 getHintParam(OsiDoDualInInitial,takeHint,strength);
64 if (strength!=OsiHintIgnore)
65 algorithm = takeHint ? -1 : 1;
66 if (algorithm>0||(specialOptions_&4194304)!=0) {
67 // Gub
68 resolveGub((9*modelPtr_->numberRows())/10);
69 return;
70 }
71 }
72 bool deleteSolver;
73 ClpSimplex * solver;
74 double time1 = CoinCpuTime();
75 int userFactorizationFrequency = modelPtr_->factorization()->maximumPivots();
76 int totalIterations=0;
77 bool abortSearch=false;
78 ClpObjective * savedObjective=NULL;
79 double savedDualLimit=modelPtr_->dblParam_[ClpDualObjectiveLimit];
80 if (fakeObjective_) {
81 // Clear (no objective, 0-1 and in B&B)
82 modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~128));
83 // See if all with costs fixed
84 int numberColumns = modelPtr_->numberColumns_;
85 const double * obj = modelPtr_->objective();
86 const double * lower = modelPtr_->columnLower();
87 const double * upper = modelPtr_->columnUpper();
88 int i;
89 for (i=0;i<numberColumns;i++) {
90 double objValue = obj[i];
91 if (objValue) {
92 if (lower[i]!=upper[i])
93 break;
94 }
95 }
96 if (i==numberColumns) {
97 // Check (Clp fast dual)
98 if ((specialOptions_&524288)==0) {
99 // Set fake
100 savedObjective=modelPtr_->objective_;
101 modelPtr_->objective_=fakeObjective_;
102 modelPtr_->dblParam_[ClpDualObjectiveLimit]=COIN_DBL_MAX;
103 } else {
104 // Set (no objective, 0-1 and in B&B)
105 modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()|128);
106 }
107 }
108 }
109 // Check (in branch and bound)
110 if ((specialOptions_&1024)==0) {
111 solver = new ClpSimplex(true);
112 deleteSolver=true;
113 solver->borrowModel(*modelPtr_);
114 // See if user set factorization frequency
115 // borrowModel does not move
116 solver->factorization()->maximumPivots(userFactorizationFrequency);
117 } else {
118 solver = modelPtr_;
119 deleteSolver=false;
120 }
121 // Treat as if user simplex not enabled
122 int saveSolveType=solver->solveType();
123 bool doingPrimal = solver->algorithm()>0;
124 if (saveSolveType==2) {
125 disableSimplexInterface();
126 solver->setSolveType(1);
127 }
128 int saveOptions = solver->specialOptions();
129 solver->setSpecialOptions(saveOptions|64|32768); // go as far as possible
130 // get original log levels
131 int saveMessageLevel=modelPtr_->logLevel();
132 int messageLevel=messageHandler()->logLevel();
133 int saveMessageLevel2 = messageLevel;
134 // Set message handler
135 solver->passInMessageHandler(handler_);
136 // But keep log level
137 solver->messageHandler()->setLogLevel(saveMessageLevel);
138 // set reasonable defaults
139 bool takeHint;
140 OsiHintStrength strength;
141 // Switch off printing if asked to
142 bool gotHint = (getHintParam(OsiDoReducePrint,takeHint,strength));
143 assert (gotHint);
144 if (strength!=OsiHintIgnore&&takeHint) {
145 if (messageLevel>0)
146 messageLevel--;
147 }
148 if (messageLevel<saveMessageLevel)
149 solver->messageHandler()->setLogLevel(messageLevel);
150 // Allow for specialOptions_==1+8 forcing saving factorization
151 int startFinishOptions=0;
152 if ((specialOptions_&9)==(1+8)) {
153 startFinishOptions =1+2+4; // allow re-use of factorization
154 }
155 bool defaultHints=true;
156 {
157 int hint;
158 for (hint=OsiDoPresolveInInitial;hint<OsiLastHintParam;hint++) {
159 if (hint!=OsiDoReducePrint&&
160 hint!=OsiDoInBranchAndCut) {
161 bool yesNo;
162 OsiHintStrength strength;
163 getHintParam(static_cast<OsiHintParam> (hint),yesNo,strength);
164 if (yesNo) {
165 defaultHints=false;
166 break;
167 }
168 if (strength != OsiHintIgnore) {
169 defaultHints=false;
170 break;
171 }
172 }
173 }
174 }
175 ClpPresolve * pinfo = NULL;
176 /*
177 If basis then do primal (as user could do dual with resolve)
178 If not then see if dual feasible (and allow for gubs etc?)
179 */
180 bool doPrimal = (basis_.numberBasicStructurals()>0);
181 setBasis(basis_,solver);
182 bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0;
183 if ((!defaultHints||doPrimal)&&!solveOptions_.getSpecialOption(6)) {
184 // scaling
185 // save initial state
186 const double * rowScale1 = solver->rowScale();
187 if (modelPtr_->solveType()==1) {
188 gotHint = (getHintParam(OsiDoScale,takeHint,strength));
189 assert (gotHint);
190 if (strength==OsiHintIgnore||takeHint) {
191 if (!solver->scalingFlag())
192 solver->scaling(3);
193 } else {
194 solver->scaling(0);
195 }
196 } else {
197 solver->scaling(0);
198 }
199 //solver->setDualBound(1.0e6);
200 //solver->setDualTolerance(1.0e-7);
201
202 //ClpDualRowSteepest steep;
203 //solver->setDualRowPivotAlgorithm(steep);
204 //solver->setPrimalTolerance(1.0e-8);
205 //ClpPrimalColumnSteepest steepP;
206 //solver->setPrimalColumnPivotAlgorithm(steepP);
207
208 // sort out hints;
209 // algorithm 0 whatever, -1 force dual, +1 force primal
210 int algorithm = 0;
211 gotHint = (getHintParam(OsiDoDualInInitial,takeHint,strength));
212 assert (gotHint);
213 if (strength!=OsiHintIgnore)
214 algorithm = takeHint ? -1 : 1;
215 // crash 0 do lightweight if all slack, 1 do, -1 don't
216 int doCrash=0;
217 gotHint = (getHintParam(OsiDoCrash,takeHint,strength));
218 assert (gotHint);
219 if (strength!=OsiHintIgnore)
220 doCrash = takeHint ? 1 : -1;
221 // doPrimal set true if any structurals in basis so switch off crash
222 if (doPrimal)
223 doCrash = -1;
224
225 // presolve
226 gotHint = (getHintParam(OsiDoPresolveInInitial,takeHint,strength));
227 assert (gotHint);
228 if (strength!=OsiHintIgnore&&takeHint) {
229 pinfo = new ClpPresolve();
230 ClpSimplex * model2 = pinfo->presolvedModel(*solver,1.0e-8);
231 if (!model2) {
232 // problem found to be infeasible - whats best?
233 model2 = solver;
234 delete pinfo;
235 pinfo = NULL;
236 } else {
237 model2->setSpecialOptions(solver->specialOptions());
238 }
239
240 // change from 200 (unless changed)
241 if (modelPtr_->factorization()->maximumPivots()==200)
242 model2->factorization()->maximumPivots(100+model2->numberRows()/50);
243 else
244 model2->factorization()->maximumPivots(userFactorizationFrequency);
245 int savePerturbation = model2->perturbation();
246 if (savePerturbation==100)
247 model2->setPerturbation(50);
248 if (!doPrimal) {
249 // faster if bounds tightened
250 //int numberInfeasibilities = model2->tightenPrimalBounds();
251 model2->tightenPrimalBounds();
252 // look further
253 bool crashResult=false;
254 if (doCrash>0)
255 crashResult = (solver->crash(1000.0,1)>0);
256 else if (doCrash==0&&algorithm>0)
257 crashResult = (solver->crash(1000.0,1)>0);
258 doPrimal=crashResult;
259 }
260 if (algorithm<0)
261 doPrimal=false;
262 else if (algorithm>0)
263 doPrimal=true;
264 if (!doPrimal) {
265 //if (numberInfeasibilities)
266 //std::cout<<"** Analysis indicates model infeasible"
267 // <<std::endl;
268 // up dual bound for safety
269 //model2->setDualBound(1.0e11);
270 disasterHandler_->setOsiModel(this);
271 if (inCbcOrOther) {
272 disasterHandler_->setSimplex(model2);
273 disasterHandler_->setWhereFrom(4);
274 model2->setDisasterHandler(disasterHandler_);
275 }
276 model2->dual(0);
277 totalIterations += model2->numberIterations();
278 if (inCbcOrOther) {
279 if(disasterHandler_->inTrouble()) {
280#ifdef COIN_DEVELOP
281 printf("dual trouble a\n");
282#endif
283 if (disasterHandler_->typeOfDisaster()) {
284 // We want to abort
285 abortSearch=true;
286 goto disaster;
287 }
288 // try just going back in
289 disasterHandler_->setPhase(1);
290 model2->dual();
291 totalIterations += model2->numberIterations();
292 if (disasterHandler_->inTrouble()) {
293#ifdef COIN_DEVELOP
294 printf("dual trouble b\n");
295#endif
296 if (disasterHandler_->typeOfDisaster()) {
297 // We want to abort
298 abortSearch=true;
299 goto disaster;
300 }
301 // try primal with original basis
302 disasterHandler_->setPhase(2);
303 setBasis(basis_,model2);
304 model2->primal();
305 totalIterations += model2->numberIterations();
306 }
307 if(disasterHandler_->inTrouble()) {
308#ifdef COIN_DEVELOP
309 printf("disaster - treat as infeasible\n");
310#endif
311 if (disasterHandler_->typeOfDisaster()) {
312 // We want to abort
313 abortSearch=true;
314 goto disaster;
315 }
316 model2->setProblemStatus(1);
317 }
318 }
319 // reset
320 model2->setDisasterHandler(NULL);
321 }
322 // check if clp thought it was in a loop
323 if (model2->status()==3&&!model2->hitMaximumIterations()) {
324 // switch algorithm
325 disasterHandler_->setOsiModel(this);
326 if (inCbcOrOther) {
327 disasterHandler_->setSimplex(model2);
328 disasterHandler_->setWhereFrom(6);
329 model2->setDisasterHandler(disasterHandler_);
330 }
331 model2->primal();
332 totalIterations += model2->numberIterations();
333 if (inCbcOrOther) {
334 if(disasterHandler_->inTrouble()) {
335#ifdef COIN_DEVELOP
336 printf("primal trouble a\n");
337#endif
338 if (disasterHandler_->typeOfDisaster()) {
339 // We want to abort
340 abortSearch=true;
341 goto disaster;
342 }
343 // try just going back in (but with dual)
344 disasterHandler_->setPhase(1);
345 model2->dual();
346 totalIterations += model2->numberIterations();
347 if (disasterHandler_->inTrouble()) {
348#ifdef COIN_DEVELOP
349 printf("primal trouble b\n");
350#endif
351 if (disasterHandler_->typeOfDisaster()) {
352 // We want to abort
353 abortSearch=true;
354 goto disaster;
355 }
356 // try primal with original basis
357 disasterHandler_->setPhase(2);
358 setBasis(basis_,model2);
359 model2->dual();
360 totalIterations += model2->numberIterations();
361 }
362 if(disasterHandler_->inTrouble()) {
363#ifdef COIN_DEVELOP
364 printf("disaster - treat as infeasible\n");
365#endif
366 if (disasterHandler_->typeOfDisaster()) {
367 // We want to abort
368 abortSearch=true;
369 goto disaster;
370 }
371 model2->setProblemStatus(1);
372 }
373 }
374 // reset
375 model2->setDisasterHandler(NULL);
376 }
377 }
378 } else {
379 // up infeasibility cost for safety
380 //model2->setInfeasibilityCost(1.0e10);
381 disasterHandler_->setOsiModel(this);
382 if (inCbcOrOther) {
383 disasterHandler_->setSimplex(model2);
384 disasterHandler_->setWhereFrom(6);
385 model2->setDisasterHandler(disasterHandler_);
386 }
387 model2->primal(1);
388 totalIterations += model2->numberIterations();
389 if (inCbcOrOther) {
390 if(disasterHandler_->inTrouble()) {
391#ifdef COIN_DEVELOP
392 printf("primal trouble a\n");
393#endif
394 if (disasterHandler_->typeOfDisaster()) {
395 // We want to abort
396 abortSearch=true;
397 goto disaster;
398 }
399 // try just going back in (but with dual)
400 disasterHandler_->setPhase(1);
401 model2->dual();
402 totalIterations += model2->numberIterations();
403 if (disasterHandler_->inTrouble()) {
404#ifdef COIN_DEVELOP
405 printf("primal trouble b\n");
406#endif
407 if (disasterHandler_->typeOfDisaster()) {
408 // We want to abort
409 abortSearch=true;
410 goto disaster;
411 }
412 // try primal with original basis
413 disasterHandler_->setPhase(2);
414 setBasis(basis_,model2);
415 model2->dual();
416 totalIterations += model2->numberIterations();
417 }
418 if(disasterHandler_->inTrouble()) {
419#ifdef COIN_DEVELOP
420 printf("disaster - treat as infeasible\n");
421#endif
422 if (disasterHandler_->typeOfDisaster()) {
423 // We want to abort
424 abortSearch=true;
425 goto disaster;
426 }
427 model2->setProblemStatus(1);
428 }
429 }
430 // reset
431 model2->setDisasterHandler(NULL);
432 }
433 // check if clp thought it was in a loop
434 if (model2->status()==3&&!model2->hitMaximumIterations()) {
435 // switch algorithm
436 disasterHandler_->setOsiModel(this);
437 if (inCbcOrOther) {
438 disasterHandler_->setSimplex(model2);
439 disasterHandler_->setWhereFrom(4);
440 model2->setDisasterHandler(disasterHandler_);
441 }
442 model2->dual(0);
443 totalIterations += model2->numberIterations();
444 if (inCbcOrOther) {
445 if(disasterHandler_->inTrouble()) {
446#ifdef COIN_DEVELOP
447 printf("dual trouble a\n");
448#endif
449 if (disasterHandler_->typeOfDisaster()) {
450 // We want to abort
451 abortSearch=true;
452 goto disaster;
453 }
454 // try just going back in
455 disasterHandler_->setPhase(1);
456 model2->dual();
457 totalIterations += model2->numberIterations();
458 if (disasterHandler_->inTrouble()) {
459#ifdef COIN_DEVELOP
460 printf("dual trouble b\n");
461#endif
462 if (disasterHandler_->typeOfDisaster()) {
463 // We want to abort
464 abortSearch=true;
465 goto disaster;
466 }
467 // try primal with original basis
468 disasterHandler_->setPhase(2);
469 setBasis(basis_,model2);
470 model2->primal();
471 totalIterations += model2->numberIterations();
472 }
473 if(disasterHandler_->inTrouble()) {
474#ifdef COIN_DEVELOP
475 printf("disaster - treat as infeasible\n");
476#endif
477 if (disasterHandler_->typeOfDisaster()) {
478 // We want to abort
479 abortSearch=true;
480 goto disaster;
481 }
482 model2->setProblemStatus(1);
483 }
484 }
485 // reset
486 model2->setDisasterHandler(NULL);
487 }
488 }
489 }
490 model2->setPerturbation(savePerturbation);
491 if (model2!=solver) {
492 int presolvedStatus = model2->status();
493 pinfo->postsolve(true);
494 delete pinfo;
495 pinfo = NULL;
496
497 delete model2;
498 int oldStatus=solver->status();
499 solver->setProblemStatus(presolvedStatus);
500 if (solver->logLevel()==63) // for gcc 4.6 bug
501 printf("pstat %d stat %d\n",presolvedStatus,oldStatus);
502 //printf("Resolving from postsolved model\n");
503 // later try without (1) and check duals before solve
504 if (presolvedStatus!=3
505 &&(presolvedStatus||oldStatus==-1)) {
506 if (!inCbcOrOther||presolvedStatus!=1) {
507 disasterHandler_->setOsiModel(this);
508 if (inCbcOrOther) {
509 disasterHandler_->setSimplex(solver); // as "borrowed"
510 disasterHandler_->setWhereFrom(6);
511 solver->setDisasterHandler(disasterHandler_);
512 }
513 solver->primal(1);
514 totalIterations += solver->numberIterations();
515 if (inCbcOrOther) {
516 if(disasterHandler_->inTrouble()) {
517#ifdef COIN_DEVELOP
518 printf("primal trouble a\n");
519#endif
520 if (disasterHandler_->typeOfDisaster()) {
521 // We want to abort
522 abortSearch=true;
523 goto disaster;
524 }
525 // try just going back in (but with dual)
526 disasterHandler_->setPhase(1);
527 solver->dual();
528 totalIterations += solver->numberIterations();
529 if (disasterHandler_->inTrouble()) {
530#ifdef COIN_DEVELOP
531 printf("primal trouble b\n");
532#endif
533 if (disasterHandler_->typeOfDisaster()) {
534 // We want to abort
535 abortSearch=true;
536 goto disaster;
537 }
538 // try primal with original basis
539 disasterHandler_->setPhase(2);
540 setBasis(basis_,solver);
541 solver->dual();
542 totalIterations += solver->numberIterations();
543 }
544 if(disasterHandler_->inTrouble()) {
545#ifdef COIN_DEVELOP
546 printf("disaster - treat as infeasible\n");
547#endif
548 if (disasterHandler_->typeOfDisaster()) {
549 // We want to abort
550 abortSearch=true;
551 goto disaster;
552 }
553 solver->setProblemStatus(1);
554 }
555 }
556 // reset
557 solver->setDisasterHandler(NULL);
558 }
559 }
560 }
561 }
562 lastAlgorithm_=1; // primal
563 //if (solver->numberIterations())
564 //printf("****** iterated %d\n",solver->numberIterations());
565 } else {
566 // do we want crash
567 if (doCrash>0)
568 solver->crash(1000.0,2);
569 else if (doCrash==0)
570 solver->crash(1000.0,0);
571 if (algorithm<0)
572 doPrimal=false;
573 else if (algorithm>0)
574 doPrimal=true;
575 disasterHandler_->setOsiModel(this);
576 disasterHandler_->setSimplex(solver); // as "borrowed"
577 bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0;
578 if (!doPrimal)
579 disasterHandler_->setWhereFrom(4);
580 else
581 disasterHandler_->setWhereFrom(6);
582 if (inCbcOrOther)
583 solver->setDisasterHandler(disasterHandler_);
584 if (!doPrimal) {
585 //printf("doing dual\n");
586 solver->dual(0);
587 totalIterations += solver->numberIterations();
588 if (inCbcOrOther) {
589 if(disasterHandler_->inTrouble()) {
590#ifdef COIN_DEVELOP
591 printf("dual trouble a\n");
592#endif
593 if (disasterHandler_->typeOfDisaster()) {
594 // We want to abort
595 abortSearch=true;
596 goto disaster;
597 }
598 // try just going back in
599 disasterHandler_->setPhase(1);
600 solver->dual();
601 totalIterations += solver->numberIterations();
602 if (disasterHandler_->inTrouble()) {
603#ifdef COIN_DEVELOP
604 printf("dual trouble b\n");
605#endif
606 if (disasterHandler_->typeOfDisaster()) {
607 // We want to abort
608 abortSearch=true;
609 goto disaster;
610 }
611 // try primal with original basis
612 disasterHandler_->setPhase(2);
613 setBasis(basis_,solver);
614 solver->primal();
615 totalIterations += solver->numberIterations();
616 }
617 if(disasterHandler_->inTrouble()) {
618#ifdef COIN_DEVELOP
619 printf("disaster - treat as infeasible\n");
620#endif
621 if (disasterHandler_->typeOfDisaster()) {
622 // We want to abort
623 abortSearch=true;
624 goto disaster;
625 }
626 solver->setProblemStatus(1);
627 }
628 }
629 // reset
630 solver->setDisasterHandler(NULL);
631 }
632 lastAlgorithm_=2; // dual
633 // check if clp thought it was in a loop
634 if (solver->status()==3&&!solver->hitMaximumIterations()) {
635 // switch algorithm
636 solver->primal(0);
637 totalIterations += solver->numberIterations();
638 lastAlgorithm_=1; // primal
639 }
640 } else {
641 //printf("doing primal\n");
642 solver->primal(1);
643 totalIterations += solver->numberIterations();
644 if (inCbcOrOther) {
645 if(disasterHandler_->inTrouble()) {
646#ifdef COIN_DEVELOP
647 printf("primal trouble a\n");
648#endif
649 if (disasterHandler_->typeOfDisaster()) {
650 // We want to abort
651 abortSearch=true;
652 goto disaster;
653 }
654 // try just going back in (but with dual)
655 disasterHandler_->setPhase(1);
656 solver->dual();
657 totalIterations += solver->numberIterations();
658 if (disasterHandler_->inTrouble()) {
659#ifdef COIN_DEVELOP
660 printf("primal trouble b\n");
661#endif
662 if (disasterHandler_->typeOfDisaster()) {
663 // We want to abort
664 abortSearch=true;
665 goto disaster;
666 }
667 // try primal with original basis
668 disasterHandler_->setPhase(2);
669 setBasis(basis_,solver);
670 solver->dual();
671 totalIterations += solver->numberIterations();
672 }
673 if(disasterHandler_->inTrouble()) {
674#ifdef COIN_DEVELOP
675 printf("disaster - treat as infeasible\n");
676#endif
677 if (disasterHandler_->typeOfDisaster()) {
678 // We want to abort
679 abortSearch=true;
680 goto disaster;
681 }
682 solver->setProblemStatus(1);
683 }
684 }
685 // reset
686 solver->setDisasterHandler(NULL);
687 }
688 lastAlgorithm_=1; // primal
689 // check if clp thought it was in a loop
690 if (solver->status()==3&&!solver->hitMaximumIterations()) {
691 // switch algorithm
692 solver->dual(0);
693 totalIterations += solver->numberIterations();
694 lastAlgorithm_=2; // dual
695 }
696 }
697 }
698 // If scaled feasible but unscaled infeasible take action
699 if (!solver->status()&&cleanupScaling_) {
700 solver->cleanup(cleanupScaling_);
701 }
702 basis_ = getBasis(solver);
703 //basis_.print();
704 const double * rowScale2 = solver->rowScale();
705 solver->setSpecialOptions(saveOptions);
706 if (!rowScale1&&rowScale2) {
707 // need to release memory
708 if (!solver->savedRowScale_) {
709 solver->setRowScale(NULL);
710 solver->setColumnScale(NULL);
711 } else {
712 solver->rowScale_=NULL;
713 solver->columnScale_=NULL;
714 }
715 }
716 } else {
717 // User doing nothing and all slack basis
718 ClpSolve options=solveOptions_;
719 bool yesNo;
720 OsiHintStrength strength;
721 getHintParam(OsiDoInBranchAndCut,yesNo,strength);
722 if (yesNo) {
723 solver->setSpecialOptions(solver->specialOptions()|1024);
724 }
725 solver->initialSolve(options);
726 totalIterations += solver->numberIterations();
727 lastAlgorithm_ = 2; // say dual
728 // If scaled feasible but unscaled infeasible take action
729 if (!solver->status()&&cleanupScaling_) {
730 solver->cleanup(cleanupScaling_);
731 }
732 basis_ = getBasis(solver);
733 //basis_.print();
734 }
735 solver->messageHandler()->setLogLevel(saveMessageLevel);
736 disaster:
737 if (deleteSolver) {
738 solver->returnModel(*modelPtr_);
739 delete solver;
740 }
741 if (startFinishOptions) {
742 int save = modelPtr_->logLevel();
743 if (save<2) modelPtr_->setLogLevel(0);
744 modelPtr_->dual(0,startFinishOptions);
745 totalIterations += modelPtr_->numberIterations();
746 modelPtr_->setLogLevel(save);
747 }
748 if (saveSolveType==2) {
749 enableSimplexInterface(doingPrimal);
750 }
751 if (savedObjective) {
752 // fix up
753 modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit;
754 //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32));
755 modelPtr_->objective_=savedObjective;
756 if (!modelPtr_->problemStatus_) {
757 CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_);
758 CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_);
759 if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0)
760 CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_);
761 modelPtr_->computeObjectiveValue();
762 }
763 }
764 modelPtr_->setNumberIterations(totalIterations);
765 handler_->setLogLevel(saveMessageLevel2);
766 if (modelPtr_->problemStatus_==3&&lastAlgorithm_==2)
767 modelPtr_->computeObjectiveValue();
768 // mark so we can pick up objective value quickly
769 modelPtr_->upperIn_=0.0;
770 time1 = CoinCpuTime()-time1;
771 totalTime += time1;
772 assert (!modelPtr_->disasterHandler());
773 if (lastAlgorithm_<1||lastAlgorithm_>2)
774 lastAlgorithm_=1;
775 if (abortSearch) {
776 lastAlgorithm_=-911;
777 modelPtr_->setProblemStatus(4);
778 }
779 modelPtr_->whatsChanged_ |= 0x30000;
780 //std::cout<<time1<<" seconds - total "<<totalTime<<std::endl;
781 delete pinfo;
782}
783//-----------------------------------------------------------------------------
784void OsiClpSolverInterface::resolve()
785{
786#ifdef COIN_DEVELOP
787 {
788 int i;
789 int n = getNumCols();
790 const double *lower = getColLower() ;
791 const double *upper = getColUpper() ;
792 for (i=0;i<n;i++) {
793 assert (lower[i]<1.0e12);
794 assert (upper[i]>-1.0e12);
795 }
796 n = getNumRows();
797 lower = getRowLower() ;
798 upper = getRowUpper() ;
799 for (i=0;i<n;i++) {
800 assert (lower[i]<1.0e12);
801 assert (upper[i]>-1.0e12);
802 }
803 }
804#endif
805 if ((stuff_.solverOptions_&65536)!=0) {
806 modelPtr_->fastDual2(&stuff_);
807 return;
808 }
809 if ((specialOptions_&2097152)!=0||(specialOptions_&4194304)!=0) {
810 bool takeHint;
811 OsiHintStrength strength;
812 int algorithm = 0;
813 getHintParam(OsiDoDualInResolve,takeHint,strength);
814 if (strength!=OsiHintIgnore)
815 algorithm = takeHint ? -1 : 1;
816 if (algorithm>0||(specialOptions_&4194304)!=0) {
817 // Gub
818 resolveGub((9*modelPtr_->numberRows())/10);
819 return;
820 }
821 }
822 //void pclp(char *);
823 //pclp("res");
824 bool takeHint;
825 OsiHintStrength strength;
826 bool gotHint = (getHintParam(OsiDoInBranchAndCut,takeHint,strength));
827 assert (gotHint);
828 // mark so we can pick up objective value quickly
829 modelPtr_->upperIn_=0.0;
830 if ((specialOptions_&4096)!=0) {
831 // Quick check to see if optimal
832 modelPtr_->checkSolutionInternal();
833 if (modelPtr_->problemStatus()==0) {
834 modelPtr_->setNumberIterations(0);
835 return;
836 }
837 }
838 int totalIterations=0;
839 bool abortSearch=false;
840 ClpObjective * savedObjective=NULL;
841 double savedDualLimit=modelPtr_->dblParam_[ClpDualObjectiveLimit];
842 if (fakeObjective_) {
843 modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~128));
844 // See if all with costs fixed
845 int numberColumns = modelPtr_->numberColumns_;
846 const double * obj = modelPtr_->objective();
847 const double * lower = modelPtr_->columnLower();
848 const double * upper = modelPtr_->columnUpper();
849 int i;
850 for (i=0;i<numberColumns;i++) {
851 double objValue = obj[i];
852 if (objValue) {
853 if (lower[i]!=upper[i])
854 break;
855 }
856 }
857 if (i==numberColumns) {
858 if ((specialOptions_&524288)==0) {
859 // Set fake
860 savedObjective=modelPtr_->objective_;
861 modelPtr_->objective_=fakeObjective_;
862 modelPtr_->dblParam_[ClpDualObjectiveLimit]=COIN_DBL_MAX;
863 } else {
864 modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()|128);
865 }
866 }
867 }
868 // If using Clp initialSolve and primal - just do here
869 gotHint = (getHintParam(OsiDoDualInResolve,takeHint,strength));
870 assert (gotHint);
871 if (strength!=OsiHintIgnore&&!takeHint&&solveOptions_.getSpecialOption(6)) {
872 ClpSolve options=solveOptions_;
873 // presolve
874 getHintParam(OsiDoPresolveInResolve,takeHint,strength);
875 if (strength!=OsiHintIgnore&&!takeHint)
876 options.setPresolveType(ClpSolve::presolveOff);
877 int saveOptions = modelPtr_->specialOptions();
878 getHintParam(OsiDoInBranchAndCut,takeHint,strength);
879 if (takeHint) {
880 modelPtr_->setSpecialOptions(modelPtr_->specialOptions()|1024);
881 }
882 setBasis(basis_,modelPtr_);
883 modelPtr_->initialSolve(options);
884 lastAlgorithm_ = 1; // say primal
885 // If scaled feasible but unscaled infeasible take action
886 if (!modelPtr_->status()&&cleanupScaling_) {
887 modelPtr_->cleanup(cleanupScaling_);
888 }
889 modelPtr_->setSpecialOptions(saveOptions); // restore
890 basis_ = getBasis(modelPtr_);
891 }
892 int saveSolveType=modelPtr_->solveType();
893 bool doingPrimal = modelPtr_->algorithm()>0;
894 if (saveSolveType==2) {
895 disableSimplexInterface();
896 }
897 int saveOptions = modelPtr_->specialOptions();
898 int startFinishOptions=0;
899 if (specialOptions_!=0x80000000) {
900 if((specialOptions_&1)==0) {
901 startFinishOptions=0;
902 modelPtr_->setSpecialOptions(saveOptions|(64|1024|32768));
903 } else {
904 startFinishOptions=1+4;
905 if ((specialOptions_&8)!=0)
906 startFinishOptions +=2; // allow re-use of factorization
907 if((specialOptions_&4)==0||!takeHint)
908 modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|4096|32768));
909 else
910 modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|2048|4096|32768));
911 }
912 } else {
913 modelPtr_->setSpecialOptions(saveOptions|64|32768);
914 }
915 //printf("options %d size %d\n",modelPtr_->specialOptions(),modelPtr_->numberColumns());
916 //modelPtr_->setSolveType(1);
917 // Set message handler to have same levels etc
918 int saveMessageLevel=modelPtr_->logLevel();
919 int messageLevel=messageHandler()->logLevel();
920 bool oldDefault;
921 CoinMessageHandler * saveHandler = modelPtr_->pushMessageHandler(handler_,oldDefault);
922 //printf("basis before dual\n");
923 //basis_.print();
924 setBasis(basis_,modelPtr_);
925#ifdef SAVE_MODEL
926 resolveTry++;
927#if SAVE_MODEL > 1
928 if (resolveTry>=loResolveTry&&
929 resolveTry<=hiResolveTry) {
930 char fileName[20];
931 sprintf(fileName,"save%d.mod",resolveTry);
932 modelPtr_->saveModel(fileName);
933 }
934#endif
935#endif
936 // set reasonable defaults
937 // Switch off printing if asked to
938 gotHint = (getHintParam(OsiDoReducePrint,takeHint,strength));
939 assert (gotHint);
940 if (strength!=OsiHintIgnore&&takeHint) {
941 if (messageLevel>0)
942 messageLevel--;
943 }
944 if (messageLevel<modelPtr_->messageHandler()->logLevel())
945 modelPtr_->messageHandler()->setLogLevel(messageLevel);
946 // See if user set factorization frequency
947 int userFactorizationFrequency = modelPtr_->factorization()->maximumPivots();
948 // scaling
949 if (modelPtr_->solveType()==1) {
950 gotHint = (getHintParam(OsiDoScale,takeHint,strength));
951 assert (gotHint);
952 if (strength==OsiHintIgnore||takeHint) {
953 if (!modelPtr_->scalingFlag())
954 modelPtr_->scaling(3);
955 } else {
956 modelPtr_->scaling(0);
957 }
958 } else {
959 modelPtr_->scaling(0);
960 }
961 // sort out hints;
962 // algorithm -1 force dual, +1 force primal
963 int algorithm = -1;
964 gotHint = (getHintParam(OsiDoDualInResolve,takeHint,strength));
965 assert (gotHint);
966 if (strength!=OsiHintIgnore)
967 algorithm = takeHint ? -1 : 1;
968 //modelPtr_->saveModel("save.bad");
969 // presolve
970 gotHint = (getHintParam(OsiDoPresolveInResolve,takeHint,strength));
971 assert (gotHint);
972 if (strength!=OsiHintIgnore&&takeHint) {
973#ifdef KEEP_SMALL
974 if (smallModel_) {
975 delete [] spareArrays_;
976 spareArrays_ = NULL;
977 delete smallModel_;
978 smallModel_=NULL;
979 }
980#endif
981 ClpPresolve pinfo;
982 if ((specialOptions_&128)!=0) {
983 specialOptions_ &= ~128;
984 }
985 if ((modelPtr_->specialOptions()&1024)!=0) {
986 pinfo.setDoDual(false);
987 pinfo.setDoTripleton(false);
988 pinfo.setDoDupcol(false);
989 pinfo.setDoDuprow(false);
990 pinfo.setDoSingletonColumn(false);
991 }
992 ClpSimplex * model2 = pinfo.presolvedModel(*modelPtr_,1.0e-8);
993 if (!model2) {
994 // problem found to be infeasible - whats best?
995 model2 = modelPtr_;
996 }
997 // return number of rows
998 int * stats = reinterpret_cast<int *> (getApplicationData());
999 if (stats) {
1000 stats[0]=model2->numberRows();
1001 stats[1]=model2->numberColumns();
1002 }
1003 //printf("rows %d -> %d, columns %d -> %d\n",
1004 // modelPtr_->numberRows(),model2->numberRows(),
1005 // modelPtr_->numberColumns(),model2->numberColumns());
1006 // change from 200
1007 if (modelPtr_->factorization()->maximumPivots()==200)
1008 model2->factorization()->maximumPivots(100+model2->numberRows()/50);
1009 else
1010 model2->factorization()->maximumPivots(userFactorizationFrequency);
1011 if (algorithm<0) {
1012 model2->dual();
1013 totalIterations += model2->numberIterations();
1014 // check if clp thought it was in a loop
1015 if (model2->status()==3&&!model2->hitMaximumIterations()) {
1016 // switch algorithm
1017 model2->primal();
1018 totalIterations += model2->numberIterations();
1019 }
1020 } else {
1021 model2->primal(1);
1022 totalIterations += model2->numberIterations();
1023 // check if clp thought it was in a loop
1024 if (model2->status()==3&&!model2->hitMaximumIterations()) {
1025 // switch algorithm
1026 model2->dual();
1027 totalIterations += model2->numberIterations();
1028 }
1029 }
1030 if (model2!=modelPtr_) {
1031 int finalStatus=model2->status();
1032 pinfo.postsolve(true);
1033
1034 delete model2;
1035 // later try without (1) and check duals before solve
1036 if (finalStatus!=3&&(finalStatus||modelPtr_->status()==-1)) {
1037 modelPtr_->primal(1);
1038 totalIterations += modelPtr_->numberIterations();
1039 lastAlgorithm_=1; // primal
1040 //if (modelPtr_->numberIterations())
1041 //printf("****** iterated %d\n",modelPtr_->numberIterations());
1042 }
1043 }
1044 } else {
1045 //modelPtr_->setLogLevel(63);
1046 //modelPtr_->setDualTolerance(1.0e-7);
1047 if (false&&modelPtr_->scalingFlag_>0&&!modelPtr_->rowScale_&&
1048 !modelPtr_->rowCopy_&&matrixByRow_) {
1049 assert (matrixByRow_->getNumElements()==modelPtr_->clpMatrix()->getNumElements());
1050 modelPtr_->setNewRowCopy(new ClpPackedMatrix(*matrixByRow_));
1051 }
1052 if (algorithm<0) {
1053 //writeMps("try1");
1054 int savePerturbation = modelPtr_->perturbation();
1055 if ((specialOptions_&2)!=0)
1056 modelPtr_->setPerturbation(100);
1057 //modelPtr_->messageHandler()->setLogLevel(1);
1058 //writeMpsNative("bad",NULL,NULL,2,1,1.0);
1059 disasterHandler_->setOsiModel(this);
1060 bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0;
1061#if 0
1062 // See how many integers fixed
1063 bool skipCrunch=true;
1064 const char * integerInformation = modelPtr_->integerType_;
1065 if (integerInformation) {
1066 int numberColumns = modelPtr_->numberColumns_;
1067 const double * lower = modelPtr_->columnLower();
1068 const double * upper = modelPtr_->columnUpper();
1069 int target=CoinMax(1,numberColumns/10000);
1070 for (int i=0;i<numberColumns;i++) {
1071 if (integerInformation[i]) {
1072 if (lower[i]==upper[i]) {
1073 target--;
1074 if (!target) {
1075 skipCrunch=false;
1076 break;
1077 }
1078 }
1079 }
1080 }
1081 }
1082#endif
1083 if((specialOptions_&1)==0||(specialOptions_&2048)!=0/*||skipCrunch*/) {
1084 disasterHandler_->setWhereFrom(0); // dual
1085 if (inCbcOrOther)
1086 modelPtr_->setDisasterHandler(disasterHandler_);
1087 bool specialScale;
1088 if ((specialOptions_&131072)!=0&&!modelPtr_->rowScale_) {
1089 modelPtr_->rowScale_ = rowScale_.array();
1090 modelPtr_->columnScale_ = columnScale_.array();
1091 specialScale=true;
1092 } else {
1093 specialScale=false;
1094 }
1095#ifdef KEEP_SMALL
1096 if (smallModel_) {
1097 delete [] spareArrays_;
1098 spareArrays_ = NULL;
1099 delete smallModel_;
1100 smallModel_=NULL;
1101 }
1102#endif
1103#ifdef CBC_STATISTICS
1104 osi_dual++;
1105#endif
1106 modelPtr_->dual(0,startFinishOptions);
1107 totalIterations += modelPtr_->numberIterations();
1108 if (specialScale) {
1109 modelPtr_->rowScale_ = NULL;
1110 modelPtr_->columnScale_ = NULL;
1111 }
1112 } else {
1113#ifdef CBC_STATISTICS
1114 osi_crunch++;
1115#endif
1116 crunch();
1117 totalIterations += modelPtr_->numberIterations();
1118 if (modelPtr_->problemStatus()==4)
1119 goto disaster;
1120 // should have already been fixed if problems
1121 inCbcOrOther=false;
1122 }
1123 if (inCbcOrOther) {
1124 if(disasterHandler_->inTrouble()) {
1125 if (disasterHandler_->typeOfDisaster()) {
1126 // We want to abort
1127 abortSearch=true;
1128 goto disaster;
1129 }
1130 // try just going back in
1131 disasterHandler_->setPhase(1);
1132 modelPtr_->dual();
1133 totalIterations += modelPtr_->numberIterations();
1134 if (disasterHandler_->inTrouble()) {
1135 if (disasterHandler_->typeOfDisaster()) {
1136 // We want to abort
1137 abortSearch=true;
1138 goto disaster;
1139 }
1140 // try primal with original basis
1141 disasterHandler_->setPhase(2);
1142 setBasis(basis_,modelPtr_);
1143 modelPtr_->primal();
1144 totalIterations += modelPtr_->numberIterations();
1145 }
1146 if(disasterHandler_->inTrouble()) {
1147#ifdef COIN_DEVELOP
1148 printf("disaster - treat as infeasible\n");
1149#endif
1150 if (disasterHandler_->typeOfDisaster()) {
1151 // We want to abort
1152 abortSearch=true;
1153 goto disaster;
1154 }
1155 modelPtr_->setProblemStatus(1);
1156 }
1157 }
1158 // reset
1159 modelPtr_->setDisasterHandler(NULL);
1160 }
1161 if (modelPtr_->problemStatus()==4) {
1162 // bad bounds?
1163 modelPtr_->setProblemStatus(1);
1164 }
1165 if (!modelPtr_->problemStatus()&&0) {
1166 int numberColumns = modelPtr_->numberColumns();
1167 const double * columnLower = modelPtr_->columnLower();
1168 const double * columnUpper = modelPtr_->columnUpper();
1169 int nBad=0;
1170 for (int i=0;i<numberColumns;i++) {
1171 if (columnLower[i]==columnUpper[i]&&modelPtr_->getColumnStatus(i)==ClpSimplex::basic) {
1172 nBad++;
1173 modelPtr_->setColumnStatus(i,ClpSimplex::isFixed);
1174 }
1175 }
1176 if (nBad) {
1177 modelPtr_->primal(1);
1178 totalIterations += modelPtr_->numberIterations();
1179 printf("%d fixed basic - %d iterations\n",nBad,modelPtr_->numberIterations());
1180 }
1181 }
1182 assert (modelPtr_->objectiveValue()<1.0e100);
1183 modelPtr_->setPerturbation(savePerturbation);
1184 lastAlgorithm_=2; // dual
1185 // check if clp thought it was in a loop
1186 if (modelPtr_->status()==3&&!modelPtr_->hitMaximumIterations()) {
1187 modelPtr_->setSpecialOptions(saveOptions);
1188 // switch algorithm
1189 //modelPtr_->messageHandler()->setLogLevel(63);
1190 // Allow for catastrophe
1191 int saveMax = modelPtr_->maximumIterations();
1192 int numberIterations = modelPtr_->numberIterations();
1193 int numberRows = modelPtr_->numberRows();
1194 int numberColumns = modelPtr_->numberColumns();
1195 if (modelPtr_->maximumIterations()>100000+numberIterations)
1196 modelPtr_->setMaximumIterations(numberIterations + 1000 + 2*numberRows+numberColumns);
1197 modelPtr_->primal(0,startFinishOptions);
1198 totalIterations += modelPtr_->numberIterations();
1199 modelPtr_->setMaximumIterations(saveMax);
1200 lastAlgorithm_=1; // primal
1201 if (modelPtr_->status()==3&&!modelPtr_->hitMaximumIterations()) {
1202#ifdef COIN_DEVELOP
1203 printf("in trouble - try all slack\n");
1204#endif
1205 CoinWarmStartBasis allSlack;
1206 setBasis(allSlack,modelPtr_);
1207 modelPtr_->dual();
1208 totalIterations += modelPtr_->numberIterations();
1209 if (modelPtr_->status()==3&&!modelPtr_->hitMaximumIterations()) {
1210 if (modelPtr_->numberPrimalInfeasibilities()) {
1211#ifdef COIN_DEVELOP
1212 printf("Real real trouble - treat as infeasible\n");
1213#endif
1214 modelPtr_->setProblemStatus(1);
1215 } else {
1216#ifdef COIN_DEVELOP
1217 printf("Real real trouble - treat as optimal\n");
1218#endif
1219 modelPtr_->setProblemStatus(0);
1220 }
1221 }
1222 }
1223 }
1224 assert (modelPtr_->objectiveValue()<1.0e100);
1225 } else {
1226#ifdef KEEP_SMALL
1227 if (smallModel_) {
1228 delete [] spareArrays_;
1229 spareArrays_ = NULL;
1230 delete smallModel_;
1231 smallModel_=NULL;
1232 }
1233#endif
1234 //printf("doing primal\n");
1235#ifdef CBC_STATISTICS
1236 osi_primal++;
1237#endif
1238 modelPtr_->primal(1,startFinishOptions);
1239 totalIterations += modelPtr_->numberIterations();
1240 lastAlgorithm_=1; // primal
1241 // check if clp thought it was in a loop
1242 if (modelPtr_->status()==3&&!modelPtr_->hitMaximumIterations()) {
1243 // switch algorithm
1244 modelPtr_->dual();
1245 totalIterations += modelPtr_->numberIterations();
1246 lastAlgorithm_=2; // dual
1247 }
1248 }
1249 }
1250 // If scaled feasible but unscaled infeasible take action
1251 //if (!modelPtr_->status()&&cleanupScaling_) {
1252 if (cleanupScaling_) {
1253 modelPtr_->cleanup(cleanupScaling_);
1254 }
1255 basis_ = getBasis(modelPtr_);
1256 disaster:
1257 //printf("basis after dual\n");
1258 //basis_.print();
1259 modelPtr_->popMessageHandler(saveHandler,oldDefault);
1260 modelPtr_->messageHandler()->setLogLevel(saveMessageLevel);
1261 if (saveSolveType==2) {
1262 int saveStatus = modelPtr_->problemStatus_;
1263 enableSimplexInterface(doingPrimal);
1264 modelPtr_->problemStatus_=saveStatus;
1265 }
1266#ifdef COIN_DEVELOP_x
1267 extern bool doingDoneBranch;
1268 if (doingDoneBranch) {
1269 if (modelPtr_->numberIterations())
1270 printf("***** done %d iterations after general\n",modelPtr_->numberIterations());
1271 doingDoneBranch=false;
1272 }
1273#endif
1274 modelPtr_->setNumberIterations(totalIterations);
1275 //modelPtr_->setSolveType(saveSolveType);
1276 if (abortSearch) {
1277 lastAlgorithm_=-911;
1278 modelPtr_->setProblemStatus(4);
1279 }
1280 if (savedObjective) {
1281 // fix up
1282 modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit;
1283 //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32));
1284 modelPtr_->objective_=savedObjective;
1285 if (!modelPtr_->problemStatus_) {
1286 CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_);
1287 CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_);
1288 if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0)
1289 CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_);
1290 modelPtr_->computeObjectiveValue();
1291 }
1292 }
1293 modelPtr_->setSpecialOptions(saveOptions); // restore
1294 if (modelPtr_->problemStatus_==3&&lastAlgorithm_==2)
1295 modelPtr_->computeObjectiveValue();
1296 if (lastAlgorithm_<1||lastAlgorithm_>2)
1297 lastAlgorithm_=1;
1298#ifdef SAVE_MODEL
1299 if (resolveTry>=loResolveTry&&
1300 resolveTry<=hiResolveTry) {
1301 printf("resolve %d took %d iterations - algorithm %d\n",resolveTry,modelPtr_->numberIterations(),lastAlgorithm_);
1302 }
1303#endif
1304 // Make sure whatsChanged not out of sync
1305 if (!modelPtr_->columnUpperWork_)
1306 modelPtr_->whatsChanged_ &= ~0xffff;
1307 modelPtr_->whatsChanged_ |= 0x30000;
1308}
1309#include "ClpSimplexOther.hpp"
1310// Resolve an LP relaxation after problem modification (try GUB)
1311void
1312OsiClpSolverInterface::resolveGub(int needed)
1313{
1314 bool takeHint;
1315 OsiHintStrength strength;
1316 // Switch off printing if asked to
1317 getHintParam(OsiDoReducePrint,takeHint,strength);
1318 int saveMessageLevel=modelPtr_->logLevel();
1319 if (strength!=OsiHintIgnore&&takeHint) {
1320 int messageLevel=messageHandler()->logLevel();
1321 if (messageLevel>0)
1322 modelPtr_->messageHandler()->setLogLevel(messageLevel-1);
1323 else
1324 modelPtr_->messageHandler()->setLogLevel(0);
1325 }
1326 //modelPtr_->messageHandler()->setLogLevel(1);
1327 setBasis(basis_,modelPtr_);
1328 // find gub
1329 int numberRows = modelPtr_->numberRows();
1330 int * which = new int[numberRows];
1331 int numberColumns = modelPtr_->numberColumns();
1332 int * whichC = new int[numberColumns+numberRows];
1333 ClpSimplex * model2 =
1334 static_cast<ClpSimplexOther *> (modelPtr_)->gubVersion(which,whichC,
1335 needed,100);
1336 if (model2) {
1337 // move in solution
1338 static_cast<ClpSimplexOther *> (model2)->setGubBasis(*modelPtr_,
1339 which,whichC);
1340 model2->setLogLevel(CoinMin(1,model2->logLevel()));
1341 ClpPrimalColumnSteepest steepest(5);
1342 model2->setPrimalColumnPivotAlgorithm(steepest);
1343 //double time1 = CoinCpuTime();
1344 model2->primal();
1345 //printf("Primal took %g seconds\n",CoinCpuTime()-time1);
1346 static_cast<ClpSimplexOther *> (model2)->getGubBasis(*modelPtr_,
1347 which,whichC);
1348 int totalIterations = model2->numberIterations();
1349 delete model2;
1350 //modelPtr_->setLogLevel(63);
1351 modelPtr_->primal(1);
1352 modelPtr_->setNumberIterations(totalIterations+modelPtr_->numberIterations());
1353 } else {
1354 modelPtr_->dual();
1355 }
1356 delete [] which;
1357 delete [] whichC;
1358 basis_ = getBasis(modelPtr_);
1359 modelPtr_->messageHandler()->setLogLevel(saveMessageLevel);
1360}
1361// Sort of lexicographic resolve
1362void
1363OsiClpSolverInterface::lexSolve()
1364{
1365#if 1
1366 abort();
1367#else
1368 ((ClpSimplexPrimal *) modelPtr_)->lexSolve();
1369 printf("itA %d\n",modelPtr_->numberIterations());
1370 modelPtr_->primal();
1371 printf("itB %d\n",modelPtr_->numberIterations());
1372 basis_ = getBasis(modelPtr_);
1373#endif
1374}
1375
1376/* Sets up solver for repeated use by Osi interface.
1377 The normal usage does things like keeping factorization around so can be used.
1378 Will also do things like keep scaling and row copy of matrix if
1379 matrix does not change.
1380 adventure:
1381 0 - safe stuff as above
1382 1 - will take more risks - if it does not work then bug which will be fixed
1383 2 - don't bother doing most extreme termination checks e.g. don't bother
1384 re-factorizing if less than 20 iterations.
1385 3 - Actually safer than 1 (mainly just keeps factorization)
1386
1387 printOut - -1 always skip round common messages instead of doing some work
1388 0 skip if normal defaults
1389 1 leaves
1390 */
1391void
1392OsiClpSolverInterface::setupForRepeatedUse(int senseOfAdventure, int printOut)
1393{
1394 // First try
1395 switch (senseOfAdventure) {
1396 case 0:
1397 specialOptions_=8;
1398 break;
1399 case 1:
1400 specialOptions_=1+2+8;
1401 break;
1402 case 2:
1403 specialOptions_=1+2+4+8;
1404 break;
1405 case 3:
1406 specialOptions_=1+8;
1407 break;
1408 }
1409 bool stopPrinting=false;
1410 if (printOut<0) {
1411 stopPrinting=true;
1412 } else if (!printOut) {
1413 bool takeHint;
1414 OsiHintStrength strength;
1415 getHintParam(OsiDoReducePrint,takeHint,strength);
1416 int messageLevel=messageHandler()->logLevel();
1417 if (strength!=OsiHintIgnore&&takeHint)
1418 messageLevel--;
1419 stopPrinting = (messageLevel<=0);
1420 }
1421#ifndef COIN_DEVELOP
1422 if (stopPrinting) {
1423 CoinMessages * messagesPointer = modelPtr_->messagesPointer();
1424 // won't even build messages
1425 messagesPointer->setDetailMessages(100,10000,reinterpret_cast<int *> (NULL));
1426 }
1427#endif
1428}
1429#ifndef NDEBUG
1430// For errors to make sure print to screen
1431// only called in debug mode
1432static void indexError(int index,
1433 std::string methodName)
1434{
1435 std::cerr<<"Illegal index "<<index<<" in OsiClpSolverInterface::"<<methodName<<std::endl;
1436 throw CoinError("Illegal index",methodName,"OsiClpSolverInterface");
1437}
1438#endif
1439//#############################################################################
1440// Parameter related methods
1441//#############################################################################
1442
1443bool
1444OsiClpSolverInterface::setIntParam(OsiIntParam key, int value)
1445{
1446 return modelPtr_->setIntParam(static_cast<ClpIntParam> (key), value);
1447}
1448
1449//-----------------------------------------------------------------------------
1450
1451bool
1452OsiClpSolverInterface::setDblParam(OsiDblParam key, double value)
1453{
1454 if (key != OsiLastDblParam ) {
1455 if (key==OsiDualObjectiveLimit||key==OsiPrimalObjectiveLimit)
1456 value *= modelPtr_->optimizationDirection();
1457 return modelPtr_->setDblParam(static_cast<ClpDblParam> (key), value);
1458 } else {
1459 return false;
1460 }
1461}
1462
1463//-----------------------------------------------------------------------------
1464
1465bool
1466OsiClpSolverInterface::setStrParam(OsiStrParam key, const std::string & value)
1467{
1468 assert (key!=OsiSolverName);
1469 if (key != OsiLastStrParam ) {
1470 return modelPtr_->setStrParam(static_cast<ClpStrParam> (key), value);
1471 } else {
1472 return false;
1473 }
1474}
1475
1476
1477//-----------------------------------------------------------------------------
1478
1479bool
1480OsiClpSolverInterface::getIntParam(OsiIntParam key, int& value) const
1481{
1482 return modelPtr_->getIntParam(static_cast<ClpIntParam> (key), value);
1483}
1484
1485//-----------------------------------------------------------------------------
1486
1487bool
1488OsiClpSolverInterface::getDblParam(OsiDblParam key, double& value) const
1489{
1490 if (key != OsiLastDblParam ) {
1491 bool condition = modelPtr_->getDblParam(static_cast<ClpDblParam> (key), value);
1492 if (key==OsiDualObjectiveLimit||key==OsiPrimalObjectiveLimit)
1493 value *= modelPtr_->optimizationDirection();
1494 return condition;
1495 } else {
1496 return false;
1497 }
1498}
1499
1500//-----------------------------------------------------------------------------
1501
1502bool
1503OsiClpSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
1504{
1505 if ( key==OsiSolverName ) {
1506 value = "clp";
1507 return true;
1508 }
1509 if (key != OsiLastStrParam ) {
1510 return modelPtr_->getStrParam(static_cast<ClpStrParam> (key), value);
1511 } else {
1512 return false;
1513 }
1514}
1515
1516
1517//#############################################################################
1518// Methods returning info on how the solution process terminated
1519//#############################################################################
1520
1521bool OsiClpSolverInterface::isAbandoned() const
1522{
1523 // not sure about -1 (should not happen)
1524 return (modelPtr_->status()==4||modelPtr_->status()==-1||
1525 (modelPtr_->status()==1&&modelPtr_->secondaryStatus()==8));
1526}
1527
1528bool OsiClpSolverInterface::isProvenOptimal() const
1529{
1530
1531 const int stat = modelPtr_->status();
1532 return (stat == 0);
1533}
1534
1535bool OsiClpSolverInterface::isProvenPrimalInfeasible() const
1536{
1537
1538 const int stat = modelPtr_->status();
1539 if (stat != 1)
1540 return false;
1541 return true;
1542}
1543
1544bool OsiClpSolverInterface::isProvenDualInfeasible() const
1545{
1546 const int stat = modelPtr_->status();
1547 return stat == 2;
1548}
1549/*
1550 NOTE - Coding if limit > 1.0e30 says that 1.0e29 is loose bound
1551 so all maximization tests are changed
1552*/
1553bool OsiClpSolverInterface::isPrimalObjectiveLimitReached() const
1554{
1555 double limit = 0.0;
1556 modelPtr_->getDblParam(ClpPrimalObjectiveLimit, limit);
1557 if (fabs(limit) > 1e30) {
1558 // was not ever set
1559 return false;
1560 }
1561
1562 const double obj = modelPtr_->objectiveValue();
1563 int maxmin = static_cast<int> (modelPtr_->optimizationDirection());
1564
1565 switch (lastAlgorithm_) {
1566 case 0: // no simplex was needed
1567 return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/;
1568 case 2: // dual simplex
1569 if (modelPtr_->status() == 0) // optimal
1570 return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/;
1571 return false;
1572 case 1: // primal simplex
1573 return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/;
1574 }
1575 return false; // fake return
1576}
1577
1578bool OsiClpSolverInterface::isDualObjectiveLimitReached() const
1579{
1580
1581 const int stat = modelPtr_->status();
1582 if (stat == 1)
1583 return true;
1584 double limit = 0.0;
1585 modelPtr_->getDblParam(ClpDualObjectiveLimit, limit);
1586 if (fabs(limit) > 1e30) {
1587 // was not ever set
1588 return false;
1589 }
1590
1591 const double obj = modelPtr_->objectiveValue();
1592 int maxmin = static_cast<int> (modelPtr_->optimizationDirection());
1593
1594 switch (lastAlgorithm_) {
1595 case 0: // no simplex was needed
1596 return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/;
1597 case 1: // primal simplex
1598 if (stat == 0) // optimal
1599 return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/;
1600 return false;
1601 case 2: // dual simplex
1602 if (stat != 0 && stat != 3)
1603 // over dual limit
1604 return true;
1605 return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/;
1606 }
1607 return false; // fake return
1608}
1609
1610bool OsiClpSolverInterface::isIterationLimitReached() const
1611{
1612 const int stat = modelPtr_->status();
1613 return (stat == 3);
1614}
1615
1616//#############################################################################
1617// WarmStart related methods
1618//#############################################################################
1619CoinWarmStart *OsiClpSolverInterface::getEmptyWarmStart () const
1620 { return (static_cast<CoinWarmStart *>(new CoinWarmStartBasis())) ; }
1621
1622CoinWarmStart* OsiClpSolverInterface::getWarmStart() const
1623{
1624
1625 return new CoinWarmStartBasis(basis_);
1626}
1627/* Get warm start information.
1628 Return warm start information for the current state of the solver
1629 interface. If there is no valid warm start information, an empty warm
1630 start object wil be returned. This does not necessarily create an
1631 object - may just point to one. must Delete set true if user
1632 should delete returned object.
1633 OsiClp version always returns pointer and false.
1634*/
1635CoinWarmStart*
1636OsiClpSolverInterface::getPointerToWarmStart(bool & mustDelete)
1637{
1638 mustDelete = false;
1639 return &basis_;
1640}
1641
1642//-----------------------------------------------------------------------------
1643
1644bool OsiClpSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
1645{
1646 modelPtr_->whatsChanged_ &= 0xffff;
1647 const CoinWarmStartBasis* ws =
1648 dynamic_cast<const CoinWarmStartBasis*>(warmstart);
1649 if (ws) {
1650 basis_ = CoinWarmStartBasis(*ws);
1651 return true;
1652 } else if (!warmstart) {
1653 // create from current basis
1654 basis_ = getBasis(modelPtr_);
1655 return true;
1656 } else {
1657 return false;
1658 }
1659}
1660
1661//#############################################################################
1662// Hotstart related methods (primarily used in strong branching)
1663//#############################################################################
1664void OsiClpSolverInterface::markHotStart()
1665{
1666#ifdef CBC_STATISTICS
1667 osi_hot++;
1668#endif
1669 //printf("HotStart options %x changed %x, small %x spare %x\n",
1670 // specialOptions_,modelPtr_->whatsChanged_,
1671 // smallModel_,spareArrays_);
1672 modelPtr_->setProblemStatus(0);
1673 saveData_.perturbation_=0;
1674 saveData_.specialOptions_ = modelPtr_->specialOptions_;
1675 modelPtr_->specialOptions_ |= 0x1000000;
1676 modelPtr_->specialOptions_ = saveData_.specialOptions_;
1677 ClpObjective * savedObjective=NULL;
1678 double savedDualLimit=modelPtr_->dblParam_[ClpDualObjectiveLimit];
1679 if (fakeObjective_) {
1680 modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~128));
1681 // See if all with costs fixed
1682 int numberColumns = modelPtr_->numberColumns_;
1683 const double * obj = modelPtr_->objective();
1684 const double * lower = modelPtr_->columnLower();
1685 const double * upper = modelPtr_->columnUpper();
1686 int i;
1687 for (i=0;i<numberColumns;i++) {
1688 double objValue = obj[i];
1689 if (objValue) {
1690 if (lower[i]!=upper[i])
1691 break;
1692 }
1693 }
1694 if (i==numberColumns) {
1695 if ((specialOptions_&524288)==0) {
1696 // Set fake
1697 savedObjective=modelPtr_->objective_;
1698 modelPtr_->objective_=fakeObjective_;
1699 modelPtr_->dblParam_[ClpDualObjectiveLimit]=COIN_DBL_MAX;
1700 saveData_.perturbation_=1;
1701 } else {
1702 modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()|128);
1703 }
1704 }
1705 }
1706#define CLEAN_HOT_START
1707#ifdef CLEAN_HOT_START
1708 if ((specialOptions_&65536)!=0) {
1709 //specialOptions_ |= 65536;
1710 saveData_.scalingFlag_=modelPtr_->logLevel();
1711 if (modelPtr_->logLevel()<2)
1712 modelPtr_->setLogLevel(0);
1713 assert ((specialOptions_&128)==0);
1714 // space for save arrays
1715 int numberColumns = modelPtr_->numberColumns();
1716 int numberRows = modelPtr_->numberRows();
1717 // Get space for strong branching
1718 int size = static_cast<int>((1+4*(numberRows+numberColumns))*sizeof(double));
1719 // and for save of original column bounds
1720 size += static_cast<int>(2*numberColumns*sizeof(double));
1721 size += static_cast<int>((1+4*numberRows+2*numberColumns)*sizeof(int));
1722 size += numberRows+numberColumns;
1723 assert (spareArrays_==NULL);
1724 spareArrays_ = new char[size];
1725 //memset(spareArrays_,0x20,size);
1726 // Setup for strong branching
1727 assert (factorization_==NULL);
1728 if ((specialOptions_&131072)!=0) {
1729 assert (lastNumberRows_>=0);
1730 if (modelPtr_->rowScale_!=rowScale_.array()) {
1731 assert(modelPtr_->columnScale_!=columnScale_.array());
1732 delete [] modelPtr_->rowScale_;
1733 modelPtr_->rowScale_=NULL;
1734 delete [] modelPtr_->columnScale_;
1735 modelPtr_->columnScale_=NULL;
1736 if (lastNumberRows_==modelPtr_->numberRows()) {
1737 // use scaling
1738 modelPtr_->rowScale_ = rowScale_.array();
1739 modelPtr_->columnScale_ = columnScale_.array();
1740 } else {
1741 specialOptions_ &= ~131072;
1742 }
1743 }
1744 lastNumberRows_ = -1 -lastNumberRows_;
1745 }
1746 factorization_ = static_cast<ClpSimplexDual *>(modelPtr_)->setupForStrongBranching(spareArrays_,numberRows,
1747 numberColumns,true);
1748 double * arrayD = reinterpret_cast<double *> (spareArrays_);
1749 arrayD[0]=modelPtr_->objectiveValue()* modelPtr_->optimizationDirection();
1750 double * saveSolution = arrayD+1;
1751 double * saveLower = saveSolution + (numberRows+numberColumns);
1752 double * saveUpper = saveLower + (numberRows+numberColumns);
1753 double * saveObjective = saveUpper + (numberRows+numberColumns);
1754 double * saveLowerOriginal = saveObjective + (numberRows+numberColumns);
1755 double * saveUpperOriginal = saveLowerOriginal + numberColumns;
1756 CoinMemcpyN( modelPtr_->columnLower(),numberColumns, saveLowerOriginal);
1757 CoinMemcpyN( modelPtr_->columnUpper(),numberColumns, saveUpperOriginal);
1758#if 0
1759 if (whichRange_&&whichRange_[0]) {
1760 // get ranging information
1761 int numberToDo = whichRange_[0];
1762 int * which = new int [numberToDo];
1763 // Convert column numbers
1764 int * backColumn = whichColumn+numberColumns;
1765 for (int i=0;i<numberToDo;i++) {
1766 int iColumn = whichRange_[i+1];
1767 which[i]=backColumn[iColumn];
1768 }
1769 double * downRange=new double [numberToDo];
1770 double * upRange=new double [numberToDo];
1771 int * whichDown = new int [numberToDo];
1772 int * whichUp = new int [numberToDo];
1773 modelPtr_->gutsOfSolution(NULL,NULL,false);
1774 // Tell code we can increase costs in some cases
1775 modelPtr_->setCurrentDualTolerance(0.0);
1776 ((ClpSimplexOther *) modelPtr_)->dualRanging(numberToDo,which,
1777 upRange, whichUp, downRange, whichDown);
1778 delete [] whichDown;
1779 delete [] whichUp;
1780 delete [] which;
1781 rowActivity_=upRange;
1782 columnActivity_=downRange;
1783 }
1784#endif
1785 if (savedObjective) {
1786 // fix up
1787 modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit;
1788 //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32));
1789 modelPtr_->objective_=savedObjective;
1790 if (!modelPtr_->problemStatus_) {
1791 CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_);
1792 CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_);
1793 if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0)
1794 CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_);
1795 modelPtr_->computeObjectiveValue();
1796 }
1797 }
1798 return;
1799 }
1800#endif
1801 if ((specialOptions_&8192)==0&&false) { // ||(specialOptions_&65536)!=0) {
1802 delete ws_;
1803 ws_ = dynamic_cast<CoinWarmStartBasis*>(getWarmStart());
1804 int numberRows = modelPtr_->numberRows();
1805 rowActivity_= new double[numberRows];
1806 CoinMemcpyN(modelPtr_->primalRowSolution(),numberRows,rowActivity_);
1807 int numberColumns = modelPtr_->numberColumns();
1808 columnActivity_= new double[numberColumns];
1809 CoinMemcpyN(modelPtr_->primalColumnSolution(),numberColumns,columnActivity_);
1810 } else {
1811#if 0
1812 int saveLevel = modelPtr_->logLevel();
1813 modelPtr_->setLogLevel(0);
1814 //modelPtr_->dual();
1815 OsiClpSolverInterface::resolve();
1816 if (modelPtr_->numberIterations()>0)
1817 printf("**** iterated large %d\n",modelPtr_->numberIterations());
1818 //else
1819 //printf("no iterations\n");
1820 modelPtr_->setLogLevel(saveLevel);
1821#endif
1822 // called from CbcNode
1823 int numberColumns = modelPtr_->numberColumns();
1824 int numberRows = modelPtr_->numberRows();
1825 // Get space for crunch and strong branching (too much)
1826 int size = static_cast<int>((1+4*(numberRows+numberColumns))*sizeof(double));
1827 // and for save of original column bounds
1828 size += static_cast<int>(2*numberColumns*sizeof(double));
1829 size += static_cast<int>((1+4*numberRows+2*numberColumns)*sizeof(int));
1830 size += numberRows+numberColumns;
1831#ifdef KEEP_SMALL
1832 if(smallModel_&&(modelPtr_->whatsChanged_&0x30000)!=0x30000) {
1833 //printf("Bounds changed ? %x\n",modelPtr_->whatsChanged_);
1834 delete smallModel_;
1835 smallModel_=NULL;
1836 }
1837 if (!smallModel_) {
1838 delete [] spareArrays_;
1839 spareArrays_ = NULL;
1840 }
1841#endif
1842 if (spareArrays_==NULL) {
1843 //if (smallModel_)
1844 //printf("small model %x\n",smallModel_);
1845 delete smallModel_;
1846 smallModel_=NULL;
1847 spareArrays_ = new char[size];
1848 //memset(spareArrays_,0x20,size);
1849 } else {
1850 double * arrayD = reinterpret_cast<double *> (spareArrays_);
1851 double * saveSolution = arrayD+1;
1852 double * saveLower = saveSolution + (numberRows+numberColumns);
1853 double * saveUpper = saveLower + (numberRows+numberColumns);
1854 double * saveObjective = saveUpper + (numberRows+numberColumns);
1855 double * saveLowerOriginal = saveObjective + (numberRows+numberColumns);
1856 double * saveUpperOriginal = saveLowerOriginal + numberColumns;
1857 double * lowerOriginal = modelPtr_->columnLower();
1858 double * upperOriginal = modelPtr_->columnUpper();
1859 arrayD = saveUpperOriginal + numberColumns;
1860 int * savePivot = reinterpret_cast<int *> (arrayD);
1861 int * whichRow = savePivot+numberRows;
1862 int * whichColumn = whichRow + 3*numberRows;
1863 int nSame=0;
1864 int nSub=0;
1865 for (int i=0;i<numberColumns;i++) {
1866 double lo = lowerOriginal[i];
1867 //char * xx = (char *) (saveLowerOriginal+i);
1868 //assert (xx[0]!=0x20||xx[1]!=0x20);
1869 //xx = (char *) (saveUpperOriginal+i);
1870 //assert (xx[0]!=0x20||xx[1]!=0x20);
1871 double loOld = saveLowerOriginal[i];
1872 //assert (!loOld||fabs(loOld)>1.0e-30);
1873 double up = upperOriginal[i];
1874 double upOld = saveUpperOriginal[i];
1875 if (lo>=loOld&&up<=upOld) {
1876 if (lo==loOld&&up==upOld) {
1877 nSame++;
1878 } else {
1879 nSub++;
1880 //if (!isInteger(i))
1881 //nSub+=10;
1882 }
1883 }
1884 }
1885 //printf("Mark Hot %d bounds same, %d interior, %d bad\n",
1886 // nSame,nSub,numberColumns-nSame-nSub);
1887 if (nSame<numberColumns) {
1888 if (nSame+nSub<numberColumns) {
1889 delete smallModel_;
1890 smallModel_=NULL;
1891 } else {
1892 // we can fix up (but should we if large number fixed?)
1893 assert (smallModel_);
1894 double * lowerSmall = smallModel_->columnLower();
1895 double * upperSmall = smallModel_->columnUpper();
1896 int numberColumns2 = smallModel_->numberColumns();
1897 for (int i=0;i<numberColumns2;i++) {
1898 int iColumn = whichColumn[i];
1899 lowerSmall[i]=lowerOriginal[iColumn];
1900 upperSmall[i]=upperOriginal[iColumn];
1901 }
1902 }
1903 }
1904 }
1905 double * arrayD = reinterpret_cast<double *> (spareArrays_);
1906 arrayD[0]=modelPtr_->objectiveValue()* modelPtr_->optimizationDirection();
1907 double * saveSolution = arrayD+1;
1908 double * saveLower = saveSolution + (numberRows+numberColumns);
1909 double * saveUpper = saveLower + (numberRows+numberColumns);
1910 double * saveObjective = saveUpper + (numberRows+numberColumns);
1911 double * saveLowerOriginal = saveObjective + (numberRows+numberColumns);
1912 double * saveUpperOriginal = saveLowerOriginal + numberColumns;
1913 arrayD = saveUpperOriginal + numberColumns;
1914 int * savePivot = reinterpret_cast<int *> (arrayD);
1915 int * whichRow = savePivot+numberRows;
1916 int * whichColumn = whichRow + 3*numberRows;
1917 int * arrayI = whichColumn + 2*numberColumns;
1918 //unsigned char * saveStatus = (unsigned char *) (arrayI+1);
1919 // Use dual region
1920 double * rhs = modelPtr_->dualRowSolution();
1921 int nBound=0;
1922 ClpSimplex * small;
1923#ifndef KEEP_SMALL
1924 assert (!smallModel_);
1925 small = static_cast<ClpSimplexOther *> (modelPtr_)->crunch(rhs,whichRow,whichColumn,nBound,true);
1926 bool needSolveInSetupHotStart=true;
1927#else
1928 bool needSolveInSetupHotStart=true;
1929 if (!smallModel_) {
1930#ifndef NDEBUG
1931 CoinFillN(whichRow,3*numberRows+2*numberColumns,-1);
1932#endif
1933 small = static_cast<ClpSimplexOther *> (modelPtr_)->crunch(rhs,whichRow,whichColumn,nBound,true);
1934#ifndef NDEBUG
1935 int nCopy = 3*numberRows+2*numberColumns;
1936 for (int i=0;i<nCopy;i++)
1937 assert (whichRow[i]>=-CoinMax(numberRows,numberColumns)&&whichRow[i]<CoinMax(numberRows,numberColumns));
1938#endif
1939 smallModel_=small;
1940 //int hotIts = small->intParam_[ClpMaxNumIterationHotStart];
1941 //if (5*small->factorization_->maximumPivots()>
1942 // 4*hotIts)
1943 //small->factorization_->maximumPivots(hotIts+1);
1944 } else {
1945 assert((modelPtr_->whatsChanged_&0x30000)==0x30000);
1946 //delete [] spareArrays_;
1947 //spareArrays_ = NULL;
1948 assert (spareArrays_);
1949 int nCopy = 3*numberRows+2*numberColumns;
1950 nBound = whichRow[nCopy];
1951#ifndef NDEBUG
1952 for (int i=0;i<nCopy;i++)
1953 assert (whichRow[i]>=-CoinMax(numberRows,numberColumns)&&whichRow[i]<CoinMax(numberRows,numberColumns));
1954#endif
1955 needSolveInSetupHotStart=false;
1956 small = smallModel_;
1957 }
1958#endif
1959 if (small) {
1960 small->specialOptions_ |= 262144;
1961 small->specialOptions_ &= ~65536;
1962 }
1963 if (small&&(specialOptions_&131072)!=0) {
1964 assert (lastNumberRows_>=0);
1965 int numberRows2 = small->numberRows();
1966 int numberColumns2 = small->numberColumns();
1967 double * rowScale2 = new double [2*numberRows2];
1968 const double * rowScale = rowScale_.array();
1969 double * inverseScale2 = rowScale2+numberRows2;
1970 const double * inverseScale = rowScale+modelPtr_->numberRows_;
1971 int i;
1972 for (i=0;i<numberRows2;i++) {
1973 int iRow = whichRow[i];
1974 rowScale2[i]=rowScale[iRow];
1975 inverseScale2[i]=inverseScale[iRow];
1976 }
1977 small->setRowScale(rowScale2);
1978 double * columnScale2 = new double [2*numberColumns2];
1979 const double * columnScale = columnScale_.array();
1980 inverseScale2 = columnScale2+numberColumns2;
1981 inverseScale = columnScale+modelPtr_->numberColumns_;
1982 for (i=0;i<numberColumns2;i++) {
1983 int iColumn = whichColumn[i];
1984 columnScale2[i]=columnScale[iColumn];
1985 inverseScale2[i]=inverseScale[iColumn];
1986 }
1987 small->setColumnScale(columnScale2);
1988 }
1989 if (!small) {
1990 // should never be infeasible .... but
1991 delete [] spareArrays_;
1992 spareArrays_=NULL;
1993 delete ws_;
1994 ws_ = dynamic_cast<CoinWarmStartBasis*>(getWarmStart());
1995 int numberRows = modelPtr_->numberRows();
1996 rowActivity_= new double[numberRows];
1997 CoinMemcpyN(modelPtr_->primalRowSolution(),numberRows,rowActivity_);
1998 int numberColumns = modelPtr_->numberColumns();
1999 columnActivity_= new double[numberColumns];
2000 CoinMemcpyN(modelPtr_->primalColumnSolution(),numberColumns,columnActivity_);
2001 modelPtr_->setProblemStatus(1);
2002 if (savedObjective) {
2003 // fix up
2004 modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit;
2005 //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32));
2006 modelPtr_->objective_=savedObjective;
2007 }
2008 return;
2009 }
2010 int clpOptions = modelPtr_->specialOptions();
2011 clpOptions &= ~65536;
2012 if((specialOptions_&1)==0) {
2013 small->setSpecialOptions(clpOptions|(64|1024));
2014 } else {
2015 if((specialOptions_&4)==0)
2016 small->setSpecialOptions(clpOptions|(64|128|512|1024|4096));
2017 else
2018 small->setSpecialOptions(clpOptions|(64|128|512|1024|2048|4096));
2019 }
2020 arrayI[0]=nBound;
2021 assert (smallModel_==NULL||small==smallModel_);
2022 if ((specialOptions_&256)!=0||1) {
2023 // only need to do this on second pass in CbcNode
2024 if (modelPtr_->logLevel()<2) small->setLogLevel(0);
2025 small->specialOptions_ |= 262144;
2026 small->moreSpecialOptions_ = modelPtr_->moreSpecialOptions_;
2027#define SETUP_HOT
2028#ifndef SETUP_HOT
2029 small->dual();
2030#else
2031 assert (factorization_==NULL);
2032 //needSolveInSetupHotStart=true;
2033 ClpFactorization * factorization = static_cast<ClpSimplexDual *>(small)->setupForStrongBranching(spareArrays_,
2034 numberRows,numberColumns,
2035 needSolveInSetupHotStart);
2036#endif
2037 if (small->numberIterations()>0&&small->logLevel()>2)
2038 printf("**** iterated small %d\n",small->numberIterations());
2039 //small->setLogLevel(0);
2040 // Could be infeasible if forced one way (and other way stopped on iterations)
2041 if (small->status()==1) {
2042#ifndef KEEP_SMALL
2043 if (small!=modelPtr_)
2044 delete small;
2045 //delete smallModel_;
2046 //smallModel_=NULL;
2047 assert (!smallModel_);
2048#else
2049 assert (small==smallModel_);
2050 if (smallModel_!=modelPtr_) {
2051 delete smallModel_;
2052 }
2053 smallModel_=NULL;
2054#endif
2055 delete [] spareArrays_;
2056 spareArrays_=NULL;
2057 delete ws_;
2058 ws_ = dynamic_cast<CoinWarmStartBasis*>(getWarmStart());
2059 int numberRows = modelPtr_->numberRows();
2060 rowActivity_= new double[numberRows];
2061 CoinMemcpyN(modelPtr_->primalRowSolution(), numberRows,rowActivity_);
2062 int numberColumns = modelPtr_->numberColumns();
2063 columnActivity_= new double[numberColumns];
2064 CoinMemcpyN(modelPtr_->primalColumnSolution(), numberColumns,columnActivity_);
2065 modelPtr_->setProblemStatus(1);
2066 if (savedObjective) {
2067 // fix up
2068 modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit;
2069 //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32));
2070 modelPtr_->objective_=savedObjective;
2071 }
2072 return;
2073 } else {
2074 // update model
2075 static_cast<ClpSimplexOther *> (modelPtr_)->afterCrunch(*small,whichRow,whichColumn,nBound);
2076 }
2077#ifndef SETUP_HOT
2078 assert (factorization_==NULL);
2079 factorization_ = static_cast<ClpSimplexDual *>(small)->setupForStrongBranching(spareArrays_,numberRows,
2080 numberColumns,false);
2081#else
2082 assert (factorization!=NULL || small->problemStatus_ );
2083 factorization_ = factorization;
2084#endif
2085 } else {
2086 assert (factorization_==NULL);
2087 factorization_ = static_cast<ClpSimplexDual *>(small)->setupForStrongBranching(spareArrays_,numberRows,
2088 numberColumns,false);
2089 }
2090 smallModel_=small;
2091 if (modelPtr_->logLevel()<2) smallModel_->setLogLevel(0);
2092 // Setup for strong branching
2093 int numberColumns2 = smallModel_->numberColumns();
2094 CoinMemcpyN( modelPtr_->columnLower(),numberColumns, saveLowerOriginal);
2095 CoinMemcpyN( modelPtr_->columnUpper(),numberColumns, saveUpperOriginal);
2096 const double * smallLower = smallModel_->columnLower();
2097 const double * smallUpper = smallModel_->columnUpper();
2098 // But modify if bounds changed in small
2099 for (int i=0;i<numberColumns2;i++) {
2100 int iColumn = whichColumn[i];
2101 saveLowerOriginal[iColumn] = CoinMax(saveLowerOriginal[iColumn],
2102 smallLower[i]);
2103 saveUpperOriginal[iColumn] = CoinMin(saveUpperOriginal[iColumn],
2104 smallUpper[i]);
2105 }
2106 if (whichRange_&&whichRange_[0]) {
2107 // get ranging information
2108 int numberToDo = whichRange_[0];
2109 int * which = new int [numberToDo];
2110 // Convert column numbers
2111 int * backColumn = whichColumn+numberColumns;
2112 for (int i=0;i<numberToDo;i++) {
2113 int iColumn = whichRange_[i+1];
2114 which[i]=backColumn[iColumn];
2115 }
2116 double * downRange=new double [numberToDo];
2117 double * upRange=new double [numberToDo];
2118 int * whichDown = new int [numberToDo];
2119 int * whichUp = new int [numberToDo];
2120 smallModel_->setFactorization(*factorization_);
2121 smallModel_->gutsOfSolution(NULL,NULL,false);
2122 // Tell code we can increase costs in some cases
2123 smallModel_->setCurrentDualTolerance(0.0);
2124 static_cast<ClpSimplexOther *> (smallModel_)->dualRanging(numberToDo,which,
2125 upRange, whichUp, downRange, whichDown);
2126 delete [] whichDown;
2127 delete [] whichUp;
2128 delete [] which;
2129 rowActivity_=upRange;
2130 columnActivity_=downRange;
2131 }
2132 }
2133 if (savedObjective) {
2134 // fix up
2135 modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit;
2136 //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32));
2137 modelPtr_->objective_=savedObjective;
2138 if (!modelPtr_->problemStatus_) {
2139 CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_);
2140 CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_);
2141 if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0)
2142 CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_);
2143 modelPtr_->computeObjectiveValue();
2144 }
2145 }
2146}
2147
2148void OsiClpSolverInterface::solveFromHotStart()
2149{
2150#ifdef KEEP_SMALL
2151 if (!spareArrays_) {
2152 assert (!smallModel_);
2153 assert (modelPtr_->problemStatus_==1);
2154 return;
2155 }
2156#endif
2157 ClpObjective * savedObjective=NULL;
2158 double savedDualLimit=modelPtr_->dblParam_[ClpDualObjectiveLimit];
2159 if (saveData_.perturbation_) {
2160 // Set fake
2161 savedObjective=modelPtr_->objective_;
2162 modelPtr_->objective_=fakeObjective_;
2163 modelPtr_->dblParam_[ClpDualObjectiveLimit]=COIN_DBL_MAX;
2164 }
2165 int numberRows = modelPtr_->numberRows();
2166 int numberColumns = modelPtr_->numberColumns();
2167 modelPtr_->getIntParam(ClpMaxNumIteration,itlimOrig_);
2168 int itlim;
2169 modelPtr_->getIntParam(ClpMaxNumIterationHotStart, itlim);
2170 // Is there an extra copy of scaled bounds
2171 int extraCopy = (modelPtr_->maximumRows_>0) ? modelPtr_->maximumRows_+modelPtr_->maximumColumns_ : 0;
2172#ifdef CLEAN_HOT_START
2173 if ((specialOptions_&65536)!=0) {
2174 double * arrayD = reinterpret_cast<double *> (spareArrays_);
2175 double saveObjectiveValue = arrayD[0];
2176 double * saveSolution = arrayD+1;
2177 int number = numberRows+numberColumns;
2178 CoinMemcpyN(saveSolution,number,modelPtr_->solutionRegion());
2179 double * saveLower = saveSolution + (numberRows+numberColumns);
2180 CoinMemcpyN(saveLower,number,modelPtr_->lowerRegion());
2181 double * saveUpper = saveLower + (numberRows+numberColumns);
2182 CoinMemcpyN(saveUpper,number,modelPtr_->upperRegion());
2183 double * saveObjective = saveUpper + (numberRows+numberColumns);
2184 CoinMemcpyN(saveObjective,number,modelPtr_->costRegion());
2185 double * saveLowerOriginal = saveObjective + (numberRows+numberColumns);
2186 double * saveUpperOriginal = saveLowerOriginal + numberColumns;
2187 arrayD = saveUpperOriginal + numberColumns;
2188 int * savePivot = reinterpret_cast<int *> (arrayD);
2189 CoinMemcpyN(savePivot,numberRows,modelPtr_->pivotVariable());
2190 int * whichRow = savePivot+numberRows;
2191 int * whichColumn = whichRow + 3*numberRows;
2192 int * arrayI = whichColumn + 2*numberColumns;
2193 unsigned char * saveStatus = reinterpret_cast<unsigned char *> (arrayI+1);
2194 CoinMemcpyN(saveStatus,number,modelPtr_->statusArray());
2195 modelPtr_->setFactorization(*factorization_);
2196 double * columnLower = modelPtr_->columnLower();
2197 double * columnUpper = modelPtr_->columnUpper();
2198 // make sure whatsChanged_ has 1 set
2199 modelPtr_->setWhatsChanged(511);
2200 double * lowerInternal = modelPtr_->lowerRegion();
2201 double * upperInternal = modelPtr_->upperRegion();
2202 double rhsScale = modelPtr_->rhsScale();
2203 const double * columnScale = NULL;
2204 if (modelPtr_->scalingFlag()>0)
2205 columnScale = modelPtr_->columnScale() ;
2206 // and do bounds in case dual needs them
2207 int iColumn;
2208 for (iColumn=0;iColumn<numberColumns;iColumn++) {
2209 if (columnLower[iColumn]>saveLowerOriginal[iColumn]) {
2210 double value = columnLower[iColumn];
2211 value *= rhsScale;
2212 if (columnScale)
2213 value /= columnScale[iColumn];
2214 lowerInternal[iColumn]=value;
2215 if (extraCopy)
2216 lowerInternal[iColumn+extraCopy]=value;
2217 }
2218 if (columnUpper[iColumn]<saveUpperOriginal[iColumn]) {
2219 double value = columnUpper[iColumn];
2220 value *= rhsScale;
2221 if (columnScale)
2222 value /= columnScale[iColumn];
2223 upperInternal[iColumn]=value;
2224 if (extraCopy)
2225 upperInternal[iColumn+extraCopy]=value;
2226 }
2227 }
2228 // Start of fast iterations
2229 bool alwaysFinish= ((specialOptions_&32)==0) ? true : false;
2230 //modelPtr_->setLogLevel(1);
2231 modelPtr_->setIntParam(ClpMaxNumIteration,itlim);
2232 int saveNumberFake = (static_cast<ClpSimplexDual *>(modelPtr_))->numberFake_;
2233 int status = (static_cast<ClpSimplexDual *>(modelPtr_))->fastDual(alwaysFinish);
2234 (static_cast<ClpSimplexDual *>(modelPtr_))->numberFake_ = saveNumberFake;
2235
2236 int problemStatus = modelPtr_->problemStatus();
2237 double objectiveValue =modelPtr_->objectiveValue() * modelPtr_->optimizationDirection();
2238 CoinAssert (modelPtr_->problemStatus()||modelPtr_->objectiveValue()<1.0e50);
2239 // make sure plausible
2240 double obj = CoinMax(objectiveValue,saveObjectiveValue);
2241 if (problemStatus==10||problemStatus<0) {
2242 // was trying to clean up or something odd
2243 if (problemStatus==10)
2244 lastAlgorithm_=1; // so won't fail on cutoff (in CbcNode)
2245 status=1;
2246 }
2247 if (status) {
2248 // not finished - might be optimal
2249 modelPtr_->checkPrimalSolution(modelPtr_->solutionRegion(0),
2250 modelPtr_->solutionRegion(1));
2251 //modelPtr_->gutsOfSolution(NULL,NULL,0);
2252 //if (problemStatus==3)
2253 //modelPtr_->computeObjectiveValue();
2254 objectiveValue =modelPtr_->objectiveValue() *
2255 modelPtr_->optimizationDirection();
2256 obj = CoinMax(objectiveValue,saveObjectiveValue);
2257 if (!modelPtr_->numberDualInfeasibilities()) {
2258 double limit = 0.0;
2259 modelPtr_->getDblParam(ClpDualObjectiveLimit, limit);
2260 if (modelPtr_->secondaryStatus()==1&&!problemStatus&&obj<limit) {
2261 obj=limit;
2262 problemStatus=3;
2263 }
2264 if (!modelPtr_->numberPrimalInfeasibilities()&&obj<limit) {
2265 problemStatus=0;
2266 } else if (problemStatus==10) {
2267 problemStatus=3;
2268 } else if (!modelPtr_->numberPrimalInfeasibilities()) {
2269 problemStatus=1; // infeasible
2270 }
2271 } else {
2272 // can't say much
2273 //if (problemStatus==3)
2274 //modelPtr_->computeObjectiveValue();
2275 lastAlgorithm_=1; // so won't fail on cutoff (in CbcNode)
2276 problemStatus=3;
2277 }
2278 } else if (!problemStatus) {
2279 if (modelPtr_->isDualObjectiveLimitReached())
2280 problemStatus=1; // infeasible
2281 }
2282 if (status&&!problemStatus) {
2283 problemStatus=3; // can't be sure
2284 lastAlgorithm_=1;
2285 }
2286 if (problemStatus<0)
2287 problemStatus=3;
2288 modelPtr_->setProblemStatus(problemStatus);
2289 modelPtr_->setObjectiveValue(obj*modelPtr_->optimizationDirection());
2290 double * solution = modelPtr_->primalColumnSolution();
2291 const double * solution2 = modelPtr_->solutionRegion();
2292 // could just do changed bounds - also try double size scale so can use * not /
2293 if (!columnScale) {
2294 for (iColumn=0;iColumn<numberColumns;iColumn++) {
2295 solution[iColumn]= solution2[iColumn];
2296 }
2297 } else {
2298 for (iColumn=0;iColumn<numberColumns;iColumn++) {
2299 solution[iColumn]= solution2[iColumn]*columnScale[iColumn];
2300 }
2301 }
2302 CoinMemcpyN(saveLowerOriginal,numberColumns,columnLower);
2303 CoinMemcpyN(saveUpperOriginal,numberColumns,columnUpper);
2304#if 0
2305 // could combine with loop above
2306 if (modelPtr_==modelPtr_)
2307 modelPtr_->computeObjectiveValue();
2308 if (status&&!problemStatus) {
2309 memset(modelPtr_->primalRowSolution(),0,numberRows*sizeof(double));
2310 modelPtr_->clpMatrix()->times(1.0,solution,modelPtr_->primalRowSolution());
2311 modelPtr_->checkSolutionInternal();
2312 //modelPtr_->setLogLevel(1);
2313 //modelPtr_->allSlackBasis();
2314 //modelPtr_->primal(1);
2315 //memset(modelPtr_->primalRowSolution(),0,numberRows*sizeof(double));
2316 //modelPtr_->clpMatrix()->times(1.0,solution,modelPtr_->primalRowSolution());
2317 //modelPtr_->checkSolutionInternal();
2318 assert (!modelPtr_->problemStatus());
2319 }
2320#endif
2321 // and back bounds
2322 CoinMemcpyN(saveLower,number,modelPtr_->lowerRegion());
2323 CoinMemcpyN(saveUpper,number,modelPtr_->upperRegion());
2324 if (extraCopy) {
2325 CoinMemcpyN(saveLower,number,modelPtr_->lowerRegion()+extraCopy);
2326 CoinMemcpyN(saveUpper,number,modelPtr_->upperRegion()+extraCopy);
2327 }
2328 modelPtr_->setIntParam(ClpMaxNumIteration,itlimOrig_);
2329 if (savedObjective) {
2330 // fix up
2331 modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit;
2332 //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32));
2333 modelPtr_->objective_=savedObjective;
2334 if (!modelPtr_->problemStatus_) {
2335 CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_);
2336 CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_);
2337 if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0)
2338 CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_);
2339 modelPtr_->computeObjectiveValue();
2340 }
2341 }
2342 return;
2343 }
2344#endif
2345 if (smallModel_==NULL) {
2346 setWarmStart(ws_);
2347 CoinMemcpyN( rowActivity_,numberRows,modelPtr_->primalRowSolution());
2348 CoinMemcpyN(columnActivity_,numberColumns,modelPtr_->primalColumnSolution());
2349 modelPtr_->setIntParam(ClpMaxNumIteration,CoinMin(itlim,9999));
2350 resolve();
2351 } else {
2352 assert (spareArrays_);
2353 double * arrayD = reinterpret_cast<double *> (spareArrays_);
2354 double saveObjectiveValue = arrayD[0];
2355 double * saveSolution = arrayD+1;
2356 int numberRows2 = smallModel_->numberRows();
2357 int numberColumns2 = smallModel_->numberColumns();
2358 int number = numberRows2+numberColumns2;
2359 CoinMemcpyN(saveSolution,number,smallModel_->solutionRegion());
2360 double * saveLower = saveSolution + (numberRows+numberColumns);
2361 CoinMemcpyN(saveLower,number,smallModel_->lowerRegion());
2362 double * saveUpper = saveLower + (numberRows+numberColumns);
2363 CoinMemcpyN(saveUpper,number,smallModel_->upperRegion());
2364 double * saveObjective = saveUpper + (numberRows+numberColumns);
2365 CoinMemcpyN(saveObjective,number,smallModel_->costRegion());
2366 double * saveLowerOriginal = saveObjective + (numberRows+numberColumns);
2367 double * saveUpperOriginal = saveLowerOriginal + numberColumns;
2368 arrayD = saveUpperOriginal + numberColumns;
2369 int * savePivot = reinterpret_cast<int *> (arrayD);
2370 CoinMemcpyN(savePivot,numberRows2,smallModel_->pivotVariable());
2371 int * whichRow = savePivot+numberRows;
2372 int * whichColumn = whichRow + 3*numberRows;
2373 int * arrayI = whichColumn + 2*numberColumns;
2374 unsigned char * saveStatus = reinterpret_cast<unsigned char *> (arrayI+1);
2375 CoinMemcpyN(saveStatus,number,smallModel_->statusArray());
2376 /* If factorization_ NULL then infeasible
2377 not really sure how could have slipped through.
2378 But this can't make situation worse */
2379 if (factorization_)
2380 smallModel_->setFactorization(*factorization_);
2381 //int * backColumn = whichColumn+numberColumns;
2382 const double * lowerBig = modelPtr_->columnLower();
2383 const double * upperBig = modelPtr_->columnUpper();
2384 // make sure whatsChanged_ has 1 set
2385 smallModel_->setWhatsChanged(511);
2386 double * lowerSmall = smallModel_->lowerRegion();
2387 double * upperSmall = smallModel_->upperRegion();
2388 double * lowerSmallReal = smallModel_->columnLower();
2389 double * upperSmallReal = smallModel_->columnUpper();
2390 int i;
2391 double rhsScale = smallModel_->rhsScale();
2392 const double * columnScale = NULL;
2393 if (smallModel_->scalingFlag()>0) {
2394 columnScale = smallModel_->columnScale();
2395 }
2396 // and do bounds in case dual needs them
2397 // may be infeasible
2398 for (i=0;i<numberColumns2;i++) {
2399 int iColumn = whichColumn[i];
2400 if (lowerBig[iColumn]>saveLowerOriginal[iColumn]) {
2401 double value = lowerBig[iColumn];
2402 lowerSmallReal[i]=value;
2403 value *= rhsScale;
2404 if (columnScale)
2405 value /= columnScale[i];
2406 lowerSmall[i]=value;
2407 }
2408 if (upperBig[iColumn]<saveUpperOriginal[iColumn]) {
2409 double value = upperBig[iColumn];
2410 upperSmallReal[i]=value;
2411 value *= rhsScale;
2412 if (columnScale)
2413 value /= columnScale[i];
2414 upperSmall[i]=value;
2415 }
2416 if (upperSmall[i]<lowerSmall[i]-1.0e-8)
2417 break;
2418 }
2419 /* If factorization_ NULL then infeasible
2420 not really sure how could have slipped through.
2421 But this can't make situation worse */
2422 bool infeasible = (i<numberColumns2||!factorization_);
2423 // Start of fast iterations
2424 bool alwaysFinish= ((specialOptions_&32)==0) ? true : false;
2425 //smallModel_->setLogLevel(1);
2426 smallModel_->setIntParam(ClpMaxNumIteration,itlim);
2427 int saveNumberFake = (static_cast<ClpSimplexDual *>(smallModel_))->numberFake_;
2428 int status;
2429 if (!infeasible) {
2430 status = static_cast<ClpSimplexDual *>(smallModel_)->fastDual(alwaysFinish);
2431 } else {
2432 status=0;
2433 smallModel_->setProblemStatus(1);
2434 }
2435 (static_cast<ClpSimplexDual *>(smallModel_))->numberFake_ = saveNumberFake;
2436 if (smallModel_->numberIterations()==-98) {
2437 printf("rrrrrrrrrrrr\n");
2438 smallModel_->checkPrimalSolution(smallModel_->solutionRegion(0),
2439 smallModel_->solutionRegion(1));
2440 //smallModel_->gutsOfSolution(NULL,NULL,0);
2441 //if (problemStatus==3)
2442 //smallModel_->computeObjectiveValue();
2443 printf("robj %g\n",smallModel_->objectiveValue() *
2444 modelPtr_->optimizationDirection());
2445 writeMps("rr.mps");
2446 smallModel_->writeMps("rr_small.mps");
2447 ClpSimplex temp = *smallModel_;
2448 printf("small\n");
2449 temp.setLogLevel(63);
2450 temp.dual();
2451 double limit = 0.0;
2452 modelPtr_->getDblParam(ClpDualObjectiveLimit, limit);
2453 if (temp.problemStatus()==0&&temp.objectiveValue()<limit) {
2454 printf("inf obj %g, true %g - offsets %g %g\n",smallModel_->objectiveValue(),
2455 temp.objectiveValue(),
2456 smallModel_->objectiveOffset(),temp.objectiveOffset());
2457 }
2458 printf("big\n");
2459 temp = *modelPtr_;
2460 temp.dual();
2461 if (temp.problemStatus()==0&&temp.objectiveValue()<limit) {
2462 printf("inf obj %g, true %g - offsets %g %g\n",smallModel_->objectiveValue(),
2463 temp.objectiveValue(),
2464 smallModel_->objectiveOffset(),temp.objectiveOffset());
2465 }
2466 }
2467 int problemStatus = smallModel_->problemStatus();
2468 double objectiveValue =smallModel_->objectiveValue() * modelPtr_->optimizationDirection();
2469 CoinAssert (smallModel_->problemStatus()||smallModel_->objectiveValue()<1.0e50);
2470 // make sure plausible
2471 double obj = CoinMax(objectiveValue,saveObjectiveValue);
2472 if (problemStatus==10||problemStatus<0) {
2473 // was trying to clean up or something odd
2474 if (problemStatus==10)
2475 lastAlgorithm_=1; // so won't fail on cutoff (in CbcNode)
2476 status=1;
2477 }
2478 if (status) {
2479 // not finished - might be optimal
2480 smallModel_->checkPrimalSolution(smallModel_->solutionRegion(0),
2481 smallModel_->solutionRegion(1));
2482 //smallModel_->gutsOfSolution(NULL,NULL,0);
2483 //if (problemStatus==3)
2484 //smallModel_->computeObjectiveValue();
2485 objectiveValue =smallModel_->objectiveValue() *
2486 modelPtr_->optimizationDirection();
2487 if (problemStatus!=10)
2488 obj = CoinMax(objectiveValue,saveObjectiveValue);
2489 if (!smallModel_->numberDualInfeasibilities()) {
2490 double limit = 0.0;
2491 modelPtr_->getDblParam(ClpDualObjectiveLimit, limit);
2492 if (smallModel_->secondaryStatus()==1&&!problemStatus&&obj<limit) {
2493#if 0
2494 // switch off
2495 ClpSimplex temp = *smallModel_;
2496 temp.dual();
2497 if (temp.problemStatus()==0&&temp.objectiveValue()<limit) {
2498 printf("inf obj %g, true %g - offsets %g %g\n",smallModel_->objectiveValue(),
2499 temp.objectiveValue(),
2500 smallModel_->objectiveOffset(),temp.objectiveOffset());
2501 }
2502 lastAlgorithm_=1;
2503 obj=limit;
2504 problemStatus=10;
2505#else
2506 obj=limit;
2507 problemStatus=3;
2508#endif
2509 }
2510 if (!smallModel_->numberPrimalInfeasibilities()&&obj<limit) {
2511 problemStatus=0;
2512#if 0
2513 ClpSimplex temp = *smallModel_;
2514 temp.dual();
2515 if (temp.numberIterations())
2516 printf("temp iterated\n");
2517 assert (temp.problemStatus()==0&&temp.objectiveValue()<limit);
2518#endif
2519 } else if (problemStatus==10) {
2520 problemStatus=3;
2521 } else if (!smallModel_->numberPrimalInfeasibilities()) {
2522 problemStatus=1; // infeasible
2523 }
2524 } else {
2525 // can't say much
2526 //if (problemStatus==3)
2527 //smallModel_->computeObjectiveValue();
2528 lastAlgorithm_=1; // so won't fail on cutoff (in CbcNode)
2529 problemStatus=3;
2530 }
2531 } else if (!problemStatus) {
2532 if (smallModel_->isDualObjectiveLimitReached())
2533 problemStatus=1; // infeasible
2534 }
2535 if (status&&!problemStatus) {
2536 problemStatus=3; // can't be sure
2537 lastAlgorithm_=1;
2538 }
2539 if (problemStatus<0)
2540 problemStatus=3;
2541 modelPtr_->setProblemStatus(problemStatus);
2542 modelPtr_->setObjectiveValue(obj*modelPtr_->optimizationDirection());
2543 modelPtr_->setSumDualInfeasibilities(smallModel_->sumDualInfeasibilities());
2544 modelPtr_->setNumberDualInfeasibilities(smallModel_->numberDualInfeasibilities());
2545 modelPtr_->setSumPrimalInfeasibilities(smallModel_->sumPrimalInfeasibilities());
2546 modelPtr_->setNumberPrimalInfeasibilities(smallModel_->numberPrimalInfeasibilities());
2547 double * solution = modelPtr_->primalColumnSolution();
2548 const double * solution2 = smallModel_->solutionRegion();
2549 if (!columnScale) {
2550 for (i=0;i<numberColumns2;i++) {
2551 int iColumn = whichColumn[i];
2552 solution[iColumn]= solution2[i];
2553 lowerSmallReal[i]=saveLowerOriginal[iColumn];
2554 upperSmallReal[i]=saveUpperOriginal[iColumn];
2555 }
2556 } else {
2557 for (i=0;i<numberColumns2;i++) {
2558 int iColumn = whichColumn[i];
2559 solution[iColumn]= solution2[i]*columnScale[i];
2560 lowerSmallReal[i]=saveLowerOriginal[iColumn];
2561 upperSmallReal[i]=saveUpperOriginal[iColumn];
2562 }
2563 }
2564 // could combine with loop above
2565 if (modelPtr_==smallModel_)
2566 modelPtr_->computeObjectiveValue();
2567#if 1
2568 if (status&&!problemStatus) {
2569 memset(modelPtr_->primalRowSolution(),0,numberRows*sizeof(double));
2570 modelPtr_->clpMatrix()->times(1.0,solution,modelPtr_->primalRowSolution());
2571 modelPtr_->checkSolutionInternal();
2572 //modelPtr_->setLogLevel(1);
2573 //modelPtr_->allSlackBasis();
2574 //modelPtr_->primal(1);
2575 //memset(modelPtr_->primalRowSolution(),0,numberRows*sizeof(double));
2576 //modelPtr_->clpMatrix()->times(1.0,solution,modelPtr_->primalRowSolution());
2577 //modelPtr_->checkSolutionInternal();
2578 assert (!modelPtr_->problemStatus());
2579 }
2580#endif
2581 modelPtr_->setNumberIterations(smallModel_->numberIterations());
2582 // and back bounds
2583 CoinMemcpyN(saveLower,number,smallModel_->lowerRegion());
2584 CoinMemcpyN(saveUpper,number,smallModel_->upperRegion());
2585 }
2586 if (savedObjective) {
2587 // fix up
2588 modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit;
2589 //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32));
2590 modelPtr_->objective_=savedObjective;
2591 if (!modelPtr_->problemStatus_) {
2592 CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_);
2593 CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_);
2594 if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0)
2595 CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_);
2596 modelPtr_->computeObjectiveValue();
2597 }
2598 }
2599 modelPtr_->setIntParam(ClpMaxNumIteration,itlimOrig_);
2600}
2601
2602void OsiClpSolverInterface::unmarkHotStart()
2603{
2604#ifdef CLEAN_HOT_START
2605 if ((specialOptions_&65536)!=0) {
2606 modelPtr_->setLogLevel(saveData_.scalingFlag_);
2607 modelPtr_->deleteRim(0);
2608 if (lastNumberRows_<0) {
2609 specialOptions_ |= 131072;
2610 lastNumberRows_ = -1 -lastNumberRows_;
2611 if (modelPtr_->rowScale_) {
2612 if (modelPtr_->rowScale_!=rowScale_.array()) {
2613 delete [] modelPtr_->rowScale_;
2614 delete [] modelPtr_->columnScale_;
2615 }
2616 modelPtr_->rowScale_=NULL;
2617 modelPtr_->columnScale_=NULL;
2618 }
2619 }
2620 delete factorization_;
2621 delete [] spareArrays_;
2622 smallModel_=NULL;
2623 spareArrays_=NULL;
2624 factorization_=NULL;
2625 delete [] rowActivity_;
2626 delete [] columnActivity_;
2627 rowActivity_=NULL;
2628 columnActivity_=NULL;
2629 return;
2630 }
2631#endif
2632 if (smallModel_==NULL) {
2633 setWarmStart(ws_);
2634 int numberRows = modelPtr_->numberRows();
2635 int numberColumns = modelPtr_->numberColumns();
2636 CoinMemcpyN( rowActivity_,numberRows,modelPtr_->primalRowSolution());
2637 CoinMemcpyN(columnActivity_,numberColumns,modelPtr_->primalColumnSolution());
2638 delete ws_;
2639 ws_ = NULL;
2640 } else {
2641#ifndef KEEP_SMALL
2642 if (smallModel_!=modelPtr_)
2643 delete smallModel_;
2644 smallModel_=NULL;
2645#else
2646 if (smallModel_==modelPtr_) {
2647 smallModel_=NULL;
2648 } else if (smallModel_) {
2649 if(!spareArrays_) {
2650 delete smallModel_;
2651 smallModel_=NULL;
2652 delete factorization_;
2653 factorization_=NULL;
2654 } else {
2655 static_cast<ClpSimplexDual *> (smallModel_)->cleanupAfterStrongBranching( factorization_);
2656 if ((smallModel_->specialOptions_&4096)==0) {
2657 delete factorization_;
2658 }
2659 }
2660 }
2661#endif
2662 //delete [] spareArrays_;
2663 //spareArrays_=NULL;
2664 factorization_=NULL;
2665 }
2666 delete [] rowActivity_;
2667 delete [] columnActivity_;
2668 rowActivity_=NULL;
2669 columnActivity_=NULL;
2670 // Make sure whatsChanged not out of sync
2671 if (!modelPtr_->columnUpperWork_)
2672 modelPtr_->whatsChanged_ &= ~0xffff;
2673 modelPtr_->specialOptions_ = saveData_.specialOptions_;
2674}
2675
2676//#############################################################################
2677// Problem information methods (original data)
2678//#############################################################################
2679
2680//------------------------------------------------------------------
2681const char * OsiClpSolverInterface::getRowSense() const
2682{
2683 extractSenseRhsRange();
2684 return rowsense_;
2685}
2686//------------------------------------------------------------------
2687const double * OsiClpSolverInterface::getRightHandSide() const
2688{
2689 extractSenseRhsRange();
2690 return rhs_;
2691}
2692//------------------------------------------------------------------
2693const double * OsiClpSolverInterface::getRowRange() const
2694{
2695 extractSenseRhsRange();
2696 return rowrange_;
2697}
2698//------------------------------------------------------------------
2699// Return information on integrality
2700//------------------------------------------------------------------
2701bool OsiClpSolverInterface::isContinuous(int colNumber) const
2702{
2703 if ( integerInformation_==NULL ) return true;
2704#ifndef NDEBUG
2705 int n = modelPtr_->numberColumns();
2706 if (colNumber<0||colNumber>=n) {
2707 indexError(colNumber,"isContinuous");
2708 }
2709#endif
2710 if ( integerInformation_[colNumber]==0 ) return true;
2711 return false;
2712}
2713bool
2714OsiClpSolverInterface::isBinary(int colNumber) const
2715{
2716#ifndef NDEBUG
2717 int n = modelPtr_->numberColumns();
2718 if (colNumber<0||colNumber>=n) {
2719 indexError(colNumber,"isBinary");
2720 }
2721#endif
2722 if ( integerInformation_==NULL || integerInformation_[colNumber]==0 ) {
2723 return false;
2724 } else {
2725 const double * cu = getColUpper();
2726 const double * cl = getColLower();
2727 if ((cu[colNumber]== 1 || cu[colNumber]== 0) &&
2728 (cl[colNumber]== 0 || cl[colNumber]==1))
2729 return true;
2730 else
2731 return false;
2732 }
2733}
2734//-----------------------------------------------------------------------------
2735bool
2736OsiClpSolverInterface::isInteger(int colNumber) const
2737{
2738#ifndef NDEBUG
2739 int n = modelPtr_->numberColumns();
2740 if (colNumber<0||colNumber>=n) {
2741 indexError(colNumber,"isInteger");
2742 }
2743#endif
2744 if ( integerInformation_==NULL || integerInformation_[colNumber]==0 )
2745 return false;
2746 else
2747 return true;
2748}
2749//-----------------------------------------------------------------------------
2750bool
2751OsiClpSolverInterface::isIntegerNonBinary(int colNumber) const
2752{
2753#ifndef NDEBUG
2754 int n = modelPtr_->numberColumns();
2755 if (colNumber<0||colNumber>=n) {
2756 indexError(colNumber,"isIntegerNonBinary");
2757 }
2758#endif
2759 if ( integerInformation_==NULL || integerInformation_[colNumber]==0 ) {
2760 return false;
2761 } else {
2762 return !isBinary(colNumber);
2763 }
2764}
2765//-----------------------------------------------------------------------------
2766bool
2767OsiClpSolverInterface::isFreeBinary(int colNumber) const
2768{
2769#ifndef NDEBUG
2770 int n = modelPtr_->numberColumns();
2771 if (colNumber<0||colNumber>=n) {
2772 indexError(colNumber,"isFreeBinary");
2773 }
2774#endif
2775 if ( integerInformation_==NULL || integerInformation_[colNumber]==0 ) {
2776 return false;
2777 } else {
2778 const double * cu = getColUpper();
2779 const double * cl = getColLower();
2780 if ((cu[colNumber]== 1) && (cl[colNumber]== 0))
2781 return true;
2782 else
2783 return false;
2784 }
2785}
2786/* Return array of column length
2787 0 - continuous
2788 1 - binary (may get fixed later)
2789 2 - general integer (may get fixed later)
2790*/
2791const char *
2792OsiClpSolverInterface::getColType(bool refresh) const
2793{
2794 if (!columnType_||refresh) {
2795 const int numCols = getNumCols() ;
2796 if (!columnType_)
2797 columnType_ = new char [numCols];
2798 if ( integerInformation_==NULL ) {
2799 memset(columnType_,0,numCols);
2800 } else {
2801 const double * cu = getColUpper();
2802 const double * cl = getColLower();
2803 for (int i = 0 ; i < numCols ; ++i) {
2804 if (integerInformation_[i]) {
2805 if ((cu[i]== 1 || cu[i]== 0) &&
2806 (cl[i]== 0 || cl[i]==1))
2807 columnType_[i]=1;
2808 else
2809 columnType_[i]=2;
2810 } else {
2811 columnType_[i]=0;
2812 }
2813 }
2814 }
2815 }
2816 return columnType_;
2817}
2818
2819/* Return true if column is integer but does not have to
2820 be declared as such.
2821 Note: This function returns true if the the column
2822 is binary or a general integer.
2823*/
2824bool
2825OsiClpSolverInterface::isOptionalInteger(int colNumber) const
2826{
2827#ifndef NDEBUG
2828 int n = modelPtr_->numberColumns();
2829 if (colNumber<0||colNumber>=n) {
2830 indexError(colNumber,"isInteger");
2831 }
2832#endif
2833 if ( integerInformation_==NULL || integerInformation_[colNumber]!=2 )
2834 return false;
2835 else
2836 return true;
2837}
2838/* Set the index-th variable to be an optional integer variable */
2839void
2840OsiClpSolverInterface::setOptionalInteger(int index)
2841{
2842 if (!integerInformation_) {
2843 integerInformation_ = new char[modelPtr_->numberColumns()];
2844 CoinFillN ( integerInformation_, modelPtr_->numberColumns(),static_cast<char> (0));
2845 }
2846#ifndef NDEBUG
2847 int n = modelPtr_->numberColumns();
2848 if (index<0||index>=n) {
2849 indexError(index,"setInteger");
2850 }
2851#endif
2852 integerInformation_[index]=2;
2853 modelPtr_->setInteger(index);
2854}
2855
2856//------------------------------------------------------------------
2857// Row and column copies of the matrix ...
2858//------------------------------------------------------------------
2859const CoinPackedMatrix * OsiClpSolverInterface::getMatrixByRow() const
2860{
2861 if ( matrixByRow_ == NULL ||
2862 matrixByRow_->getNumElements() !=
2863 modelPtr_->clpMatrix()->getNumElements() ) {
2864 delete matrixByRow_;
2865 matrixByRow_ = new CoinPackedMatrix();
2866 matrixByRow_->setExtraGap(0.0);
2867 matrixByRow_->setExtraMajor(0.0);
2868 matrixByRow_->reverseOrderedCopyOf(*modelPtr_->matrix());
2869 //matrixByRow_->removeGaps();
2870#if 0
2871 CoinPackedMatrix back;
2872 std::cout<<"start check"<<std::endl;
2873 back.reverseOrderedCopyOf(*matrixByRow_);
2874 modelPtr_->matrix()->isEquivalent2(back);
2875 std::cout<<"stop check"<<std::endl;
2876#endif
2877 }
2878 assert (matrixByRow_->getNumElements()==modelPtr_->clpMatrix()->getNumElements());
2879 return matrixByRow_;
2880}
2881
2882const CoinPackedMatrix * OsiClpSolverInterface::getMatrixByCol() const
2883{
2884 return modelPtr_->matrix();
2885}
2886
2887// Get pointer to mutable column-wise copy of matrix (returns NULL if not meaningful)
2888CoinPackedMatrix *
2889OsiClpSolverInterface::getMutableMatrixByCol() const
2890{
2891 ClpPackedMatrix * matrix = dynamic_cast<ClpPackedMatrix *>(modelPtr_->matrix_) ;
2892 if (matrix)
2893 return matrix->getPackedMatrix();
2894 else
2895 return NULL;
2896}
2897
2898//------------------------------------------------------------------
2899std::vector<double*> OsiClpSolverInterface::getDualRays(int /*maxNumRays*/,
2900 bool fullRay) const
2901{
2902 if (fullRay == true) {
2903 throw CoinError("Full dual rays not yet implemented.","getDualRays",
2904 "OsiClpSolverInterface");
2905 }
2906 return std::vector<double*>(1, modelPtr_->infeasibilityRay());
2907}
2908//------------------------------------------------------------------
2909std::vector<double*> OsiClpSolverInterface::getPrimalRays(int /*maxNumRays*/) const
2910{
2911 return std::vector<double*>(1, modelPtr_->unboundedRay());
2912}
2913//#############################################################################
2914void
2915OsiClpSolverInterface::setContinuous(int index)
2916{
2917
2918 if (integerInformation_) {
2919#ifndef NDEBUG
2920 int n = modelPtr_->numberColumns();
2921 if (index<0||index>=n) {
2922 indexError(index,"setContinuous");
2923 }
2924#endif
2925 integerInformation_[index]=0;
2926 }
2927 modelPtr_->setContinuous(index);
2928}
2929//-----------------------------------------------------------------------------
2930void
2931OsiClpSolverInterface::setInteger(int index)
2932{
2933 if (!integerInformation_) {
2934 integerInformation_ = new char[modelPtr_->numberColumns()];
2935 CoinFillN ( integerInformation_, modelPtr_->numberColumns(),static_cast<char> (0));
2936 }
2937#ifndef NDEBUG
2938 int n = modelPtr_->numberColumns();
2939 if (index<0||index>=n) {
2940 indexError(index,"setInteger");
2941 }
2942#endif
2943 integerInformation_[index]=1;
2944 modelPtr_->setInteger(index);
2945}
2946//-----------------------------------------------------------------------------
2947void
2948OsiClpSolverInterface::setContinuous(const int* indices, int len)
2949{
2950 if (integerInformation_) {
2951#ifndef NDEBUG
2952 int n = modelPtr_->numberColumns();
2953#endif
2954 int i;
2955 for (i=0; i<len;i++) {
2956 int colNumber = indices[i];
2957#ifndef NDEBUG
2958 if (colNumber<0||colNumber>=n) {
2959 indexError(colNumber,"setContinuous");
2960 }
2961#endif
2962 integerInformation_[colNumber]=0;
2963 modelPtr_->setContinuous(colNumber);
2964 }
2965 }
2966}
2967//-----------------------------------------------------------------------------
2968void
2969OsiClpSolverInterface::setInteger(const int* indices, int len)
2970{
2971 if (!integerInformation_) {
2972 integerInformation_ = new char[modelPtr_->numberColumns()];
2973 CoinFillN ( integerInformation_, modelPtr_->numberColumns(),static_cast<char> (0));
2974 }
2975#ifndef NDEBUG
2976 int n = modelPtr_->numberColumns();
2977#endif
2978 int i;
2979 for (i=0; i<len;i++) {
2980 int colNumber = indices[i];
2981#ifndef NDEBUG
2982 if (colNumber<0||colNumber>=n) {
2983 indexError(colNumber,"setInteger");
2984 }
2985#endif
2986 integerInformation_[colNumber]=1;
2987 modelPtr_->setInteger(colNumber);
2988 }
2989}
2990/* Set the objective coefficients for all columns
2991 array [getNumCols()] is an array of values for the objective.
2992 This defaults to a series of set operations and is here for speed.
2993*/
2994void
2995OsiClpSolverInterface::setObjective(const double * array)
2996{
2997 // Say can't gurantee optimal basis etc
2998 lastAlgorithm_=999;
2999 modelPtr_->whatsChanged_ &= (0xffff&~64);
3000 int n = modelPtr_->numberColumns() ;
3001 if (fakeMinInSimplex_) {
3002 std::transform(array,array+n,
3003 modelPtr_->objective(),std::negate<double>()) ;
3004 } else {
3005 CoinMemcpyN(array,n,modelPtr_->objective());
3006 }
3007}
3008/* Set the lower bounds for all columns
3009 array [getNumCols()] is an array of values for the objective.
3010 This defaults to a series of set operations and is here for speed.
3011*/
3012void
3013OsiClpSolverInterface::setColLower(const double * array)
3014{
3015 // Say can't gurantee optimal basis etc
3016 lastAlgorithm_=999;
3017 modelPtr_->whatsChanged_ &= (0x1ffff&128);
3018 CoinMemcpyN(array,modelPtr_->numberColumns(),
3019 modelPtr_->columnLower());
3020}
3021/* Set the upper bounds for all columns
3022 array [getNumCols()] is an array of values for the objective.
3023 This defaults to a series of set operations and is here for speed.
3024*/
3025void
3026OsiClpSolverInterface::setColUpper(const double * array)
3027{
3028 // Say can't gurantee optimal basis etc
3029 lastAlgorithm_=999;
3030 modelPtr_->whatsChanged_ &= (0x1ffff&256);
3031 CoinMemcpyN(array,modelPtr_->numberColumns(),
3032 modelPtr_->columnUpper());
3033}
3034//-----------------------------------------------------------------------------
3035void OsiClpSolverInterface::setColSolution(const double * cs)
3036{
3037 // Say can't gurantee optimal basis etc
3038 lastAlgorithm_=999;
3039 CoinDisjointCopyN(cs,modelPtr_->numberColumns(),
3040 modelPtr_->primalColumnSolution());
3041 if (modelPtr_->solveType()==2) {
3042 // directly into code as well
3043 CoinDisjointCopyN(cs,modelPtr_->numberColumns(),
3044 modelPtr_->solutionRegion(1));
3045 }
3046 // compute row activity
3047 memset(modelPtr_->primalRowSolution(),0,modelPtr_->numberRows()*sizeof(double));
3048 modelPtr_->times(1.0,modelPtr_->primalColumnSolution(),modelPtr_->primalRowSolution());
3049}
3050//-----------------------------------------------------------------------------
3051void OsiClpSolverInterface::setRowPrice(const double * rs)
3052{
3053 CoinDisjointCopyN(rs,modelPtr_->numberRows(),
3054 modelPtr_->dualRowSolution());
3055 if (modelPtr_->solveType()==2) {
3056 // directly into code as well (? sign )
3057 CoinDisjointCopyN(rs,modelPtr_->numberRows(),
3058 modelPtr_->djRegion(0));
3059 }
3060 // compute reduced costs
3061 memcpy(modelPtr_->dualColumnSolution(),modelPtr_->objective(),
3062 modelPtr_->numberColumns()*sizeof(double));
3063 modelPtr_->transposeTimes(-1.0,modelPtr_->dualRowSolution(),modelPtr_->dualColumnSolution());
3064}
3065
3066//#############################################################################
3067// Problem modifying methods (matrix)
3068//#############################################################################
3069void
3070OsiClpSolverInterface::addCol(const CoinPackedVectorBase& vec,
3071 const double collb, const double colub,
3072 const double obj)
3073{
3074 int numberColumns = modelPtr_->numberColumns();
3075 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|8|64|128|256));
3076 modelPtr_->resize(modelPtr_->numberRows(),numberColumns+1);
3077 linearObjective_ = modelPtr_->objective();
3078 basis_.resize(modelPtr_->numberRows(),numberColumns+1);
3079 setColBounds(numberColumns,collb,colub);
3080 setObjCoeff(numberColumns,obj);
3081 if (!modelPtr_->clpMatrix())
3082 modelPtr_->createEmptyMatrix();
3083 modelPtr_->matrix()->appendCol(vec);
3084 if (integerInformation_) {
3085 char * temp = new char[numberColumns+1];
3086 CoinMemcpyN(integerInformation_,numberColumns,temp);
3087 delete [] integerInformation_;
3088 integerInformation_ = temp;
3089 integerInformation_[numberColumns]=0;
3090 }
3091 freeCachedResults();
3092}
3093//-----------------------------------------------------------------------------
3094/* Add a column (primal variable) to the problem. */
3095void
3096OsiClpSolverInterface::addCol(int numberElements, const int * rows, const double * elements,
3097 const double collb, const double colub,
3098 const double obj)
3099{
3100 CoinPackedVector column(numberElements, rows, elements);
3101 addCol(column,collb,colub,obj);
3102}
3103// Add a named column (primal variable) to the problem.
3104void
3105OsiClpSolverInterface::addCol(const CoinPackedVectorBase& vec,
3106 const double collb, const double colub,
3107 const double obj, std::string name)
3108{
3109 int ndx = getNumCols() ;
3110 addCol(vec,collb,colub,obj) ;
3111 setColName(ndx,name) ;
3112}
3113//-----------------------------------------------------------------------------
3114void
3115OsiClpSolverInterface::addCols(const int numcols,
3116 const CoinPackedVectorBase * const * cols,
3117 const double* collb, const double* colub,
3118 const double* obj)
3119{
3120 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|8|64|128|256));
3121 int numberColumns = modelPtr_->numberColumns();
3122 modelPtr_->resize(modelPtr_->numberRows(),numberColumns+numcols);
3123 linearObjective_ = modelPtr_->objective();
3124 basis_.resize(modelPtr_->numberRows(),numberColumns+numcols);
3125 double * lower = modelPtr_->columnLower()+numberColumns;
3126 double * upper = modelPtr_->columnUpper()+numberColumns;
3127 double * objective = modelPtr_->objective()+numberColumns;
3128 int iCol;
3129 if (collb) {
3130 for (iCol = 0; iCol < numcols; iCol++) {
3131 lower[iCol]= forceIntoRange(collb[iCol], -OsiClpInfinity, OsiClpInfinity);
3132 if (lower[iCol]<-1.0e27)
3133 lower[iCol]=-COIN_DBL_MAX;
3134 }
3135 } else {
3136 CoinFillN ( lower, numcols,0.0);
3137 }
3138 if (colub) {
3139 for (iCol = 0; iCol < numcols; iCol++) {
3140 upper[iCol]= forceIntoRange(colub[iCol], -OsiClpInfinity, OsiClpInfinity);
3141 if (upper[iCol]>1.0e27)
3142 upper[iCol]=COIN_DBL_MAX;
3143 }
3144 } else {
3145 CoinFillN ( upper, numcols,COIN_DBL_MAX);
3146 }
3147 if (obj) {
3148 for (iCol = 0; iCol < numcols; iCol++) {
3149 objective[iCol] = obj[iCol];
3150 }
3151 } else {
3152 CoinFillN ( objective, numcols,0.0);
3153 }
3154 if (!modelPtr_->clpMatrix())
3155 modelPtr_->createEmptyMatrix();
3156 modelPtr_->matrix()->appendCols(numcols,cols);
3157 if (integerInformation_) {
3158 char * temp = new char[numberColumns+numcols];
3159 CoinMemcpyN(integerInformation_,numberColumns,temp);
3160 delete [] integerInformation_;
3161 integerInformation_ = temp;
3162 for (iCol = 0; iCol < numcols; iCol++)
3163 integerInformation_[numberColumns+iCol]=0;
3164 }
3165 freeCachedResults();
3166}
3167void
3168OsiClpSolverInterface::addCols(const int numcols,
3169 const int * columnStarts, const int * rows, const double * elements,
3170 const double* collb, const double* colub,
3171 const double* obj)
3172{
3173 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|8|64|128|256));
3174 int numberColumns = modelPtr_->numberColumns();
3175 modelPtr_->resize(modelPtr_->numberRows(),numberColumns+numcols);
3176 linearObjective_ = modelPtr_->objective();
3177 basis_.resize(modelPtr_->numberRows(),numberColumns+numcols);
3178 double * lower = modelPtr_->columnLower()+numberColumns;
3179 double * upper = modelPtr_->columnUpper()+numberColumns;
3180 double * objective = modelPtr_->objective()+numberColumns;
3181 int iCol;
3182 if (collb) {
3183 for (iCol = 0; iCol < numcols; iCol++) {
3184 lower[iCol]= forceIntoRange(collb[iCol], -OsiClpInfinity, OsiClpInfinity);
3185 if (lower[iCol]<-1.0e27)
3186 lower[iCol]=-COIN_DBL_MAX;
3187 }
3188 } else {
3189 CoinFillN ( lower, numcols,0.0);
3190 }
3191 if (colub) {
3192 for (iCol = 0; iCol < numcols; iCol++) {
3193 upper[iCol]= forceIntoRange(colub[iCol], -OsiClpInfinity, OsiClpInfinity);
3194 if (upper[iCol]>1.0e27)
3195 upper[iCol]=COIN_DBL_MAX;
3196 }
3197 } else {
3198 CoinFillN ( upper, numcols,COIN_DBL_MAX);
3199 }
3200 if (obj) {
3201 for (iCol = 0; iCol < numcols; iCol++) {
3202 objective[iCol] = obj[iCol];
3203 }
3204 } else {
3205 CoinFillN ( objective, numcols,0.0);
3206 }
3207 if (!modelPtr_->clpMatrix())
3208 modelPtr_->createEmptyMatrix();
3209 modelPtr_->matrix()->appendCols(numcols,columnStarts,rows,elements);
3210 if (integerInformation_) {
3211 char * temp = new char[numberColumns+numcols];
3212 CoinMemcpyN(integerInformation_,numberColumns,temp);
3213 delete [] integerInformation_;
3214 integerInformation_ = temp;
3215 for (iCol = 0; iCol < numcols; iCol++)
3216 integerInformation_[numberColumns+iCol]=0;
3217 }
3218 freeCachedResults();
3219}
3220//-----------------------------------------------------------------------------
3221void
3222OsiClpSolverInterface::deleteCols(const int num, const int * columnIndices)
3223{
3224 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|8|64|128|256));
3225 findIntegers(false);
3226 deleteBranchingInfo(num,columnIndices);
3227 modelPtr_->deleteColumns(num,columnIndices);
3228 int nameDiscipline;
3229 getIntParam(OsiNameDiscipline,nameDiscipline) ;
3230 if (num&&nameDiscipline) {
3231 // Very clumsy (and inefficient) - need to sort and then go backwards in ? chunks
3232 int * indices = CoinCopyOfArray(columnIndices,num);
3233 std::sort(indices,indices+num);
3234 int num2=num;
3235 while(num2) {
3236 int next = indices[num2-1];
3237 int firstDelete = num2-1;
3238 int i;
3239 for (i=num2-2;i>=0;i--) {
3240 if (indices[i]+1==next) {
3241 next --;
3242 firstDelete=i;
3243 } else {
3244 break;
3245 }
3246 }
3247 OsiSolverInterface::deleteColNames(indices[firstDelete],num2-firstDelete);
3248 num2 = firstDelete;
3249 assert (num2>=0);
3250 }
3251 delete [] indices;
3252 }
3253 // synchronize integers (again)
3254 if (integerInformation_) {
3255 int numberColumns = modelPtr_->numberColumns();
3256 for (int i=0;i<numberColumns;i++) {
3257 if (modelPtr_->isInteger(i))
3258 integerInformation_[i]=1;
3259 else
3260 integerInformation_[i]=0;
3261 }
3262 }
3263 basis_.deleteColumns(num,columnIndices);
3264 linearObjective_ = modelPtr_->objective();
3265 freeCachedResults();
3266}
3267//-----------------------------------------------------------------------------
3268void
3269OsiClpSolverInterface::addRow(const CoinPackedVectorBase& vec,
3270 const double rowlb, const double rowub)
3271{
3272 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32));
3273 freeCachedResults0();
3274 int numberRows = modelPtr_->numberRows();
3275 modelPtr_->resize(numberRows+1,modelPtr_->numberColumns());
3276 basis_.resize(numberRows+1,modelPtr_->numberColumns());
3277 setRowBounds(numberRows,rowlb,rowub);
3278 if (!modelPtr_->clpMatrix())
3279 modelPtr_->createEmptyMatrix();
3280 modelPtr_->matrix()->appendRow(vec);
3281 freeCachedResults1();
3282}
3283//-----------------------------------------------------------------------------
3284void OsiClpSolverInterface::addRow(const CoinPackedVectorBase& vec,
3285 const double rowlb, const double rowub,
3286 std::string name)
3287{
3288 int ndx = getNumRows() ;
3289 addRow(vec,rowlb,rowub) ;
3290 setRowName(ndx,name) ;
3291}
3292//-----------------------------------------------------------------------------
3293void
3294OsiClpSolverInterface::addRow(const CoinPackedVectorBase& vec,
3295 const char rowsen, const double rowrhs,
3296 const double rowrng)
3297{
3298 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32));
3299 freeCachedResults0();
3300 int numberRows = modelPtr_->numberRows();
3301 modelPtr_->resize(numberRows+1,modelPtr_->numberColumns());
3302 basis_.resize(numberRows+1,modelPtr_->numberColumns());
3303 double rowlb = 0, rowub = 0;
3304 convertSenseToBound(rowsen, rowrhs, rowrng, rowlb, rowub);
3305 setRowBounds(numberRows,rowlb,rowub);
3306 if (!modelPtr_->clpMatrix())
3307 modelPtr_->createEmptyMatrix();
3308 modelPtr_->matrix()->appendRow(vec);
3309 freeCachedResults1();
3310}
3311//-----------------------------------------------------------------------------
3312void
3313OsiClpSolverInterface::addRow(int numberElements, const int * columns, const double * elements,
3314 const double rowlb, const double rowub)
3315{
3316 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32));
3317 freeCachedResults0();
3318 int numberRows = modelPtr_->numberRows();
3319 modelPtr_->resize(numberRows+1,modelPtr_->numberColumns());
3320 basis_.resize(numberRows+1,modelPtr_->numberColumns());
3321 setRowBounds(numberRows,rowlb,rowub);
3322 if (!modelPtr_->clpMatrix())
3323 modelPtr_->createEmptyMatrix();
3324 modelPtr_->matrix()->appendRow(numberElements, columns, elements);
3325 CoinBigIndex starts[2];
3326 starts[0]=0;
3327 starts[1]=numberElements;
3328 redoScaleFactors( 1,starts, columns, elements);
3329 freeCachedResults1();
3330}
3331//-----------------------------------------------------------------------------
3332void
3333OsiClpSolverInterface::addRows(const int numrows,
3334 const CoinPackedVectorBase * const * rows,
3335 const double* rowlb, const double* rowub)
3336{
3337 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32));
3338 freeCachedResults0();
3339 int numberRows = modelPtr_->numberRows();
3340 modelPtr_->resize(numberRows+numrows,modelPtr_->numberColumns());
3341 basis_.resize(numberRows+numrows,modelPtr_->numberColumns());
3342 double * lower = modelPtr_->rowLower()+numberRows;
3343 double * upper = modelPtr_->rowUpper()+numberRows;
3344 int iRow;
3345 for (iRow = 0; iRow < numrows; iRow++) {
3346 if (rowlb)
3347 lower[iRow]= forceIntoRange(rowlb[iRow], -OsiClpInfinity, OsiClpInfinity);
3348 else
3349 lower[iRow]=-OsiClpInfinity;
3350 if (rowub)
3351 upper[iRow]= forceIntoRange(rowub[iRow], -OsiClpInfinity, OsiClpInfinity);
3352 else
3353 upper[iRow]=OsiClpInfinity;
3354 if (lower[iRow]<-1.0e27)
3355 lower[iRow]=-COIN_DBL_MAX;
3356 if (upper[iRow]>1.0e27)
3357 upper[iRow]=COIN_DBL_MAX;
3358 }
3359 if (!modelPtr_->clpMatrix())
3360 modelPtr_->createEmptyMatrix();
3361 modelPtr_->matrix()->appendRows(numrows,rows);
3362 freeCachedResults1();
3363}
3364//-----------------------------------------------------------------------------
3365void
3366OsiClpSolverInterface::addRows(const int numrows,
3367 const CoinPackedVectorBase * const * rows,
3368 const char* rowsen, const double* rowrhs,
3369 const double* rowrng)
3370{
3371 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32));
3372 freeCachedResults0();
3373 int numberRows = modelPtr_->numberRows();
3374 modelPtr_->resize(numberRows+numrows,modelPtr_->numberColumns());
3375 basis_.resize(numberRows+numrows,modelPtr_->numberColumns());
3376 double * lower = modelPtr_->rowLower()+numberRows;
3377 double * upper = modelPtr_->rowUpper()+numberRows;
3378 int iRow;
3379 for (iRow = 0; iRow < numrows; iRow++) {
3380 double rowlb = 0, rowub = 0;
3381 convertSenseToBound(rowsen[iRow], rowrhs[iRow], rowrng[iRow],
3382 rowlb, rowub);
3383 lower[iRow]= forceIntoRange(rowlb, -OsiClpInfinity, OsiClpInfinity);
3384 upper[iRow]= forceIntoRange(rowub, -OsiClpInfinity, OsiClpInfinity);
3385 if (lower[iRow]<-1.0e27)
3386 lower[iRow]=-COIN_DBL_MAX;
3387 if (upper[iRow]>1.0e27)
3388 upper[iRow]=COIN_DBL_MAX;
3389 }
3390 if (!modelPtr_->clpMatrix())
3391 modelPtr_->createEmptyMatrix();
3392 modelPtr_->matrix()->appendRows(numrows,rows);
3393 freeCachedResults1();
3394}
3395void
3396OsiClpSolverInterface::addRows(const int numrows,
3397 const int * rowStarts, const int * columns, const double * element,
3398 const double* rowlb, const double* rowub)
3399{
3400 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32));
3401 freeCachedResults0();
3402 int numberRows = modelPtr_->numberRows();
3403 modelPtr_->resize(numberRows+numrows,modelPtr_->numberColumns());
3404 basis_.resize(numberRows+numrows,modelPtr_->numberColumns());
3405 double * lower = modelPtr_->rowLower()+numberRows;
3406 double * upper = modelPtr_->rowUpper()+numberRows;
3407 int iRow;
3408 for (iRow = 0; iRow < numrows; iRow++) {
3409 if (rowlb)
3410 lower[iRow]= forceIntoRange(rowlb[iRow], -OsiClpInfinity, OsiClpInfinity);
3411 else
3412 lower[iRow]=-OsiClpInfinity;
3413 if (rowub)
3414 upper[iRow]= forceIntoRange(rowub[iRow], -OsiClpInfinity, OsiClpInfinity);
3415 else
3416 upper[iRow]=OsiClpInfinity;
3417 if (lower[iRow]<-1.0e27)
3418 lower[iRow]=-COIN_DBL_MAX;
3419 if (upper[iRow]>1.0e27)
3420 upper[iRow]=COIN_DBL_MAX;
3421 }
3422 if (!modelPtr_->clpMatrix())
3423 modelPtr_->createEmptyMatrix();
3424 modelPtr_->matrix()->appendRows(numrows,rowStarts,columns,element);
3425 redoScaleFactors( numrows,rowStarts, columns, element);
3426 freeCachedResults1();
3427}
3428//-----------------------------------------------------------------------------
3429void
3430OsiClpSolverInterface::deleteRows(const int num, const int * rowIndices)
3431{
3432 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32));
3433 // will still be optimal if all rows basic
3434 bool allBasic=true;
3435 int numBasis = basis_.getNumArtificial();
3436 for (int i=0;i<num;i++) {
3437 int iRow = rowIndices[i];
3438 if (iRow<numBasis) {
3439 if (basis_.getArtifStatus(iRow)!=CoinWarmStartBasis::basic) {
3440 allBasic=false;
3441 break;
3442 }
3443 }
3444 }
3445 int saveAlgorithm = allBasic ? lastAlgorithm_ : 999;
3446 modelPtr_->deleteRows(num,rowIndices);
3447 int nameDiscipline;
3448 getIntParam(OsiNameDiscipline,nameDiscipline) ;
3449 if (num&&nameDiscipline) {
3450 // Very clumsy (and inefficient) - need to sort and then go backwards in ? chunks
3451 int * indices = CoinCopyOfArray(rowIndices,num);
3452 std::sort(indices,indices+num);
3453 int num2=num;
3454 while(num2) {
3455 int next = indices[num2-1];
3456 int firstDelete = num2-1;
3457 int i;
3458 for (i=num2-2;i>=0;i--) {
3459 if (indices[i]+1==next) {
3460 next --;
3461 firstDelete=i;
3462 } else {
3463 break;
3464 }
3465 }
3466 OsiSolverInterface::deleteRowNames(indices[firstDelete],num2-firstDelete);
3467 num2 = firstDelete;
3468 assert (num2>=0);
3469 }
3470 delete [] indices;
3471 }
3472 basis_.deleteRows(num,rowIndices);
3473 CoinPackedMatrix * saveRowCopy = matrixByRow_;
3474 matrixByRow_=NULL;
3475 freeCachedResults();
3476 modelPtr_->setNewRowCopy(NULL);
3477 delete modelPtr_->scaledMatrix_;
3478 modelPtr_->scaledMatrix_=NULL;
3479 if (saveRowCopy) {
3480#if 1
3481 matrixByRow_=saveRowCopy;
3482 matrixByRow_->deleteRows(num,rowIndices);
3483 assert (matrixByRow_->getNumElements()==modelPtr_->clpMatrix()->getNumElements());
3484#else
3485 delete saveRowCopy;
3486#endif
3487 }
3488 lastAlgorithm_ = saveAlgorithm;
3489 if ((specialOptions_&131072)!=0)
3490 lastNumberRows_=modelPtr_->numberRows();
3491}
3492
3493//#############################################################################
3494// Methods to input a problem
3495//#############################################################################
3496
3497void
3498OsiClpSolverInterface::loadProblem(const CoinPackedMatrix& matrix,
3499 const double* collb, const double* colub,
3500 const double* obj,
3501 const double* rowlb, const double* rowub)
3502{
3503 modelPtr_->whatsChanged_ = 0;
3504 // Get rid of integer information (modelPtr will get rid of its copy)
3505 delete [] integerInformation_;
3506 integerInformation_=NULL;
3507 modelPtr_->loadProblem(matrix, collb, colub, obj, rowlb, rowub);
3508 linearObjective_ = modelPtr_->objective();
3509 freeCachedResults();
3510 basis_=CoinWarmStartBasis();
3511 if (ws_) {
3512 delete ws_;
3513 ws_ = 0;
3514 }
3515}
3516
3517//-----------------------------------------------------------------------------
3518
3519/*
3520 Expose the method that takes ClpMatrixBase. User request. Can't hurt, given
3521 the number of non-OSI methods already here.
3522*/
3523void OsiClpSolverInterface::loadProblem (const ClpMatrixBase& matrix,
3524 const double* collb,
3525 const double* colub,
3526 const double* obj,
3527 const double* rowlb,
3528 const double* rowub)
3529{
3530 modelPtr_->whatsChanged_ = 0;
3531 // Get rid of integer information (modelPtr will get rid of its copy)
3532 delete [] integerInformation_;
3533 integerInformation_=NULL;
3534 modelPtr_->loadProblem(matrix,collb,colub,obj,rowlb,rowub);
3535 linearObjective_ = modelPtr_->objective();
3536 freeCachedResults();
3537 basis_=CoinWarmStartBasis();
3538 if (ws_) {
3539 delete ws_;
3540 ws_ = 0;
3541 }
3542}
3543
3544//-----------------------------------------------------------------------------
3545
3546void
3547OsiClpSolverInterface::assignProblem(CoinPackedMatrix*& matrix,
3548 double*& collb, double*& colub,
3549 double*& obj,
3550 double*& rowlb, double*& rowub)
3551{
3552 modelPtr_->whatsChanged_ = 0;
3553 // Get rid of integer information (modelPtr will get rid of its copy)
3554 loadProblem(*matrix, collb, colub, obj, rowlb, rowub);
3555 delete matrix; matrix = NULL;
3556 delete[] collb; collb = NULL;
3557 delete[] colub; colub = NULL;
3558 delete[] obj; obj = NULL;
3559 delete[] rowlb; rowlb = NULL;
3560 delete[] rowub; rowub = NULL;
3561}
3562
3563//-----------------------------------------------------------------------------
3564
3565void
3566OsiClpSolverInterface::loadProblem(const CoinPackedMatrix& matrix,
3567 const double* collb, const double* colub,
3568 const double* obj,
3569 const char* rowsen, const double* rowrhs,
3570 const double* rowrng)
3571{
3572 modelPtr_->whatsChanged_ = 0;
3573 // Get rid of integer information (modelPtr will get rid of its copy)
3574 // assert( rowsen != NULL );
3575 // assert( rowrhs != NULL );
3576 // If any of Rhs NULLs then create arrays
3577 int numrows = matrix.getNumRows();
3578 const char * rowsenUse = rowsen;
3579 if (!rowsen) {
3580 char * rowsen = new char [numrows];
3581 for (int i=0;i<numrows;i++)
3582 rowsen[i]='G';
3583 rowsenUse = rowsen;
3584 }
3585 const double * rowrhsUse = rowrhs;
3586 if (!rowrhs) {
3587 double * rowrhs = new double [numrows];
3588 for (int i=0;i<numrows;i++)
3589 rowrhs[i]=0.0;
3590 rowrhsUse = rowrhs;
3591 }
3592 const double * rowrngUse = rowrng;
3593 if (!rowrng) {
3594 double * rowrng = new double [numrows];
3595 for (int i=0;i<numrows;i++)
3596 rowrng[i]=0.0;
3597 rowrngUse = rowrng;
3598 }
3599 double * rowlb = new double[numrows];
3600 double * rowub = new double[numrows];
3601 for (int i = numrows-1; i >= 0; --i) {
3602 convertSenseToBound(rowsenUse[i],rowrhsUse[i],rowrngUse[i],rowlb[i],rowub[i]);
3603 }
3604 if (rowsen!=rowsenUse)
3605 delete [] rowsenUse;
3606 if (rowrhs!=rowrhsUse)
3607 delete [] rowrhsUse;
3608 if (rowrng!=rowrngUse)
3609 delete [] rowrngUse;
3610 loadProblem(matrix, collb, colub, obj, rowlb, rowub);
3611 delete [] rowlb;
3612 delete [] rowub;
3613}
3614
3615//-----------------------------------------------------------------------------
3616
3617void
3618OsiClpSolverInterface::assignProblem(CoinPackedMatrix*& matrix,
3619 double*& collb, double*& colub,
3620 double*& obj,
3621 char*& rowsen, double*& rowrhs,
3622 double*& rowrng)
3623{
3624 modelPtr_->whatsChanged_ = 0;
3625 // Get rid of integer information (modelPtr will get rid of its copy)
3626 loadProblem(*matrix, collb, colub, obj, rowsen, rowrhs, rowrng);
3627 delete matrix; matrix = NULL;
3628 delete[] collb; collb = NULL;
3629 delete[] colub; colub = NULL;
3630 delete[] obj; obj = NULL;
3631 delete[] rowsen; rowsen = NULL;
3632 delete[] rowrhs; rowrhs = NULL;
3633 delete[] rowrng; rowrng = NULL;
3634}
3635
3636//-----------------------------------------------------------------------------
3637
3638void
3639OsiClpSolverInterface::loadProblem(const int numcols, const int numrows,
3640 const CoinBigIndex * start, const int* index,
3641 const double* value,
3642 const double* collb, const double* colub,
3643 const double* obj,
3644 const double* rowlb, const double* rowub)
3645{
3646 modelPtr_->whatsChanged_ = 0;
3647 // Get rid of integer information (modelPtr will get rid of its copy)
3648 delete [] integerInformation_;
3649 integerInformation_=NULL;
3650 modelPtr_->loadProblem(numcols, numrows, start, index,
3651 value, collb, colub, obj,
3652 rowlb, rowub);
3653 linearObjective_ = modelPtr_->objective();
3654 freeCachedResults();
3655 basis_=CoinWarmStartBasis();
3656 if (ws_) {
3657 delete ws_;
3658 ws_ = 0;
3659 }
3660}
3661//-----------------------------------------------------------------------------
3662
3663void
3664OsiClpSolverInterface::loadProblem(const int numcols, const int numrows,
3665 const CoinBigIndex * start, const int* index,
3666 const double* value,
3667 const double* collb, const double* colub,
3668 const double* obj,
3669 const char* rowsen, const double* rowrhs,
3670 const double* rowrng)
3671{
3672 modelPtr_->whatsChanged_ = 0;
3673 // Get rid of integer information (modelPtr will get rid of its copy)
3674 // If any of Rhs NULLs then create arrays
3675 const char * rowsenUse = rowsen;
3676 if (!rowsen) {
3677 char * rowsen = new char [numrows];
3678 for (int i=0;i<numrows;i++)
3679 rowsen[i]='G';
3680 rowsenUse = rowsen;
3681 }
3682 const double * rowrhsUse = rowrhs;
3683 if (!rowrhs) {
3684 double * rowrhs = new double [numrows];
3685 for (int i=0;i<numrows;i++)
3686 rowrhs[i]=0.0;
3687 rowrhsUse = rowrhs;
3688 }
3689 const double * rowrngUse = rowrng;
3690 if (!rowrng) {
3691 double * rowrng = new double [numrows];
3692 for (int i=0;i<numrows;i++)
3693 rowrng[i]=0.0;
3694 rowrngUse = rowrng;
3695 }
3696 double * rowlb = new double[numrows];
3697 double * rowub = new double[numrows];
3698 for (int i = numrows-1; i >= 0; --i) {
3699 convertSenseToBound(rowsenUse[i],rowrhsUse[i],rowrngUse[i],rowlb[i],rowub[i]);
3700 }
3701 if (rowsen!=rowsenUse)
3702 delete [] rowsenUse;
3703 if (rowrhs!=rowrhsUse)
3704 delete [] rowrhsUse;
3705 if (rowrng!=rowrngUse)
3706 delete [] rowrngUse;
3707 loadProblem(numcols, numrows, start, index, value, collb, colub, obj,
3708 rowlb, rowub);
3709 delete[] rowlb;
3710 delete[] rowub;
3711}
3712// This loads a model from a coinModel object - returns number of errors
3713int
3714OsiClpSolverInterface::loadFromCoinModel ( CoinModel & modelObject, bool keepSolution)
3715{
3716 modelPtr_->whatsChanged_ = 0;
3717 int numberErrors = 0;
3718 // Set arrays for normal use
3719 double * rowLower = modelObject.rowLowerArray();
3720 double * rowUpper = modelObject.rowUpperArray();
3721 double * columnLower = modelObject.columnLowerArray();
3722 double * columnUpper = modelObject.columnUpperArray();
3723 double * objective = modelObject.objectiveArray();
3724 int * integerType = modelObject.integerTypeArray();
3725 double * associated = modelObject.associatedArray();
3726 // If strings then do copies
3727 if (modelObject.stringsExist()) {
3728 numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
3729 objective, integerType,associated);
3730 }
3731 CoinPackedMatrix matrix;
3732 modelObject.createPackedMatrix(matrix,associated);
3733 int numberRows = modelObject.numberRows();
3734 int numberColumns = modelObject.numberColumns();
3735 CoinWarmStart * ws = getWarmStart();
3736 bool restoreBasis = keepSolution && numberRows&&numberRows==getNumRows()&&
3737 numberColumns==getNumCols();
3738 loadProblem(matrix,
3739 columnLower, columnUpper, objective, rowLower, rowUpper);
3740 if (restoreBasis)
3741 setWarmStart(ws);
3742 delete ws;
3743 // Do names if wanted
3744 int numberItems;
3745 numberItems = modelObject.rowNames()->numberItems();
3746 if (numberItems) {
3747 const char *const * rowNames=modelObject.rowNames()->names();
3748 modelPtr_->copyRowNames(rowNames,0,numberItems);
3749 }
3750 numberItems = modelObject.columnNames()->numberItems();
3751 if (numberItems) {
3752 const char *const * columnNames=modelObject.columnNames()->names();
3753 modelPtr_->copyColumnNames(columnNames,0,numberItems);
3754 }
3755 // Do integers if wanted
3756 assert(integerType);
3757 for (int iColumn=0;iColumn<numberColumns;iColumn++) {
3758 if (integerType[iColumn])
3759 setInteger(iColumn);
3760 }
3761 if (rowLower!=modelObject.rowLowerArray()||
3762 columnLower!=modelObject.columnLowerArray()) {
3763 delete [] rowLower;
3764 delete [] rowUpper;
3765 delete [] columnLower;
3766 delete [] columnUpper;
3767 delete [] objective;
3768 delete [] integerType;
3769 delete [] associated;
3770 //if (numberErrors)
3771 // handler_->message(CLP_BAD_STRING_VALUES,messages_)
3772 // <<numberErrors
3773 // <<CoinMessageEol;
3774 }
3775 modelPtr_->optimizationDirection_ = modelObject.optimizationDirection();
3776 return numberErrors;
3777}
3778
3779//-----------------------------------------------------------------------------
3780// Write mps files
3781//-----------------------------------------------------------------------------
3782
3783void OsiClpSolverInterface::writeMps(const char * filename,
3784 const char * extension,
3785 double objSense) const
3786{
3787 std::string f(filename);
3788 std::string e(extension);
3789 std::string fullname;
3790 if (e!="") {
3791 fullname = f + "." + e;
3792 } else {
3793 // no extension so no trailing period
3794 fullname = f;
3795 }
3796 // get names
3797 const char * const * const rowNames = modelPtr_->rowNamesAsChar();
3798 const char * const * const columnNames = modelPtr_->columnNamesAsChar();
3799 // Fall back on Osi version - possibly with names
3800 OsiSolverInterface::writeMpsNative(fullname.c_str(),
3801 const_cast<const char **>(rowNames),
3802 const_cast<const char **>(columnNames),0,2,objSense,
3803 numberSOS_,setInfo_);
3804 if (rowNames) {
3805 modelPtr_->deleteNamesAsChar(rowNames, modelPtr_->numberRows_+1);
3806 modelPtr_->deleteNamesAsChar(columnNames, modelPtr_->numberColumns_);
3807 }
3808}
3809
3810int
3811OsiClpSolverInterface::writeMpsNative(const char *filename,
3812 const char ** rowNames, const char ** columnNames,
3813 int formatType,int numberAcross,double objSense) const
3814{
3815 return OsiSolverInterface::writeMpsNative(filename, rowNames, columnNames,
3816 formatType, numberAcross,objSense,
3817 numberSOS_,setInfo_);
3818}
3819
3820//#############################################################################
3821// CLP specific public interfaces
3822//#############################################################################
3823
3824ClpSimplex * OsiClpSolverInterface::getModelPtr() const
3825{
3826 int saveAlgorithm = lastAlgorithm_;
3827 //freeCachedResults();
3828 lastAlgorithm_ = saveAlgorithm;
3829 //bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0;
3830 return modelPtr_;
3831}
3832
3833//-------------------------------------------------------------------
3834
3835//#############################################################################
3836// Constructors, destructors clone and assignment
3837//#############################################################################
3838//-------------------------------------------------------------------
3839// Default Constructor
3840//-------------------------------------------------------------------
3841OsiClpSolverInterface::OsiClpSolverInterface ()
3842:
3843OsiSolverInterface(),
3844rowsense_(NULL),
3845rhs_(NULL),
3846rowrange_(NULL),
3847ws_(NULL),
3848rowActivity_(NULL),
3849columnActivity_(NULL),
3850numberSOS_(0),
3851setInfo_(NULL),
3852smallModel_(NULL),
3853factorization_(NULL),
3854smallestElementInCut_(1.0e-15),
3855smallestChangeInCut_(1.0e-10),
3856largestAway_(-1.0),
3857spareArrays_(NULL),
3858matrixByRow_(NULL),
3859matrixByRowAtContinuous_(NULL),
3860integerInformation_(NULL),
3861whichRange_(NULL),
3862fakeMinInSimplex_(false),
3863linearObjective_(NULL),
3864cleanupScaling_(0),
3865specialOptions_(0x80000000),
3866baseModel_(NULL),
3867lastNumberRows_(0),
3868continuousModel_(NULL),
3869fakeObjective_(NULL)
3870{
3871 //printf("in default %x\n",this);
3872 modelPtr_=NULL;
3873 notOwned_=false;
3874 disasterHandler_ = new OsiClpDisasterHandler();
3875 reset();
3876}
3877
3878//-------------------------------------------------------------------
3879// Clone
3880//-------------------------------------------------------------------
3881OsiSolverInterface * OsiClpSolverInterface::clone(bool CopyData) const
3882{
3883 //printf("in clone %x\n",this);
3884 OsiClpSolverInterface * newSolver;
3885 if (CopyData) {
3886 newSolver = new OsiClpSolverInterface(*this);
3887 } else {
3888 newSolver = new OsiClpSolverInterface();
3889 }
3890#if 0
3891 const double * obj = newSolver->getObjCoefficients();
3892 const double * oldObj = getObjCoefficients();
3893 if(newSolver->getNumCols()>3787)
3894 printf("%x - obj %x (from %x) val %g\n",newSolver,obj,oldObj,obj[3787]);
3895#endif
3896 return newSolver;
3897}
3898
3899
3900//-------------------------------------------------------------------
3901// Copy constructor
3902//-------------------------------------------------------------------
3903OsiClpSolverInterface::OsiClpSolverInterface (
3904 const OsiClpSolverInterface & rhs)
3905: OsiSolverInterface(rhs),
3906rowsense_(NULL),
3907rhs_(NULL),
3908rowrange_(NULL),
3909ws_(NULL),
3910rowActivity_(NULL),
3911columnActivity_(NULL),
3912 stuff_(rhs.stuff_),
3913numberSOS_(rhs.numberSOS_),
3914setInfo_(NULL),
3915smallModel_(NULL),
3916factorization_(NULL),
3917smallestElementInCut_(rhs.smallestElementInCut_),
3918smallestChangeInCut_(rhs.smallestChangeInCut_),
3919largestAway_(-1.0),
3920spareArrays_(NULL),
3921basis_(),
3922itlimOrig_(9999999),
3923lastAlgorithm_(0),
3924notOwned_(false),
3925matrixByRow_(NULL),
3926matrixByRowAtContinuous_(NULL),
3927integerInformation_(NULL),
3928whichRange_(NULL),
3929fakeMinInSimplex_(rhs.fakeMinInSimplex_)
3930{
3931 //printf("in copy %x - > %x\n",&rhs,this);
3932 if ( rhs.modelPtr_ )
3933 modelPtr_ = new ClpSimplex(*rhs.modelPtr_);
3934 else
3935 modelPtr_ = new ClpSimplex();
3936 if ( rhs.baseModel_ )
3937 baseModel_ = new ClpSimplex(*rhs.baseModel_);
3938 else
3939 baseModel_ = NULL;
3940 if ( rhs.continuousModel_ )
3941 continuousModel_ = new ClpSimplex(*rhs.continuousModel_);
3942 else
3943 continuousModel_ = NULL;
3944 if (rhs.matrixByRowAtContinuous_)
3945 matrixByRowAtContinuous_ = new CoinPackedMatrix(*rhs.matrixByRowAtContinuous_);
3946 if ( rhs.disasterHandler_ )
3947 disasterHandler_ = dynamic_cast<OsiClpDisasterHandler *>(rhs.disasterHandler_->clone());
3948 else
3949 disasterHandler_ = NULL;
3950 if (rhs.fakeObjective_)
3951 fakeObjective_ = new ClpLinearObjective(*rhs.fakeObjective_);
3952 else
3953 fakeObjective_ = NULL;
3954 linearObjective_ = modelPtr_->objective();
3955 if ( rhs.ws_ )
3956 ws_ = new CoinWarmStartBasis(*rhs.ws_);
3957 basis_ = rhs.basis_;
3958 if (rhs.integerInformation_) {
3959 int numberColumns = modelPtr_->numberColumns();
3960 integerInformation_ = new char[numberColumns];
3961 CoinMemcpyN(rhs.integerInformation_, numberColumns,integerInformation_);
3962 }
3963 saveData_ = rhs.saveData_;
3964 solveOptions_ = rhs.solveOptions_;
3965 cleanupScaling_ = rhs.cleanupScaling_;
3966 specialOptions_ = rhs.specialOptions_;
3967 lastNumberRows_ = rhs.lastNumberRows_;
3968 rowScale_ = rhs.rowScale_;
3969 columnScale_ = rhs.columnScale_;
3970 fillParamMaps();
3971 messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
3972 if (numberSOS_) {
3973 setInfo_ = new CoinSet[numberSOS_];
3974 for (int i=0;i<numberSOS_;i++)
3975 setInfo_[i]=rhs.setInfo_[i];
3976 }
3977}
3978
3979// Borrow constructor - only delete one copy
3980OsiClpSolverInterface::OsiClpSolverInterface (ClpSimplex * rhs,
3981 bool reallyOwn)
3982:
3983OsiSolverInterface(),
3984rowsense_(NULL),
3985rhs_(NULL),
3986rowrange_(NULL),
3987ws_(NULL),
3988rowActivity_(NULL),
3989columnActivity_(NULL),
3990numberSOS_(0),
3991setInfo_(NULL),
3992smallModel_(NULL),
3993factorization_(NULL),
3994smallestElementInCut_(1.0e-15),
3995smallestChangeInCut_(1.0e-10),
3996largestAway_(-1.0),
3997spareArrays_(NULL),
3998basis_(),
3999itlimOrig_(9999999),
4000lastAlgorithm_(0),
4001notOwned_(false),
4002matrixByRow_(NULL),
4003matrixByRowAtContinuous_(NULL),
4004integerInformation_(NULL),
4005whichRange_(NULL),
4006fakeMinInSimplex_(false),
4007cleanupScaling_(0),
4008specialOptions_(0x80000000),
4009baseModel_(NULL),
4010lastNumberRows_(0),
4011continuousModel_(NULL),
4012fakeObjective_(NULL)
4013{
4014 disasterHandler_ = new OsiClpDisasterHandler();
4015 //printf("in borrow %x - > %x\n",&rhs,this);
4016 modelPtr_ = rhs;
4017 basis_.resize(modelPtr_->numberRows(),modelPtr_->numberColumns());
4018 linearObjective_ = modelPtr_->objective();
4019 if (rhs) {
4020 notOwned_=!reallyOwn;
4021
4022 if (rhs->integerInformation()) {
4023 int numberColumns = modelPtr_->numberColumns();
4024 integerInformation_ = new char[numberColumns];
4025 CoinMemcpyN(rhs->integerInformation(), numberColumns,integerInformation_);
4026 }
4027 }
4028 fillParamMaps();
4029}
4030
4031// Releases so won't error
4032void
4033OsiClpSolverInterface::releaseClp()
4034{
4035 modelPtr_=NULL;
4036 notOwned_=false;
4037}
4038
4039//-------------------------------------------------------------------
4040// Destructor
4041//-------------------------------------------------------------------
4042OsiClpSolverInterface::~OsiClpSolverInterface ()
4043{
4044 //printf("in destructor %x\n",this);
4045 freeCachedResults();
4046 if (!notOwned_)
4047 delete modelPtr_;
4048 delete baseModel_;
4049 delete continuousModel_;
4050 delete disasterHandler_;
4051 delete fakeObjective_;
4052 delete ws_;
4053 delete [] rowActivity_;
4054 delete [] columnActivity_;
4055 delete [] setInfo_;
4056#ifdef KEEP_SMALL
4057 if (smallModel_) {
4058 delete [] spareArrays_;
4059 spareArrays_ = NULL;
4060 delete smallModel_;
4061 smallModel_=NULL;
4062 }
4063#endif
4064 assert(smallModel_==NULL);
4065 assert(factorization_==NULL);
4066 assert(spareArrays_==NULL);
4067 delete [] integerInformation_;
4068 delete matrixByRowAtContinuous_;
4069 delete matrixByRow_;
4070}
4071
4072//-------------------------------------------------------------------
4073// Assignment operator
4074//-------------------------------------------------------------------
4075OsiClpSolverInterface &
4076OsiClpSolverInterface::operator=(const OsiClpSolverInterface& rhs)
4077{
4078 if (this != &rhs) {
4079 //printf("in = %x - > %x\n",&rhs,this);
4080 OsiSolverInterface::operator=(rhs);
4081 freeCachedResults();
4082 if (!notOwned_)
4083 delete modelPtr_;
4084 delete ws_;
4085 if ( rhs.modelPtr_ )
4086 modelPtr_ = new ClpSimplex(*rhs.modelPtr_);
4087 delete baseModel_;
4088 if ( rhs.baseModel_ )
4089 baseModel_ = new ClpSimplex(*rhs.baseModel_);
4090 else
4091 baseModel_ = NULL;
4092 delete continuousModel_;
4093 if ( rhs.continuousModel_ )
4094 continuousModel_ = new ClpSimplex(*rhs.continuousModel_);
4095 else
4096 continuousModel_ = NULL;
4097 delete matrixByRowAtContinuous_;
4098 delete matrixByRow_;
4099 matrixByRow_=NULL;
4100 if (rhs.matrixByRowAtContinuous_)
4101 matrixByRowAtContinuous_ = new CoinPackedMatrix(*rhs.matrixByRowAtContinuous_);
4102 else
4103 matrixByRowAtContinuous_=NULL;
4104 delete disasterHandler_;
4105 if ( rhs.disasterHandler_ )
4106 disasterHandler_ = dynamic_cast<OsiClpDisasterHandler *>(rhs.disasterHandler_->clone());
4107 else
4108 disasterHandler_ = NULL;
4109 delete fakeObjective_;
4110 if (rhs.fakeObjective_)
4111 fakeObjective_ = new ClpLinearObjective(*rhs.fakeObjective_);
4112 else
4113 fakeObjective_ = NULL;
4114 notOwned_=false;
4115 linearObjective_ = modelPtr_->objective();
4116 saveData_ = rhs.saveData_;
4117 solveOptions_ = rhs.solveOptions_;
4118 cleanupScaling_ = rhs.cleanupScaling_;
4119 specialOptions_ = rhs.specialOptions_;
4120 lastNumberRows_ = rhs.lastNumberRows_;
4121 rowScale_ = rhs.rowScale_;
4122 columnScale_ = rhs.columnScale_;
4123 basis_ = rhs.basis_;
4124 stuff_ = rhs.stuff_;
4125 if (rhs.integerInformation_) {
4126 int numberColumns = modelPtr_->numberColumns();
4127 integerInformation_ = new char[numberColumns];
4128 CoinMemcpyN(rhs.integerInformation_, numberColumns,integerInformation_);
4129 }
4130 if ( rhs.ws_ )
4131 ws_ = new CoinWarmStartBasis(*rhs.ws_);
4132 else
4133 ws_=NULL;
4134 delete [] rowActivity_;
4135 delete [] columnActivity_;
4136 rowActivity_=NULL;
4137 columnActivity_=NULL;
4138 delete [] setInfo_;
4139 numberSOS_ = rhs.numberSOS_;
4140 setInfo_=NULL;
4141 if (numberSOS_) {
4142 setInfo_ = new CoinSet[numberSOS_];
4143 for (int i=0;i<numberSOS_;i++)
4144 setInfo_[i]=rhs.setInfo_[i];
4145 }
4146 assert(smallModel_==NULL);
4147 assert(factorization_==NULL);
4148 smallestElementInCut_ = rhs.smallestElementInCut_;
4149 smallestChangeInCut_ = rhs.smallestChangeInCut_;
4150 largestAway_ = -1.0;
4151 assert(spareArrays_==NULL);
4152 basis_ = rhs.basis_;
4153 fillParamMaps();
4154 messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
4155 }
4156 return *this;
4157}
4158
4159//#############################################################################
4160// Applying cuts
4161//#############################################################################
4162
4163void OsiClpSolverInterface::applyRowCut( const OsiRowCut & rowCut )
4164{
4165 applyRowCuts(1, &rowCut);
4166}
4167/* Apply a collection of row cuts which are all effective.
4168 applyCuts seems to do one at a time which seems inefficient.
4169*/
4170void
4171OsiClpSolverInterface::applyRowCuts(int numberCuts, const OsiRowCut * cuts)
4172{
4173 if (numberCuts) {
4174 // Say can't gurantee optimal basis etc
4175 lastAlgorithm_=999;
4176
4177 // Thanks to js
4178 const OsiRowCut * * cutsp = new const OsiRowCut * [numberCuts];
4179 for (int i=0;i<numberCuts;i++)
4180 cutsp[i] = &cuts[i];
4181
4182 applyRowCuts(numberCuts, cutsp);
4183
4184 delete [] cutsp;
4185 }
4186}
4187/* Apply a collection of row cuts which are all effective.
4188 applyCuts seems to do one at a time which seems inefficient.
4189*/
4190void
4191OsiClpSolverInterface::applyRowCuts(int numberCuts, const OsiRowCut ** cuts)
4192{
4193 int i;
4194 if (!numberCuts)
4195 return;
4196 modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32));
4197 CoinPackedMatrix * saveRowCopy = matrixByRow_;
4198 matrixByRow_=NULL;
4199#if 0 // was #ifndef NDEBUG
4200 int nameDiscipline;
4201 getIntParam(OsiNameDiscipline,nameDiscipline) ;
4202 assert (!nameDiscipline);
4203#endif
4204 freeCachedResults0();
4205 // Say can't gurantee optimal basis etc
4206 lastAlgorithm_=999;
4207 int numberRows = modelPtr_->numberRows();
4208 modelPtr_->resize(numberRows+numberCuts,modelPtr_->numberColumns());
4209 basis_.resize(numberRows+numberCuts,modelPtr_->numberColumns());
4210 // redo as relaxed - use modelPtr_-> addRows with starts etc
4211 int size = 0;
4212 for (i=0;i<numberCuts;i++)
4213 size += cuts[i]->row().getNumElements();
4214 CoinBigIndex * starts = new CoinBigIndex [numberCuts+1];
4215 int * indices = new int[size];
4216 double * elements = new double[size];
4217 double * lower = modelPtr_->rowLower()+numberRows;
4218 double * upper = modelPtr_->rowUpper()+numberRows;
4219 const double * columnLower = modelPtr_->columnLower();
4220 const double * columnUpper = modelPtr_->columnUpper();
4221 size=0;
4222 for (i=0;i<numberCuts;i++) {
4223 double rowLb = cuts[i]->lb();
4224 double rowUb = cuts[i]->ub();
4225 int n=cuts[i]->row().getNumElements();
4226 const int * index = cuts[i]->row().getIndices();
4227 const double * elem = cuts[i]->row().getElements();
4228 starts[i]=size;
4229 for (int j=0;j<n;j++) {
4230 double value = elem[j];
4231 int column = index[j];
4232 if (fabs(value)>=smallestChangeInCut_) {
4233 // always take
4234 indices[size]=column;
4235 elements[size++]=value;
4236 } else if (fabs(value)>=smallestElementInCut_) {
4237 double lowerValue = columnLower[column];
4238 double upperValue = columnUpper[column];
4239 double difference = upperValue-lowerValue;
4240 if (difference<1.0e20&&difference*fabs(value)<smallestChangeInCut_&&
4241 (rowLb<-1.0e20||rowUb>1.0e20)) {
4242 // Take out and adjust to relax
4243 //printf("small el %g adjusted\n",value);
4244 if (rowLb>-1.0e20) {
4245 // just lower bound on row
4246 if (value>0.0) {
4247 // pretend at upper
4248 rowLb -= value*upperValue;
4249 } else {
4250 // pretend at lower
4251 rowLb -= value*lowerValue;
4252 }
4253 } else {
4254 // just upper bound on row
4255 if (value>0.0) {
4256 // pretend at lower
4257 rowUb -= value*lowerValue;
4258 } else {
4259 // pretend at upper
4260 rowUb -= value*upperValue;
4261 }
4262 }
4263 } else {
4264 // take (unwillingly)
4265 indices[size]=column;
4266 elements[size++]=value;
4267 }
4268 } else {
4269 //printf("small el %g ignored\n",value);
4270 }
4271 }
4272 lower[i]= forceIntoRange(rowLb, -OsiClpInfinity, OsiClpInfinity);
4273 upper[i]= forceIntoRange(rowUb, -OsiClpInfinity, OsiClpInfinity);
4274 if (lower[i]<-1.0e27)
4275 lower[i]=-COIN_DBL_MAX;
4276 if (upper[i]>1.0e27)
4277 upper[i]=COIN_DBL_MAX;
4278 }
4279 starts[numberCuts]=size;
4280 if (!modelPtr_->clpMatrix())
4281 modelPtr_->createEmptyMatrix();
4282 //modelPtr_->matrix()->appendRows(numberCuts,rows);
4283 modelPtr_->clpMatrix()->appendMatrix(numberCuts,0,starts,indices,elements);
4284 modelPtr_->setNewRowCopy(NULL);
4285 freeCachedResults1();
4286 redoScaleFactors( numberCuts,starts, indices, elements);
4287 if (saveRowCopy) {
4288#if 1
4289 matrixByRow_=saveRowCopy;
4290 matrixByRow_->appendRows(numberCuts,starts,indices,elements,0);
4291 assert (matrixByRow_->getNumElements()==modelPtr_->clpMatrix()->getNumElements());
4292#else
4293 delete saveRowCopy;
4294#endif
4295 }
4296 delete [] starts;
4297 delete [] indices;
4298 delete [] elements;
4299
4300}
4301//#############################################################################
4302// Apply Cuts
4303//#############################################################################
4304
4305OsiSolverInterface::ApplyCutsReturnCode
4306OsiClpSolverInterface::applyCuts( const OsiCuts & cs, double effectivenessLb )
4307{
4308 OsiSolverInterface::ApplyCutsReturnCode retVal;
4309 int i;
4310
4311 // Loop once for each column cut
4312 for ( i=0; i<cs.sizeColCuts(); i ++ ) {
4313 if ( cs.colCut(i).effectiveness() < effectivenessLb ) {
4314 retVal.incrementIneffective();
4315 continue;
4316 }
4317 if ( !cs.colCut(i).consistent() ) {
4318 retVal.incrementInternallyInconsistent();
4319 continue;
4320 }
4321 if ( !cs.colCut(i).consistent(*this) ) {
4322 retVal.incrementExternallyInconsistent();
4323 continue;
4324 }
4325 if ( cs.colCut(i).infeasible(*this) ) {
4326 retVal.incrementInfeasible();
4327 continue;
4328 }
4329 applyColCut( cs.colCut(i) );
4330 retVal.incrementApplied();
4331 }
4332
4333 // Loop once for each row cut
4334 const OsiRowCut ** addCuts = new const OsiRowCut* [cs.sizeRowCuts()];
4335 int nAdd=0;
4336 for ( i=0; i<cs.sizeRowCuts(); i ++ ) {
4337 if ( cs.rowCut(i).effectiveness() < effectivenessLb ) {
4338 retVal.incrementIneffective();
4339 continue;
4340 }
4341 if ( !cs.rowCut(i).consistent() ) {
4342 retVal.incrementInternallyInconsistent();
4343 continue;
4344 }
4345 if ( !cs.rowCut(i).consistent(*this) ) {
4346 retVal.incrementExternallyInconsistent();
4347 continue;
4348 }
4349 if ( cs.rowCut(i).infeasible(*this) ) {
4350 retVal.incrementInfeasible();
4351 continue;
4352 }
4353 addCuts[nAdd++] = cs.rowCutPtr(i);
4354 retVal.incrementApplied();
4355 }
4356 // now apply
4357 applyRowCuts(nAdd,addCuts);
4358 delete [] addCuts;
4359
4360 return retVal;
4361}
4362// Extend scale factors
4363void
4364OsiClpSolverInterface::redoScaleFactors(int numberAdd,const CoinBigIndex * starts,
4365 const int * indices, const double * elements)
4366{
4367 if ((specialOptions_&131072)!=0) {
4368 int numberRows = modelPtr_->numberRows()-numberAdd;
4369 assert (lastNumberRows_==numberRows); // ???
4370 int iRow;
4371 int newNumberRows = numberRows + numberAdd;
4372 rowScale_.extend(static_cast<int>(2*newNumberRows*sizeof(double)));
4373 double * rowScale = rowScale_.array();
4374 double * oldInverseScale = rowScale + lastNumberRows_;
4375 double * inverseRowScale = rowScale + newNumberRows;
4376 for (iRow=lastNumberRows_-1;iRow>=0;iRow--)
4377 inverseRowScale[iRow] = oldInverseScale[iRow] ;
4378 //int numberColumns = baseModel_->numberColumns();
4379 const double * columnScale = columnScale_.array();
4380 //const double * inverseColumnScale = columnScale + numberColumns;
4381 // Geometric mean on row scales
4382 // adjust arrays
4383 rowScale += lastNumberRows_;
4384 inverseRowScale += lastNumberRows_;
4385 for (iRow=0;iRow<numberAdd;iRow++) {
4386 CoinBigIndex j;
4387 double largest=1.0e-20;
4388 double smallest=1.0e50;
4389 for (j=starts[iRow];j<starts[iRow+1];j++) {
4390 int iColumn = indices[j];
4391 double value = fabs(elements[j]);
4392 // Don't bother with tiny elements
4393 if (value>1.0e-20) {
4394 value *= columnScale[iColumn];
4395 largest = CoinMax(largest,value);
4396 smallest = CoinMin(smallest,value);
4397 }
4398 }
4399 double scale=sqrt(smallest*largest);
4400 scale=CoinMax(1.0e-10,CoinMin(1.0e10,scale));
4401 inverseRowScale[iRow]=scale;
4402 rowScale[iRow]=1.0/scale;
4403 }
4404 lastNumberRows_=newNumberRows;
4405 }
4406}
4407// Delete all scale factor stuff and reset option
4408void OsiClpSolverInterface::deleteScaleFactors()
4409{
4410 delete baseModel_;
4411 baseModel_=NULL;
4412 lastNumberRows_=0;
4413 specialOptions_ &= ~131072;
4414}
4415//-----------------------------------------------------------------------------
4416
4417void OsiClpSolverInterface::applyColCut( const OsiColCut & cc )
4418{
4419 modelPtr_->whatsChanged_ &= (0x1ffff&~(128|256));
4420 // Say can't gurantee optimal basis etc
4421 lastAlgorithm_=999;
4422 double * lower = modelPtr_->columnLower();
4423 double * upper = modelPtr_->columnUpper();
4424 const CoinPackedVector & lbs = cc.lbs();
4425 const CoinPackedVector & ubs = cc.ubs();
4426 int i;
4427
4428 for ( i=0; i<lbs.getNumElements(); i++ ) {
4429 int iCol = lbs.getIndices()[i];
4430 double value = lbs.getElements()[i];
4431 if ( value > lower[iCol] )
4432 lower[iCol]= value;
4433 }
4434 for ( i=0; i<ubs.getNumElements(); i++ ) {
4435 int iCol = ubs.getIndices()[i];
4436 double value = ubs.getElements()[i];
4437 if ( value < upper[iCol] )
4438 upper[iCol]= value;
4439 }
4440}
4441//#############################################################################
4442// Private methods
4443//#############################################################################
4444
4445
4446//-------------------------------------------------------------------
4447
4448void OsiClpSolverInterface::freeCachedResults() const
4449{
4450 // Say can't gurantee optimal basis etc
4451 lastAlgorithm_=999;
4452 delete [] rowsense_;
4453 delete [] rhs_;
4454 delete [] rowrange_;
4455 delete matrixByRow_;
4456 if (modelPtr_&&modelPtr_->scaledMatrix_) {
4457 delete modelPtr_->scaledMatrix_;
4458 modelPtr_->scaledMatrix_=NULL;
4459 }
4460 //delete ws_;
4461 rowsense_=NULL;
4462 rhs_=NULL;
4463 rowrange_=NULL;
4464 matrixByRow_=NULL;
4465 //ws_ = NULL;
4466 if (modelPtr_&&modelPtr_->clpMatrix()) {
4467 modelPtr_->clpMatrix()->refresh(modelPtr_); // make sure all clean
4468#ifndef NDEBUG
4469 ClpPackedMatrix * clpMatrix = dynamic_cast<ClpPackedMatrix *> (modelPtr_->clpMatrix());
4470 if (clpMatrix) {
4471 if (clpMatrix->getNumCols())
4472 assert (clpMatrix->getNumRows()==modelPtr_->getNumRows());
4473 if (clpMatrix->getNumRows())
4474 assert (clpMatrix->getNumCols()==modelPtr_->getNumCols());
4475 }
4476#endif
4477 }
4478}
4479
4480//-------------------------------------------------------------------
4481
4482void OsiClpSolverInterface::freeCachedResults0() const
4483{
4484 delete [] rowsense_;
4485 delete [] rhs_;
4486 delete [] rowrange_;
4487 rowsense_=NULL;
4488 rhs_=NULL;
4489 rowrange_=NULL;
4490}
4491
4492//-------------------------------------------------------------------
4493
4494void OsiClpSolverInterface::freeCachedResults1() const
4495{
4496 // Say can't gurantee optimal basis etc
4497 lastAlgorithm_=999;
4498 delete matrixByRow_;
4499 matrixByRow_=NULL;
4500 //ws_ = NULL;
4501 if (modelPtr_&&modelPtr_->clpMatrix()) {
4502 delete modelPtr_->scaledMatrix_;
4503 modelPtr_->scaledMatrix_=NULL;
4504 modelPtr_->clpMatrix()->refresh(modelPtr_); // make sure all clean
4505#ifndef NDEBUG
4506 ClpPackedMatrix * clpMatrix = dynamic_cast<ClpPackedMatrix *> (modelPtr_->clpMatrix());
4507 if (clpMatrix) {
4508 assert (clpMatrix->getNumRows()==modelPtr_->getNumRows());
4509 assert (clpMatrix->getNumCols()==modelPtr_->getNumCols());
4510 }
4511#endif
4512 }
4513}
4514
4515//------------------------------------------------------------------
4516void OsiClpSolverInterface::extractSenseRhsRange() const
4517{
4518 if (rowsense_ == NULL) {
4519 // all three must be NULL
4520 assert ((rhs_ == NULL) && (rowrange_ == NULL));
4521
4522 int nr=modelPtr_->numberRows();
4523 if ( nr!=0 ) {
4524 rowsense_ = new char[nr];
4525 rhs_ = new double[nr];
4526 rowrange_ = new double[nr];
4527 std::fill(rowrange_,rowrange_+nr,0.0);
4528
4529 const double * lb = modelPtr_->rowLower();
4530 const double * ub = modelPtr_->rowUpper();
4531
4532 int i;
4533 for ( i=0; i<nr; i++ ) {
4534 convertBoundToSense(lb[i], ub[i], rowsense_[i], rhs_[i], rowrange_[i]);
4535 }
4536 }
4537 }
4538}
4539// Set language
4540void
4541OsiClpSolverInterface::newLanguage(CoinMessages::Language language)
4542{
4543 modelPtr_->newLanguage(language);
4544 OsiSolverInterface::newLanguage(language);
4545}
4546//#############################################################################
4547
4548void
4549OsiClpSolverInterface::fillParamMaps()
4550{
4551 assert (static_cast<int> (OsiMaxNumIteration)== static_cast<int>(ClpMaxNumIteration));
4552 assert (static_cast<int> (OsiMaxNumIterationHotStart)==static_cast<int>(ClpMaxNumIterationHotStart));
4553 //assert (static_cast<int> (OsiLastIntParam)== static_cast<int>(ClpLastIntParam));
4554
4555 assert (static_cast<int> (OsiDualObjectiveLimit)== static_cast<int>(ClpDualObjectiveLimit));
4556 assert (static_cast<int> (OsiPrimalObjectiveLimit)==static_cast<int>(ClpPrimalObjectiveLimit));
4557 assert (static_cast<int> (OsiDualTolerance)== static_cast<int>(ClpDualTolerance));
4558 assert (static_cast<int> (OsiPrimalTolerance)== static_cast<int>(ClpPrimalTolerance));
4559 assert (static_cast<int> (OsiObjOffset)== static_cast<int>(ClpObjOffset));
4560 //assert (static_cast<int> (OsiLastDblParam)== static_cast<int>(ClpLastDblParam));
4561
4562 assert (static_cast<int> (OsiProbName)== static_cast<int> (ClpProbName));
4563 //strParamMap_[OsiLastStrParam] = ClpLastStrParam;
4564}
4565// Sets up basis
4566void
4567OsiClpSolverInterface::setBasis ( const CoinWarmStartBasis & basis)
4568{
4569 setBasis(basis,modelPtr_);
4570 setWarmStart(&basis);
4571}
4572// Warm start
4573CoinWarmStartBasis
4574OsiClpSolverInterface::getBasis(ClpSimplex * model) const
4575{
4576 int iRow,iColumn;
4577 int numberRows = model->numberRows();
4578 int numberColumns = model->numberColumns();
4579 CoinWarmStartBasis basis;
4580 basis.setSize(numberColumns,numberRows);
4581 if (model->statusExists()) {
4582 // Flip slacks
4583 int lookupA[]={0,1,3,2,0,2};
4584 for (iRow=0;iRow<numberRows;iRow++) {
4585 int iStatus = model->getRowStatus(iRow);
4586 iStatus = lookupA[iStatus];
4587 basis.setArtifStatus(iRow,static_cast<CoinWarmStartBasis::Status> (iStatus));
4588 }
4589 int lookupS[]={0,1,2,3,0,3};
4590 for (iColumn=0;iColumn<numberColumns;iColumn++) {
4591 int iStatus = model->getColumnStatus(iColumn);
4592 iStatus = lookupS[iStatus];
4593 basis.setStructStatus(iColumn,static_cast<CoinWarmStartBasis::Status> (iStatus));
4594 }
4595 }
4596 //basis.print();
4597 return basis;
4598}
4599// Warm start from statusArray
4600CoinWarmStartBasis *
4601OsiClpSolverInterface::getBasis(const unsigned char * statusArray) const
4602{
4603 int iRow,iColumn;
4604 int numberRows = modelPtr_->numberRows();
4605 int numberColumns = modelPtr_->numberColumns();
4606 CoinWarmStartBasis * basis = new CoinWarmStartBasis();
4607 basis->setSize(numberColumns,numberRows);
4608 // Flip slacks
4609 int lookupA[]={0,1,3,2,0,2};
4610 for (iRow=0;iRow<numberRows;iRow++) {
4611 int iStatus = statusArray[numberColumns+iRow]&7;
4612 iStatus = lookupA[iStatus];
4613 basis->setArtifStatus(iRow,static_cast<CoinWarmStartBasis::Status> (iStatus));
4614 }
4615 int lookupS[]={0,1,2,3,0,3};
4616 for (iColumn=0;iColumn<numberColumns;iColumn++) {
4617 int iStatus = statusArray[iColumn]&7;
4618 iStatus = lookupS[iStatus];
4619 basis->setStructStatus(iColumn,static_cast<CoinWarmStartBasis::Status> (iStatus));
4620 }
4621 //basis->print();
4622 return basis;
4623}
4624// Sets up basis
4625void
4626OsiClpSolverInterface::setBasis ( const CoinWarmStartBasis & basis,
4627 ClpSimplex * model)
4628{
4629 // Say can't gurantee optimal basis etc
4630 lastAlgorithm_=999;
4631 // transform basis to status arrays
4632 int iRow,iColumn;
4633 int numberRows = model->numberRows();
4634 int numberColumns = model->numberColumns();
4635 if (!model->statusExists()) {
4636 /*
4637 get status arrays
4638 ClpBasis would seem to have overheads and we will need
4639 extra bits anyway.
4640 */
4641 model->createStatus();
4642 }
4643 if (basis.getNumArtificial()!=numberRows||
4644 basis.getNumStructural()!=numberColumns) {
4645 CoinWarmStartBasis basis2 = basis;
4646 // resize
4647 basis2.resize(numberRows,numberColumns);
4648 // move status
4649 model->createStatus();
4650 // For rows lower and upper are flipped
4651 for (iRow=0;iRow<numberRows;iRow++) {
4652 int stat = basis2.getArtifStatus(iRow);
4653 if (stat>1)
4654 stat = 5 - stat; // so 2->3 and 3->2
4655 model->setRowStatus(iRow, static_cast<ClpSimplex::Status> (stat));
4656 }
4657 for (iColumn=0;iColumn<numberColumns;iColumn++) {
4658 model->setColumnStatus(iColumn,
4659 static_cast<ClpSimplex::Status> (basis2.getStructStatus(iColumn)));
4660 }
4661 } else {
4662 // move status
4663 model->createStatus();
4664 // For rows lower and upper are flipped
4665 for (iRow=0;iRow<numberRows;iRow++) {
4666 int stat = basis.getArtifStatus(iRow);
4667 if (stat>1)
4668 stat = 5 - stat; // so 2->3 and 3->2
4669 model->setRowStatus(iRow, static_cast<ClpSimplex::Status> (stat));
4670 }
4671 for (iColumn=0;iColumn<numberColumns;iColumn++) {
4672 model->setColumnStatus(iColumn,
4673 static_cast<ClpSimplex::Status> (basis.getStructStatus(iColumn)));
4674 }
4675 }
4676}
4677// Warm start difference from basis_ to statusArray
4678CoinWarmStartDiff *
4679OsiClpSolverInterface::getBasisDiff(const unsigned char * statusArray) const
4680{
4681 int iRow,iColumn;
4682 int numberRows = modelPtr_->numberRows();
4683 int numberColumns = modelPtr_->numberColumns();
4684 CoinWarmStartBasis basis;
4685 basis.setSize(numberColumns,numberRows);
4686 assert (modelPtr_->statusExists());
4687 int lookupS[]={0,1,2,3,0,3};
4688 for (iColumn=0;iColumn<numberColumns;iColumn++) {
4689 int iStatus = statusArray[iColumn]&7;
4690 iStatus = lookupS[iStatus];
4691 basis.setStructStatus(iColumn,static_cast<CoinWarmStartBasis::Status> (iStatus));
4692 }
4693 statusArray += numberColumns;
4694 // Flip slacks
4695 int lookupA[]={0,1,3,2,0,2};
4696 for (iRow=0;iRow<numberRows;iRow++) {
4697 int iStatus = statusArray[iRow]&7;
4698 iStatus = lookupA[iStatus];
4699 basis.setArtifStatus(iRow,static_cast<CoinWarmStartBasis::Status> (iStatus));
4700 }
4701 // Now basis is what we want while basis_ is old
4702 CoinWarmStartDiff * difference = basis.generateDiff(&basis_);
4703 return difference;
4704}
4705/*
4706 Read an mps file from the given filename - returns number of errors
4707 (see CoinMpsIO class)
4708*/
4709int
4710OsiClpSolverInterface::readMps(const char *filename,
4711 const char *extension )
4712{
4713 // Get rid of integer stuff
4714 delete [] integerInformation_;
4715 integerInformation_=NULL;
4716 freeCachedResults();
4717
4718 CoinMpsIO m;
4719 m.setInfinity(getInfinity());
4720 m.passInMessageHandler(modelPtr_->messageHandler());
4721 *m.messagesPointer()=modelPtr_->coinMessages();
4722
4723 delete [] setInfo_;
4724 setInfo_=NULL;
4725 numberSOS_=0;
4726 CoinSet ** sets=NULL;
4727 // Temporarily reduce log level to get CoinMpsIO to shut up.
4728 int saveLogLevel = modelPtr_->messageHandler()->logLevel() ;
4729 modelPtr_->messageHandler()->setLogLevel(0) ;
4730 int numberErrors = m.readMps(filename,extension,numberSOS_,sets);
4731 modelPtr_->messageHandler()->setLogLevel(saveLogLevel) ;
4732 if (numberSOS_) {
4733 setInfo_ = new CoinSet[numberSOS_];
4734 for (int i=0;i<numberSOS_;i++) {
4735 setInfo_[i]=*sets[i];
4736 delete sets[i];
4737 }
4738 delete [] sets;
4739 }
4740 handler_->message(COIN_SOLVER_MPS,messages_)
4741 <<m.getProblemName()<< numberErrors <<CoinMessageEol;
4742 if (!numberErrors) {
4743
4744 // set objective function offest
4745 setDblParam(OsiObjOffset,m.objectiveOffset());
4746
4747 // set problem name
4748 setStrParam(OsiProbName,m.getProblemName());
4749
4750 // no errors
4751 loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(),
4752 m.getObjCoefficients(),m.getRowSense(),m.getRightHandSide(),
4753 m.getRowRange());
4754 const char * integer = m.integerColumns();
4755 int nCols=m.getNumCols();
4756 int nRows=m.getNumRows();
4757 if (integer) {
4758 int i,n=0;
4759 int * index = new int [nCols];
4760 for (i=0;i<nCols;i++) {
4761 if (integer[i]) {
4762 index[n++]=i;
4763 }
4764 }
4765 setInteger(index,n);
4766 delete [] index;
4767 if (n)
4768 modelPtr_->copyInIntegerInformation(integer);
4769 }
4770
4771 // set objective name
4772 setObjName(m.getObjectiveName());
4773
4774 // Always keep names
4775 int nameDiscipline;
4776 getIntParam(OsiNameDiscipline,nameDiscipline) ;
4777 int iRow;
4778 std::vector<std::string> rowNames = std::vector<std::string> ();
4779 std::vector<std::string> columnNames = std::vector<std::string> ();
4780 rowNames.reserve(nRows);
4781 for (iRow=0;iRow<nRows;iRow++) {
4782 const char * name = m.rowName(iRow);
4783 rowNames.push_back(name);
4784 if (nameDiscipline)
4785 OsiSolverInterface::setRowName(iRow,name) ;
4786 }
4787
4788 int iColumn;
4789 columnNames.reserve(nCols);
4790 for (iColumn=0;iColumn<nCols;iColumn++) {
4791 const char * name = m.columnName(iColumn);
4792 columnNames.push_back(name);
4793 if (nameDiscipline)
4794 OsiSolverInterface::setColName(iColumn,name) ;
4795 }
4796 modelPtr_->copyNames(rowNames,columnNames);
4797 }
4798 return numberErrors;
4799}
4800int
4801OsiClpSolverInterface::readMps(const char *filename, const char*extension,
4802 int & numberSets, CoinSet ** & sets)
4803{
4804 int numberErrors = readMps(filename,extension);
4805 numberSets= numberSOS_;
4806 sets = &setInfo_;
4807 return numberErrors;
4808}
4809/* Read an mps file from the given filename returns
4810 number of errors (see OsiMpsReader class) */
4811int
4812OsiClpSolverInterface::readMps(const char *filename,bool keepNames,bool allowErrors)
4813{
4814 // Get rid of integer stuff
4815 delete [] integerInformation_;
4816 integerInformation_=NULL;
4817 freeCachedResults();
4818
4819 CoinMpsIO m;
4820 m.setInfinity(getInfinity());
4821 m.passInMessageHandler(modelPtr_->messageHandler());
4822 *m.messagesPointer()=modelPtr_->coinMessages();
4823 m.setSmallElementValue(CoinMax(modelPtr_->getSmallElementValue(),
4824 m.getSmallElementValue()));
4825
4826 delete [] setInfo_;
4827 setInfo_=NULL;
4828 numberSOS_=0;
4829 CoinSet ** sets=NULL;
4830 int numberErrors = m.readMps(filename,"",numberSOS_,sets);
4831 if (numberSOS_) {
4832 setInfo_ = new CoinSet[numberSOS_];
4833 for (int i=0;i<numberSOS_;i++) {
4834 setInfo_[i]=*sets[i];
4835 delete sets[i];
4836 }
4837 delete [] sets;
4838 }
4839 handler_->message(COIN_SOLVER_MPS,messages_)
4840 <<m.getProblemName()<< numberErrors <<CoinMessageEol;
4841 if (!numberErrors||((numberErrors>0&&numberErrors<100000)&&allowErrors)) {
4842
4843 // set objective function offest
4844 setDblParam(OsiObjOffset,m.objectiveOffset());
4845
4846 // set problem name
4847 setStrParam(OsiProbName,m.getProblemName());
4848
4849 // set objective name
4850 setObjName(m.getObjectiveName());
4851
4852 // no errors
4853 loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(),
4854 m.getObjCoefficients(),m.getRowSense(),m.getRightHandSide(),
4855 m.getRowRange());
4856 int nCols=m.getNumCols();
4857 // get quadratic part
4858 if (m.reader()->whichSection ( ) == COIN_QUAD_SECTION ) {
4859 int * start=NULL;
4860 int * column = NULL;
4861 double * element = NULL;
4862 int status=m.readQuadraticMps(NULL,start,column,element,2);
4863 if (!status)
4864 modelPtr_->loadQuadraticObjective(nCols,start,column,element);
4865 delete [] start;
4866 delete [] column;
4867 delete [] element;
4868 }
4869 const char * integer = m.integerColumns();
4870 int nRows=m.getNumRows();
4871 if (integer) {
4872 int i,n=0;
4873 int * index = new int [nCols];
4874 for (i=0;i<nCols;i++) {
4875 if (integer[i]) {
4876 index[n++]=i;
4877 }
4878 }
4879 setInteger(index,n);
4880 delete [] index;
4881 if (n)
4882 modelPtr_->copyInIntegerInformation(integer);
4883 }
4884 if (keepNames) {
4885 // keep names
4886 int nameDiscipline;
4887 getIntParam(OsiNameDiscipline,nameDiscipline) ;
4888 int iRow;
4889 std::vector<std::string> rowNames = std::vector<std::string> ();
4890 std::vector<std::string> columnNames = std::vector<std::string> ();
4891 rowNames.reserve(nRows);
4892 for (iRow=0;iRow<nRows;iRow++) {
4893 const char * name = m.rowName(iRow);
4894 rowNames.push_back(name);
4895 if (nameDiscipline)
4896 OsiSolverInterface::setRowName(iRow,name) ;
4897 }
4898
4899 int iColumn;
4900 columnNames.reserve(nCols);
4901 for (iColumn=0;iColumn<nCols;iColumn++) {
4902 const char * name = m.columnName(iColumn);
4903 columnNames.push_back(name);
4904 if (nameDiscipline)
4905 OsiSolverInterface::setColName(iColumn,name) ;
4906 }
4907 modelPtr_->copyNames(rowNames,columnNames);
4908 }
4909 }
4910 return numberErrors;
4911}
4912// Read file in LP format (with names)
4913int
4914OsiClpSolverInterface::readLp(const char *filename, const double epsilon )
4915{
4916 CoinLpIO m;
4917 m.passInMessageHandler(modelPtr_->messageHandler());
4918 *m.messagesPointer()=modelPtr_->coinMessages();
4919 m.readLp(filename, epsilon);
4920 freeCachedResults();
4921
4922 // set objective function offest
4923 setDblParam(OsiObjOffset, 0);
4924
4925 // set problem name
4926 setStrParam(OsiProbName, m.getProblemName());
4927
4928 // set objective name
4929 setObjName(m.getObjName());
4930
4931 // no errors
4932 loadProblem(*m.getMatrixByRow(), m.getColLower(), m.getColUpper(),
4933 m.getObjCoefficients(), m.getRowLower(), m.getRowUpper());
4934
4935 const char *integer = m.integerColumns();
4936 int nCols = m.getNumCols();
4937 int nRows = m.getNumRows();
4938 if (integer) {
4939 int i, n = 0;
4940 int *index = new int [nCols];
4941 for (i=0; i<nCols; i++) {
4942 if (integer[i]) {
4943 index[n++] = i;
4944 }
4945 }
4946 setInteger(index,n);
4947 delete [] index;
4948 }
4949 // Always keep names
4950 int nameDiscipline;
4951 getIntParam(OsiNameDiscipline,nameDiscipline) ;
4952 int iRow;
4953 std::vector<std::string> rowNames = std::vector<std::string> ();
4954 std::vector<std::string> columnNames = std::vector<std::string> ();
4955 rowNames.reserve(nRows);
4956 for (iRow=0;iRow<nRows;iRow++) {
4957 const char * name = m.rowName(iRow);
4958 rowNames.push_back(name);
4959 if (nameDiscipline)
4960 OsiSolverInterface::setRowName(iRow,name) ;
4961 }
4962
4963 int iColumn;
4964 columnNames.reserve(nCols);
4965 for (iColumn=0;iColumn<nCols;iColumn++) {
4966 const char * name = m.columnName(iColumn);
4967 columnNames.push_back(name);
4968 if (nameDiscipline)
4969 OsiSolverInterface::setColName(iColumn,name) ;
4970 }
4971 modelPtr_->copyNames(rowNames,columnNames);
4972 return(0);
4973}
4974/* Write the problem into an Lp file of the given filename.
4975 If objSense is non zero then -1.0 forces the code to write a
4976 maximization objective and +1.0 to write a minimization one.
4977 If 0.0 then solver can do what it wants.
4978 This version calls writeLpNative with names */
4979void
4980OsiClpSolverInterface::writeLp(const char *filename,
4981 const char *extension ,
4982 double epsilon ,
4983 int numberAcross ,
4984 int decimals ,
4985 double objSense ,
4986 bool changeNameOnRange) const
4987{
4988 std::string f(filename);
4989 std::string e(extension);
4990 std::string fullname;
4991 if (e!="") {
4992 fullname = f + "." + e;
4993 } else {
4994 // no extension so no trailing period
4995 fullname = f;
4996 }
4997 // get names
4998 const char * const * const rowNames = modelPtr_->rowNamesAsChar();
4999 const char * const * const columnNames = modelPtr_->columnNamesAsChar();
5000 // Fall back on Osi version - possibly with names
5001 OsiSolverInterface::writeLpNative(fullname.c_str(),
5002 rowNames,columnNames, epsilon, numberAcross,
5003 decimals, objSense,changeNameOnRange);
5004 if (rowNames) {
5005 modelPtr_->deleteNamesAsChar(rowNames, modelPtr_->numberRows_+1);
5006 modelPtr_->deleteNamesAsChar(columnNames, modelPtr_->numberColumns_);
5007 }
5008}
5009void
5010OsiClpSolverInterface::writeLp(FILE * fp,
5011 double epsilon ,
5012 int numberAcross ,
5013 int decimals ,
5014 double objSense ,
5015 bool changeNameOnRange) const
5016{
5017 // get names
5018 const char * const * const rowNames = modelPtr_->rowNamesAsChar();
5019 const char * const * const columnNames = modelPtr_->columnNamesAsChar();
5020 // Fall back on Osi version - possibly with names
5021 OsiSolverInterface::writeLpNative(fp,
5022 rowNames,columnNames, epsilon, numberAcross,
5023 decimals, objSense,changeNameOnRange);
5024 if (rowNames) {
5025 modelPtr_->deleteNamesAsChar(rowNames, modelPtr_->numberRows_+1);
5026 modelPtr_->deleteNamesAsChar(columnNames, modelPtr_->numberColumns_);
5027 }
5028}
5029/*
5030 I (JJF) am getting incredibly annoyed because I can't just replace a matrix.
5031 The default behavior of this is do nothing so only use where that would not matter
5032 e.g. strengthening a matrix for MIP
5033*/
5034void
5035OsiClpSolverInterface::replaceMatrixOptional(const CoinPackedMatrix & matrix)
5036{
5037 modelPtr_->whatsChanged_ &= (0xffff&~(2|4|8));
5038 replaceMatrix(matrix);
5039}
5040// And if it does matter (not used at present)
5041void
5042OsiClpSolverInterface::replaceMatrix(const CoinPackedMatrix & matrix)
5043{
5044 modelPtr_->whatsChanged_ &= (0xffff&~(2|4|8));
5045 delete modelPtr_->matrix_;
5046 delete modelPtr_->rowCopy_;
5047 modelPtr_->rowCopy_=NULL;
5048 if (matrix.isColOrdered()) {
5049 modelPtr_->matrix_=new ClpPackedMatrix(matrix);
5050 } else {
5051 CoinPackedMatrix matrix2;
5052 matrix2.setExtraGap(0.0);
5053 matrix2.setExtraMajor(0.0);
5054 matrix2.reverseOrderedCopyOf(matrix);
5055 modelPtr_->matrix_=new ClpPackedMatrix(matrix2);
5056 }
5057 modelPtr_->matrix_->setDimensions(modelPtr_->numberRows_,modelPtr_->numberColumns_);
5058 freeCachedResults();
5059}
5060// Get pointer to array[getNumCols()] of primal solution vector
5061const double *
5062OsiClpSolverInterface::getColSolution() const
5063{
5064 if (modelPtr_->solveType()!=2) {
5065 return modelPtr_->primalColumnSolution();
5066 } else {
5067 // simplex interface
5068 return modelPtr_->solutionRegion(1);
5069 }
5070}
5071
5072// Get pointer to array[getNumRows()] of dual prices
5073const double *
5074OsiClpSolverInterface::getRowPrice() const
5075{
5076 if (modelPtr_->solveType()!=2) {
5077 return modelPtr_->dualRowSolution();
5078 } else {
5079 // simplex interface
5080 //return modelPtr_->djRegion(0);
5081 return modelPtr_->dualRowSolution();
5082 }
5083}
5084
5085// Get a pointer to array[getNumCols()] of reduced costs
5086const double *
5087OsiClpSolverInterface::getReducedCost() const
5088{
5089 if (modelPtr_->solveType()!=2) {
5090 return modelPtr_->dualColumnSolution();
5091 } else {
5092 // simplex interface
5093 return modelPtr_->djRegion(1);
5094 }
5095}
5096
5097/* Get pointer to array[getNumRows()] of row activity levels (constraint
5098 matrix times the solution vector */
5099const double *
5100OsiClpSolverInterface::getRowActivity() const
5101{
5102 if (modelPtr_->solveType()!=2) {
5103 return modelPtr_->primalRowSolution();
5104 } else {
5105 // simplex interface
5106 return modelPtr_->solutionRegion(0);
5107 }
5108}
5109double
5110OsiClpSolverInterface::getObjValue() const
5111{
5112 if (modelPtr_->numberIterations()||modelPtr_->upperIn_!=-COIN_DBL_MAX) {
5113 // This does not pass unitTest when getObjValue is called before solve.
5114 //printf("obj a %g %g\n",modelPtr_->objectiveValue(),
5115 // OsiSolverInterface::getObjValue());
5116 if (fakeMinInSimplex_)
5117 return -modelPtr_->objectiveValue() ;
5118 else
5119 return modelPtr_->objectiveValue();
5120 } else {
5121 return OsiSolverInterface::getObjValue();
5122 }
5123}
5124
5125/* Set an objective function coefficient */
5126void
5127OsiClpSolverInterface::setObjCoeff( int elementIndex, double elementValue )
5128{
5129 modelPtr_->whatsChanged_ &= 0xffff;
5130 // Say can't gurantee optimal basis etc
5131 lastAlgorithm_=999;
5132#ifndef NDEBUG
5133 int n = modelPtr_->numberColumns();
5134 if (elementIndex<0||elementIndex>=n) {
5135 indexError(elementIndex,"setObjCoeff");
5136 }
5137#endif
5138 modelPtr_->setObjectiveCoefficient(elementIndex,
5139 ((fakeMinInSimplex_)?-elementValue:elementValue));
5140}
5141
5142/* Set a single column lower bound<br>
5143 Use -DBL_MAX for -infinity. */
5144void
5145OsiClpSolverInterface::setColLower( int index, double elementValue )
5146{
5147 modelPtr_->whatsChanged_ &= 0x1ffff;
5148#ifndef NDEBUG
5149 int n = modelPtr_->numberColumns();
5150 if (index<0||index>=n) {
5151 indexError(index,"setColLower");
5152 }
5153#endif
5154 double currentValue = modelPtr_->columnActivity_[index];
5155 bool changed=(currentValue<elementValue-modelPtr_->primalTolerance()||
5156 index>=basis_.getNumStructural()||
5157 basis_.getStructStatus(index)==CoinWarmStartBasis::atLowerBound);
5158 // Say can't gurantee optimal basis etc
5159 if (changed)
5160 lastAlgorithm_=999;
5161 if (!modelPtr_->lower_)
5162 modelPtr_->whatsChanged_ &= ~0xffff; // switch off
5163 modelPtr_->setColumnLower(index,elementValue);
5164}
5165
5166/* Set a single column upper bound<br>
5167 Use DBL_MAX for infinity. */
5168void
5169OsiClpSolverInterface::setColUpper( int index, double elementValue )
5170{
5171 modelPtr_->whatsChanged_ &= 0x1ffff;
5172#ifndef NDEBUG
5173 int n = modelPtr_->numberColumns();
5174 if (index<0||index>=n) {
5175 indexError(index,"setColUpper");
5176 }
5177#endif
5178 double currentValue = modelPtr_->columnActivity_[index];
5179 bool changed=(currentValue>elementValue+modelPtr_->primalTolerance()||
5180 index>=basis_.getNumStructural()||
5181 basis_.getStructStatus(index)==CoinWarmStartBasis::atUpperBound);
5182 // Say can't gurantee optimal basis etc
5183 if (changed)
5184 lastAlgorithm_=999;
5185 if (!modelPtr_->upper_)
5186 modelPtr_->whatsChanged_ &= ~0xffff; // switch off
5187 modelPtr_->setColumnUpper(index,elementValue);
5188}
5189
5190/* Set a single column lower and upper bound */
5191void
5192OsiClpSolverInterface::setColBounds( int elementIndex,
5193 double lower, double upper )
5194{
5195 modelPtr_->whatsChanged_ &= 0x1ffff;
5196 // Say can't gurantee optimal basis etc
5197 lastAlgorithm_=999;
5198#ifndef NDEBUG
5199 int n = modelPtr_->numberColumns();
5200 if (elementIndex<0||elementIndex>=n) {
5201 indexError(elementIndex,"setColBounds");
5202 }
5203#endif
5204 if (!modelPtr_->lower_)
5205 modelPtr_->whatsChanged_ &= ~0xffff; // switch off
5206 modelPtr_->setColumnBounds(elementIndex,lower,upper);
5207}
5208void OsiClpSolverInterface::setColSetBounds(const int* indexFirst,
5209 const int* indexLast,
5210 const double* boundList)
5211{
5212 modelPtr_->whatsChanged_ &= 0x1ffff;
5213 // Say can't gurantee optimal basis etc
5214 lastAlgorithm_=999;
5215#ifndef NDEBUG
5216 int n = modelPtr_->numberColumns();
5217 const int * indexFirst2=indexFirst;
5218 while (indexFirst2 != indexLast) {
5219 const int iColumn=*indexFirst2++;
5220 if (iColumn<0||iColumn>=n) {
5221 indexError(iColumn,"setColSetBounds");
5222 }
5223 }
5224#endif
5225 modelPtr_->setColSetBounds(indexFirst,indexLast,boundList);
5226}
5227//------------------------------------------------------------------
5228/* Set a single row lower bound<br>
5229 Use -DBL_MAX for -infinity. */
5230void
5231OsiClpSolverInterface::setRowLower( int elementIndex, double elementValue ) {
5232 // Say can't gurantee optimal basis etc
5233 lastAlgorithm_=999;
5234 modelPtr_->whatsChanged_ &= 0xffff;
5235#ifndef NDEBUG
5236 int n = modelPtr_->numberRows();
5237 if (elementIndex<0||elementIndex>=n) {
5238 indexError(elementIndex,"setRowLower");
5239 }
5240#endif
5241 modelPtr_->setRowLower(elementIndex , elementValue);
5242 if (rowsense_!=NULL) {
5243 assert ((rhs_ != NULL) && (rowrange_ != NULL));
5244 convertBoundToSense(modelPtr_->rowLower_[elementIndex],
5245 modelPtr_->rowUpper_[elementIndex],
5246 rowsense_[elementIndex], rhs_[elementIndex], rowrange_[elementIndex]);
5247 }
5248}
5249
5250/* Set a single row upper bound<br>
5251 Use DBL_MAX for infinity. */
5252void
5253OsiClpSolverInterface::setRowUpper( int elementIndex, double elementValue ) {
5254 modelPtr_->whatsChanged_ &= 0xffff;
5255 // Say can't gurantee optimal basis etc
5256 lastAlgorithm_=999;
5257#ifndef NDEBUG
5258 int n = modelPtr_->numberRows();
5259 if (elementIndex<0||elementIndex>=n) {
5260 indexError(elementIndex,"setRowUpper");
5261 }
5262#endif
5263 modelPtr_->setRowUpper(elementIndex , elementValue);
5264 if (rowsense_!=NULL) {
5265 assert ((rhs_ != NULL) && (rowrange_ != NULL));
5266 convertBoundToSense(modelPtr_->rowLower_[elementIndex],
5267 modelPtr_->rowUpper_[elementIndex],
5268 rowsense_[elementIndex], rhs_[elementIndex], rowrange_[elementIndex]);
5269 }
5270}
5271
5272/* Set a single row lower and upper bound */
5273void
5274OsiClpSolverInterface::setRowBounds( int elementIndex,
5275 double lower, double upper ) {
5276 modelPtr_->whatsChanged_ &= 0xffff;
5277 // Say can't gurantee optimal basis etc
5278 lastAlgorithm_=999;
5279#ifndef NDEBUG
5280 int n = modelPtr_->numberRows();
5281 if (elementIndex<0||elementIndex>=n) {
5282 indexError(elementIndex,"setRowBounds");
5283 }
5284#endif
5285 modelPtr_->setRowBounds(elementIndex,lower,upper);
5286 if (rowsense_!=NULL) {
5287 assert ((rhs_ != NULL) && (rowrange_ != NULL));
5288 convertBoundToSense(modelPtr_->rowLower_[elementIndex],
5289 modelPtr_->rowUpper_[elementIndex],
5290 rowsense_[elementIndex], rhs_[elementIndex], rowrange_[elementIndex]);
5291 }
5292}
5293//-----------------------------------------------------------------------------
5294void
5295OsiClpSolverInterface::setRowType(int i, char sense, double rightHandSide,
5296 double range)
5297{
5298 modelPtr_->whatsChanged_ &= 0xffff;
5299 // Say can't gurantee optimal basis etc
5300 lastAlgorithm_=999;
5301#ifndef NDEBUG
5302 int n = modelPtr_->numberRows();
5303 if (i<0||i>=n) {
5304 indexError(i,"setRowType");
5305 }
5306#endif
5307 double lower = 0, upper = 0;
5308 convertSenseToBound(sense, rightHandSide, range, lower, upper);
5309 setRowBounds(i, lower, upper);
5310 // If user is using sense then set
5311 if (rowsense_) {
5312 rowsense_[i] = sense;
5313 rhs_[i] = rightHandSide;
5314 rowrange_[i] = range;
5315 }
5316}
5317// Set name of row
5318void
5319//OsiClpSolverInterface::setRowName(int rowIndex, std::string & name)
5320OsiClpSolverInterface::setRowName(int rowIndex, std::string name)
5321{
5322 if (rowIndex>=0&&rowIndex<modelPtr_->numberRows()) {
5323 int nameDiscipline;
5324 getIntParam(OsiNameDiscipline,nameDiscipline) ;
5325 if (nameDiscipline) {
5326 modelPtr_->setRowName(rowIndex,name);
5327 OsiSolverInterface::setRowName(rowIndex,name) ;
5328 }
5329 }
5330}
5331// Return name of row if one exists or Rnnnnnnn
5332// we ignore maxLen
5333std::string
5334OsiClpSolverInterface::getRowName(int rowIndex, unsigned int /*maxLen*/) const
5335{
5336 if (rowIndex == getNumRows())
5337 return getObjName();
5338 return modelPtr_->getRowName(rowIndex);
5339}
5340
5341// Set name of col
5342void
5343//OsiClpSolverInterface::setColName(int colIndex, std::string & name)
5344OsiClpSolverInterface::setColName(int colIndex, std::string name)
5345{
5346 if (colIndex>=0&&colIndex<modelPtr_->numberColumns()) {
5347 int nameDiscipline;
5348 getIntParam(OsiNameDiscipline,nameDiscipline) ;
5349 if (nameDiscipline) {
5350 modelPtr_->setColumnName(colIndex,name);
5351 OsiSolverInterface::setColName(colIndex,name) ;
5352 }
5353 }
5354}
5355// Return name of col if one exists or Rnnnnnnn
5356std::string
5357OsiClpSolverInterface::getColName(int colIndex, unsigned int /*maxLen*/) const
5358{
5359 return modelPtr_->getColumnName(colIndex);
5360}
5361
5362
5363//-----------------------------------------------------------------------------
5364void OsiClpSolverInterface::setRowSetBounds(const int* indexFirst,
5365 const int* indexLast,
5366 const double* boundList)
5367{
5368 modelPtr_->whatsChanged_ &= 0xffff;
5369 // Say can't gurantee optimal basis etc
5370 lastAlgorithm_=999;
5371#ifndef NDEBUG
5372 int n = modelPtr_->numberRows();
5373 const int * indexFirst2=indexFirst;
5374 while (indexFirst2 != indexLast) {
5375 const int iColumn=*indexFirst2++;
5376 if (iColumn<0||iColumn>=n) {
5377 indexError(iColumn,"setColumnSetBounds");
5378 }
5379 }
5380#endif
5381 modelPtr_->setRowSetBounds(indexFirst,indexLast,boundList);
5382 if (rowsense_ != NULL) {
5383 assert ((rhs_ != NULL) && (rowrange_ != NULL));
5384 double * lower = modelPtr_->rowLower();
5385 double * upper = modelPtr_->rowUpper();
5386 while (indexFirst != indexLast) {
5387 const int iRow=*indexFirst++;
5388 convertBoundToSense(lower[iRow], upper[iRow],
5389 rowsense_[iRow], rhs_[iRow], rowrange_[iRow]);
5390 }
5391 }
5392}
5393//-----------------------------------------------------------------------------
5394void
5395OsiClpSolverInterface::setRowSetTypes(const int* indexFirst,
5396 const int* indexLast,
5397 const char* senseList,
5398 const double* rhsList,
5399 const double* rangeList)
5400{
5401 modelPtr_->whatsChanged_ &= 0xffff;
5402 // Say can't gurantee optimal basis etc
5403 lastAlgorithm_=999;
5404#ifndef NDEBUG
5405 int n = modelPtr_->numberRows();
5406#endif
5407 const int len = static_cast<int>(indexLast - indexFirst);
5408 while (indexFirst != indexLast) {
5409 const int iRow= *indexFirst++;
5410#ifndef NDEBUG
5411 if (iRow<0||iRow>=n) {
5412 indexError(iRow,"isContinuous");
5413 }
5414#endif
5415 double lowerValue = 0;
5416 double upperValue = 0;
5417 if (rangeList){
5418 convertSenseToBound(*senseList++, *rhsList++, *rangeList++,
5419 lowerValue, upperValue);
5420 } else {
5421 convertSenseToBound(*senseList++, *rhsList++, 0,
5422 lowerValue, upperValue);
5423 }
5424 modelPtr_->setRowBounds(iRow,lowerValue,upperValue);
5425 }
5426 if (rowsense_ != NULL) {
5427 assert ((rhs_ != NULL) && (rowrange_ != NULL));
5428 indexFirst -= len;
5429 senseList -= len;
5430 rhsList -= len;
5431 if (rangeList)
5432 rangeList -= len;
5433 while (indexFirst != indexLast) {
5434 const int iRow=*indexFirst++;
5435 rowsense_[iRow] = *senseList++;
5436 rhs_[iRow] = *rhsList++;
5437 if (rangeList)
5438 rowrange_[iRow] = *rangeList++;
5439 }
5440 }
5441}
5442
5443/*
5444 Clp's copy-in/copy-out design paradigm is a challenge for the simplex modes.
5445 Normal operation goes like this:
5446 * startup() loads clp's work arrays, performing scaling for numerical
5447 stability and compensating for max.
5448 * clp solves the problem
5449 * finish() unloads the work arrays into answer arrays, undoing scaling
5450 and max compensation.
5451 There are two solutions: undo scaling and max on demand, or make them
5452 into noops. The various getBInv* methods undo scaling on demand (but
5453 see special option 512) and do not need to worry about max. Other get
5454 solution methods are not coded to do this, so the second approach is
5455 used. For simplex modes, turn off scaling (necessary for both primal and
5456 dual solutions) and temporarily convert max to min (necessary for dual
5457 solution). This makes the unscaling in getBInv* superfluous, but don't
5458 remove it. Arguably the better solution here would be to go through and
5459 add unscaling and max compensation to the get solution methods. Look for
5460 fakeMinInSimplex to see the places this propagates to.
5461
5462 TODO: setRowPrice never has worked properly, and I didn't try to fix it in
5463 this go-round.
5464
5465 As of 100907, change applied to [enable|disable]Factorization (mode 1).
5466 Limitation of [enable|disable]SimplexInterface (mode 2) noted in
5467 documentation. -- lh, 100907 --
5468*/
5469/*
5470 Enables normal operation of subsequent functions. This method is supposed
5471 to ensure that all typical things (like reduced costs, etc.) are updated
5472 when individual pivots are executed and can be queried by other methods
5473*/
5474void
5475OsiClpSolverInterface::enableSimplexInterface(bool doingPrimal)
5476{
5477 modelPtr_->whatsChanged_ &= 0xffff;
5478 if (modelPtr_->solveType()==2)
5479 return;
5480 assert (modelPtr_->solveType()==1);
5481 int saveIts = modelPtr_->numberIterations_;
5482 modelPtr_->setSolveType(2);
5483 if (doingPrimal)
5484 modelPtr_->setAlgorithm(1);
5485 else
5486 modelPtr_->setAlgorithm(-1);
5487 // Do initialization
5488 saveData_ = modelPtr_->saveData();
5489 saveData_.scalingFlag_=modelPtr_->scalingFlag();
5490 modelPtr_->scaling(0);
5491 specialOptions_ = 0x80000000;
5492 // set infeasibility cost up
5493 modelPtr_->setInfeasibilityCost(1.0e12);
5494 ClpDualRowDantzig dantzig;
5495 modelPtr_->setDualRowPivotAlgorithm(dantzig);
5496 ClpPrimalColumnDantzig dantzigP;
5497 dantzigP.saveWeights(modelPtr_,0); // set modelPtr
5498 modelPtr_->setPrimalColumnPivotAlgorithm(dantzigP);
5499 int saveOptions = modelPtr_->specialOptions_;
5500 modelPtr_->specialOptions_ &= ~262144;
5501 delete modelPtr_->scaledMatrix_;
5502 modelPtr_->scaledMatrix_=NULL;
5503#ifdef NDEBUG
5504 modelPtr_->startup(0);
5505#else
5506 int returnCode=modelPtr_->startup(0);
5507 assert (!returnCode||returnCode==2);
5508#endif
5509 modelPtr_->specialOptions_=saveOptions;
5510 modelPtr_->numberIterations_=saveIts;
5511}
5512
5513//Undo whatever setting changes the above method had to make
5514void
5515OsiClpSolverInterface::disableSimplexInterface()
5516{
5517 modelPtr_->whatsChanged_ &= 0xffff;
5518 assert (modelPtr_->solveType()==2);
5519 // declare optimality anyway (for message handler)
5520 modelPtr_->setProblemStatus(0);
5521 modelPtr_->setSolveType(1);
5522 // message will not appear anyway
5523 int saveMessageLevel=modelPtr_->messageHandler()->logLevel();
5524 modelPtr_->messageHandler()->setLogLevel(0);
5525 modelPtr_->finish();
5526 modelPtr_->messageHandler()->setLogLevel(saveMessageLevel);
5527 modelPtr_->restoreData(saveData_);
5528 modelPtr_->scaling(saveData_.scalingFlag_);
5529 ClpDualRowSteepest steepest;
5530 modelPtr_->setDualRowPivotAlgorithm(steepest);
5531 ClpPrimalColumnSteepest steepestP;
5532 modelPtr_->setPrimalColumnPivotAlgorithm(steepestP);
5533 basis_ = getBasis(modelPtr_);
5534 modelPtr_->setSolveType(1);
5535}
5536
5537/*
5538 Force scaling off. If the client thinks we're maximising, arrange it so
5539 that clp sees minimisation while the client still sees maximisation. In
5540 keeping with the spirit of the getBInv methods, special option 512 will
5541 leave all work to the client.
5542*/
5543void
5544OsiClpSolverInterface::enableFactorization() const
5545{
5546 saveData_.specialOptions_=specialOptions_;
5547 // Try to preserve work regions, reuse factorization
5548 if ((specialOptions_&(1+8))!=1+8)
5549 setSpecialOptionsMutable((1+8)|specialOptions_);
5550 // Are we allowed to make the output sensible to mere mortals?
5551 if ((specialOptions_&512)==0) {
5552 // Force scaling to off
5553 saveData_.scalingFlag_ = modelPtr_->scalingFlag() ;
5554 modelPtr_->scaling(0) ;
5555 // Temporarily force to min but keep a copy of original objective.
5556 if (getObjSense() < 0.0) {
5557 fakeMinInSimplex_ = true ;
5558 modelPtr_->setOptimizationDirection(1.0) ;
5559 double *c = modelPtr_->objective() ;
5560 int n = getNumCols() ;
5561 linearObjective_ = new double[n] ;
5562 CoinMemcpyN(c,n,linearObjective_) ;
5563 std::transform(c,c+n,c,std::negate<double>()) ;
5564 }
5565 }
5566 int saveStatus = modelPtr_->problemStatus_;
5567#ifdef NDEBUG
5568 modelPtr_->startup(0);
5569#else
5570 int returnCode=modelPtr_->startup(0);
5571 assert (!returnCode||returnCode==2);
5572#endif
5573 modelPtr_->problemStatus_=saveStatus;
5574}
5575
5576/*
5577 Undo enableFactorization. Retrieve the special options and scaling and
5578 remove the temporary objective used to fake minimisation in clp.
5579*/
5580void
5581OsiClpSolverInterface::disableFactorization() const
5582{
5583 specialOptions_=saveData_.specialOptions_;
5584 // declare optimality anyway (for message handler)
5585 modelPtr_->setProblemStatus(0);
5586 // message will not appear anyway
5587 int saveMessageLevel=modelPtr_->messageHandler()->logLevel();
5588 modelPtr_->messageHandler()->setLogLevel(0);
5589 modelPtr_->finish();
5590 modelPtr_->messageHandler()->setLogLevel(saveMessageLevel);
5591 // Client asked for transforms on the way in, so back out.
5592 if ((specialOptions_&512)==0) {
5593 modelPtr_->scaling(saveData_.scalingFlag_) ;
5594 if (fakeMinInSimplex_ == true) {
5595 fakeMinInSimplex_ = false ;
5596 modelPtr_->setOptimizationDirection(-1.0) ;
5597 double *c = modelPtr_->objective() ;
5598 int n = getNumCols() ;
5599 std::transform(c,c+n,c,std::negate<double>()) ;
5600 delete[] linearObjective_ ;
5601 }
5602 }
5603}
5604
5605
5606
5607/* The following two methods may be replaced by the
5608 methods of OsiSolverInterface using OsiWarmStartBasis if:
5609 1. OsiWarmStartBasis resize operation is implemented
5610 more efficiently and
5611 2. It is ensured that effects on the solver are the same
5612
5613 Returns a basis status of the structural/artificial variables
5614*/
5615void
5616OsiClpSolverInterface::getBasisStatus(int* cstat, int* rstat) const
5617{
5618 int iRow,iColumn;
5619 int numberRows = modelPtr_->numberRows();
5620 int numberColumns = modelPtr_->numberColumns();
5621 const double * pi = modelPtr_->dualRowSolution();
5622 const double * dj = modelPtr_->dualColumnSolution();
5623 double multiplier = modelPtr_->optimizationDirection();
5624 // Flip slacks
5625 int lookupA[]={0,1,3,2,0,3};
5626 for (iRow=0;iRow<numberRows;iRow++) {
5627 int iStatus = modelPtr_->getRowStatus(iRow);
5628 if (iStatus==5) {
5629 // Fixed - look at reduced cost
5630 if (pi[iRow]*multiplier>1.0e-7)
5631 iStatus = 3;
5632 }
5633 iStatus = lookupA[iStatus];
5634 rstat[iRow]=iStatus;
5635 }
5636 int lookupS[]={0,1,2,3,0,3};
5637 for (iColumn=0;iColumn<numberColumns;iColumn++) {
5638 int iStatus = modelPtr_->getColumnStatus(iColumn);
5639 if (iStatus==5) {
5640 // Fixed - look at reduced cost
5641 if (dj[iColumn]*multiplier<-1.0e-7)
5642 iStatus = 2;
5643 }
5644 iStatus = lookupS[iStatus];
5645 cstat[iColumn]=iStatus;
5646 }
5647}
5648
5649//Set the status of structural/artificial variables
5650//Returns 0 if OK, 1 if problem is bad e.g. duplicate elements, too large ...
5651int
5652OsiClpSolverInterface::setBasisStatus(const int* cstat, const int* rstat)
5653{
5654 modelPtr_->whatsChanged_ &= 0xffff;
5655 // Say can't gurantee optimal basis etc
5656 lastAlgorithm_=999;
5657 modelPtr_->createStatus();
5658 int i, n;
5659 double * lower, * upper, * solution;
5660 n=modelPtr_->numberRows();
5661 lower = modelPtr_->rowLower();
5662 upper = modelPtr_->rowUpper();
5663 solution = modelPtr_->primalRowSolution();
5664 // For rows lower and upper are flipped
5665 int lookupA[]={0,1,3,2};
5666 for (i=0;i<n;i++) {
5667 int status = lookupA[rstat[i]];
5668 if (status<0||status>3)
5669 status = 3;
5670 if (lower[i]<-1.0e50&&upper[i]>1.0e50&&status!=1)
5671 status = 0; // set free if should be
5672 else if (lower[i]<-1.0e50&&status==3)
5673 status = 2; // can't be at lower bound
5674 else if (upper[i]>1.0e50&&status==2)
5675 status = 3; // can't be at upper bound
5676 switch (status) {
5677 // free or superbasic
5678 case 0:
5679 if (lower[i]<-1.0e50&&upper[i]>1.0e50) {
5680 modelPtr_->setRowStatus(i,ClpSimplex::isFree);
5681 if (fabs(solution[i])>1.0e20)
5682 solution[i]=0.0;
5683 } else {
5684 modelPtr_->setRowStatus(i,ClpSimplex::superBasic);
5685 if (fabs(solution[i])>1.0e20)
5686 solution[i]=0.0;
5687 }
5688 break;
5689 case 1:
5690 // basic
5691 modelPtr_->setRowStatus(i,ClpSimplex::basic);
5692 break;
5693 case 2:
5694 // at upper bound
5695 solution[i]=upper[i];
5696 if (upper[i]>lower[i])
5697 modelPtr_->setRowStatus(i,ClpSimplex::atUpperBound);
5698 else
5699 modelPtr_->setRowStatus(i,ClpSimplex::isFixed);
5700 break;
5701 case 3:
5702 // at lower bound
5703 solution[i]=lower[i];
5704 if (upper[i]>lower[i])
5705 modelPtr_->setRowStatus(i,ClpSimplex::atLowerBound);
5706 else
5707 modelPtr_->setRowStatus(i,ClpSimplex::isFixed);
5708 break;
5709 }
5710 }
5711 n=modelPtr_->numberColumns();
5712 lower = modelPtr_->columnLower();
5713 upper = modelPtr_->columnUpper();
5714 solution = modelPtr_->primalColumnSolution();
5715 for (i=0;i<n;i++) {
5716 int status = cstat[i];
5717 if (status<0||status>3)
5718 status = 3;
5719 if (lower[i]<-1.0e50&&upper[i]>1.0e50&&status!=1)
5720 status = 0; // set free if should be
5721 else if (lower[i]<-1.0e50&&status==3)
5722 status = 2; // can't be at lower bound
5723 else if (upper[i]>1.0e50&&status==2)
5724 status = 3; // can't be at upper bound
5725 switch (status) {
5726 // free or superbasic
5727 case 0:
5728 if (lower[i]<-1.0e50&&upper[i]>1.0e50) {
5729 modelPtr_->setColumnStatus(i,ClpSimplex::isFree);
5730 if (fabs(solution[i])>1.0e20)
5731 solution[i]=0.0;
5732 } else {
5733 modelPtr_->setColumnStatus(i,ClpSimplex::superBasic);
5734 if (fabs(solution[i])>1.0e20)
5735 solution[i]=0.0;
5736 }
5737 break;
5738 case 1:
5739 // basic
5740 modelPtr_->setColumnStatus(i,ClpSimplex::basic);
5741 break;
5742 case 2:
5743 // at upper bound
5744 solution[i]=upper[i];
5745 if (upper[i]>lower[i])
5746 modelPtr_->setColumnStatus(i,ClpSimplex::atUpperBound);
5747 else
5748 modelPtr_->setColumnStatus(i,ClpSimplex::isFixed);
5749 break;
5750 case 3:
5751 // at lower bound
5752 solution[i]=lower[i];
5753 if (upper[i]>lower[i])
5754 modelPtr_->setColumnStatus(i,ClpSimplex::atLowerBound);
5755 else
5756 modelPtr_->setColumnStatus(i,ClpSimplex::isFixed);
5757 break;
5758 }
5759 }
5760 // say first time
5761 modelPtr_->statusOfProblem(true);
5762 // May be bad model
5763 if (modelPtr_->status()==4)
5764 return 1;
5765 // Save
5766 basis_ = getBasis(modelPtr_);
5767 return 0;
5768}
5769
5770/* Perform a pivot by substituting a colIn for colOut in the basis.
5771 The status of the leaving variable is given in statOut. Where
5772 1 is to upper bound, -1 to lower bound
5773 Return code is 0 for okay,
5774 1 if inaccuracy forced re-factorization (should be okay) and
5775 -1 for singular factorization
5776*/
5777int
5778OsiClpSolverInterface::pivot(int colIn, int colOut, int outStatus)
5779{
5780 assert (modelPtr_->solveType()==2);
5781 // convert to Clp style (what about flips?)
5782 if (colIn<0)
5783 colIn = modelPtr_->numberColumns()+(-1-colIn);
5784 if (colOut<0)
5785 colOut = modelPtr_->numberColumns()+(-1-colOut);
5786 // in clp direction of out is reversed
5787 outStatus = - outStatus;
5788 // set in clp
5789 modelPtr_->setDirectionOut(outStatus);
5790 modelPtr_->setSequenceIn(colIn);
5791 modelPtr_->setSequenceOut(colOut);
5792 // do pivot
5793 return modelPtr_->pivot();
5794}
5795
5796/* Obtain a result of the primal pivot
5797 Outputs: colOut -- leaving column, outStatus -- its status,
5798 t -- step size, and, if dx!=NULL, *dx -- primal ray direction.
5799 Inputs: colIn -- entering column, sign -- direction of its change (+/-1).
5800 Both for colIn and colOut, artificial variables are index by
5801 the negative of the row index minus 1.
5802 Return code (for now): 0 -- leaving variable found,
5803 -1 -- everything else?
5804 Clearly, more informative set of return values is required
5805 Primal and dual solutions are updated
5806*/
5807int
5808OsiClpSolverInterface::primalPivotResult(int colIn, int sign,
5809 int& colOut, int& outStatus,
5810 double& t, CoinPackedVector* dx)
5811{
5812 assert (modelPtr_->solveType()==2);
5813 // convert to Clp style
5814 if (colIn<0)
5815 colIn = modelPtr_->numberColumns()+(-1-colIn);
5816 // set in clp
5817 modelPtr_->setDirectionIn(sign);
5818 modelPtr_->setSequenceIn(colIn);
5819 modelPtr_->setSequenceOut(-1);
5820 int returnCode = modelPtr_->primalPivotResult();
5821 t = modelPtr_->theta();
5822 int numberColumns = modelPtr_->numberColumns();
5823 if (dx) {
5824 double * ray = modelPtr_->unboundedRay();
5825 if (ray)
5826 dx->setFullNonZero(numberColumns,ray);
5827 else
5828 printf("No ray?\n");
5829 delete [] ray;
5830 }
5831 outStatus = - modelPtr_->directionOut();
5832 colOut = modelPtr_->sequenceOut();
5833 if (colOut>= numberColumns)
5834 colOut = -1-(colOut - numberColumns);
5835 return returnCode;
5836}
5837
5838/* Obtain a result of the dual pivot (similar to the previous method)
5839 Differences: entering variable and a sign of its change are now
5840 the outputs, the leaving variable and its statuts -- the inputs
5841 If dx!=NULL, then *dx contains dual ray
5842 Return code: same
5843*/
5844int
5845OsiClpSolverInterface::dualPivotResult(int& /*colIn*/, int& /*sign*/,
5846 int /*colOut*/, int /*outStatus*/,
5847 double& /*t*/, CoinPackedVector* /*dx*/)
5848{
5849 assert (modelPtr_->solveType()==2);
5850 abort();
5851 return 0;
5852}
5853
5854/*
5855 This method should not leave a permanent change in the solver. For
5856 this reason, save a copy of the cost region and replace it after we've
5857 calculated the duals and reduced costs.
5858
5859 On the good side, if we're maximising, we should negate the objective on
5860 the way in and negate the duals on the way out. Since clp won't be doing
5861 anything more with c, we can exploit (-1)(-1) = 1 and do nothing.
5862*/
5863void
5864OsiClpSolverInterface::getReducedGradient(
5865 double* columnReducedCosts,
5866 double * duals,
5867 const double * c) const
5868{
5869 //assert (modelPtr_->solveType()==2);
5870 // could do this faster with coding inside Clp
5871 // save current costs
5872 int numberColumns = modelPtr_->numberColumns();
5873 double * save = new double [numberColumns];
5874 double * obj = modelPtr_->costRegion();
5875 CoinMemcpyN(obj,numberColumns,save);
5876 // Compute new duals and reduced costs.
5877 const double * columnScale = modelPtr_->columnScale();
5878 if (!columnScale) {
5879 CoinMemcpyN(c,numberColumns,obj) ;
5880 } else {
5881 // need to scale
5882 for (int i=0;i<numberColumns;i++)
5883 obj[i] = c[i]*columnScale[i];
5884 }
5885 modelPtr_->computeDuals(NULL);
5886
5887 // Restore previous cost vector
5888 CoinMemcpyN(save,numberColumns,obj);
5889 delete [] save;
5890
5891 // Transfer results to parameters
5892 int numberRows = modelPtr_->numberRows();
5893 const double * dualScaled = modelPtr_->dualRowSolution();
5894 const double * djScaled = modelPtr_->djRegion(1);
5895 if (!columnScale) {
5896 CoinMemcpyN(dualScaled,numberRows,duals) ;
5897 CoinMemcpyN(djScaled,numberColumns,columnReducedCosts) ;
5898 } else {
5899 // need to scale
5900 const double * rowScale = modelPtr_->rowScale();
5901 for (int i=0;i<numberRows;i++)
5902 duals[i] = dualScaled[i]*rowScale[i];
5903 for (int i=0;i<numberColumns;i++)
5904 columnReducedCosts[i] = djScaled[i]/columnScale[i];
5905 }
5906}
5907
5908#if 0
5909
5910 Deleted from OsiSimplex API 100828. Leave the code here for a bit just in
5911 case someone yells. -- lh, 100828 --
5912
5913/* Set a new objective and apply the old basis so that the
5914 reduced costs are properly updated
5915*/
5916void OsiClpSolverInterface::setObjectiveAndRefresh(const double* c)
5917{
5918 modelPtr_->whatsChanged_ &= (0xffff&~(64));
5919 assert (modelPtr_->solveType()==2);
5920 int numberColumns = modelPtr_->numberColumns();
5921 CoinMemcpyN(c,numberColumns,modelPtr_->objective());
5922 if (modelPtr_->nonLinearCost()) {
5923 modelPtr_->nonLinearCost()->refreshCosts(c);
5924 }
5925 CoinMemcpyN(c,numberColumns,modelPtr_->costRegion());
5926 modelPtr_->computeDuals(NULL);
5927}
5928#endif
5929
5930//Get a row of the tableau (slack part in slack if not NULL)
5931void
5932OsiClpSolverInterface::getBInvARow(int row, double* z, double * slack) const
5933{
5934#ifndef NDEBUG
5935 int n = modelPtr_->numberRows();
5936 if (row<0||row>=n) {
5937 indexError(row,"getBInvARow");
5938 }
5939#endif
5940 //assert (modelPtr_->solveType()==2||(specialOptions_&1));
5941 CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0);
5942 CoinIndexedVector * rowArray1 = modelPtr_->rowArray(1);
5943 CoinIndexedVector * columnArray0 = modelPtr_->columnArray(0);
5944 CoinIndexedVector * columnArray1 = modelPtr_->columnArray(1);
5945 rowArray0->clear();
5946 rowArray1->clear();
5947 columnArray0->clear();
5948 columnArray1->clear();
5949 int numberRows = modelPtr_->numberRows();
5950 int numberColumns = modelPtr_->numberColumns();
5951 // put +1 in row
5952 // But swap if pivot variable was slack as clp stores slack as -1.0
5953 const int * pivotVariable = modelPtr_->pivotVariable();
5954 const double * rowScale = modelPtr_->rowScale();
5955 const double * columnScale = modelPtr_->columnScale();
5956 int pivot = pivotVariable[row];
5957 double value;
5958 // And if scaled then adjust
5959 if (!rowScale) {
5960 if (pivot<numberColumns)
5961 value = 1.0;
5962 else
5963 value = -1.0;
5964 } else {
5965 if (pivot<numberColumns)
5966 value = columnScale[pivot];
5967 else
5968 value = -1.0/rowScale[pivot-numberColumns];
5969 }
5970 rowArray1->insert(row,value);
5971 modelPtr_->factorization()->updateColumnTranspose(rowArray0,rowArray1);
5972 // put row of tableau in rowArray1 and columnArray0
5973 modelPtr_->clpMatrix()->transposeTimes(modelPtr_,1.0,
5974 rowArray1,columnArray1,columnArray0);
5975 // If user is sophisticated then let her/him do work
5976 if ((specialOptions_&512)==0) {
5977 // otherwise copy and clear
5978 if (!rowScale) {
5979 CoinMemcpyN(columnArray0->denseVector(),numberColumns,z);
5980 } else {
5981 double * array = columnArray0->denseVector();
5982 for (int i=0;i<numberColumns;i++)
5983 z[i] = array[i]/columnScale[i];
5984 }
5985 if (slack) {
5986 if (!rowScale) {
5987 CoinMemcpyN(rowArray1->denseVector(),numberRows,slack);
5988 } else {
5989 double * array = rowArray1->denseVector();
5990 for (int i=0;i<numberRows;i++)
5991 slack[i] = array[i]*rowScale[i];
5992 }
5993 }
5994 columnArray0->clear();
5995 rowArray1->clear();
5996 }
5997 // don't need to clear everything always, but doesn't cost
5998 rowArray0->clear();
5999 columnArray1->clear();
6000}
6001//Get a row of the tableau (slack part in slack if not NULL)
6002void
6003OsiClpSolverInterface::getBInvARow(int row, CoinIndexedVector * columnArray0, CoinIndexedVector * slack,
6004 bool keepScaled) const
6005{
6006#ifndef NDEBUG
6007 int nx = modelPtr_->numberRows();
6008 if (row<0||row>=nx) {
6009 indexError(row,"getBInvARow");
6010 }
6011#endif
6012 //assert (modelPtr_->solveType()==2||(specialOptions_&1));
6013 CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0);
6014 CoinIndexedVector * rowArray1 = slack ? slack : modelPtr_->rowArray(1);
6015 CoinIndexedVector * columnArray1 = modelPtr_->columnArray(1);
6016 rowArray0->clear();
6017 rowArray1->clear();
6018 columnArray0->clear();
6019 columnArray1->clear();
6020 //int numberRows = modelPtr_->numberRows();
6021 int numberColumns = modelPtr_->numberColumns();
6022 // put +1 in row
6023 // But swap if pivot variable was slack as clp stores slack as -1.0
6024 const int * pivotVariable = modelPtr_->pivotVariable();
6025 const double * rowScale = modelPtr_->rowScale();
6026 const double * columnScale = modelPtr_->columnScale();
6027 int pivot = pivotVariable[row];
6028 double value;
6029 // And if scaled then adjust
6030 if (!rowScale) {
6031 if (pivot<numberColumns)
6032 value = 1.0;
6033 else
6034 value = -1.0;
6035 } else {
6036 if (pivot<numberColumns)
6037 value = columnScale[pivot];
6038 else
6039 value = -1.0/rowScale[pivot-numberColumns];
6040 }
6041 rowArray1->insert(row,value);
6042 modelPtr_->factorization()->updateColumnTranspose(rowArray0,rowArray1);
6043 // put row of tableau in rowArray1 and columnArray0
6044 modelPtr_->clpMatrix()->transposeTimes(modelPtr_,1.0,
6045 rowArray1,columnArray1,columnArray0);
6046 int n;
6047 const int * which;
6048 double * array;
6049 // deal with scaling etc
6050 if (rowScale&&!keepScaled) {
6051 int j;
6052 // First columns
6053 n = columnArray0->getNumElements();
6054 which = columnArray0->getIndices();
6055 array = columnArray0->denseVector();
6056 for (j=0; j < n; j++) {
6057 int k=which[j];
6058 array[k] /= columnScale[k];
6059 }
6060 if (slack) {
6061 n = slack->getNumElements();
6062 which = slack->getIndices();
6063 array = slack->denseVector();
6064 for(j=0; j < n; j++) {
6065 int k=which[j];
6066 array[k] *= rowScale[k];
6067 }
6068 }
6069 }
6070 if (!slack)
6071 rowArray1->clear();
6072}
6073
6074//Get a row of the basis inverse
6075void
6076OsiClpSolverInterface::getBInvRow(int row, double* z) const
6077
6078{
6079#ifndef NDEBUG
6080 int n = modelPtr_->numberRows();
6081 if (row<0||row>=n) {
6082 indexError(row,"getBInvRow");
6083 }
6084#endif
6085 //assert (modelPtr_->solveType()==2||(specialOptions_&1)!=0);
6086 ClpFactorization * factorization = modelPtr_->factorization();
6087 CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0);
6088 CoinIndexedVector * rowArray1 = modelPtr_->rowArray(1);
6089 rowArray0->clear();
6090 rowArray1->clear();
6091 // put +1 in row
6092 // But swap if pivot variable was slack as clp stores slack as -1.0
6093 double value = (modelPtr_->pivotVariable()[row]<modelPtr_->numberColumns()) ? 1.0 : -1.0;
6094 int numberRows = modelPtr_->numberRows();
6095 int numberColumns = modelPtr_->numberColumns();
6096 const double * rowScale = modelPtr_->rowScale();
6097 const double * columnScale = modelPtr_->columnScale();
6098 const int * pivotVariable = modelPtr_->pivotVariable();
6099 // but scale
6100 if (rowScale) {
6101 int pivot = pivotVariable[row];
6102 if (pivot<numberColumns)
6103 value *= columnScale[pivot];
6104 else
6105 value /= rowScale[pivot-numberColumns];
6106 }
6107 rowArray1->insert(row,value);
6108 factorization->updateColumnTranspose(rowArray0,rowArray1);
6109 // If user is sophisticated then let her/him do work
6110 if ((specialOptions_&512)==0) {
6111 // otherwise copy and clear
6112 if (!rowScale) {
6113 CoinMemcpyN(rowArray1->denseVector(),modelPtr_->numberRows(),z);
6114 } else {
6115 double * array = rowArray1->denseVector();
6116 for (int i=0;i<numberRows;i++) {
6117 z[i] = array[i] * rowScale[i];
6118 }
6119 }
6120 rowArray1->clear();
6121 }
6122}
6123
6124//Get a column of the tableau
6125void
6126OsiClpSolverInterface::getBInvACol(int col, double* vec) const
6127{
6128 //assert (modelPtr_->solveType()==2||(specialOptions_&1)!=0);
6129 CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0);
6130 CoinIndexedVector * rowArray1 = modelPtr_->rowArray(1);
6131 rowArray0->clear();
6132 rowArray1->clear();
6133 // get column of matrix
6134#ifndef NDEBUG
6135 int n = modelPtr_->numberColumns()+modelPtr_->numberRows();
6136 if (col<0||col>=n) {
6137 indexError(col,"getBInvACol");
6138 }
6139#endif
6140 int numberRows = modelPtr_->numberRows();
6141 int numberColumns = modelPtr_->numberColumns();
6142 const int * pivotVariable = modelPtr_->pivotVariable();
6143 const double * rowScale = modelPtr_->rowScale();
6144 const double * columnScale = modelPtr_->columnScale();
6145 if (!rowScale) {
6146 if (col<numberColumns) {
6147 modelPtr_->unpack(rowArray1,col);
6148 } else {
6149 rowArray1->insert(col-numberColumns,1.0);
6150 }
6151 } else {
6152 if (col<numberColumns) {
6153 modelPtr_->unpack(rowArray1,col);
6154 double multiplier = 1.0/columnScale[col];
6155 int number = rowArray1->getNumElements();
6156 int * index = rowArray1->getIndices();
6157 double * array = rowArray1->denseVector();
6158 for (int i=0;i<number;i++) {
6159 int iRow = index[i];
6160 // make sure not packed
6161 assert (array[iRow]);
6162 array[iRow] *= multiplier;
6163 }
6164 } else {
6165 rowArray1->insert(col-numberColumns,rowScale[col-numberColumns]);
6166 }
6167 }
6168 modelPtr_->factorization()->updateColumn(rowArray0,rowArray1,false);
6169 // If user is sophisticated then let her/him do work
6170 if ((specialOptions_&512)==0) {
6171 // otherwise copy and clear
6172 // But swap if pivot variable was slack as clp stores slack as -1.0
6173 double * array = rowArray1->denseVector();
6174 if (!rowScale) {
6175 for (int i=0;i<numberRows;i++) {
6176 double multiplier = (pivotVariable[i]<numberColumns) ? 1.0 : -1.0;
6177 vec[i] = multiplier * array[i];
6178 }
6179 } else {
6180 for (int i=0;i<numberRows;i++) {
6181 int pivot = pivotVariable[i];
6182 if (pivot<numberColumns)
6183 vec[i] = array[i] * columnScale[pivot];
6184 else
6185 vec[i] = - array[i] / rowScale[pivot-numberColumns];
6186 }
6187 }
6188 rowArray1->clear();
6189 }
6190}
6191//Get a column of the tableau
6192void
6193OsiClpSolverInterface::getBInvACol(int col, CoinIndexedVector * rowArray1) const
6194{
6195 CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0);
6196 rowArray0->clear();
6197 rowArray1->clear();
6198 // get column of matrix
6199#ifndef NDEBUG
6200 int nx = modelPtr_->numberColumns()+modelPtr_->numberRows();
6201 if (col<0||col>=nx) {
6202 indexError(col,"getBInvACol");
6203 }
6204#endif
6205 //int numberRows = modelPtr_->numberRows();
6206 int numberColumns = modelPtr_->numberColumns();
6207 const int * pivotVariable = modelPtr_->pivotVariable();
6208 const double * rowScale = modelPtr_->rowScale();
6209 const double * columnScale = modelPtr_->columnScale();
6210 if (!rowScale) {
6211 if (col<numberColumns) {
6212 modelPtr_->unpack(rowArray1,col);
6213 } else {
6214 rowArray1->insert(col-numberColumns,1.0);
6215 }
6216 } else {
6217 if (col<numberColumns) {
6218 modelPtr_->unpack(rowArray1,col);
6219 double multiplier = 1.0/columnScale[col];
6220 int number = rowArray1->getNumElements();
6221 int * index = rowArray1->getIndices();
6222 double * array = rowArray1->denseVector();
6223 for (int i=0;i<number;i++) {
6224 int iRow = index[i];
6225 // make sure not packed
6226 assert (array[iRow]);
6227 array[iRow] *= multiplier;
6228 }
6229 } else {
6230 rowArray1->insert(col-numberColumns,rowScale[col-numberColumns]);
6231 }
6232 }
6233 modelPtr_->factorization()->updateColumn(rowArray0,rowArray1,false);
6234 // Deal with stuff
6235 int n = rowArray1->getNumElements();
6236 const int * which = rowArray1->getIndices();
6237 double * array = rowArray1->denseVector();
6238 for(int j=0; j < n; j++){
6239 int k=which[j];
6240 // need to know pivot variable for +1/-1 (slack) and row/column scaling
6241 int pivot = pivotVariable[k];
6242 if (pivot<numberColumns) {
6243 if (columnScale)
6244 array[k] *= columnScale[pivot];
6245 } else {
6246 if (!rowScale) {
6247 array[k] = -array[k];
6248 } else {
6249 array[k] = -array[k]/rowScale[pivot-numberColumns];
6250 }
6251 }
6252 }
6253}
6254
6255//Get an updated column
6256void
6257OsiClpSolverInterface::getBInvACol(CoinIndexedVector * rowArray1) const
6258{
6259 CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0);
6260 rowArray0->clear();
6261 // get column of matrix
6262 //int numberRows = modelPtr_->numberRows();
6263 int numberColumns = modelPtr_->numberColumns();
6264 const int * pivotVariable = modelPtr_->pivotVariable();
6265 const double * rowScale = modelPtr_->rowScale();
6266 const double * columnScale = modelPtr_->columnScale();
6267 // rowArray1 is not a column - so column scale can't be applied before
6268 modelPtr_->factorization()->updateColumn(rowArray0,rowArray1,false);
6269 // Deal with stuff
6270 int n = rowArray1->getNumElements();
6271 const int * which = rowArray1->getIndices();
6272 double * array = rowArray1->denseVector();
6273 for(int j=0; j < n; j++){
6274 int k=which[j];
6275 // need to know pivot variable for +1/-1 (slack) and row/column scaling
6276 int pivot = pivotVariable[k];
6277 if (pivot<numberColumns) {
6278 if (columnScale)
6279 array[k] *= columnScale[pivot];
6280 } else {
6281 if (!rowScale) {
6282 array[k] = -array[k];
6283 } else {
6284 array[k] = -array[k]/rowScale[pivot-numberColumns];
6285 }
6286 }
6287 }
6288}
6289
6290//Get a column of the basis inverse
6291void
6292OsiClpSolverInterface::getBInvCol(int col, double* vec) const
6293{
6294 //assert (modelPtr_->solveType()==2||(specialOptions_&1)!=0);
6295 ClpFactorization * factorization = modelPtr_->factorization();
6296 CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0);
6297 CoinIndexedVector * rowArray1 = modelPtr_->rowArray(1);
6298 rowArray0->clear();
6299 rowArray1->clear();
6300#ifndef NDEBUG
6301 int n = modelPtr_->numberRows();
6302 if (col<0||col>=n) {
6303 indexError(col,"getBInvCol");
6304 }
6305#endif
6306 // put +1 in row
6307 int numberRows = modelPtr_->numberRows();
6308 int numberColumns = modelPtr_->numberColumns();
6309 const double * rowScale = modelPtr_->rowScale();
6310 const double * columnScale = modelPtr_->columnScale();
6311 const int * pivotVariable = modelPtr_->pivotVariable();
6312 // but scale
6313 double value;
6314 if (!rowScale) {
6315 value=1.0;
6316 } else {
6317 value = rowScale[col];
6318 }
6319 rowArray1->insert(col,value);
6320 factorization->updateColumn(rowArray0,rowArray1,false);
6321 // If user is sophisticated then let her/him do work
6322 if ((specialOptions_&512)==0) {
6323 // otherwise copy and clear
6324 // But swap if pivot variable was slack as clp stores slack as -1.0
6325 double * array = rowArray1->denseVector();
6326 if (!rowScale) {
6327 for (int i=0;i<numberRows;i++) {
6328 double multiplier = (pivotVariable[i]<numberColumns) ? 1.0 : -1.0;
6329 vec[i] = multiplier * array[i];
6330 }
6331 } else {
6332 for (int i=0;i<numberRows;i++) {
6333 int pivot = pivotVariable[i];
6334 double value = array[i];
6335 if (pivot<numberColumns)
6336 vec[i] = value * columnScale[pivot];
6337 else
6338 vec[i] = - value / rowScale[pivot-numberColumns];
6339 }
6340 }
6341 rowArray1->clear();
6342 }
6343}
6344
6345/* Get basic indices (order of indices corresponds to the
6346 order of elements in a vector returned by getBInvACol() and
6347 getBInvCol()).
6348*/
6349void
6350OsiClpSolverInterface::getBasics(int* index) const
6351{
6352 //assert (modelPtr_->solveType()==2||(specialOptions_&1)!=0);
6353 assert (index);
6354 if (modelPtr_->pivotVariable()) {
6355 CoinMemcpyN(modelPtr_->pivotVariable(),modelPtr_->numberRows(),index);
6356 } else {
6357 std::cerr<<"getBasics is only available with enableSimplexInterface."
6358 <<std::endl;
6359 std::cerr<<"much of the same information can be had from getWarmStart."
6360 <<std::endl;
6361 throw CoinError("No pivot variable array","getBasics",
6362 "OsiClpSolverInterface");
6363 }
6364}
6365//Returns true if a basis is available and optimal
6366bool
6367OsiClpSolverInterface::basisIsAvailable() const
6368{
6369 return (lastAlgorithm_==1||lastAlgorithm_==2)&&(!modelPtr_->problemStatus_);
6370}
6371// Resets as if default constructor
6372void
6373OsiClpSolverInterface::reset()
6374{
6375 setInitialData(); // clear base class
6376 freeCachedResults();
6377 if (!notOwned_)
6378 delete modelPtr_;
6379 delete ws_;
6380 ws_ = NULL;
6381 delete [] rowActivity_;
6382 delete [] columnActivity_;
6383 assert(smallModel_==NULL);
6384 assert(factorization_==NULL);
6385 smallestElementInCut_ = 1.0e-15;
6386 smallestChangeInCut_ = 1.0e-10;
6387 largestAway_ = -1.0;
6388 assert(spareArrays_==NULL);
6389 delete [] integerInformation_;
6390 rowActivity_ = NULL;
6391 columnActivity_ = NULL;
6392 integerInformation_ = NULL;
6393 basis_ = CoinWarmStartBasis();
6394 itlimOrig_=9999999;
6395 lastAlgorithm_=0;
6396 notOwned_=false;
6397 modelPtr_ = new ClpSimplex();
6398 linearObjective_ = NULL;
6399 fillParamMaps();
6400}
6401// Set a hint parameter
6402bool
6403OsiClpSolverInterface::setHintParam(OsiHintParam key, bool yesNo,
6404 OsiHintStrength strength,
6405 void * otherInformation)
6406{
6407 if ( OsiSolverInterface::setHintParam(key,yesNo,strength,otherInformation)) {
6408 // special coding for branch and cut
6409 if (yesNo&&strength == OsiHintDo&&key==OsiDoInBranchAndCut) {
6410 if ( specialOptions_==0x80000000) {
6411 setupForRepeatedUse(0,0);
6412 specialOptions_=0;
6413 }
6414 // set normal
6415 specialOptions_ &= (2047|3*8192|15*65536|2097152|4194304);
6416 if (otherInformation!=NULL) {
6417 int * array = static_cast<int *> (otherInformation);
6418 if (array[0]>=0||array[0]<=2)
6419 specialOptions_ |= array[0]<<10;
6420 }
6421 }
6422 // Printing
6423 if (key==OsiDoReducePrint) {
6424 handler_->setLogLevel(yesNo ? 0 : 1);
6425 }
6426 return true;
6427 } else {
6428 return false;
6429 }
6430}
6431
6432// Crunch down model
6433void
6434OsiClpSolverInterface::crunch()
6435{
6436 //if (modelPtr_->scalingFlag_>0&&!modelPtr_->rowScale_&&
6437 // modelPtr_->rowCopy_) {
6438 //printf("BBBB could crunch2\n");
6439 //}
6440 int numberColumns = modelPtr_->numberColumns();
6441 int numberRows = modelPtr_->numberRows();
6442 int totalIterations=0;
6443 bool abortSearch=false;
6444 // Use dual region
6445 double * rhs = modelPtr_->dualRowSolution();
6446 // Get space for strong branching
6447 int size = static_cast<int>((1+4*(numberRows+numberColumns))*sizeof(double));
6448 // and for save of original column bounds
6449 size += static_cast<int>(2*numberColumns*sizeof(double));
6450 size += static_cast<int>((1+4*numberRows+2*numberColumns)*sizeof(int));
6451 size += numberRows+numberColumns;
6452#ifdef KEEP_SMALL
6453 char * spareArrays = NULL;
6454 if(!(modelPtr_->whatsChanged_&0x30000)) {
6455 delete smallModel_;
6456 smallModel_ = NULL;
6457 delete [] spareArrays_;
6458 spareArrays_ = NULL;
6459 }
6460 if (!spareArrays_) {
6461 spareArrays = new char[size];
6462 //memset(spareArrays,0x20,size);
6463 } else {
6464 spareArrays = spareArrays_;
6465 }
6466 double * arrayD = reinterpret_cast<double *> (spareArrays);
6467 double * saveSolution = arrayD+1;
6468 double * saveLower = saveSolution + (numberRows+numberColumns);
6469 double * saveUpper = saveLower + (numberRows+numberColumns);
6470 double * saveObjective = saveUpper + (numberRows+numberColumns);
6471 double * saveLowerOriginal = saveObjective + (numberRows+numberColumns);
6472 double * saveUpperOriginal = saveLowerOriginal + numberColumns;
6473 double * lowerOriginal = modelPtr_->columnLower();
6474 double * upperOriginal = modelPtr_->columnUpper();
6475 int * savePivot = reinterpret_cast<int *> (saveUpperOriginal + numberColumns);
6476 int * whichRow = savePivot+numberRows;
6477 int * whichColumn = whichRow + 3*numberRows;
6478 int * arrayI = whichColumn + 2*numberColumns;
6479 if (spareArrays_) {
6480 assert (smallModel_);
6481 int nSame=0;
6482 int nSub=0;
6483 for (int i=0;i<numberColumns;i++) {
6484 double lo = lowerOriginal[i];
6485 //char * xx = (char *) (saveLowerOriginal+i);
6486 //assert (xx[0]!=0x20||xx[1]!=0x20);
6487 double loOld = saveLowerOriginal[i];
6488 //assert (!loOld||fabs(loOld)>1.0e-30);
6489 double up = upperOriginal[i];
6490 double upOld = saveUpperOriginal[i];
6491 if (lo>=loOld&&up<=upOld) {
6492 if (lo==loOld&&up==upOld) {
6493 nSame++;
6494 } else {
6495 nSub++;
6496 //if (!isInteger(i))
6497 //nSub+=10;
6498 }
6499 }
6500 }
6501 //printf("%d bounds same, %d interior, %d bad\n",
6502 // nSame,nSub,numberColumns-nSame-nSub);
6503 if (nSame<numberColumns) {
6504 if (nSame+nSub<numberColumns||nSub>0) {
6505 delete smallModel_;
6506 smallModel_=NULL;
6507 } else {
6508 // we can fix up (but should we if large number fixed?)
6509 assert (smallModel_);
6510 double * lowerSmall = smallModel_->columnLower();
6511 double * upperSmall = smallModel_->columnUpper();
6512 int numberColumns2 = smallModel_->numberColumns();
6513 for (int i=0;i<numberColumns2;i++) {
6514 int iColumn = whichColumn[i];
6515 lowerSmall[i]=lowerOriginal[iColumn];
6516 upperSmall[i]=upperOriginal[iColumn];
6517 }
6518 }
6519 }
6520 }
6521 CoinMemcpyN( lowerOriginal,numberColumns, saveLowerOriginal);
6522 CoinMemcpyN( upperOriginal,numberColumns, saveUpperOriginal);
6523 if (smallModel_) {
6524 if (!spareArrays_) {
6525 assert((specialOptions_&131072)==0);
6526#if 1
6527 delete smallModel_;
6528 smallModel_=NULL;
6529#endif
6530 }
6531 }
6532 //spareArrays=spareArrays_;
6533 //spareArrays_ = NULL;
6534#else
6535 assert (spareArrays_==NULL);
6536 int * whichRow = new int[3*numberRows+2*numberColumns];
6537 int * whichColumn = whichRow+3*numberRows;
6538#endif
6539 int nBound;
6540#ifdef KEEP_SMALL
6541 bool tightenBounds = ((specialOptions_&64)==0) ? false : true;
6542 bool moreBounds=false;
6543 ClpSimplex * small=NULL;
6544 if (!smallModel_) {
6545#ifndef NDEBUG
6546 CoinFillN(whichRow,3*numberRows+2*numberColumns,-1);
6547#endif
6548 small = static_cast<ClpSimplexOther *>
6549 (modelPtr_)->crunch(rhs,whichRow,whichColumn,
6550 nBound,moreBounds,tightenBounds);
6551#ifndef NDEBUG
6552 int nCopy = 3*numberRows+2*numberColumns;
6553 for (int i=0;i<nCopy;i++)
6554 assert (whichRow[i]>=-CoinMax(numberRows,numberColumns)&&whichRow[i]<CoinMax(numberRows,numberColumns));
6555#endif
6556 smallModel_=small;
6557 spareArrays_ = spareArrays;
6558 } else {
6559 assert((modelPtr_->whatsChanged_&0x30000));
6560 //delete [] spareArrays_;
6561 //spareArrays_ = NULL;
6562 assert (spareArrays_);
6563 int nCopy = 3*numberRows+2*numberColumns;
6564 nBound = whichRow[nCopy];
6565#ifndef NDEBUG
6566 for (int i=0;i<nCopy;i++)
6567 assert (whichRow[i]>=-CoinMax(numberRows,numberColumns)&&whichRow[i]<CoinMax(numberRows,numberColumns));
6568#endif
6569 small = smallModel_;
6570 }
6571#if 0 //def CLP_INVESTIGATE
6572#ifndef NDEBUG
6573 if (smallModel_) {
6574 int * whichColumn = whichRow+3*numberRows;
6575 unsigned char * stat1=modelPtr_->status_;
6576 int nr1=modelPtr_->numberRows_;
6577 int nc1=modelPtr_->numberColumns_;
6578 unsigned char * stat2=smallModel_->status_;
6579 int nr2=smallModel_->numberRows_;
6580 int nc2=smallModel_->numberColumns_;
6581 int n=0;
6582 for (int i=0;i<nr2+nc2;i++) {
6583 if ((stat2[i]&7)==1)
6584 n++;
6585 }
6586 assert (n==nr2);
6587 n=0;
6588 for (int i=0;i<nr1+nc1;i++) {
6589 if ((stat1[i]&7)==1)
6590 n++;
6591 }
6592 assert (n==nr1);
6593 //const double * lo1=modelPtr_->columnLower_;
6594 //const double * up1=modelPtr_->columnUpper_;
6595 //const double * lo2=smallModel_->columnLower_;
6596 //const double * up2=smallModel_->columnUpper_;
6597 int nBad=0;
6598 for (int i=0;i<nc2;i++) {
6599 int j=whichColumn[i];
6600 if ((stat2[i]&7)!=(stat1[j]&7)) {
6601 if ((stat2[i]&7)==5) {
6602 if ((stat1[j]&7)==1)
6603 nBad++;
6604 } else {
6605 assert ((stat2[i]&7)==(stat1[j]&7));
6606 }
6607 }
6608 }
6609 for (int i=0;i<nr2;i++) {
6610 int j=whichRow[i];
6611 if ((stat2[i+nc2]&7)!=(stat1[j+nc1]&7)) {
6612 if ((stat2[i+nc2]&7)==5) {
6613 assert ((stat1[j+nc1]&7)!=1);
6614 } else {
6615 assert ((stat2[i+nc2]&7)==(stat1[j+nc1]&7));
6616 }
6617 }
6618 }
6619 if (nBad) {
6620 printf("%d basic moved to fixed\n",nBad);
6621 }
6622 }
6623#endif
6624#endif
6625#else
6626 bool tightenBounds = false;
6627 bool moreBounds=true;
6628#ifndef NDEBUG
6629 CoinFillN(whichRow,3*numberRows+2*numberColumns,-1);
6630#endif
6631 ClpSimplex * small = static_cast<ClpSimplexOther *>
6632 (modelPtr_)->crunch(rhs,whichRow,whichColumn,
6633 nBound,moreBounds,tightenBounds);
6634#endif
6635 bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0;
6636 if (small) {
6637 small->specialOptions_ |= 262144;
6638 if ((specialOptions_&131072)!=0) {
6639 assert (lastNumberRows_>=0);
6640 int numberRows2 = small->numberRows();
6641 int numberColumns2 = small->numberColumns();
6642 double * rowScale2 = new double [2*numberRows2];
6643 assert (rowScale_.getSize()>=2*numberRows);
6644 const double * rowScale = rowScale_.array();
6645 double * inverseScale2 = rowScale2+numberRows2;
6646 const double * inverseScale = rowScale+modelPtr_->numberRows_;
6647 int i;
6648 for (i=0;i<numberRows2;i++) {
6649 int iRow = whichRow[i];
6650 assert (iRow>=0&&iRow<numberRows);
6651 rowScale2[i]=rowScale[iRow];
6652 inverseScale2[i]=inverseScale[iRow];
6653 }
6654 small->setRowScale(rowScale2);
6655 double * columnScale2 = new double [2*numberColumns2];
6656 assert (columnScale_.getSize()>=2*numberColumns);
6657 const double * columnScale = columnScale_.array();
6658 inverseScale2 = columnScale2+numberColumns2;
6659 inverseScale = columnScale+modelPtr_->numberColumns_;
6660 for (i=0;i<numberColumns2;i++) {
6661 int iColumn = whichColumn[i];
6662 //assert (iColumn<numberColumns);
6663 columnScale2[i]=columnScale[iColumn];
6664 inverseScale2[i]=inverseScale[iColumn];
6665 }
6666 small->setColumnScale(columnScale2);
6667 }
6668 disasterHandler_->setOsiModel(this);
6669 if (inCbcOrOther) {
6670 disasterHandler_->setSimplex(small);
6671 disasterHandler_->setWhereFrom(1); // crunch
6672 small->setDisasterHandler(disasterHandler_);
6673 }
6674#if 0
6675 const double * obj =small->objective();
6676 int numberColumns2 = small->numberColumns();
6677 int iColumn;
6678 for (iColumn=0;iColumn<numberColumns2;iColumn++) {
6679 if (obj[iColumn])
6680 break;
6681 }
6682 if (iColumn<numberColumns2)
6683 small->dual();
6684 else
6685 small->primal(); // No objective - use primal!
6686#else
6687 small->moreSpecialOptions_ = modelPtr_->moreSpecialOptions_;
6688 small->dual(0,7);
6689#endif
6690 totalIterations += small->numberIterations();
6691 int problemStatus = small->problemStatus();
6692 if (problemStatus>=0&&problemStatus<=2) {
6693 modelPtr_->setProblemStatus(problemStatus);
6694 if (!inCbcOrOther||!problemStatus) {
6695 // Scaling may have changed - if so pass across
6696 if (modelPtr_->scalingFlag()==4)
6697 modelPtr_->scaling(small->scalingFlag());
6698 static_cast<ClpSimplexOther *> (modelPtr_)->afterCrunch(*small,whichRow,whichColumn,nBound);
6699 if ((specialOptions_&1048576)==0) {
6700 // get correct rays
6701 if (problemStatus==2)
6702 modelPtr_->primal(1);
6703 else if (problemStatus==1)
6704 modelPtr_->dual();
6705 } else {
6706 delete [] modelPtr_->ray_;
6707 modelPtr_->ray_=NULL;
6708 }
6709 }
6710#ifdef KEEP_SMALL
6711 //assert (!smallModel_);
6712 //smallModel_ = small;
6713 small=NULL;
6714 int nCopy = 3*numberRows+2*numberColumns;
6715 //int * copy = CoinCopyOfArrayPartial(whichRow,nCopy+1,nCopy);
6716 whichRow[nCopy]=nBound;
6717 assert (arrayI[0]==nBound);
6718 arrayI[0]=nBound; // same
6719 spareArrays_ = spareArrays;
6720 spareArrays=NULL;
6721#endif
6722 } else if (problemStatus!=3) {
6723 modelPtr_->setProblemStatus(1);
6724 } else {
6725 if (problemStatus==3) {
6726 // may be problems
6727 if (inCbcOrOther&&disasterHandler_->inTrouble()) {
6728 if (disasterHandler_->typeOfDisaster()) {
6729 // We want to abort
6730 abortSearch=true;
6731 goto disaster;
6732 }
6733 // in case scaling bad
6734 small->setRowScale(NULL);
6735 small->setColumnScale(NULL);
6736 // try just going back in
6737 disasterHandler_->setPhase(1);
6738 small->dual();
6739 totalIterations += small->numberIterations();
6740 if (disasterHandler_->inTrouble()) {
6741 if (disasterHandler_->typeOfDisaster()) {
6742 // We want to abort
6743 abortSearch=true;
6744 goto disaster;
6745 }
6746 // try primal on original model
6747 disasterHandler_->setPhase(2);
6748 disasterHandler_->setOsiModel(this);
6749 modelPtr_->setDisasterHandler(disasterHandler_);
6750 modelPtr_->primal();
6751 totalIterations += modelPtr_->numberIterations();
6752 if(disasterHandler_->inTrouble()) {
6753#ifdef COIN_DEVELOP
6754 printf("disaster crunch - treat as infeasible\n");
6755#endif
6756 if (disasterHandler_->typeOfDisaster()) {
6757 // We want to abort
6758 abortSearch=true;
6759 goto disaster;
6760 }
6761 modelPtr_->setProblemStatus(1);
6762 }
6763 // give up for now
6764 modelPtr_->setDisasterHandler(NULL);
6765 } else {
6766 modelPtr_->setProblemStatus(small->problemStatus());
6767 }
6768 } else {
6769 small->computeObjectiveValue();
6770 modelPtr_->setObjectiveValue(small->objectiveValue());
6771 modelPtr_->setProblemStatus(3);
6772 }
6773 } else {
6774 modelPtr_->setProblemStatus(3);
6775 }
6776 }
6777 disaster:
6778 delete small;
6779#ifdef KEEP_SMALL
6780 if (small==smallModel_) {
6781 smallModel_ = NULL;
6782 delete [] spareArrays_;
6783 spareArrays_ = NULL;
6784 spareArrays = NULL;
6785 }
6786#endif
6787 } else {
6788 modelPtr_->setProblemStatus(1);
6789#ifdef KEEP_SMALL
6790 delete [] spareArrays_;
6791 spareArrays_ = NULL;
6792 spareArrays = NULL;
6793#endif
6794 }
6795 modelPtr_->setNumberIterations(totalIterations);
6796 if (abortSearch) {
6797 lastAlgorithm_=-911;
6798 modelPtr_->setProblemStatus(4);
6799 }
6800#ifdef KEEP_SMALL
6801 delete [] spareArrays;
6802#else
6803 delete [] whichRow;
6804#endif
6805}
6806// Synchronize model
6807void
6808OsiClpSolverInterface::synchronizeModel()
6809{
6810 if ((specialOptions_ &128)!=0) {
6811 if (!modelPtr_->rowScale_&&(specialOptions_&131072)!=0) {
6812 assert (lastNumberRows_==modelPtr_->numberRows_);
6813 int numberRows = modelPtr_->numberRows();
6814 int numberColumns = modelPtr_->numberColumns();
6815 double * rowScale = CoinCopyOfArray(rowScale_.array(),2*numberRows);
6816 modelPtr_->setRowScale(rowScale);
6817 double * columnScale = CoinCopyOfArray(columnScale_.array(),2*numberColumns);
6818 modelPtr_->setColumnScale(columnScale);
6819 modelPtr_->setRowScale(NULL);
6820 modelPtr_->setColumnScale(NULL);
6821 }
6822 }
6823}
6824// Returns true if has OsiSimplex methods
6825/* Returns 1 if can just do getBInv etc
6826 2 if has all OsiSimplex methods
6827 and 0 if it has none */
6828int
6829OsiClpSolverInterface::canDoSimplexInterface() const
6830{
6831 return 2;
6832}
6833// Pass in sos stuff from AMPl
6834void
6835OsiClpSolverInterface::setSOSData(int numberSOS,const char * type,
6836 const int * start,const int * indices, const double * weights)
6837{
6838 delete [] setInfo_;
6839 setInfo_=NULL;
6840 numberSOS_=numberSOS;
6841 if (numberSOS_) {
6842 setInfo_ = new CoinSet[numberSOS_];
6843 for (int i=0;i<numberSOS_;i++) {
6844 int iStart = start[i];
6845 setInfo_[i]=CoinSosSet(start[i+1]-iStart,indices+iStart,weights ? weights+iStart : NULL,
6846 type[i]);
6847 }
6848 }
6849}
6850/* Identify integer variables and SOS and create corresponding objects.
6851
6852 Record integer variables and create an OsiSimpleInteger object for each
6853 one. All existing OsiSimpleInteger objects will be destroyed.
6854 If the solver supports SOS then do the same for SOS.
6855
6856 If justCount then no objects created and we just store numberIntegers_
6857 Returns number of SOS
6858*/
6859int
6860OsiClpSolverInterface::findIntegersAndSOS(bool justCount)
6861{
6862 findIntegers(justCount);
6863 int nObjects=0;
6864 OsiObject ** oldObject = object_;
6865 int iObject;
6866 int numberSOS=0;
6867 for (iObject = 0;iObject<numberObjects_;iObject++) {
6868 OsiSOS * obj =
6869 dynamic_cast <OsiSOS *>(oldObject[iObject]) ;
6870 if (obj)
6871 numberSOS++;
6872 }
6873 if (numberSOS_&&!numberSOS) {
6874 // make a large enough array for new objects
6875 nObjects = numberObjects_;
6876 numberObjects_=numberSOS_+nObjects;
6877 if (numberObjects_)
6878 object_ = new OsiObject * [numberObjects_];
6879 else
6880 object_=NULL;
6881 // copy
6882 CoinMemcpyN(oldObject,nObjects,object_);
6883 // Delete old array (just array)
6884 delete [] oldObject;
6885
6886 for (int i=0;i<numberSOS_;i++) {
6887 CoinSet * set = setInfo_+i;
6888 object_[nObjects++] =
6889 new OsiSOS(this,set->numberEntries(),set->which(),set->weights(),
6890 set->setType());
6891 }
6892 } else if (!numberSOS_&&numberSOS) {
6893 // create Coin sets
6894 assert (!setInfo_);
6895 setInfo_ = new CoinSet[numberSOS];
6896 for (iObject = 0;iObject<numberObjects_;iObject++) {
6897 OsiSOS * obj =
6898 dynamic_cast <OsiSOS *>(oldObject[iObject]) ;
6899 if (obj)
6900 setInfo_[numberSOS_++]=CoinSosSet(obj->numberMembers(),obj->members(),obj->weights(),obj->sosType());
6901 }
6902 } else if (numberSOS!=numberSOS_) {
6903 printf("mismatch on SOS\n");
6904 }
6905 return numberSOS_;
6906}
6907// below needed for pathetic branch and bound code
6908#include <vector>
6909#include <map>
6910
6911// Trivial class for Branch and Bound
6912
6913class OsiNodeSimple {
6914
6915public:
6916
6917 // Default Constructor
6918 OsiNodeSimple ();
6919
6920 // Constructor from current state (and list of integers)
6921 // Also chooses branching variable (if none set to -1)
6922 OsiNodeSimple (OsiSolverInterface &model,
6923 int numberIntegers, int * integer,
6924 CoinWarmStart * basis);
6925 void gutsOfConstructor (OsiSolverInterface &model,
6926 int numberIntegers, int * integer,
6927 CoinWarmStart * basis);
6928 // Copy constructor
6929 OsiNodeSimple ( const OsiNodeSimple &);
6930
6931 // Assignment operator
6932 OsiNodeSimple & operator=( const OsiNodeSimple& rhs);
6933
6934 // Destructor
6935 ~OsiNodeSimple ();
6936 // Work of destructor
6937 void gutsOfDestructor();
6938 // Extension - true if other extension of this
6939 bool extension(const OsiNodeSimple & other,
6940 const double * originalLower,
6941 const double * originalUpper) const;
6942 inline void incrementDescendants()
6943 { descendants_++;}
6944 // Public data
6945 // Basis (should use tree, but not as wasteful as bounds!)
6946 CoinWarmStart * basis_;
6947 // Objective value (COIN_DBL_MAX) if spare node
6948 double objectiveValue_;
6949 // Branching variable (0 is first integer)
6950 int variable_;
6951 // Way to branch - -1 down (first), 1 up, -2 down (second), 2 up (second)
6952 int way_;
6953 // Number of integers (for length of arrays)
6954 int numberIntegers_;
6955 // Current value
6956 double value_;
6957 // Number of descendant nodes (so 2 is in interior)
6958 int descendants_;
6959 // Parent
6960 int parent_;
6961 // Previous in chain
6962 int previous_;
6963 // Next in chain
6964 int next_;
6965 // Now I must use tree
6966 // Bounds stored in full (for integers)
6967 int * lower_;
6968 int * upper_;
6969};
6970
6971
6972OsiNodeSimple::OsiNodeSimple() :
6973 basis_(NULL),
6974 objectiveValue_(COIN_DBL_MAX),
6975 variable_(-100),
6976 way_(-1),
6977 numberIntegers_(0),
6978 value_(0.5),
6979 descendants_(-1),
6980 parent_(-1),
6981 previous_(-1),
6982 next_(-1),
6983 lower_(NULL),
6984 upper_(NULL)
6985{
6986}
6987OsiNodeSimple::OsiNodeSimple(OsiSolverInterface & model,
6988 int numberIntegers, int * integer,CoinWarmStart * basis)
6989{
6990 gutsOfConstructor(model,numberIntegers,integer,basis);
6991}
6992void
6993OsiNodeSimple::gutsOfConstructor(OsiSolverInterface & model,
6994 int numberIntegers, int * integer,CoinWarmStart * basis)
6995{
6996 basis_ = basis;
6997 variable_=-1;
6998 way_=-1;
6999 numberIntegers_=numberIntegers;
7000 value_=0.0;
7001 descendants_ = 0;
7002 parent_ = -1;
7003 previous_ = -1;
7004 next_ = -1;
7005 if (model.isProvenOptimal()&&!model.isDualObjectiveLimitReached()) {
7006 objectiveValue_ = model.getObjSense()*model.getObjValue();
7007 } else {
7008 objectiveValue_ = 1.0e100;
7009 lower_ = NULL;
7010 upper_ = NULL;
7011 return; // node cutoff
7012 }
7013 lower_ = new int [numberIntegers_];
7014 upper_ = new int [numberIntegers_];
7015 assert (upper_!=NULL);
7016 const double * lower = model.getColLower();
7017 const double * upper = model.getColUpper();
7018 const double * solution = model.getColSolution();
7019 int i;
7020 // Hard coded integer tolerance
7021#define INTEGER_TOLERANCE 1.0e-6
7022 ///////// Start of Strong branching code - can be ignored
7023 // Number of strong branching candidates
7024#define STRONG_BRANCHING 5
7025#ifdef STRONG_BRANCHING
7026 double upMovement[STRONG_BRANCHING];
7027 double downMovement[STRONG_BRANCHING];
7028 double solutionValue[STRONG_BRANCHING];
7029 int chosen[STRONG_BRANCHING];
7030 int iSmallest=0;
7031 // initialize distance from integer
7032 for (i=0;i<STRONG_BRANCHING;i++) {
7033 upMovement[i]=0.0;
7034 chosen[i]=-1;
7035 }
7036 variable_=-1;
7037 // This has hard coded integer tolerance
7038 double mostAway=INTEGER_TOLERANCE;
7039 int numberAway=0;
7040 for (i=0;i<numberIntegers;i++) {
7041 int iColumn = integer[i];
7042 lower_[i]=static_cast<int>(lower[iColumn]);
7043 upper_[i]=static_cast<int>(upper[iColumn]);
7044 double value = solution[iColumn];
7045 value = CoinMax(value,static_cast<double> (lower_[i]));
7046 value = CoinMin(value,static_cast<double> (upper_[i]));
7047 double nearest = floor(value+0.5);
7048 if (fabs(value-nearest)>INTEGER_TOLERANCE)
7049 numberAway++;
7050 if (fabs(value-nearest)>mostAway) {
7051 double away = fabs(value-nearest);
7052 if (away>upMovement[iSmallest]) {
7053 //add to list
7054 upMovement[iSmallest]=away;
7055 solutionValue[iSmallest]=value;
7056 chosen[iSmallest]=i;
7057 int j;
7058 iSmallest=-1;
7059 double smallest = 1.0;
7060 for (j=0;j<STRONG_BRANCHING;j++) {
7061 if (upMovement[j]<smallest) {
7062 smallest=upMovement[j];
7063 iSmallest=j;
7064 }
7065 }
7066 }
7067 }
7068 }
7069 int numberStrong=0;
7070 for (i=0;i<STRONG_BRANCHING;i++) {
7071 if (chosen[i]>=0) {
7072 numberStrong ++;
7073 variable_ = chosen[i];
7074 }
7075 }
7076 // out strong branching if bit set
7077 OsiClpSolverInterface* clp =
7078 dynamic_cast<OsiClpSolverInterface*>(&model);
7079 if (clp&&(clp->specialOptions()&16)!=0&&numberStrong>1) {
7080 int j;
7081 int iBest=-1;
7082 double best = 0.0;
7083 for (j=0;j<STRONG_BRANCHING;j++) {
7084 if (upMovement[j]>best) {
7085 best=upMovement[j];
7086 iBest=j;
7087 }
7088 }
7089 numberStrong=1;
7090 variable_=chosen[iBest];
7091 }
7092 if (numberStrong==1) {
7093 // just one - makes it easy
7094 int iColumn = integer[variable_];
7095 double value = solution[iColumn];
7096 value = CoinMax(value,static_cast<double> (lower_[variable_]));
7097 value = CoinMin(value,static_cast<double> (upper_[variable_]));
7098 double nearest = floor(value+0.5);
7099 value_=value;
7100 if (value<=nearest)
7101 way_=1; // up
7102 else
7103 way_=-1; // down
7104 } else if (numberStrong) {
7105 // more than one - choose
7106 bool chooseOne=true;
7107 model.markHotStart();
7108 for (i=0;i<STRONG_BRANCHING;i++) {
7109 int iInt = chosen[i];
7110 if (iInt>=0) {
7111 int iColumn = integer[iInt];
7112 double value = solutionValue[i]; // value of variable in original
7113 double objectiveChange;
7114 value = CoinMax(value,static_cast<double> (lower_[iInt]));
7115 value = CoinMin(value,static_cast<double> (upper_[iInt]));
7116
7117 // try down
7118
7119 model.setColUpper(iColumn,floor(value));
7120 model.solveFromHotStart();
7121 model.setColUpper(iColumn,upper_[iInt]);
7122 if (model.isProvenOptimal()&&!model.isDualObjectiveLimitReached()) {
7123 objectiveChange = model.getObjSense()*model.getObjValue()
7124 - objectiveValue_;
7125 } else {
7126 objectiveChange = 1.0e100;
7127 }
7128 assert (objectiveChange>-1.0e-5);
7129 objectiveChange = CoinMax(objectiveChange,0.0);
7130 downMovement[i]=objectiveChange;
7131
7132 // try up
7133
7134 model.setColLower(iColumn,ceil(value));
7135 model.solveFromHotStart();
7136 model.setColLower(iColumn,lower_[iInt]);
7137 if (model.isProvenOptimal()&&!model.isDualObjectiveLimitReached()) {
7138 objectiveChange = model.getObjSense()*model.getObjValue()
7139 - objectiveValue_;
7140 } else {
7141 objectiveChange = 1.0e100;
7142 }
7143 assert (objectiveChange>-1.0e-5);
7144 objectiveChange = CoinMax(objectiveChange,0.0);
7145 upMovement[i]=objectiveChange;
7146
7147 /* Possibilities are:
7148 Both sides feasible - store
7149 Neither side feasible - set objective high and exit
7150 One side feasible - change bounds and resolve
7151 */
7152 bool solveAgain=false;
7153 if (upMovement[i]<1.0e100) {
7154 if(downMovement[i]<1.0e100) {
7155 // feasible - no action
7156 } else {
7157 // up feasible, down infeasible
7158 solveAgain = true;
7159 model.setColLower(iColumn,ceil(value));
7160 }
7161 } else {
7162 if(downMovement[i]<1.0e100) {
7163 // down feasible, up infeasible
7164 solveAgain = true;
7165 model.setColUpper(iColumn,floor(value));
7166 } else {
7167 // neither side feasible
7168 objectiveValue_=1.0e100;
7169 chooseOne=false;
7170 break;
7171 }
7172 }
7173 if (solveAgain) {
7174 // need to solve problem again - signal this
7175 variable_ = numberIntegers;
7176 chooseOne=false;
7177 break;
7178 }
7179 }
7180 }
7181 if (chooseOne) {
7182 // choose the one that makes most difference both ways
7183 double best = -1.0;
7184 double best2 = -1.0;
7185 for (i=0;i<STRONG_BRANCHING;i++) {
7186 int iInt = chosen[i];
7187 if (iInt>=0) {
7188 //std::cout<<"Strong branching on "
7189 // <<i<<""<<iInt<<" down "<<downMovement[i]
7190 // <<" up "<<upMovement[i]
7191 // <<" value "<<solutionValue[i]
7192 // <<std::endl;
7193 bool better = false;
7194 if (CoinMin(upMovement[i],downMovement[i])>best) {
7195 // smaller is better
7196 better=true;
7197 } else if (CoinMin(upMovement[i],downMovement[i])>best-1.0e-5) {
7198 if (CoinMax(upMovement[i],downMovement[i])>best2+1.0e-5) {
7199 // smaller is about same, but larger is better
7200 better=true;
7201 }
7202 }
7203 if (better) {
7204 best = CoinMin(upMovement[i],downMovement[i]);
7205 best2 = CoinMax(upMovement[i],downMovement[i]);
7206 variable_ = iInt;
7207 double value = solutionValue[i];
7208 value = CoinMax(value,static_cast<double> (lower_[variable_]));
7209 value = CoinMin(value,static_cast<double> (upper_[variable_]));
7210 value_=value;
7211 if (upMovement[i]<=downMovement[i])
7212 way_=1; // up
7213 else
7214 way_=-1; // down
7215 }
7216 }
7217 }
7218 }
7219 // Delete the snapshot
7220 model.unmarkHotStart();
7221 }
7222 ////// End of Strong branching
7223#else
7224 variable_=-1;
7225 // This has hard coded integer tolerance
7226 double mostAway=INTEGER_TOLERANCE;
7227 int numberAway=0;
7228 for (i=0;i<numberIntegers;i++) {
7229 int iColumn = integer[i];
7230 lower_[i]=static_cast<int>(lower[iColumn]);
7231 upper_[i]=static_cast<int>(upper[iColumn]);
7232 double value = solution[iColumn];
7233 value = CoinMax(value,(double) lower_[i]);
7234 value = CoinMin(value,(double) upper_[i]);
7235 double nearest = floor(value+0.5);
7236 if (fabs(value-nearest)>INTEGER_TOLERANCE)
7237 numberAway++;
7238 if (fabs(value-nearest)>mostAway) {
7239 mostAway=fabs(value-nearest);
7240 variable_=i;
7241 value_=value;
7242 if (value<=nearest)
7243 way_=1; // up
7244 else
7245 way_=-1; // down
7246 }
7247 }
7248#endif
7249}
7250
7251OsiNodeSimple::OsiNodeSimple(const OsiNodeSimple & rhs)
7252{
7253 if (rhs.basis_)
7254 basis_=rhs.basis_->clone();
7255 else
7256 basis_ = NULL;
7257 objectiveValue_=rhs.objectiveValue_;
7258 variable_=rhs.variable_;
7259 way_=rhs.way_;
7260 numberIntegers_=rhs.numberIntegers_;
7261 value_=rhs.value_;
7262 descendants_ = rhs.descendants_;
7263 parent_ = rhs.parent_;
7264 previous_ = rhs.previous_;
7265 next_ = rhs.next_;
7266 lower_=NULL;
7267 upper_=NULL;
7268 if (rhs.lower_!=NULL) {
7269 lower_ = new int [numberIntegers_];
7270 upper_ = new int [numberIntegers_];
7271 assert (upper_!=NULL);
7272 CoinMemcpyN(rhs.lower_,numberIntegers_,lower_);
7273 CoinMemcpyN(rhs.upper_,numberIntegers_,upper_);
7274 }
7275}
7276
7277OsiNodeSimple &
7278OsiNodeSimple::operator=(const OsiNodeSimple & rhs)
7279{
7280 if (this != &rhs) {
7281 gutsOfDestructor();
7282 if (rhs.basis_)
7283 basis_=rhs.basis_->clone();
7284 objectiveValue_=rhs.objectiveValue_;
7285 variable_=rhs.variable_;
7286 way_=rhs.way_;
7287 numberIntegers_=rhs.numberIntegers_;
7288 value_=rhs.value_;
7289 descendants_ = rhs.descendants_;
7290 parent_ = rhs.parent_;
7291 previous_ = rhs.previous_;
7292 next_ = rhs.next_;
7293 if (rhs.lower_!=NULL) {
7294 lower_ = new int [numberIntegers_];
7295 upper_ = new int [numberIntegers_];
7296 assert (upper_!=NULL);
7297 CoinMemcpyN(rhs.lower_,numberIntegers_,lower_);
7298 CoinMemcpyN(rhs.upper_,numberIntegers_,upper_);
7299 }
7300 }
7301 return *this;
7302}
7303
7304
7305OsiNodeSimple::~OsiNodeSimple ()
7306{
7307 gutsOfDestructor();
7308}
7309// Work of destructor
7310void
7311OsiNodeSimple::gutsOfDestructor()
7312{
7313 delete [] lower_;
7314 delete [] upper_;
7315 delete basis_;
7316 lower_ = NULL;
7317 upper_ = NULL;
7318 basis_ = NULL;
7319 objectiveValue_ = COIN_DBL_MAX;
7320}
7321// Extension - true if other extension of this
7322bool
7323OsiNodeSimple::extension(const OsiNodeSimple & other,
7324 const double * originalLower,
7325 const double * originalUpper) const
7326{
7327 bool ok=true;
7328 for (int i=0;i<numberIntegers_;i++) {
7329 if (upper_[i]<originalUpper[i]||
7330 lower_[i]>originalLower[i]) {
7331 if (other.upper_[i]>upper_[i]||
7332 other.lower_[i]<lower_[i]) {
7333 ok=false;
7334 break;
7335 }
7336 }
7337 }
7338 return ok;
7339}
7340
7341#include <vector>
7342#define FUNNY_BRANCHING 1
7343#define FUNNY_TREE
7344#ifndef FUNNY_TREE
7345// Vector of OsiNodeSimples
7346typedef std::vector<OsiNodeSimple> OsiVectorNode;
7347#else
7348// Must code up by hand
7349class OsiVectorNode {
7350
7351public:
7352
7353 // Default Constructor
7354 OsiVectorNode ();
7355
7356 // Copy constructor
7357 OsiVectorNode ( const OsiVectorNode &);
7358
7359 // Assignment operator
7360 OsiVectorNode & operator=( const OsiVectorNode& rhs);
7361
7362 // Destructor
7363 ~OsiVectorNode ();
7364 // Size
7365 inline int size() const
7366 { return size_-sizeDeferred_;}
7367 // Push
7368 void push_back(const OsiNodeSimple & node);
7369 // Last one in (or other criterion)
7370 OsiNodeSimple back() const;
7371 // Get rid of last one
7372 void pop_back();
7373 // Works out best one
7374 int best() const;
7375
7376 // Public data
7377 // Maximum size
7378 int maximumSize_;
7379 // Current size
7380 int size_;
7381 // Number still hanging around
7382 int sizeDeferred_;
7383 // First spare
7384 int firstSpare_;
7385 // First
7386 int first_;
7387 // Last
7388 int last_;
7389 // Chosen one
7390 mutable int chosen_;
7391 // Nodes
7392 OsiNodeSimple * nodes_;
7393};
7394
7395
7396OsiVectorNode::OsiVectorNode() :
7397 maximumSize_(10),
7398 size_(0),
7399 sizeDeferred_(0),
7400 firstSpare_(0),
7401 first_(-1),
7402 last_(-1)
7403{
7404 nodes_ = new OsiNodeSimple[maximumSize_];
7405 for (int i=0;i<maximumSize_;i++) {
7406 nodes_[i].previous_=i-1;
7407 nodes_[i].next_=i+1;
7408 }
7409}
7410
7411OsiVectorNode::OsiVectorNode(const OsiVectorNode & rhs)
7412{
7413 maximumSize_ = rhs.maximumSize_;
7414 size_ = rhs.size_;
7415 sizeDeferred_ = rhs.sizeDeferred_;
7416 firstSpare_ = rhs.firstSpare_;
7417 first_ = rhs.first_;
7418 last_ = rhs.last_;
7419 nodes_ = new OsiNodeSimple[maximumSize_];
7420 for (int i=0;i<maximumSize_;i++) {
7421 nodes_[i] = rhs.nodes_[i];
7422 }
7423}
7424
7425OsiVectorNode &
7426OsiVectorNode::operator=(const OsiVectorNode & rhs)
7427{
7428 if (this != &rhs) {
7429 delete [] nodes_;
7430 maximumSize_ = rhs.maximumSize_;
7431 size_ = rhs.size_;
7432 sizeDeferred_ = rhs.sizeDeferred_;
7433 firstSpare_ = rhs.firstSpare_;
7434 first_ = rhs.first_;
7435 last_ = rhs.last_;
7436 nodes_ = new OsiNodeSimple[maximumSize_];
7437 for (int i=0;i<maximumSize_;i++) {
7438 nodes_[i] = rhs.nodes_[i];
7439 }
7440 }
7441 return *this;
7442}
7443
7444
7445OsiVectorNode::~OsiVectorNode ()
7446{
7447 delete [] nodes_;
7448}
7449// Push
7450void
7451OsiVectorNode::push_back(const OsiNodeSimple & node)
7452{
7453 if (size_==maximumSize_) {
7454 assert (firstSpare_==size_);
7455 maximumSize_ = (maximumSize_*3)+10;
7456 OsiNodeSimple * temp = new OsiNodeSimple[maximumSize_];
7457 int i;
7458 for (i=0;i<size_;i++) {
7459 temp[i]=nodes_[i];
7460 }
7461 delete [] nodes_;
7462 nodes_ = temp;
7463 //firstSpare_=size_;
7464 int last = -1;
7465 for ( i=size_;i<maximumSize_;i++) {
7466 nodes_[i].previous_=last;
7467 nodes_[i].next_=i+1;
7468 last = i;
7469 }
7470 }
7471 assert (firstSpare_<maximumSize_);
7472 assert (nodes_[firstSpare_].previous_<0);
7473 int next = nodes_[firstSpare_].next_;
7474 nodes_[firstSpare_]=node;
7475 if (last_>=0) {
7476 assert (nodes_[last_].next_==-1);
7477 nodes_[last_].next_=firstSpare_;
7478 }
7479 nodes_[firstSpare_].previous_=last_;
7480 nodes_[firstSpare_].next_=-1;
7481 if (last_==-1) {
7482 assert (first_==-1);
7483 first_ = firstSpare_;
7484 }
7485 last_=firstSpare_;
7486 if (next>=0&&next<maximumSize_) {
7487 firstSpare_ = next;
7488 nodes_[firstSpare_].previous_=-1;
7489 } else {
7490 firstSpare_=maximumSize_;
7491 }
7492 chosen_ = -1;
7493 //best();
7494 size_++;
7495 assert (node.descendants_<=2);
7496 if (node.descendants_==2)
7497 sizeDeferred_++;
7498}
7499// Works out best one
7500int
7501OsiVectorNode::best() const
7502{
7503 // can modify
7504 chosen_=-1;
7505 if (chosen_<0) {
7506 chosen_=last_;
7507#if FUNNY_BRANCHING
7508 while (nodes_[chosen_].descendants_==2) {
7509 chosen_ = nodes_[chosen_].previous_;
7510 assert (chosen_>=0);
7511 }
7512#endif
7513 }
7514 return chosen_;
7515}
7516// Last one in (or other criterion)
7517OsiNodeSimple
7518OsiVectorNode::back() const
7519{
7520 assert (last_>=0);
7521 return nodes_[best()];
7522}
7523// Get rid of last one
7524void
7525OsiVectorNode::pop_back()
7526{
7527 // Temporary until more sophisticated
7528 //assert (last_==chosen_);
7529 if (nodes_[chosen_].descendants_==2)
7530 sizeDeferred_--;
7531 int previous = nodes_[chosen_].previous_;
7532 int next = nodes_[chosen_].next_;
7533 nodes_[chosen_].gutsOfDestructor();
7534 if (previous>=0) {
7535 nodes_[previous].next_=next;
7536 } else {
7537 first_ = next;
7538 }
7539 if (next>=0) {
7540 nodes_[next].previous_ = previous;
7541 } else {
7542 last_ = previous;
7543 }
7544 nodes_[chosen_].previous_=-1;
7545 if (firstSpare_>=0) {
7546 nodes_[chosen_].next_ = firstSpare_;
7547 } else {
7548 nodes_[chosen_].next_ = -1;
7549 }
7550 firstSpare_ = chosen_;
7551 chosen_ = -1;
7552 assert (size_>0);
7553 size_--;
7554}
7555#endif
7556// Invoke solver's built-in enumeration algorithm
7557void
7558OsiClpSolverInterface::branchAndBound() {
7559 double time1 = CoinCpuTime();
7560 // solve LP
7561 initialSolve();
7562 int funnyBranching=FUNNY_BRANCHING;
7563
7564 if (isProvenOptimal()&&!isDualObjectiveLimitReached()) {
7565 // Continuous is feasible - find integers
7566 int numberIntegers=0;
7567 int numberColumns = getNumCols();
7568 int iColumn;
7569 int i;
7570 for (iColumn=0;iColumn<numberColumns;iColumn++) {
7571 if( isInteger(iColumn))
7572 numberIntegers++;
7573 }
7574 if (!numberIntegers) {
7575 std::cout<<"No integer variables"
7576 <<std::endl;
7577 return;
7578 }
7579 int * which = new int[numberIntegers]; // which variables are integer
7580 // original bounds
7581 int * originalLower = new int[numberIntegers];
7582 int * originalUpper = new int[numberIntegers];
7583 int * relaxedLower = new int[numberIntegers];
7584 int * relaxedUpper = new int[numberIntegers];
7585 {
7586 const double * lower = getColLower();
7587 const double * upper = getColUpper();
7588 numberIntegers=0;
7589 for (iColumn=0;iColumn<numberColumns;iColumn++) {
7590 if( isInteger(iColumn)) {
7591 originalLower[numberIntegers]=static_cast<int> (lower[iColumn]);
7592 if (upper[iColumn]>1.0e9) {
7593 // This is not meant to be a bulletproof code
7594 setColUpper(iColumn,1.0e9);
7595 }
7596 originalUpper[numberIntegers]=static_cast<int> (upper[iColumn]);
7597 which[numberIntegers++]=iColumn;
7598 }
7599 }
7600 }
7601 double direction = getObjSense();
7602 // empty tree
7603 OsiVectorNode branchingTree;
7604
7605 // Add continuous to it;
7606 OsiNodeSimple rootNode(*this,numberIntegers,which,getWarmStart());
7607 // something extra may have been fixed by strong branching
7608 // if so go round again
7609 while (rootNode.variable_==numberIntegers) {
7610 resolve();
7611 rootNode = OsiNodeSimple(*this,numberIntegers,which,getWarmStart());
7612 }
7613 if (rootNode.objectiveValue_<1.0e100) {
7614 // push on stack
7615 branchingTree.push_back(rootNode);
7616 }
7617
7618 // For printing totals
7619 int numberIterations=0;
7620 int numberNodes =0;
7621 int nRedundantUp=0;
7622 int nRedundantDown=0;
7623 int nRedundantUp2=0;
7624 int nRedundantDown2=0;
7625 OsiNodeSimple bestNode;
7626 ////// Start main while of branch and bound
7627 // while until nothing on stack
7628 while (branchingTree.size()) {
7629 // last node
7630 OsiNodeSimple node = branchingTree.back();
7631 int kNode = branchingTree.chosen_;
7632 branchingTree.pop_back();
7633 assert (node.descendants_<2);
7634 numberNodes++;
7635 if (node.variable_>=0) {
7636 // branch - do bounds
7637 for (i=0;i<numberIntegers;i++) {
7638 iColumn=which[i];
7639 setColBounds( iColumn,node.lower_[i],node.upper_[i]);
7640 }
7641 // move basis
7642 setWarmStart(node.basis_);
7643 // do branching variable
7644 node.incrementDescendants();
7645 if (node.way_<0) {
7646 setColUpper(which[node.variable_],floor(node.value_));
7647 // now push back node if more to come
7648 if (node.way_==-1) {
7649 node.way_=+2; // Swap direction
7650 branchingTree.push_back(node);
7651 } else if (funnyBranching) {
7652 // put back on tree anyway
7653 branchingTree.push_back(node);
7654 }
7655 } else {
7656 setColLower(which[node.variable_],ceil(node.value_));
7657 // now push back node if more to come
7658 if (node.way_==1) {
7659 node.way_=-2; // Swap direction
7660 branchingTree.push_back(node);
7661 } else if (funnyBranching) {
7662 // put back on tree anyway
7663 branchingTree.push_back(node);
7664 }
7665 }
7666
7667 // solve
7668 resolve();
7669 CoinWarmStart * ws = getWarmStart();
7670 const CoinWarmStartBasis* wsb =
7671 dynamic_cast<const CoinWarmStartBasis*>(ws);
7672 assert (wsb!=NULL); // make sure not volume
7673 numberIterations += getIterationCount();
7674 // fix on reduced costs
7675 int nFixed0=0,nFixed1=0;
7676 double cutoff;
7677 getDblParam(OsiDualObjectiveLimit,cutoff);
7678 double gap=(cutoff-modelPtr_->objectiveValue())*direction+1.0e-4;
7679 if (gap<1.0e10&&isProvenOptimal()&&!isDualObjectiveLimitReached()) {
7680 const double * dj = getReducedCost();
7681 const double * lower = getColLower();
7682 const double * upper = getColUpper();
7683 for (i=0;i<numberIntegers;i++) {
7684 iColumn=which[i];
7685 if (upper[iColumn]>lower[iColumn]) {
7686 double djValue = dj[iColumn]*direction;
7687 if (wsb->getStructStatus(iColumn)==CoinWarmStartBasis::atLowerBound&&
7688 djValue>gap) {
7689 nFixed0++;
7690 setColUpper(iColumn,lower[iColumn]);
7691 } else if (wsb->getStructStatus(iColumn)==CoinWarmStartBasis::atUpperBound&&
7692 -djValue>gap) {
7693 nFixed1++;
7694 setColLower(iColumn,upper[iColumn]);
7695 }
7696 }
7697 }
7698 //if (nFixed0+nFixed1)
7699 //printf("%d fixed to lower, %d fixed to upper\n",nFixed0,nFixed1);
7700 }
7701 if (!isIterationLimitReached()) {
7702 if (isProvenOptimal()&&!isDualObjectiveLimitReached()) {
7703#if FUNNY_BRANCHING
7704 // See if branched variable off bounds
7705 const double * dj = getReducedCost();
7706 const double * lower = getColLower();
7707 const double * upper = getColUpper();
7708 const double * solution = getColSolution();
7709 // Better to use "natural" value - need flag to say fixed
7710 for (i=0;i<numberIntegers;i++) {
7711 iColumn=which[i];
7712 relaxedLower[i]=originalLower[i];
7713 relaxedUpper[i]=originalUpper[i];
7714 double djValue = dj[iColumn]*direction;
7715 if (djValue>1.0e-6) {
7716 // wants to go down
7717 if (lower[iColumn]>originalLower[i]) {
7718 // Lower bound active
7719 relaxedLower[i]=static_cast<int> (lower[iColumn]);
7720 }
7721 if (upper[iColumn]<originalUpper[i]) {
7722 // Upper bound NOT active
7723 }
7724 } else if (djValue<-1.0e-6) {
7725 // wants to go up
7726 if (lower[iColumn]>originalLower[i]) {
7727 // Lower bound NOT active
7728 }
7729 if (upper[iColumn]<originalUpper[i]) {
7730 // Upper bound active
7731 relaxedUpper[i]=static_cast<int> (upper[iColumn]);
7732 }
7733 }
7734 }
7735 // See if can do anything
7736 {
7737 /*
7738 If kNode is on second branch then
7739 a) If other feasible could free up as well
7740 b) If other infeasible could do something clever.
7741 For now - we have to give up
7742 */
7743 int jNode=branchingTree.nodes_[kNode].parent_;
7744 bool canDelete = (branchingTree.nodes_[kNode].descendants_<2);
7745 while (jNode>=0) {
7746 OsiNodeSimple & node = branchingTree.nodes_[jNode];
7747 int next = node.parent_;
7748 if (node.descendants_<2) {
7749 int variable = node.variable_;
7750 iColumn=which[variable];
7751 double value = node.value_;
7752 double djValue = dj[iColumn]*direction;
7753 assert (node.way_==2||node.way_==-2);
7754 // we don't know which branch it was - look at current bounds
7755 if (upper[iColumn]<value&&node.lower_[variable]<upper[iColumn]) {
7756 // must have been down branch
7757 if (djValue>1.0e-3||solution[iColumn]<upper[iColumn]-1.0e-5) {
7758 if (canDelete) {
7759 nRedundantDown++;
7760#if 1
7761 printf("%d redundant branch down with value %g current upper %g solution %g dj %g\n",
7762 variable,node.value_,upper[iColumn],solution[iColumn],djValue);
7763#endif
7764 node.descendants_=2; // ignore
7765 branchingTree.sizeDeferred_++;
7766 int newUpper = originalUpper[variable];
7767 if (next>=0) {
7768 OsiNodeSimple & node2 = branchingTree.nodes_[next];
7769 newUpper = node2.upper_[variable];
7770 }
7771 if (branchingTree.nodes_[jNode].parent_!=next)
7772 assert (newUpper>upper[iColumn]);
7773 setColUpper(iColumn,newUpper);
7774 int kNode2=next;
7775 int jNode2=branchingTree.nodes_[kNode].parent_;
7776 assert (newUpper>branchingTree.nodes_[kNode].upper_[variable]);
7777 branchingTree.nodes_[kNode].upper_[variable]= newUpper;
7778 while (jNode2!=kNode2) {
7779 OsiNodeSimple & node2 = branchingTree.nodes_[jNode2];
7780 int next = node2.parent_;
7781 if (next!=kNode2)
7782 assert (newUpper>node2.upper_[variable]);
7783 node2.upper_[variable]= newUpper;
7784 jNode2=next;
7785 }
7786 } else {
7787 // can't delete but can add other way to jNode
7788 nRedundantDown2++;
7789 OsiNodeSimple & node2 = branchingTree.nodes_[kNode];
7790 assert (node2.way_==2||node2.way_==-2);
7791 double value2 = node2.value_;
7792 int variable2 = node2.variable_;
7793 int iColumn2 = which[variable2];
7794 if (variable != variable2) {
7795 if (node2.way_==2&&upper[iColumn2]<value2) {
7796 // must have been down branch which was done - carry over
7797 int newUpper = static_cast<int> (floor(value2));
7798 assert (newUpper<node.upper_[variable2]);
7799 node.upper_[variable2]=newUpper;
7800 } else if (node2.way_==-2&&lower[iColumn2]>value2) {
7801 // must have been up branch which was done - carry over
7802 int newLower = static_cast<int> (ceil(value2));
7803 assert (newLower>node.lower_[variable2]);
7804 node.lower_[variable2]=newLower;
7805 }
7806 if (node.lower_[variable2]>node.upper_[variable2]) {
7807 // infeasible
7808 node.descendants_=2; // ignore
7809 branchingTree.sizeDeferred_++;
7810 }
7811 }
7812 }
7813 break;
7814 }
7815 // we don't know which branch it was - look at current bounds
7816 } else if (lower[iColumn]>value&&node.upper_[variable]>lower[iColumn]) {
7817 // must have been up branch
7818 if (djValue<-1.0e-3||solution[iColumn]>lower[iColumn]+1.0e-5) {
7819 if (canDelete) {
7820 nRedundantUp++;
7821#if 1
7822 printf("%d redundant branch up with value %g current lower %g solution %g dj %g\n",
7823 variable,node.value_,lower[iColumn],solution[iColumn],djValue);
7824#endif
7825 node.descendants_=2; // ignore
7826 branchingTree.sizeDeferred_++;
7827 int newLower = originalLower[variable];
7828 if (next>=0) {
7829 OsiNodeSimple & node2 = branchingTree.nodes_[next];
7830 newLower = node2.lower_[variable];
7831 }
7832 if (branchingTree.nodes_[jNode].parent_!=next)
7833 assert (newLower<lower[iColumn]);
7834 setColLower(iColumn,newLower);
7835 int kNode2=next;
7836 int jNode2=branchingTree.nodes_[kNode].parent_;
7837 assert (newLower<branchingTree.nodes_[kNode].lower_[variable]);
7838 branchingTree.nodes_[kNode].lower_[variable]= newLower;
7839 while (jNode2!=kNode2) {
7840 OsiNodeSimple & node2 = branchingTree.nodes_[jNode2];
7841 int next = node2.parent_;
7842 if (next!=kNode2)
7843 assert (newLower<node2.lower_[variable]);
7844 node2.lower_[variable]=newLower;
7845 jNode2=next;
7846 }
7847 } else {
7848 // can't delete but can add other way to jNode
7849 nRedundantUp2++;
7850 OsiNodeSimple & node2 = branchingTree.nodes_[kNode];
7851 assert (node2.way_==2||node2.way_==-2);
7852 double value2 = node2.value_;
7853 int variable2 = node2.variable_;
7854 int iColumn2 = which[variable2];
7855 if (variable != variable2) {
7856 if (node2.way_==2&&upper[iColumn2]<value2) {
7857 // must have been down branch which was done - carry over
7858 int newUpper = static_cast<int> (floor(value2));
7859 assert (newUpper<node.upper_[variable2]);
7860 node.upper_[variable2]=newUpper;
7861 } else if (node2.way_==-2&&lower[iColumn2]>value2) {
7862 // must have been up branch which was done - carry over
7863 int newLower = static_cast<int> (ceil(value2));
7864 assert (newLower>node.lower_[variable2]);
7865 node.lower_[variable2]=newLower;
7866 }
7867 if (node.lower_[variable2]>node.upper_[variable2]) {
7868 // infeasible
7869 node.descendants_=2; // ignore
7870 branchingTree.sizeDeferred_++;
7871 }
7872 }
7873 }
7874 break;
7875 }
7876 }
7877 } else {
7878 break;
7879 }
7880 jNode=next;
7881 }
7882 }
7883 // solve
7884 //resolve();
7885 //assert(!getIterationCount());
7886 if ((numberNodes%1000)==0)
7887 printf("%d nodes, redundant down %d (%d) up %d (%d) tree size %d\n",
7888 numberNodes,nRedundantDown,nRedundantDown2,nRedundantUp,nRedundantUp2,branchingTree.size());
7889#else
7890 if ((numberNodes%1000)==0)
7891 printf("%d nodes, tree size %d\n",
7892 numberNodes,branchingTree.size());
7893#endif
7894 if (CoinCpuTime()-time1>3600.0) {
7895 printf("stopping after 3600 seconds\n");
7896 exit(77);
7897 }
7898 OsiNodeSimple newNode(*this,numberIntegers,which,ws);
7899 // something extra may have been fixed by strong branching
7900 // if so go round again
7901 while (newNode.variable_==numberIntegers) {
7902 resolve();
7903 newNode = OsiNodeSimple(*this,numberIntegers,which,getWarmStart());
7904 }
7905 if (newNode.objectiveValue_<1.0e100) {
7906 if (newNode.variable_>=0)
7907 assert (fabs(newNode.value_-floor(newNode.value_+0.5))>1.0e-6);
7908 newNode.parent_ = kNode;
7909 // push on stack
7910 branchingTree.push_back(newNode);
7911 }
7912 } else {
7913 // infeasible
7914 delete ws;
7915 }
7916 } else {
7917 // maximum iterations - exit
7918 std::cout<<"Exiting on maximum iterations"
7919 <<std::endl;
7920 break;
7921 }
7922 } else {
7923 // integer solution - save
7924 bestNode = node;
7925 // set cutoff (hard coded tolerance)
7926 setDblParam(OsiDualObjectiveLimit,(bestNode.objectiveValue_-1.0e-5)*direction);
7927 std::cout<<"Integer solution of "
7928 <<bestNode.objectiveValue_
7929 <<" found after "<<numberIterations
7930 <<" iterations and "<<numberNodes<<" nodes"
7931 <<std::endl;
7932 }
7933 }
7934 ////// End main while of branch and bound
7935 std::cout<<"Search took "
7936 <<numberIterations
7937 <<" iterations and "<<numberNodes<<" nodes"
7938 <<std::endl;
7939 if (bestNode.numberIntegers_) {
7940 // we have a solution restore
7941 // do bounds
7942 for (i=0;i<numberIntegers;i++) {
7943 iColumn=which[i];
7944 setColBounds( iColumn,bestNode.lower_[i],bestNode.upper_[i]);
7945 }
7946 // move basis
7947 setWarmStart(bestNode.basis_);
7948 // set cutoff so will be good (hard coded tolerance)
7949 setDblParam(OsiDualObjectiveLimit,(bestNode.objectiveValue_+1.0e-5)*direction);
7950 resolve();
7951 } else {
7952 modelPtr_->setProblemStatus(1);
7953 }
7954 delete [] which;
7955 delete [] originalLower;
7956 delete [] originalUpper;
7957 delete [] relaxedLower;
7958 delete [] relaxedUpper;
7959 } else {
7960 if(messageHandler())
7961 *messageHandler() <<"The LP relaxation is infeasible" <<CoinMessageEol;
7962 modelPtr_->setProblemStatus(1);
7963 //throw CoinError("The LP relaxation is infeasible or too expensive",
7964 //"branchAndBound", "OsiClpSolverInterface");
7965 }
7966}
7967void
7968OsiClpSolverInterface::setSpecialOptions(unsigned int value)
7969{
7970 if ((value&131072)!=0&&(specialOptions_&131072)==0) {
7971 // Try and keep scaling factors around
7972 delete baseModel_;
7973 baseModel_ = new ClpSimplex(*modelPtr_);
7974 ClpPackedMatrix * clpMatrix =
7975 dynamic_cast< ClpPackedMatrix*>(baseModel_->matrix_);
7976 if (!clpMatrix||clpMatrix->scale(baseModel_)) {
7977 // switch off again
7978 delete baseModel_;
7979 baseModel_=NULL;
7980 value &= ~131072;
7981 } else {
7982 // Off current scaling
7983 modelPtr_->setRowScale(NULL);
7984 modelPtr_->setColumnScale(NULL);
7985 lastNumberRows_=baseModel_->numberRows();
7986 rowScale_ = CoinDoubleArrayWithLength(2*lastNumberRows_,0);
7987 int i;
7988 double * scale;
7989 double * inverseScale;
7990 scale = rowScale_.array();
7991 inverseScale = scale + lastNumberRows_;
7992 const double * rowScale = baseModel_->rowScale_;
7993 for (i=0;i<lastNumberRows_;i++) {
7994 scale[i] = rowScale[i];
7995 inverseScale[i] = 1.0/scale[i];
7996 }
7997 int numberColumns = baseModel_->numberColumns();
7998 columnScale_ = CoinDoubleArrayWithLength(2*numberColumns,0);
7999 scale = columnScale_.array();
8000 inverseScale = scale + numberColumns;
8001 const double * columnScale = baseModel_->columnScale_;
8002 for (i=0;i<numberColumns;i++) {
8003 scale[i] = columnScale[i];
8004 inverseScale[i] = 1.0/scale[i];
8005 }
8006 }
8007 }
8008 specialOptions_=value;
8009 if ((specialOptions_&0x80000000)!=0) {
8010 // unset top bit if anything set
8011 if (specialOptions_!=0x80000000)
8012 specialOptions_ &= 0x7fffffff;
8013 }
8014}
8015void
8016OsiClpSolverInterface::setSpecialOptionsMutable(unsigned int value) const
8017{
8018 specialOptions_=value;
8019 if ((specialOptions_&0x80000000)!=0) {
8020 // unset top bit if anything set
8021 if (specialOptions_!=0x80000000)
8022 specialOptions_ &= 0x7fffffff;
8023 }
8024}
8025/* If solver wants it can save a copy of "base" (continuous) model here
8026 */
8027void
8028OsiClpSolverInterface::saveBaseModel()
8029{
8030 delete continuousModel_;
8031 continuousModel_ = new ClpSimplex(*modelPtr_);
8032 delete matrixByRowAtContinuous_;
8033 matrixByRowAtContinuous_ = new CoinPackedMatrix();
8034 matrixByRowAtContinuous_->setExtraGap(0.0);
8035 matrixByRowAtContinuous_->setExtraMajor(0.0);
8036 matrixByRowAtContinuous_->reverseOrderedCopyOf(*modelPtr_->matrix());
8037 //continuousModel_->createRim(63);
8038}
8039// Pass in disaster handler
8040void
8041OsiClpSolverInterface::passInDisasterHandler(OsiClpDisasterHandler * handler)
8042{
8043 delete disasterHandler_;
8044 if ( handler )
8045 disasterHandler_ = dynamic_cast<OsiClpDisasterHandler *>(handler->clone());
8046 else
8047 disasterHandler_ = NULL;
8048}
8049/* Strip off rows to get to this number of rows.
8050 If solver wants it can restore a copy of "base" (continuous) model here
8051*/
8052void
8053OsiClpSolverInterface::restoreBaseModel(int numberRows)
8054{
8055 if (continuousModel_&&continuousModel_->numberRows()==numberRows) {
8056 modelPtr_->numberRows_ = numberRows;
8057 //ClpDisjointCopyN ( continuousModel_->columnLower_, modelPtr_->numberColumns_,modelPtr_->columnLower_ );
8058 //ClpDisjointCopyN ( continuousModel_->columnUpper_, modelPtr_->numberColumns_,modelPtr_->columnUpper_ );
8059 // Could keep copy of scaledMatrix_ around??
8060 delete modelPtr_->scaledMatrix_;
8061 modelPtr_->scaledMatrix_=NULL;
8062 if (continuousModel_->rowCopy_) {
8063 modelPtr_->copy(continuousModel_->rowCopy_,modelPtr_->rowCopy_);
8064 } else {
8065 delete modelPtr_->rowCopy_;
8066 modelPtr_->rowCopy_=NULL;
8067 }
8068 modelPtr_->copy(continuousModel_->matrix_,modelPtr_->matrix_);
8069 if (matrixByRowAtContinuous_) {
8070 if (matrixByRow_) {
8071 *matrixByRow_ = *matrixByRowAtContinuous_;
8072 } else {
8073 //printf("BBBB could new\n");
8074 // matrixByRow_ = new CoinPackedMatrix(*matrixByRowAtContinuous_);
8075 }
8076 } else {
8077 delete matrixByRow_;
8078 matrixByRow_=NULL;
8079 }
8080 } else {
8081 OsiSolverInterface::restoreBaseModel(numberRows);
8082 }
8083}
8084// Tighten bounds - lightweight
8085int
8086OsiClpSolverInterface::tightenBounds(int lightweight)
8087{
8088 if (!integerInformation_||(specialOptions_&262144)!=0)
8089 return 0; // no integers
8090 //CoinPackedMatrix matrixByRow(*getMatrixByRow());
8091 int numberRows = getNumRows();
8092 int numberColumns = getNumCols();
8093
8094 int iRow,iColumn;
8095
8096 // Row copy
8097 //const double * elementByRow = matrixByRow.getElements();
8098 //const int * column = matrixByRow.getIndices();
8099 //const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
8100 //const int * rowLength = matrixByRow.getVectorLengths();
8101
8102 const double * columnUpper = getColUpper();
8103 const double * columnLower = getColLower();
8104 const double * rowUpper = getRowUpper();
8105 const double * rowLower = getRowLower();
8106
8107 // Column copy of matrix
8108 const double * element = getMatrixByCol()->getElements();
8109 const int * row = getMatrixByCol()->getIndices();
8110 const CoinBigIndex * columnStart = getMatrixByCol()->getVectorStarts();
8111 const int * columnLength = getMatrixByCol()->getVectorLengths();
8112 const double *objective = getObjCoefficients() ;
8113 double direction = getObjSense();
8114 double * down = new double [numberRows];
8115 if (lightweight>0) {
8116 int * first = new int[numberRows];
8117 CoinZeroN(first,numberRows);
8118 CoinZeroN(down,numberRows);
8119 double * sum = new double [numberRows];
8120 CoinZeroN(sum,numberRows);
8121 int numberTightened=0;
8122 for (int iColumn=0;iColumn<numberColumns;iColumn++) {
8123 CoinBigIndex start = columnStart[iColumn];
8124 CoinBigIndex end = start + columnLength[iColumn];
8125 double lower = columnLower[iColumn];
8126 double upper = columnUpper[iColumn];
8127 if (lower==upper) {
8128 for (CoinBigIndex j=start;j<end;j++) {
8129 int iRow = row[j];
8130 double value = element[j];
8131 down[iRow] += value*lower;
8132 sum[iRow] += fabs(value*lower);
8133 }
8134 } else {
8135 for (CoinBigIndex j=start;j<end;j++) {
8136 int iRow = row[j];
8137 int n=first[iRow];
8138 if (n==0&&element[j])
8139 first[iRow]=-iColumn-1;
8140 else if (n<0)
8141 first[iRow]=2;
8142 }
8143 }
8144 }
8145 double tolerance = 1.0e-6;
8146 const char * integerInformation = modelPtr_->integerType_;
8147 for (int iRow=0;iRow<numberRows;iRow++) {
8148 int iColumn = first[iRow];
8149 if (iColumn<0) {
8150 iColumn = -iColumn-1;
8151 if ((integerInformation&&integerInformation[iColumn])||lightweight==2) {
8152 double lowerRow = rowLower[iRow];
8153 if (lowerRow>-1.0e20)
8154 lowerRow -= down[iRow];
8155 double upperRow = rowUpper[iRow];
8156 if (upperRow<1.0e20)
8157 upperRow -= down[iRow];
8158 double lower = columnLower[iColumn];
8159 double upper = columnUpper[iColumn];
8160 double value=0.0;
8161 for (CoinBigIndex j = columnStart[iColumn];
8162 j<columnStart[iColumn]+columnLength[iColumn];j++) {
8163 if (iRow==row[j]) {
8164 value=element[j];
8165 break;
8166 }
8167 }
8168 assert (value);
8169 // convert rowLower and Upper to implied bounds on column
8170 double newLower=-COIN_DBL_MAX;
8171 double newUpper=COIN_DBL_MAX;
8172 if (value>0.0) {
8173 if (lowerRow>-1.0e20)
8174 newLower = lowerRow/value;
8175 if (upperRow<1.0e20)
8176 newUpper = upperRow/value;
8177 } else {
8178 if (upperRow<1.0e20)
8179 newLower = upperRow/value;
8180 if (lowerRow>-1.0e20)
8181 newUpper = lowerRow/value;
8182 }
8183 double tolerance2 = 1.0e-6+1.0e-8*sum[iRow];
8184 if (integerInformation&&integerInformation[iColumn]) {
8185 if (newLower-floor(newLower)<tolerance2)
8186 newLower=floor(newLower);
8187 else
8188 newLower=ceil(newLower);
8189 if (ceil(newUpper)-newUpper<tolerance2)
8190 newUpper=ceil(newUpper);
8191 else
8192 newUpper=floor(newUpper);
8193 }
8194 if (newLower>lower+10.0*tolerance2||
8195 newUpper<upper-10.0*tolerance2) {
8196 numberTightened++;
8197 newLower = CoinMax(lower,newLower);
8198 newUpper = CoinMin(upper,newUpper);
8199 if (newLower>newUpper+tolerance) {
8200 //printf("XXYY inf on bound\n");
8201 numberTightened=-1;
8202 break;
8203 }
8204 setColLower(iColumn,newLower);
8205 setColUpper(iColumn,CoinMax(newLower,newUpper));
8206 }
8207 }
8208 }
8209 }
8210 delete [] first;
8211 delete [] down;
8212 delete [] sum;
8213 return numberTightened;
8214 }
8215 double * up = new double [numberRows];
8216 double * sum = new double [numberRows];
8217 int * type = new int [numberRows];
8218 CoinZeroN(down,numberRows);
8219 CoinZeroN(up,numberRows);
8220 CoinZeroN(sum,numberRows);
8221 CoinZeroN(type,numberRows);
8222 double infinity = getInfinity();
8223 for (iColumn=0;iColumn<numberColumns;iColumn++) {
8224 CoinBigIndex start = columnStart[iColumn];
8225 CoinBigIndex end = start + columnLength[iColumn];
8226 double lower = columnLower[iColumn];
8227 double upper = columnUpper[iColumn];
8228 if (lower==upper) {
8229 for (CoinBigIndex j=start;j<end;j++) {
8230 int iRow = row[j];
8231 double value = element[j];
8232 sum[iRow]+=2.0*fabs(value*lower);
8233 if ((type[iRow]&1)==0)
8234 down[iRow] += value*lower;
8235 if ((type[iRow]&2)==0)
8236 up[iRow] += value*lower;
8237 }
8238 } else {
8239 for (CoinBigIndex j=start;j<end;j++) {
8240 int iRow = row[j];
8241 double value = element[j];
8242 if (value>0.0) {
8243 if ((type[iRow]&1)==0) {
8244 if (lower!=-infinity) {
8245 down[iRow] += value*lower;
8246 sum[iRow]+=fabs(value*lower);
8247 } else {
8248 type[iRow] |= 1;
8249 }
8250 }
8251 if ((type[iRow]&2)==0) {
8252 if (upper!=infinity) {
8253 up[iRow] += value*upper;
8254 sum[iRow]+=fabs(value*upper);
8255 } else {
8256 type[iRow] |= 2;
8257 }
8258 }
8259 } else {
8260 if ((type[iRow]&1)==0) {
8261 if (upper!=infinity) {
8262 down[iRow] += value*upper;
8263 sum[iRow]+=fabs(value*upper);
8264 } else {
8265 type[iRow] |= 1;
8266 }
8267 }
8268 if ((type[iRow]&2)==0) {
8269 if (lower!=-infinity) {
8270 up[iRow] += value*lower;
8271 sum[iRow]+=fabs(value*lower);
8272 } else {
8273 type[iRow] |= 2;
8274 }
8275 }
8276 }
8277 }
8278 }
8279 }
8280 int nTightened=0;
8281 double tolerance = 1.0e-6;
8282 for (iRow=0;iRow<numberRows;iRow++) {
8283 if ((type[iRow]&1)!=0)
8284 down[iRow]=-infinity;
8285 if (down[iRow]>rowUpper[iRow]) {
8286 if (down[iRow]>rowUpper[iRow]+tolerance+1.0e-8*sum[iRow]) {
8287 // infeasible
8288#ifdef COIN_DEVELOP
8289 printf("infeasible on row %d\n",iRow);
8290#endif
8291 nTightened=-1;
8292 break;
8293 } else {
8294 down[iRow]=rowUpper[iRow];
8295 }
8296 }
8297 if ((type[iRow]&2)!=0)
8298 up[iRow]=infinity;
8299 if (up[iRow]<rowLower[iRow]) {
8300 if (up[iRow]<rowLower[iRow]-tolerance-1.0e-8*sum[iRow]) {
8301 // infeasible
8302#ifdef COIN_DEVELOP
8303 printf("infeasible on row %d\n",iRow);
8304#endif
8305 nTightened=-1;
8306 break;
8307 } else {
8308 up[iRow]=rowLower[iRow];
8309 }
8310 }
8311 }
8312 if (nTightened)
8313 numberColumns=0; // so will skip
8314 for (iColumn=0;iColumn<numberColumns;iColumn++) {
8315 double lower = columnLower[iColumn];
8316 double upper = columnUpper[iColumn];
8317 double gap = upper-lower;
8318 if (!gap)
8319 continue;
8320 int canGo=0;
8321 CoinBigIndex start = columnStart[iColumn];
8322 CoinBigIndex end = start + columnLength[iColumn];
8323 if (lower<-1.0e8&&upper>1.0e8)
8324 continue; // Could do severe damage to accuracy
8325 if (integerInformation_[iColumn]) {
8326 if (lower!=floor(lower+0.5)) {
8327#ifdef COIN_DEVELOP
8328 printf("increasing lower bound on %d from %g to %g\n",iColumn,
8329 lower,ceil(lower));
8330#endif
8331 lower=ceil(lower);
8332 gap=upper-lower;
8333 setColLower(iColumn,lower);
8334 }
8335 if (upper!=floor(upper+0.5)) {
8336#ifdef COIN_DEVELOP
8337 printf("decreasing upper bound on %d from %g to %g\n",iColumn,
8338 upper,floor(upper));
8339#endif
8340 upper=floor(upper);
8341 gap=upper-lower;
8342 setColUpper(iColumn,upper);
8343 }
8344 double newLower=lower;
8345 double newUpper=upper;
8346 for (CoinBigIndex j=start;j<end;j++) {
8347 int iRow = row[j];
8348 double value = element[j];
8349 if (value>0.0) {
8350 if ((type[iRow]&1)==0) {
8351 // has to be at most something
8352 if (down[iRow] + value*gap > rowUpper[iRow]+tolerance) {
8353 double newGap = (rowUpper[iRow]-down[iRow])/value;
8354 // adjust
8355 newGap += 1.0e-10*sum[iRow];
8356 newGap = floor(newGap);
8357 if (lower+newGap<newUpper)
8358 newUpper=lower+newGap;
8359 }
8360 }
8361 if (down[iRow]<rowLower[iRow])
8362 canGo |=1; // can't go down without affecting result
8363 if ((type[iRow]&2)==0) {
8364 // has to be at least something
8365 if (up[iRow] - value*gap < rowLower[iRow]-tolerance) {
8366 double newGap = (up[iRow]-rowLower[iRow])/value;
8367 // adjust
8368 newGap += 1.0e-10*sum[iRow];
8369 newGap = floor(newGap);
8370 if (upper-newGap>newLower)
8371 newLower=upper-newGap;
8372 }
8373 }
8374 if (up[iRow]>rowUpper[iRow])
8375 canGo |=2; // can't go up without affecting result
8376 } else {
8377 if ((type[iRow]&1)==0) {
8378 // has to be at least something
8379 if (down[iRow] - value*gap > rowUpper[iRow]+tolerance) {
8380 double newGap = -(rowUpper[iRow]-down[iRow])/value;
8381 // adjust
8382 newGap += 1.0e-10*sum[iRow];
8383 newGap = floor(newGap);
8384 if (upper-newGap>newLower)
8385 newLower=upper-newGap;
8386 }
8387 }
8388 if (up[iRow]>rowUpper[iRow])
8389 canGo |=1; // can't go down without affecting result
8390 if ((type[iRow]&2)==0) {
8391 // has to be at most something
8392 if (up[iRow] + value*gap < rowLower[iRow]-tolerance) {
8393 double newGap = -(up[iRow]-rowLower[iRow])/value;
8394 // adjust
8395 newGap += 1.0e-10*sum[iRow];
8396 newGap = floor(newGap);
8397 if (lower+newGap<newUpper)
8398 newUpper=lower+newGap;
8399 }
8400 }
8401 if (down[iRow]<rowLower[iRow])
8402 canGo |=2; // can't go up without affecting result
8403 }
8404 }
8405 if (newUpper<upper||newLower>lower) {
8406 nTightened++;
8407 if (newLower>newUpper) {
8408 // infeasible
8409#if COIN_DEVELOP>1
8410 printf("infeasible on column %d\n",iColumn);
8411#endif
8412 nTightened=-1;
8413 break;
8414 } else {
8415 setColLower(iColumn,newLower);
8416 setColUpper(iColumn,newUpper);
8417 }
8418 for (CoinBigIndex j=start;j<end;j++) {
8419 int iRow = row[j];
8420 double value = element[j];
8421 if (value>0.0) {
8422 if ((type[iRow]&1)==0) {
8423 down[iRow] += value*(newLower-lower);
8424 }
8425 if ((type[iRow]&2)==0) {
8426 up[iRow] += value*(newUpper-upper);
8427 }
8428 } else {
8429 if ((type[iRow]&1)==0) {
8430 down[iRow] += value*(newUpper-upper);
8431 }
8432 if ((type[iRow]&2)==0) {
8433 up[iRow] += value*(newLower-lower);
8434 }
8435 }
8436 }
8437 } else {
8438 if (canGo!=3) {
8439 double objValue = direction*objective[iColumn];
8440 if (objValue>=0.0&&(canGo&1)==0) {
8441#if COIN_DEVELOP>2
8442 printf("dual fix down on column %d\n",iColumn);
8443#endif
8444 // Only if won't cause numerical problems
8445 if (lower>-1.0e10) {
8446 nTightened++;
8447 setColUpper(iColumn,lower);
8448 }
8449 } else if (objValue<=0.0&&(canGo&2)==0) {
8450#if COIN_DEVELOP>2
8451 printf("dual fix up on column %d\n",iColumn);
8452#endif
8453 // Only if won't cause numerical problems
8454 if (upper<1.0e10) {
8455 nTightened++;
8456 setColLower(iColumn,upper);
8457 }
8458 }
8459 }
8460 }
8461 } else {
8462 // just do dual tests
8463 for (CoinBigIndex j=start;j<end;j++) {
8464 int iRow = row[j];
8465 double value = element[j];
8466 if (value>0.0) {
8467 if (down[iRow]<rowLower[iRow])
8468 canGo |=1; // can't go down without affecting result
8469 if (up[iRow]>rowUpper[iRow])
8470 canGo |=2; // can't go up without affecting result
8471 } else {
8472 if (up[iRow]>rowUpper[iRow])
8473 canGo |=1; // can't go down without affecting result
8474 if (down[iRow]<rowLower[iRow])
8475 canGo |=2; // can't go up without affecting result
8476 }
8477 }
8478 if (canGo!=3) {
8479 double objValue = direction*objective[iColumn];
8480 if (objValue>=0.0&&(canGo&1)==0) {
8481#if COIN_DEVELOP>2
8482 printf("dual fix down on continuous column %d lower %g\n",
8483 iColumn,lower);
8484#endif
8485 // Only if won't cause numerical problems
8486 if (lower>-1.0e10) {
8487 nTightened++;
8488 setColUpper(iColumn,lower);
8489 }
8490 } else if (objValue<=0.0&&(canGo&2)==0) {
8491#if COIN_DEVELOP>2
8492 printf("dual fix up on continuous column %d upper %g\n",
8493 iColumn,upper);
8494#endif
8495 // Only if won't cause numerical problems
8496 if (upper<1.0e10) {
8497 nTightened++;
8498 setColLower(iColumn,upper);
8499 }
8500 }
8501 }
8502 }
8503 }
8504 if (lightweight<0) {
8505 // get max down and up again
8506 CoinZeroN(down,numberRows);
8507 CoinZeroN(up,numberRows);
8508 CoinZeroN(type,numberRows);
8509 int * seqDown = new int [2*numberRows];
8510 int * seqUp=seqDown+numberRows;
8511 for (int i=0;i<numberRows;i++) {
8512 seqDown[i]=-1;
8513 seqUp[i]=-1;
8514 }
8515 for (iColumn=0;iColumn<numberColumns;iColumn++) {
8516 CoinBigIndex start = columnStart[iColumn];
8517 CoinBigIndex end = start + columnLength[iColumn];
8518 double lower = columnLower[iColumn];
8519 double upper = columnUpper[iColumn];
8520 if (lower==upper) {
8521 for (CoinBigIndex j=start;j<end;j++) {
8522 int iRow = row[j];
8523 double value = element[j];
8524 if ((type[iRow]&1)==0)
8525 down[iRow] += value*lower;
8526 if ((type[iRow]&2)==0)
8527 up[iRow] += value*lower;
8528 }
8529 } else {
8530 for (CoinBigIndex j=start;j<end;j++) {
8531 int iRow = row[j];
8532 double value = element[j];
8533 if (value>0.0) {
8534 if ((type[iRow]&1)==0) {
8535 if (lower>-1.0e8) {
8536 down[iRow] += value*lower;
8537 } else if (seqDown[iRow]<0) {
8538 seqDown[iRow]=iColumn;
8539 } else {
8540 type[iRow] |= 1;
8541 }
8542 }
8543 if ((type[iRow]&2)==0) {
8544 if (upper<1.0e8) {
8545 up[iRow] += value*upper;
8546 sum[iRow]+=fabs(value*upper);
8547 } else if (seqUp[iRow]<0) {
8548 seqUp[iRow]=iColumn;
8549 } else {
8550 type[iRow] |= 2;
8551 }
8552 }
8553 } else {
8554 if ((type[iRow]&1)==0) {
8555 if (upper<1.0e8) {
8556 down[iRow] += value*upper;
8557 sum[iRow]+=fabs(value*upper);
8558 } else if (seqDown[iRow]<0) {
8559 seqDown[iRow]=iColumn;
8560 } else {
8561 type[iRow] |= 1;
8562 }
8563 }
8564 if ((type[iRow]&2)==0) {
8565 if (lower>-1.0e8) {
8566 up[iRow] += value*lower;
8567 sum[iRow]+=fabs(value*lower);
8568 } else if (seqUp[iRow]<0) {
8569 seqUp[iRow]=iColumn;
8570 } else {
8571 type[iRow] |= 2;
8572 }
8573 }
8574 }
8575 }
8576 }
8577 }
8578 for (iColumn=0;iColumn<numberColumns;iColumn++) {
8579 double lower = columnLower[iColumn];
8580 double upper = columnUpper[iColumn];
8581 double gap = upper-lower;
8582 if (!gap)
8583 continue;
8584 CoinBigIndex start = columnStart[iColumn];
8585 CoinBigIndex end = start + columnLength[iColumn];
8586 if (lower<-1.0e8&&upper>1.0e8)
8587 continue; // Could do severe damage to accuracy
8588 double newLower=upper;
8589 double newUpper=lower;
8590 bool badUpper=false;
8591 bool badLower=false;
8592 double objValue = objective[iColumn]*direction;
8593 for (CoinBigIndex j=start;j<end;j++) {
8594 int iRow = row[j];
8595 double value = element[j];
8596 if (value>0.0) {
8597 if (rowLower[iRow]>-COIN_DBL_MAX) {
8598 if (!badUpper&&(type[iRow]&1)==0&&
8599 (seqDown[iRow]<0||seqDown[iRow]==iColumn)) {
8600 double s=down[iRow];
8601 if (seqDown[iRow]!=iColumn)
8602 s -= lower*value;
8603 if (s+newUpper*value<rowLower[iRow]) {
8604 newUpper = CoinMax(newUpper,(rowLower[iRow]-s)/value);
8605 }
8606 } else {
8607 badUpper=true;
8608 }
8609 }
8610 if (rowUpper[iRow]<COIN_DBL_MAX) {
8611 if (!badLower&&(type[iRow]&2)==0&&
8612 (seqUp[iRow]<0||seqUp[iRow]==iColumn)) {
8613 double s=up[iRow];
8614 if (seqUp[iRow]!=iColumn)
8615 s -= upper*value;
8616 if (s+newLower*value>rowUpper[iRow]) {
8617 newLower = CoinMin(newLower,(rowUpper[iRow]-s)/value);
8618 }
8619 } else {
8620 badLower=true;
8621 }
8622 }
8623 } else {
8624 if (rowUpper[iRow]<COIN_DBL_MAX) {
8625 if (!badUpper&&(type[iRow]&2)==0&&
8626 (seqUp[iRow]<0||seqUp[iRow]==iColumn)) {
8627 double s=up[iRow];
8628 if (seqUp[iRow]!=iColumn)
8629 s -= lower*value;
8630 if (s+newUpper*value>rowUpper[iRow]) {
8631 newUpper = CoinMax(newUpper,(rowUpper[iRow]-s)/value);
8632 }
8633 } else {
8634 badUpper=true;
8635 }
8636 }
8637 if (rowLower[iRow]>-COIN_DBL_MAX) {
8638 if (!badLower&&(type[iRow]&1)==0&&
8639 (seqDown[iRow]<0||seqDown[iRow]==iColumn)) {
8640 double s=down[iRow];
8641 if (seqDown[iRow]!=iColumn)
8642 s -= lower*value;
8643 if (s+newLower*value<rowLower[iRow]) {
8644 newLower = CoinMin(newLower,(rowLower[iRow]-s)/value);
8645 }
8646 } else {
8647 badLower=true;
8648 }
8649 }
8650 }
8651 }
8652 if (badLower||objValue>0.0)
8653 newLower=lower;
8654 if (badUpper||objValue<0.0)
8655 newUpper=upper;
8656 if (newUpper<upper||newLower>lower) {
8657 nTightened++;
8658 if (newLower>newUpper) {
8659 // infeasible
8660#if COIN_DEVELOP>0
8661 printf("infeasible on column %d\n",iColumn);
8662#endif
8663 nTightened=-1;
8664 break;
8665 } else {
8666 newLower=CoinMax(newLower,lower);
8667 newUpper=CoinMin(newUpper,upper);
8668 if (integerInformation_[iColumn]) {
8669 newLower=ceil(newLower-1.0e-5);
8670 newUpper=floor(newUpper+1.0e-5);
8671 }
8672 setColLower(iColumn,newLower);
8673 setColUpper(iColumn,newUpper);
8674 }
8675 }
8676 }
8677 delete [] seqDown;
8678 }
8679 delete [] type;
8680 delete [] down;
8681 delete [] up;
8682 delete [] sum;
8683 return nTightened;
8684}
8685// Return number of entries in L part of current factorization
8686CoinBigIndex
8687OsiClpSolverInterface::getSizeL() const
8688{
8689 return modelPtr_->factorization_->numberElementsL();
8690}
8691// Return number of entries in U part of current factorization
8692CoinBigIndex
8693OsiClpSolverInterface::getSizeU() const
8694{
8695 return modelPtr_->factorization_->numberElementsU();
8696}
8697/* Add a named row (constraint) to the problem.
8698 */
8699void
8700OsiClpSolverInterface::addRow(const CoinPackedVectorBase& vec,
8701 const char rowsen, const double rowrhs,
8702 const double rowrng, std::string name)
8703{
8704 int ndx = getNumRows() ;
8705 addRow(vec,rowsen,rowrhs,rowrng) ;
8706 setRowName(ndx,name) ;
8707}
8708/* Add a named column (primal variable) to the problem.
8709 */
8710void
8711OsiClpSolverInterface::addCol(int numberElements,
8712 const int* rows, const double* elements,
8713 const double collb, const double colub,
8714 const double obj, std::string name)
8715{
8716 int ndx = getNumCols() ;
8717 addCol(numberElements,rows,elements,collb,colub,obj) ;
8718 setColName(ndx,name) ;
8719}
8720/* Start faster dual - returns negative if problems 1 if infeasible,
8721 Options to pass to solver
8722 1 - create external reduced costs for columns
8723 2 - create external reduced costs for rows
8724 4 - create external row activity (columns always done)
8725 Above only done if feasible
8726 When set resolve does less work
8727*/
8728int
8729OsiClpSolverInterface::startFastDual(int options)
8730{
8731 stuff_.zap(3);
8732 stuff_.solverOptions_=options;
8733 return modelPtr_->startFastDual2(&stuff_);
8734}
8735// Sets integer tolerance and increment
8736void
8737OsiClpSolverInterface::setStuff(double tolerance,double increment)
8738{
8739 stuff_.integerTolerance_ = tolerance;
8740 stuff_.integerIncrement_ = increment;
8741}
8742// Stops faster dual
8743void
8744OsiClpSolverInterface::stopFastDual()
8745{
8746 modelPtr_->stopFastDual2(&stuff_);
8747}
8748// Compute largest amount any at continuous away from bound
8749void
8750OsiClpSolverInterface::computeLargestAway()
8751{
8752 // get largest scaled away from bound
8753 ClpSimplex temp=*modelPtr_;
8754 // save logLevel (in case derived message handler)
8755 int saveLogLevel=temp.logLevel();
8756 temp.setLogLevel(0);
8757 temp.dual();
8758 if (temp.status()==1)
8759 temp.primal(); // may mean we have optimal so continuous cutoff
8760 temp.dual(0,7);
8761 temp.setLogLevel(saveLogLevel);
8762 double largestScaled=1.0e-12;
8763 double largest=1.0e-12;
8764 int numberRows = temp.numberRows();
8765 const double * rowPrimal = temp.primalRowSolution();
8766 const double * rowLower = temp.rowLower();
8767 const double * rowUpper = temp.rowUpper();
8768 const double * rowScale = temp.rowScale();
8769 int iRow;
8770 for (iRow=0;iRow<numberRows;iRow++) {
8771 double value = rowPrimal[iRow];
8772 double above = value-rowLower[iRow];
8773 double below = rowUpper[iRow]-value;
8774 if (above<1.0e12) {
8775 largest = CoinMax(largest,above);
8776 }
8777 if (below<1.0e12) {
8778 largest = CoinMax(largest,below);
8779 }
8780 if (rowScale) {
8781 double multiplier = rowScale[iRow];
8782 above *= multiplier;
8783 below *= multiplier;
8784 }
8785 if (above<1.0e12) {
8786 largestScaled = CoinMax(largestScaled,above);
8787 }
8788 if (below<1.0e12) {
8789 largestScaled = CoinMax(largestScaled,below);
8790 }
8791 }
8792
8793 int numberColumns = temp.numberColumns();
8794 const double * columnPrimal = temp.primalColumnSolution();
8795 const double * columnLower = temp.columnLower();
8796 const double * columnUpper = temp.columnUpper();
8797 const double * columnScale = temp.columnScale();
8798 int iColumn;
8799 for (iColumn=0;iColumn<numberColumns;iColumn++) {
8800 double value = columnPrimal[iColumn];
8801 double above = value-columnLower[iColumn];
8802 double below = columnUpper[iColumn]-value;
8803 if (above<1.0e12) {
8804 largest = CoinMax(largest,above);
8805 }
8806 if (below<1.0e12) {
8807 largest = CoinMax(largest,below);
8808 }
8809 if (columnScale) {
8810 double multiplier = 1.0/columnScale[iColumn];
8811 above *= multiplier;
8812 below *= multiplier;
8813 }
8814 if (above<1.0e12) {
8815 largestScaled = CoinMax(largestScaled,above);
8816 }
8817 if (below<1.0e12) {
8818 largestScaled = CoinMax(largestScaled,below);
8819 }
8820 }
8821#ifdef COIN_DEVELOP
8822 std::cout<<"Largest (scaled) away from bound "<<largestScaled
8823 <<" unscaled "<<largest<<std::endl;
8824#endif
8825 largestAway_ = largestScaled;
8826 // go for safety
8827 if (numberRows>4000)
8828 modelPtr_->setSpecialOptions(modelPtr_->specialOptions()&~(2048+4096));
8829}
8830// Pass in Message handler (not deleted at end)
8831void
8832OsiClpSolverInterface::passInMessageHandler(CoinMessageHandler * handler)
8833{
8834 if (defaultHandler_) {
8835 delete handler_;
8836 handler_ = NULL;
8837 }
8838 defaultHandler_=false;
8839 handler_=handler;
8840 if (modelPtr_)
8841 modelPtr_->passInMessageHandler(handler);
8842}
8843// Set log level (will also set underlying solver's log level)
8844void
8845OsiClpSolverInterface::setLogLevel(int value)
8846{
8847 handler_->setLogLevel(value);
8848 if (modelPtr_)
8849 modelPtr_->setLogLevel(value);
8850}
8851// Set fake objective (and take ownership)
8852void
8853OsiClpSolverInterface::setFakeObjective(ClpLinearObjective * fakeObjective)
8854{
8855 delete fakeObjective_;
8856 fakeObjective_ = fakeObjective;
8857}
8858// Set fake objective
8859void
8860OsiClpSolverInterface::setFakeObjective(double * fakeObjective)
8861{
8862 delete fakeObjective_;
8863 if (fakeObjective)
8864 fakeObjective_ = new ClpLinearObjective(fakeObjective,
8865 modelPtr_->numberColumns_);
8866 else
8867 fakeObjective_ = NULL;
8868}
8869/* Solve when primal column and dual row solutions are near-optimal
8870 options - 0 no presolve (use primal and dual)
8871 1 presolve (just use primal)
8872 2 no presolve (just use primal)
8873 basis - 0 use all slack basis
8874 1 try and put some in basis
8875*/
8876void
8877OsiClpSolverInterface::crossover(int options,int basis)
8878{
8879 int numberRows = modelPtr_->getNumRows();
8880 int numberColumns = modelPtr_->getNumCols();
8881 // Get row activities and column reduced costs
8882 const double * objective = modelPtr_->objective();
8883 double direction = modelPtr_->optimizationDirection();
8884 double * dual = modelPtr_->dualRowSolution();
8885 double * dj = modelPtr_->dualColumnSolution();
8886 CoinMemcpyN(objective,numberColumns,dj);
8887 if (direction==-1.0) {
8888 for (int i=0;i<numberColumns;i++)
8889 dj[i] = - dj[i];
8890 }
8891 modelPtr_->clpMatrix()->transposeTimes(-1.0,dual,dj);
8892 double * rowActivity = modelPtr_->primalRowSolution();
8893 double * columnActivity = modelPtr_->primalColumnSolution();
8894 CoinZeroN(rowActivity,numberRows);
8895 modelPtr_->clpMatrix()->times(1.0,columnActivity,rowActivity);
8896 modelPtr_->checkSolution();
8897 printf("%d primal infeasibilities summing to %g\n",
8898 modelPtr_->numberPrimalInfeasibilities(),
8899 modelPtr_->sumPrimalInfeasibilities());
8900 printf("%d dual infeasibilities summing to %g\n",
8901 modelPtr_->numberDualInfeasibilities(),
8902 modelPtr_->sumDualInfeasibilities());
8903 // get which variables are fixed
8904 double * saveLower=NULL;
8905 double * saveUpper=NULL;
8906 ClpPresolve pinfo2;
8907 bool extraPresolve=false;
8908 bool useBoth= (options==0);
8909 // create all slack basis
8910 modelPtr_->createStatus();
8911 // Point to model - so can use in presolved model
8912 ClpSimplex * model2 = modelPtr_;
8913 double tolerance = modelPtr_->primalTolerance()*10.0;
8914 if (options==1) {
8915 int numberTotal = numberRows+numberColumns;
8916 saveLower = new double [numberTotal];
8917 saveUpper = new double [numberTotal];
8918 CoinMemcpyN(modelPtr_->columnLower(),numberColumns,saveLower);
8919 CoinMemcpyN(modelPtr_->rowLower(),numberRows,saveLower+numberColumns);
8920 CoinMemcpyN(modelPtr_->columnUpper(),numberColumns,saveUpper);
8921 CoinMemcpyN(modelPtr_->rowUpper(),numberRows,saveUpper+numberColumns);
8922 double * lower = modelPtr_->columnLower();
8923 double * upper = modelPtr_->columnUpper();
8924 double * solution = modelPtr_->primalColumnSolution();
8925 int nFix=0;
8926 for (int i=0;i<numberColumns;i++) {
8927 if (lower[i]<upper[i]&&(lower[i]>-1.0e10||upper[i]<1.0e10)) {
8928 double value = solution[i];
8929 if (value<lower[i]+tolerance&&value-lower[i]<upper[i]-value) {
8930 solution[i]=lower[i];
8931 upper[i]=lower[i];
8932 nFix++;
8933 } else if (value>upper[i]-tolerance&&value-lower[i]>upper[i]-value) {
8934 solution[i]=upper[i];
8935 lower[i]=upper[i];
8936 nFix++;
8937 }
8938 }
8939 }
8940#ifdef CLP_INVESTIGATE
8941 printf("%d columns fixed\n",nFix);
8942#endif
8943#if 0
8944 int nr=modelPtr_->numberRows();
8945 lower = modelPtr_->rowLower();
8946 upper = modelPtr_->rowUpper();
8947 solution = modelPtr_->primalRowSolution();
8948 nFix=0;
8949 for (int i=0;i<nr;i++) {
8950 if (lower[i]<upper[i]) {
8951 double value = solution[i];
8952 if (value<lower[i]+tolerance&&value-lower[i]<upper[i]-value) {
8953 solution[i]=lower[i];
8954 upper[i]=lower[i];
8955 nFix++;
8956 } else if (value>upper[i]-tolerance&&value-lower[i]>upper[i]-value) {
8957 solution[i]=upper[i];
8958 lower[i]=upper[i];
8959 nFix++;
8960 }
8961 }
8962 }
8963#ifdef CLP_INVESTIGATE
8964 printf("%d row slacks fixed\n",nFix);
8965#endif
8966#endif
8967 extraPresolve=true;
8968 // do presolve
8969 model2 = pinfo2.presolvedModel(*modelPtr_,modelPtr_->presolveTolerance(),
8970 false,5,true);
8971 if (!model2) {
8972 model2=modelPtr_;
8973 CoinMemcpyN(saveLower,numberColumns,model2->columnLower());
8974 CoinMemcpyN(saveLower+numberColumns,numberRows,model2->rowLower());
8975 delete [] saveLower;
8976 CoinMemcpyN(saveUpper,numberColumns,model2->columnUpper());
8977 CoinMemcpyN(saveUpper+numberColumns,numberRows,model2->rowUpper());
8978 delete [] saveUpper;
8979 saveLower=NULL;
8980 saveUpper=NULL;
8981 extraPresolve=false;
8982 }
8983 }
8984 if (model2->factorizationFrequency()==200) {
8985 // User did not touch preset
8986 model2->defaultFactorizationFrequency();
8987 }
8988 if (basis) {
8989 // throw some into basis
8990 int numberRows = model2->numberRows();
8991 int numberColumns = model2->numberColumns();
8992 double * dsort = new double[numberColumns];
8993 int * sort = new int[numberColumns];
8994 int n=0;
8995 const double * columnLower = model2->columnLower();
8996 const double * columnUpper = model2->columnUpper();
8997 double * primalSolution = model2->primalColumnSolution();
8998 const double * dualSolution = model2->dualColumnSolution();
8999 int i;
9000 for ( i=0;i<numberRows;i++)
9001 model2->setRowStatus(i,ClpSimplex::superBasic);
9002 for ( i=0;i<numberColumns;i++) {
9003 double distance = CoinMin(columnUpper[i]-primalSolution[i],
9004 primalSolution[i]-columnLower[i]);
9005 if (distance>tolerance) {
9006 if (fabs(dualSolution[i])<1.0e-5)
9007 distance *= 100.0;
9008 dsort[n]=-distance;
9009 sort[n++]=i;
9010 model2->setStatus(i,ClpSimplex::superBasic);
9011 } else if (distance>tolerance) {
9012 model2->setStatus(i,ClpSimplex::superBasic);
9013 } else if (primalSolution[i]<=columnLower[i]+tolerance) {
9014 model2->setStatus(i,ClpSimplex::atLowerBound);
9015 primalSolution[i]=columnLower[i];
9016 } else {
9017 model2->setStatus(i,ClpSimplex::atUpperBound);
9018 primalSolution[i]=columnUpper[i];
9019 }
9020 }
9021 CoinSort_2(dsort,dsort+n,sort);
9022 n = CoinMin(numberRows,n);
9023 for ( i=0;i<n;i++) {
9024 int iColumn = sort[i];
9025 model2->setStatus(iColumn,ClpSimplex::basic);
9026 }
9027 delete [] sort;
9028 delete [] dsort;
9029 }
9030 // Start crossover
9031 if (useBoth) {
9032 int numberRows = model2->numberRows();
9033 int numberColumns = model2->numberColumns();
9034 double * rowPrimal = new double [numberRows];
9035 double * columnPrimal = new double [numberColumns];
9036 double * rowDual = new double [numberRows];
9037 double * columnDual = new double [numberColumns];
9038 // move solutions
9039 CoinMemcpyN(model2->primalRowSolution(),
9040 numberRows,rowPrimal);
9041 CoinMemcpyN(model2->dualRowSolution(),
9042 numberRows,rowDual);
9043 CoinMemcpyN(model2->primalColumnSolution(),
9044 numberColumns,columnPrimal);
9045 CoinMemcpyN(model2->dualColumnSolution(),
9046 numberColumns,columnDual);
9047 // primal values pass
9048 double saveScale = model2->objectiveScale();
9049 model2->setObjectiveScale(1.0e-3);
9050 model2->primal(2);
9051 model2->setObjectiveScale(saveScale);
9052 // save primal solution and copy back dual
9053 CoinMemcpyN(model2->primalRowSolution(),
9054 numberRows,rowPrimal);
9055 CoinMemcpyN(rowDual,
9056 numberRows,model2->dualRowSolution());
9057 CoinMemcpyN(model2->primalColumnSolution(),
9058 numberColumns,columnPrimal);
9059 CoinMemcpyN(columnDual,
9060 numberColumns,model2->dualColumnSolution());
9061 // clean up reduced costs and flag variables
9062 double * dj = model2->dualColumnSolution();
9063 double * cost = model2->objective();
9064 double * saveCost = new double[numberColumns];
9065 CoinMemcpyN(cost,numberColumns,saveCost);
9066 double * saveLower = new double[numberColumns];
9067 double * lower = model2->columnLower();
9068 CoinMemcpyN(lower,numberColumns,saveLower);
9069 double * saveUpper = new double[numberColumns];
9070 double * upper = model2->columnUpper();
9071 CoinMemcpyN(upper,numberColumns,saveUpper);
9072 int i;
9073 for ( i=0;i<numberColumns;i++) {
9074 if (model2->getStatus(i)==ClpSimplex::basic) {
9075 dj[i]=0.0;
9076 } else if (model2->getStatus(i)==ClpSimplex::atLowerBound) {
9077 if (direction*dj[i]<tolerance) {
9078 if (direction*dj[i]<0.0) {
9079 //if (dj[i]<-1.0e-3)
9080 //printf("bad dj at lb %d %g\n",i,dj[i]);
9081 cost[i] -= dj[i];
9082 dj[i]=0.0;
9083 }
9084 } else {
9085 upper[i]=lower[i];
9086 }
9087 } else if (model2->getStatus(i)==ClpSimplex::atUpperBound) {
9088 if (direction*dj[i]>tolerance) {
9089 if (direction*dj[i]>0.0) {
9090 //if (dj[i]>1.0e-3)
9091 //printf("bad dj at ub %d %g\n",i,dj[i]);
9092 cost[i] -= dj[i];
9093 dj[i]=0.0;
9094 }
9095 } else {
9096 lower[i]=upper[i];
9097 }
9098 }
9099 }
9100 // just dual values pass
9101 model2->dual(2);
9102 CoinMemcpyN(saveCost,numberColumns,cost);
9103 delete [] saveCost;
9104 CoinMemcpyN(saveLower,numberColumns,lower);
9105 delete [] saveLower;
9106 CoinMemcpyN(saveUpper,numberColumns,upper);
9107 delete [] saveUpper;
9108 // move solutions
9109 CoinMemcpyN(rowPrimal,
9110 numberRows,model2->primalRowSolution());
9111 CoinMemcpyN(columnPrimal,
9112 numberColumns,model2->primalColumnSolution());
9113 // and finish
9114 delete [] rowPrimal;
9115 delete [] columnPrimal;
9116 delete [] rowDual;
9117 delete [] columnDual;
9118 model2->setObjectiveScale(1.0e-3);
9119 model2->primal(2);
9120 model2->setObjectiveScale(saveScale);
9121 model2->primal(1);
9122 } else {
9123 // primal values pass
9124 double saveScale = model2->objectiveScale();
9125 model2->setObjectiveScale(1.0e-3);
9126 model2->primal(2);
9127 model2->setObjectiveScale(saveScale);
9128 model2->primal(1);
9129 }
9130 if (extraPresolve) {
9131 pinfo2.postsolve(true);
9132 delete model2;
9133 modelPtr_->primal(1);
9134 CoinMemcpyN(saveLower,numberColumns,modelPtr_->columnLower());
9135 CoinMemcpyN(saveLower+numberColumns,numberRows,modelPtr_->rowLower());
9136 CoinMemcpyN(saveUpper,numberColumns,modelPtr_->columnUpper());
9137 CoinMemcpyN(saveUpper+numberColumns,numberRows,modelPtr_->rowUpper());
9138 delete [] saveLower;
9139 delete [] saveUpper;
9140 modelPtr_->primal(1);
9141 }
9142 // Save basis in Osi object
9143 setWarmStart(NULL);
9144}
9145
9146//#############################################################################
9147// Constructors / Destructor / Assignment
9148//#############################################################################
9149
9150//-------------------------------------------------------------------
9151// Default Constructor
9152//-------------------------------------------------------------------
9153OsiClpDisasterHandler::OsiClpDisasterHandler (OsiClpSolverInterface * model)
9154 : ClpDisasterHandler(),
9155 osiModel_(model),
9156 whereFrom_(0),
9157 phase_(0),
9158 inTrouble_(false)
9159{
9160 if (model)
9161 setSimplex(model->getModelPtr());
9162}
9163
9164//-------------------------------------------------------------------
9165// Copy constructor
9166//-------------------------------------------------------------------
9167OsiClpDisasterHandler::OsiClpDisasterHandler (const OsiClpDisasterHandler & rhs)
9168 : ClpDisasterHandler(rhs),
9169 osiModel_(rhs.osiModel_),
9170 whereFrom_(rhs.whereFrom_),
9171 phase_(rhs.phase_),
9172 inTrouble_(rhs.inTrouble_)
9173{
9174}
9175
9176
9177//-------------------------------------------------------------------
9178// Destructor
9179//-------------------------------------------------------------------
9180OsiClpDisasterHandler::~OsiClpDisasterHandler ()
9181{
9182}
9183
9184//----------------------------------------------------------------
9185// Assignment operator
9186//-------------------------------------------------------------------
9187OsiClpDisasterHandler &
9188OsiClpDisasterHandler::operator=(const OsiClpDisasterHandler& rhs)
9189{
9190 if (this != &rhs) {
9191 ClpDisasterHandler::operator=(rhs);
9192 osiModel_ = rhs.osiModel_;
9193 whereFrom_ = rhs.whereFrom_;
9194 phase_ = rhs.phase_;
9195 inTrouble_ = rhs.inTrouble_;
9196 }
9197 return *this;
9198}
9199//-------------------------------------------------------------------
9200// Clone
9201//-------------------------------------------------------------------
9202ClpDisasterHandler * OsiClpDisasterHandler::clone() const
9203{
9204 return new OsiClpDisasterHandler(*this);
9205}
9206
9207void
9208OsiClpDisasterHandler::intoSimplex()
9209{
9210 inTrouble_=false;
9211}
9212bool
9213OsiClpDisasterHandler::check() const
9214{
9215 // Exit if really large number of iterations
9216 if (model_->numberIterations()> model_->baseIteration()+100000+100*(model_->numberRows()+model_->numberColumns()))
9217 return true;
9218 if ((whereFrom_&2)==0||!model_->nonLinearCost()) {
9219 // dual
9220 if (model_->numberIterations()<model_->baseIteration()+model_->numberRows()+1000) {
9221 return false;
9222 } else if (phase_<2) {
9223 if (model_->numberIterations()> model_->baseIteration()+2*model_->numberRows()+model_->numberColumns()+2000||
9224 model_->largestDualError()>=1.0e-1) {
9225 // had model_->numberDualInfeasibilitiesWithoutFree()||
9226#ifdef COIN_DEVELOP
9227 printf("trouble in phase %d\n",phase_);
9228#endif
9229 if (osiModel_->largestAway()>0.0) {
9230 // go for safety
9231 model_->setSpecialOptions(model_->specialOptions()&~(2048+4096));
9232 int frequency = model_->factorizationFrequency();
9233 if (frequency>100)
9234 frequency=100;
9235 model_->setFactorizationFrequency(frequency);
9236 double oldBound = model_->dualBound();
9237 double newBound = CoinMax(1.0001e8,
9238 CoinMin(10.0*osiModel_->largestAway(),1.e10));
9239 if (newBound!=oldBound) {
9240 model_->setDualBound(newBound);
9241 if (model_->upperRegion()&&model_->algorithm()<0) {
9242 // need to fix up fake bounds
9243 (static_cast<ClpSimplexDual *>(model_))->resetFakeBounds(0);
9244 }
9245 }
9246 osiModel_->setLargestAway(-1.0);
9247 }
9248 return true;
9249 } else {
9250 return false;
9251 }
9252 } else {
9253 assert (phase_==2);
9254 if (model_->numberIterations()> model_->baseIteration()+3*model_->numberRows()+model_->numberColumns()+2000||
9255 model_->largestPrimalError()>=1.0e3) {
9256#ifdef COIN_DEVELOP
9257 printf("trouble in phase %d\n",phase_);
9258#endif
9259 return true;
9260 } else {
9261 return false;
9262 }
9263 }
9264 } else {
9265 // primal
9266 if (model_->numberIterations()<model_->baseIteration()+2*model_->numberRows()+model_->numberColumns()+4000) {
9267 return false;
9268 } else if (phase_<2) {
9269 if (model_->numberIterations()> model_->baseIteration()+3*model_->numberRows()+2000+
9270 model_->numberColumns()&&
9271 model_->numberDualInfeasibilitiesWithoutFree()>0&&
9272 model_->numberPrimalInfeasibilities()>0&&
9273 model_->nonLinearCost()->changeInCost()>1.0e8) {
9274#ifdef COIN_DEVELOP
9275 printf("trouble in phase %d\n",phase_);
9276#endif
9277 return true;
9278 } else {
9279 return false;
9280 }
9281 } else {
9282 assert (phase_==2);
9283 if (model_->numberIterations()> model_->baseIteration()+3*model_->numberRows()+2000||
9284 model_->largestPrimalError()>=1.0e3) {
9285#ifdef COIN_DEVELOP
9286 printf("trouble in phase %d\n",phase_);
9287#endif
9288 return true;
9289 } else {
9290 return false;
9291 }
9292 }
9293 }
9294}
9295void
9296OsiClpDisasterHandler::saveInfo()
9297{
9298 inTrouble_=true;
9299}
9300// Type of disaster 0 can fix, 1 abort
9301int
9302OsiClpDisasterHandler::typeOfDisaster()
9303{
9304 return 0;
9305}
9306/* set model. */
9307void
9308OsiClpDisasterHandler::setOsiModel(OsiClpSolverInterface * model)
9309{
9310 osiModel_=model;
9311 model_=model->getModelPtr();
9312}
9313// Create C++ lines to get to current state
9314void
9315OsiClpSolverInterface::generateCpp( FILE * fp)
9316{
9317 modelPtr_->generateCpp(fp,true);
9318 // Stuff that can't be done easily
9319 // setupForRepeatedUse here
9320 if (!messageHandler()->prefix())
9321 fprintf(fp,"3 clpModel->messageHandler()->setPrefix(false);\n");
9322 OsiClpSolverInterface defaultModel;
9323 OsiClpSolverInterface * other = &defaultModel;
9324 int iValue1, iValue2;
9325 double dValue1, dValue2;
9326 bool takeHint1,takeHint2;
9327 int add;
9328 OsiHintStrength strength1,strength2;
9329 std::string strengthName[] = {"OsiHintIgnore","OsiHintTry","OsiHintDo",
9330 "OsiForceDo"};
9331 iValue1 = this->specialOptions();
9332 iValue2 = other->specialOptions();
9333 fprintf(fp,"%d int save_specialOptions = osiclpModel->specialOptions();\n",iValue1==iValue2 ? 2 : 1);
9334 fprintf(fp,"%d osiclpModel->setSpecialOptions(%d);\n",iValue1==iValue2 ? 4 : 3,iValue1);
9335 fprintf(fp,"%d osiclpModel->setSpecialOptions(save_specialOptions);\n",iValue1==iValue2 ? 7 : 6);
9336 iValue1 = this->messageHandler()->logLevel();
9337 iValue2 = other->messageHandler()->logLevel();
9338 fprintf(fp,"%d int save_messageHandler = osiclpModel->messageHandler()->logLevel();\n",iValue1==iValue2 ? 2 : 1);
9339 fprintf(fp,"%d osiclpModel->messageHandler()->setLogLevel(%d);\n",iValue1==iValue2 ? 4 : 3,iValue1);
9340 fprintf(fp,"%d osiclpModel->messageHandler()->setLogLevel(save_messageHandler);\n",iValue1==iValue2 ? 7 : 6);
9341 iValue1 = this->cleanupScaling();
9342 iValue2 = other->cleanupScaling();
9343 fprintf(fp,"%d int save_cleanupScaling = osiclpModel->cleanupScaling();\n",iValue1==iValue2 ? 2 : 1);
9344 fprintf(fp,"%d osiclpModel->setCleanupScaling(%d);\n",iValue1==iValue2 ? 4 : 3,iValue1);
9345 fprintf(fp,"%d osiclpModel->setCleanupScaling(save_cleanupScaling);\n",iValue1==iValue2 ? 7 : 6);
9346 dValue1 = this->smallestElementInCut();
9347 dValue2 = other->smallestElementInCut();
9348 fprintf(fp,"%d double save_smallestElementInCut = osiclpModel->smallestElementInCut();\n",dValue1==dValue2 ? 2 : 1);
9349 fprintf(fp,"%d osiclpModel->setSmallestElementInCut(%g);\n",dValue1==dValue2 ? 4 : 3,dValue1);
9350 fprintf(fp,"%d osiclpModel->setSmallestElementInCut(save_smallestElementInCut);\n",dValue1==dValue2 ? 7 : 6);
9351 dValue1 = this->smallestChangeInCut();
9352 dValue2 = other->smallestChangeInCut();
9353 fprintf(fp,"%d double save_smallestChangeInCut = osiclpModel->smallestChangeInCut();\n",dValue1==dValue2 ? 2 : 1);
9354 fprintf(fp,"%d osiclpModel->setSmallestChangeInCut(%g);\n",dValue1==dValue2 ? 4 : 3,dValue1);
9355 fprintf(fp,"%d osiclpModel->setSmallestChangeInCut(save_smallestChangeInCut);\n",dValue1==dValue2 ? 7 : 6);
9356 this->getIntParam(OsiMaxNumIterationHotStart,iValue1);
9357 other->getIntParam(OsiMaxNumIterationHotStart,iValue2);
9358 fprintf(fp,"%d int save_OsiMaxNumIterationHotStart;\n",iValue1==iValue2 ? 2 : 1);
9359 fprintf(fp,"%d osiclpModel->getIntParam(OsiMaxNumIterationHotStart,save_OsiMaxNumIterationHotStart);\n",iValue1==iValue2 ? 2 : 1);
9360 fprintf(fp,"%d osiclpModel->setIntParam(OsiMaxNumIterationHotStart,%d);\n",iValue1==iValue2 ? 4 : 3,iValue1);
9361 fprintf(fp,"%d osiclpModel->setIntParam(OsiMaxNumIterationHotStart,save_OsiMaxNumIterationHotStart);\n",iValue1==iValue2 ? 7 : 6);
9362 this->getDblParam(OsiDualObjectiveLimit,dValue1);
9363 other->getDblParam(OsiDualObjectiveLimit,dValue2);
9364 fprintf(fp,"%d double save_OsiDualObjectiveLimit;\n",dValue1==dValue2 ? 2 : 1);
9365 fprintf(fp,"%d osiclpModel->getDblParam(OsiDualObjectiveLimit,save_OsiDualObjectiveLimit);\n",dValue1==dValue2 ? 2 : 1);
9366 fprintf(fp,"%d osiclpModel->setDblParam(OsiDualObjectiveLimit,%g);\n",dValue1==dValue2 ? 4 : 3,dValue1);
9367 fprintf(fp,"%d osiclpModel->setDblParam(OsiDualObjectiveLimit,save_OsiDualObjectiveLimit);\n",dValue1==dValue2 ? 7 : 6);
9368 this->getDblParam(OsiPrimalObjectiveLimit,dValue1);
9369 other->getDblParam(OsiPrimalObjectiveLimit,dValue2);
9370 fprintf(fp,"%d double save_OsiPrimalObjectiveLimit;\n",dValue1==dValue2 ? 2 : 1);
9371 fprintf(fp,"%d osiclpModel->getDblParam(OsiPrimalObjectiveLimit,save_OsiPrimalObjectiveLimit);\n",dValue1==dValue2 ? 2 : 1);
9372 fprintf(fp,"%d osiclpModel->setDblParam(OsiPrimalObjectiveLimit,%g);\n",dValue1==dValue2 ? 4 : 3,dValue1);
9373 fprintf(fp,"%d osiclpModel->setDblParam(OsiPrimalObjectiveLimit,save_OsiPrimalObjectiveLimit);\n",dValue1==dValue2 ? 7 : 6);
9374 this->getHintParam(OsiDoPresolveInInitial,takeHint1,strength1);
9375 other->getHintParam(OsiDoPresolveInInitial,takeHint2,strength2);
9376 add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0;
9377 fprintf(fp,"%d bool saveHint_OsiDoPresolveInInitial;\n",add+1);
9378 fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoPresolveInInitial;\n",add+1);
9379 fprintf(fp,"%d osiclpModel->getHintParam(OsiDoPresolveInInitial,saveHint_OsiDoPresolveInInitial,saveStrength_OsiDoPresolveInInitial);\n",add+1);
9380 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoPresolveInInitial,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str());
9381 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoPresolveInInitial,saveHint_OsiDoPresolveInInitial,saveStrength_OsiDoPresolveInInitial);\n",add+6);
9382 this->getHintParam(OsiDoDualInInitial,takeHint1,strength1);
9383 other->getHintParam(OsiDoDualInInitial,takeHint2,strength2);
9384 add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0;
9385 fprintf(fp,"%d bool saveHint_OsiDoDualInInitial;\n",add+1);
9386 fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoDualInInitial;\n",add+1);
9387 fprintf(fp,"%d osiclpModel->getHintParam(OsiDoDualInInitial,saveHint_OsiDoDualInInitial,saveStrength_OsiDoDualInInitial);\n",add+1);
9388 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoDualInInitial,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str());
9389 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoDualInInitial,saveHint_OsiDoDualInInitial,saveStrength_OsiDoDualInInitial);\n",add+6);
9390 this->getHintParam(OsiDoPresolveInResolve,takeHint1,strength1);
9391 other->getHintParam(OsiDoPresolveInResolve,takeHint2,strength2);
9392 add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0;
9393 fprintf(fp,"%d bool saveHint_OsiDoPresolveInResolve;\n",add+1);
9394 fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoPresolveInResolve;\n",add+1);
9395 fprintf(fp,"%d osiclpModel->getHintParam(OsiDoPresolveInResolve,saveHint_OsiDoPresolveInResolve,saveStrength_OsiDoPresolveInResolve);\n",add+1);
9396 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoPresolveInResolve,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str());
9397 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoPresolveInResolve,saveHint_OsiDoPresolveInResolve,saveStrength_OsiDoPresolveInResolve);\n",add+6);
9398 this->getHintParam(OsiDoDualInResolve,takeHint1,strength1);
9399 other->getHintParam(OsiDoDualInResolve,takeHint2,strength2);
9400 add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0;
9401 fprintf(fp,"%d bool saveHint_OsiDoDualInResolve;\n",add+1);
9402 fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoDualInResolve;\n",add+1);
9403 fprintf(fp,"%d osiclpModel->getHintParam(OsiDoDualInResolve,saveHint_OsiDoDualInResolve,saveStrength_OsiDoDualInResolve);\n",add+1);
9404 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoDualInResolve,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str());
9405 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoDualInResolve,saveHint_OsiDoDualInResolve,saveStrength_OsiDoDualInResolve);\n",add+6);
9406 this->getHintParam(OsiDoScale,takeHint1,strength1);
9407 other->getHintParam(OsiDoScale,takeHint2,strength2);
9408 add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0;
9409 fprintf(fp,"%d bool saveHint_OsiDoScale;\n",add+1);
9410 fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoScale;\n",add+1);
9411 fprintf(fp,"%d osiclpModel->getHintParam(OsiDoScale,saveHint_OsiDoScale,saveStrength_OsiDoScale);\n",add+1);
9412 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoScale,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str());
9413 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoScale,saveHint_OsiDoScale,saveStrength_OsiDoScale);\n",add+6);
9414 this->getHintParam(OsiDoCrash,takeHint1,strength1);
9415 other->getHintParam(OsiDoCrash,takeHint2,strength2);
9416 add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0;
9417 fprintf(fp,"%d bool saveHint_OsiDoCrash;\n",add+1);
9418 fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoCrash;\n",add+1);
9419 fprintf(fp,"%d osiclpModel->getHintParam(OsiDoCrash,saveHint_OsiDoCrash,saveStrength_OsiDoCrash);\n",add+1);
9420 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoCrash,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str());
9421 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoCrash,saveHint_OsiDoCrash,saveStrength_OsiDoCrash);\n",add+6);
9422 this->getHintParam(OsiDoReducePrint,takeHint1,strength1);
9423 other->getHintParam(OsiDoReducePrint,takeHint2,strength2);
9424 add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0;
9425 fprintf(fp,"%d bool saveHint_OsiDoReducePrint;\n",add+1);
9426 fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoReducePrint;\n",add+1);
9427 fprintf(fp,"%d osiclpModel->getHintParam(OsiDoReducePrint,saveHint_OsiDoReducePrint,saveStrength_OsiDoReducePrint);\n",add+1);
9428 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoReducePrint,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str());
9429 fprintf(fp,"%d osiclpModel->setHintParam(OsiDoReducePrint,saveHint_OsiDoReducePrint,saveStrength_OsiDoReducePrint);\n",add+6);
9430}
9431// So unit test can find out if NDEBUG set
9432bool OsiClpHasNDEBUG()
9433{
9434#ifdef NDEBUG
9435 return true;
9436#else
9437 return false;
9438#endif
9439}
9440