1 /* $Id: ClpSolve.cpp 2449 2019-04-08 03:34:28Z stefan $ */
2 // Copyright (C) 2003, 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 // This file has higher level solve functions
7 
8 #include "CoinPragma.hpp"
9 #include "ClpConfig.h"
10 
11 // check already here if COIN_HAS_GLPK is defined, since we do not want to get confused by a COIN_HAS_GLPK in config_coinutils.h
12 #if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK)
13 #define UFL_BARRIER
14 #endif
15 
16 #include <math.h>
17 #ifdef _MSC_VER
18 #include <windows.h> // for Sleep()
19 #ifdef small
20 #undef small
21 #endif
22 #else
23 #include <unistd.h> // for usleep()
24 #endif
25 
26 #include "CoinHelperFunctions.hpp"
27 #include "ClpHelperFunctions.hpp"
28 #include "CoinSort.hpp"
29 #include "ClpFactorization.hpp"
30 #include "ClpSimplex.hpp"
31 #include "ClpSimplexOther.hpp"
32 #include "ClpSimplexDual.hpp"
33 #ifndef SLIM_CLP
34 #include "ClpQuadraticObjective.hpp"
35 #include "ClpInterior.hpp"
36 #include "ClpCholeskyDense.hpp"
37 #include "ClpCholeskyBase.hpp"
38 #include "ClpPlusMinusOneMatrix.hpp"
39 #include "ClpNetworkMatrix.hpp"
40 #endif
41 #include "ClpEventHandler.hpp"
42 #include "ClpLinearObjective.hpp"
43 #include "ClpSolve.hpp"
44 #include "ClpPackedMatrix.hpp"
45 #include "ClpMessage.hpp"
46 #include "CoinTime.hpp"
47 #if CLP_HAS_ABC
48 #include "CoinAbcCommon.hpp"
49 #endif
50 #ifdef ABC_INHERIT
51 #include "AbcSimplex.hpp"
52 #include "AbcSimplexFactorization.hpp"
53 #endif
54 #include "CoinStructuredModel.hpp"
55 double zz_slack_value = 0.0;
56 #ifdef CLP_USEFUL_PRINTOUT
57 double debugDouble[10];
58 int debugInt[24];
59 #endif
60 
61 #include "ClpPresolve.hpp"
62 #ifndef SLIM_CLP
63 #include "Idiot.hpp"
64 #ifdef COIN_HAS_WSMP
65 #include "ClpCholeskyWssmp.hpp"
66 #include "ClpCholeskyWssmpKKT.hpp"
67 #endif
68 #include "ClpCholeskyUfl.hpp"
69 #ifdef TAUCS_BARRIER
70 #include "ClpCholeskyTaucs.hpp"
71 #endif
72 #ifdef PARDISO_BARRIER
73 #include "ClpCholeskyPardiso.hpp"
74 #endif
75 #include "ClpCholeskyMumps.hpp"
76 #ifdef COIN_HAS_VOL
77 #include "VolVolume.hpp"
78 #include "CoinHelperFunctions.hpp"
79 #include "CoinPackedMatrix.hpp"
80 #include "CoinMpsIO.hpp"
81 //#############################################################################
82 
83 class lpHook : public VOL_user_hooks {
84 private:
85   lpHook(const lpHook &);
86   lpHook &operator=(const lpHook &);
87 
88 private:
89   /// Pointer to dense vector of structural variable upper bounds
90   double *colupper_;
91   /// Pointer to dense vector of structural variable lower bounds
92   double *collower_;
93   /// Pointer to dense vector of objective coefficients
94   double *objcoeffs_;
95   /// Pointer to dense vector of right hand sides
96   double *rhs_;
97   /// Pointer to dense vector of senses
98   char *sense_;
99 
100   /// The problem matrix in a row ordered form
101   CoinPackedMatrix rowMatrix_;
102   /// The problem matrix in a column ordered form
103   CoinPackedMatrix colMatrix_;
104 
105 public:
106   lpHook(double *clb, double *cub, double *obj,
107     double *rhs, char *sense, const CoinPackedMatrix &mat);
108   virtual ~lpHook();
109 
110 public:
111   // for all hooks: return value of -1 means that volume should quit
112   /** compute reduced costs
113          @param u (IN) the dual variables
114          @param rc (OUT) the reduced cost with respect to the dual values
115      */
116   virtual int compute_rc(const VOL_dvector &u, VOL_dvector &rc);
117 
118   /** Solve the subproblem for the subgradient step.
119          @param dual (IN) the dual variables
120          @param rc (IN) the reduced cost with respect to the dual values
121          @param lcost (OUT) the lagrangean cost with respect to the dual values
122          @param x (OUT) the primal result of solving the subproblem
123          @param v (OUT) b-Ax for the relaxed constraints
124          @param pcost (OUT) the primal objective value of <code>x</code>
125      */
126   virtual int solve_subproblem(const VOL_dvector &dual, const VOL_dvector &rc,
127     double &lcost, VOL_dvector &x, VOL_dvector &v,
128     double &pcost);
129   /** Starting from the primal vector x, run a heuristic to produce
130          an integer solution
131          @param x (IN) the primal vector
132          @param heur_val (OUT) the value of the integer solution (return
133          <code>DBL_MAX</code> here if no feas sol was found
134      */
heuristics(const VOL_problem & p,const VOL_dvector & x,double & heur_val)135   virtual int heuristics(const VOL_problem &p,
136     const VOL_dvector &x, double &heur_val)
137   {
138     return 0;
139   }
140 };
141 
142 //#############################################################################
143 
lpHook(double * clb,double * cub,double * obj,double * rhs,char * sense,const CoinPackedMatrix & mat)144 lpHook::lpHook(double *clb, double *cub, double *obj,
145   double *rhs, char *sense,
146   const CoinPackedMatrix &mat)
147 {
148   colupper_ = cub;
149   collower_ = clb;
150   objcoeffs_ = obj;
151   rhs_ = rhs;
152   sense_ = sense;
153   assert(mat.isColOrdered());
154   colMatrix_.copyOf(mat);
155   rowMatrix_.reverseOrderedCopyOf(mat);
156 }
157 
158 //-----------------------------------------------------------------------------
159 
~lpHook()160 lpHook::~lpHook()
161 {
162 }
163 
164 //#############################################################################
165 
compute_rc(const VOL_dvector & u,VOL_dvector & rc)166 int lpHook::compute_rc(const VOL_dvector &u, VOL_dvector &rc)
167 {
168   rowMatrix_.transposeTimes(u.v, rc.v);
169   const int psize = rowMatrix_.getNumCols();
170 
171   for (int i = 0; i < psize; ++i)
172     rc[i] = objcoeffs_[i] - rc[i];
173   return 0;
174 }
175 
176 //-----------------------------------------------------------------------------
177 
solve_subproblem(const VOL_dvector & dual,const VOL_dvector & rc,double & lcost,VOL_dvector & x,VOL_dvector & v,double & pcost)178 int lpHook::solve_subproblem(const VOL_dvector &dual, const VOL_dvector &rc,
179   double &lcost, VOL_dvector &x, VOL_dvector &v,
180   double &pcost)
181 {
182   int i;
183   const int psize = x.size();
184   const int dsize = v.size();
185 
186   // compute the lagrangean solution corresponding to the reduced costs
187   for (i = 0; i < psize; ++i)
188     x[i] = (rc[i] >= 0.0) ? collower_[i] : colupper_[i];
189 
190   // compute the lagrangean value (rhs*dual + primal*rc)
191   lcost = 0;
192   for (i = 0; i < dsize; ++i)
193     lcost += rhs_[i] * dual[i];
194   for (i = 0; i < psize; ++i)
195     lcost += x[i] * rc[i];
196 
197   // compute the rhs - lhs
198   colMatrix_.times(x.v, v.v);
199   for (i = 0; i < dsize; ++i)
200     v[i] = rhs_[i] - v[i];
201 
202   // compute the lagrangean primal objective
203   pcost = 0;
204   for (i = 0; i < psize; ++i)
205     pcost += x[i] * objcoeffs_[i];
206 
207   return 0;
208 }
209 
210 //#############################################################################
211 /** A quick inlined function to convert from lb/ub style constraint
212     definition to sense/rhs/range style */
213 inline void
convertBoundToSense(const double lower,const double upper,char & sense,double & right,double & range)214 convertBoundToSense(const double lower, const double upper,
215   char &sense, double &right,
216   double &range)
217 {
218   range = 0.0;
219   if (lower > -1.0e20) {
220     if (upper < 1.0e20) {
221       right = upper;
222       if (upper == lower) {
223         sense = 'E';
224       } else {
225         sense = 'R';
226         range = upper - lower;
227       }
228     } else {
229       sense = 'G';
230       right = lower;
231     }
232   } else {
233     if (upper < 1.0e20) {
234       sense = 'L';
235       right = upper;
236     } else {
237       sense = 'N';
238       right = 0.0;
239     }
240   }
241 }
242 
243 static int
solveWithVolume(ClpSimplex * model,int numberPasses,int doIdiot)244 solveWithVolume(ClpSimplex *model, int numberPasses, int doIdiot)
245 {
246   VOL_problem volprob;
247   volprob.parm.gap_rel_precision = 0.00001;
248   volprob.parm.maxsgriters = 3000;
249   if (numberPasses > 3000) {
250     volprob.parm.maxsgriters = numberPasses;
251     volprob.parm.primal_abs_precision = 0.0;
252     volprob.parm.minimum_rel_ascent = 0.00001;
253   } else if (doIdiot > 0) {
254     volprob.parm.maxsgriters = doIdiot;
255   }
256   if (model->logLevel() < 2)
257     volprob.parm.printflag = 0;
258   else
259     volprob.parm.printflag = 3;
260   const CoinPackedMatrix *mat = model->matrix();
261   int psize = model->numberColumns();
262   int dsize = model->numberRows();
263   char *sense = new char[dsize];
264   double *rhs = new double[dsize];
265 
266   // Set the lb/ub on the duals
267   volprob.dsize = dsize;
268   volprob.psize = psize;
269   volprob.dual_lb.allocate(dsize);
270   volprob.dual_ub.allocate(dsize);
271   int i;
272   const double *rowLower = model->rowLower();
273   const double *rowUpper = model->rowUpper();
274   for (i = 0; i < dsize; ++i) {
275     double range;
276     convertBoundToSense(rowLower[i], rowUpper[i],
277       sense[i], rhs[i], range);
278     switch (sense[i]) {
279     case 'E':
280       volprob.dual_lb[i] = -1.0e31;
281       volprob.dual_ub[i] = 1.0e31;
282       break;
283     case 'L':
284       volprob.dual_lb[i] = -1.0e31;
285       volprob.dual_ub[i] = 0.0;
286       break;
287     case 'G':
288       volprob.dual_lb[i] = 0.0;
289       volprob.dual_ub[i] = 1.0e31;
290       break;
291     default:
292       printf("Volume Algorithm can't work if there is a non ELG row\n");
293       return 1;
294     }
295   }
296   // Check bounds
297   double *saveLower = model->columnLower();
298   double *saveUpper = model->columnUpper();
299   bool good = true;
300   for (i = 0; i < psize; i++) {
301     if (saveLower[i] < -1.0e20 || saveUpper[i] > 1.0e20) {
302       good = false;
303       break;
304     }
305   }
306   if (!good) {
307     saveLower = CoinCopyOfArray(model->columnLower(), psize);
308     saveUpper = CoinCopyOfArray(model->columnUpper(), psize);
309     for (i = 0; i < psize; i++) {
310       if (saveLower[i] < -1.0e20)
311         saveLower[i] = -1.0e20;
312       if (saveUpper[i] > 1.0e20)
313         saveUpper[i] = 1.0e20;
314     }
315   }
316   lpHook myHook(saveLower, saveUpper,
317     model->objective(),
318     rhs, sense, *mat);
319 
320   volprob.solve(myHook, false /* no warmstart */);
321 
322   if (saveLower != model->columnLower()) {
323     delete[] saveLower;
324     delete[] saveUpper;
325   }
326   //------------- extract the solution ---------------------------
327 
328   //printf("Best lagrangean value: %f\n", volprob.value);
329 
330   double avg = 0;
331   for (i = 0; i < dsize; ++i) {
332     switch (sense[i]) {
333     case 'E':
334       avg += CoinAbs(volprob.viol[i]);
335       break;
336     case 'L':
337       if (volprob.viol[i] < 0)
338         avg += (-volprob.viol[i]);
339       break;
340     case 'G':
341       if (volprob.viol[i] > 0)
342         avg += volprob.viol[i];
343       break;
344     }
345   }
346 
347   //printf("Average primal constraint violation: %f\n", avg/dsize);
348 
349   // volprob.dsol contains the dual solution (dual feasible)
350   // volprob.psol contains the primal solution
351   //              (NOT necessarily primal feasible)
352   CoinMemcpyN(volprob.dsol.v, dsize, model->dualRowSolution());
353   CoinMemcpyN(volprob.psol.v, psize, model->primalColumnSolution());
354   return 0;
355 }
356 #endif
357 static ClpInterior *currentModel2 = NULL;
358 #endif
359 //#############################################################################
360 // Allow for interrupts
361 // But is this threadsafe ? (so switched off by option)
362 
363 #include "CoinSignal.hpp"
364 static ClpSimplex *currentModel = NULL;
365 #ifdef ABC_INHERIT
366 static AbcSimplex *currentAbcModel = NULL;
367 #endif
368 
369 extern "C" {
370 static void
371 #if defined(_MSC_VER)
372   __cdecl
373 #endif // _MSC_VER
signal_handler(int)374   signal_handler(int /*whichSignal*/)
375 {
376   if (currentModel != NULL)
377     currentModel->setMaximumIterations(0); // stop at next iterations
378 #ifdef ABC_INHERIT
379   if (currentAbcModel != NULL)
380     currentAbcModel->setMaximumIterations(0); // stop at next iterations
381 #endif
382 #ifndef SLIM_CLP
383   if (currentModel2 != NULL)
384     currentModel2->setMaximumBarrierIterations(0); // stop at next iterations
385 #endif
386   return;
387 }
388 }
389 #if ABC_INSTRUMENT > 1
390 int abcPricing[20];
391 int abcPricingDense[20];
392 static int trueNumberRows;
393 static int numberTypes;
394 #define MAX_TYPES 25
395 #define MAX_COUNT 20
396 #define MAX_FRACTION 101
397 static char *types[MAX_TYPES];
398 static double counts[MAX_TYPES][MAX_COUNT];
399 static double countsFraction[MAX_TYPES][MAX_FRACTION];
400 static double *currentCounts;
401 static double *currentCountsFraction;
402 static int currentType;
403 static double workMultiplier[MAX_TYPES];
404 static double work[MAX_TYPES];
405 static double currentWork;
406 static double otherWork[MAX_TYPES];
407 static int timesCalled[MAX_TYPES];
408 static int timesStarted[MAX_TYPES];
409 static int fractionDivider;
instrument_initialize(int numberRows)410 void instrument_initialize(int numberRows)
411 {
412   trueNumberRows = numberRows;
413   numberTypes = 0;
414   memset(counts, 0, sizeof(counts));
415   currentCounts = NULL;
416   memset(countsFraction, 0, sizeof(countsFraction));
417   currentCountsFraction = NULL;
418   memset(workMultiplier, 0, sizeof(workMultiplier));
419   memset(work, 0, sizeof(work));
420   memset(otherWork, 0, sizeof(otherWork));
421   memset(timesCalled, 0, sizeof(timesCalled));
422   memset(timesStarted, 0, sizeof(timesStarted));
423   currentType = -1;
424   fractionDivider = (numberRows + MAX_FRACTION - 2) / (MAX_FRACTION - 1);
425 }
instrument_start(const char * type,int numberRowsEtc)426 void instrument_start(const char *type, int numberRowsEtc)
427 {
428   if (currentType >= 0)
429     instrument_end();
430   currentType = -1;
431   currentWork = 0.0;
432   for (int i = 0; i < numberTypes; i++) {
433     if (!strcmp(types[i], type)) {
434       currentType = i;
435       break;
436     }
437   }
438   if (currentType == -1) {
439     assert(numberTypes < MAX_TYPES);
440     currentType = numberTypes;
441     types[numberTypes++] = strdup(type);
442   }
443   currentCounts = &counts[currentType][0];
444   currentCountsFraction = &countsFraction[currentType][0];
445   timesStarted[currentType]++;
446   assert(trueNumberRows);
447   workMultiplier[currentType] += static_cast< double >(numberRowsEtc) / static_cast< double >(trueNumberRows);
448 }
instrument_add(int count)449 void instrument_add(int count)
450 {
451   assert(currentType >= 0);
452   currentWork += count;
453   timesCalled[currentType]++;
454   if (count < MAX_COUNT - 1)
455     currentCounts[count]++;
456   else
457     currentCounts[MAX_COUNT - 1]++;
458   assert(count / fractionDivider >= 0 && count / fractionDivider < MAX_FRACTION);
459   currentCountsFraction[count / fractionDivider]++;
460 }
instrument_do(const char * type,double count)461 void instrument_do(const char *type, double count)
462 {
463   int iType = -1;
464   for (int i = 0; i < numberTypes; i++) {
465     if (!strcmp(types[i], type)) {
466       iType = i;
467       break;
468     }
469   }
470   if (iType == -1) {
471     assert(numberTypes < MAX_TYPES);
472     iType = numberTypes;
473     types[numberTypes++] = strdup(type);
474   }
475   timesStarted[iType]++;
476   otherWork[iType] += count;
477 }
instrument_end()478 void instrument_end()
479 {
480   work[currentType] += currentWork;
481   currentType = -1;
482 }
instrument_end_and_adjust(double factor)483 void instrument_end_and_adjust(double factor)
484 {
485   work[currentType] += currentWork * factor;
486   currentType = -1;
487 }
instrument_print()488 void instrument_print()
489 {
490   for (int iType = 0; iType < numberTypes; iType++) {
491     currentCounts = &counts[iType][0];
492     currentCountsFraction = &countsFraction[iType][0];
493     if (!otherWork[iType]) {
494       printf("%s started %d times, used %d times, work %g (average length %.1f) multiplier %g\n",
495         types[iType], timesStarted[iType], timesCalled[iType],
496         work[iType], work[iType] / (timesCalled[iType] + 1.0e-100), workMultiplier[iType] / (timesStarted[iType] + 1.0e-100));
497       int n = 0;
498       for (int i = 0; i < MAX_COUNT - 1; i++) {
499         if (currentCounts[i]) {
500           if (n == 5) {
501             n = 0;
502             printf("\n");
503           }
504           n++;
505           printf("(%d els,%.0f times) ", i, currentCounts[i]);
506         }
507       }
508       if (currentCounts[MAX_COUNT - 1]) {
509         if (n == 5) {
510           n = 0;
511           printf("\n");
512         }
513         n++;
514         printf("(>=%d els,%.0f times) ", MAX_COUNT - 1, currentCounts[MAX_COUNT - 1]);
515       }
516       printf("\n");
517       int largestFraction;
518       int nBig = 0;
519       for (largestFraction = MAX_FRACTION - 1; largestFraction >= 10; largestFraction--) {
520         double count = currentCountsFraction[largestFraction];
521         if (count && largestFraction > 10)
522           nBig++;
523         if (nBig > 4)
524           break;
525       }
526       int chunk = (largestFraction + 5) / 10;
527       int lo = 0;
528       for (int iChunk = 0; iChunk < largestFraction; iChunk += chunk) {
529         int hi = CoinMin(lo + chunk * fractionDivider, trueNumberRows);
530         double sum = 0.0;
531         for (int i = iChunk; i < CoinMin(iChunk + chunk, MAX_FRACTION); i++)
532           sum += currentCountsFraction[i];
533         if (sum)
534           printf("(%d-%d %.0f) ", lo, hi, sum);
535         lo = hi;
536       }
537       for (int i = lo / fractionDivider; i < MAX_FRACTION; i++) {
538         if (currentCountsFraction[i])
539           printf("(%d %.0f) ", i * fractionDivider, currentCountsFraction[i]);
540       }
541       printf("\n");
542     } else {
543       printf("%s started %d times, used %d times, work %g multiplier %g other work %g\n",
544         types[iType], timesStarted[iType], timesCalled[iType],
545         work[iType], workMultiplier[iType], otherWork[iType]);
546     }
547     free(types[iType]);
548   }
549 }
550 #endif
551 #if ABC_PARALLEL == 2
552 #ifndef FAKE_CILK
553 int number_cilk_workers = 0;
554 #include <cilk/cilk_api.h>
555 #endif
556 #endif
557 #ifdef ABC_INHERIT
558 AbcSimplex *
dealWithAbc(int solveType,int startUp,bool interrupt)559 ClpSimplex::dealWithAbc(int solveType, int startUp,
560   bool interrupt)
561 {
562   bool keepAbc = startUp >= 10;
563   startUp = startUp % 10;
564   AbcSimplex *abcModel2 = NULL;
565   if (!this->abcState() || !numberRows_ || !numberColumns_) {
566     //this->readBasis("aaa.bas");
567     if (!solveType) {
568       this->dual(0);
569     } else if (solveType == 1) {
570       int ifValuesPass = startUp ? 1 : 0;
571       if (startUp == 3)
572         ifValuesPass = 2;
573       this->primal(ifValuesPass);
574     }
575     //this->writeBasis("a.bas",true);
576   } else {
577     abcModel2 = new AbcSimplex(*this);
578     if (interrupt)
579       currentAbcModel = abcModel2;
580     //if (abcSimplex_) {
581     // move factorization stuff
582     abcModel2->factorization()->synchronize(this->factorization(), abcModel2);
583     //}
584     //abcModel2->startPermanentArrays();
585     int crashState = abcModel2->abcState() & (256 + 512 + 1024);
586     abcModel2->setAbcState(CLP_ABC_WANTED | crashState | (abcModel2->abcState() & 15));
587     int ifValuesPass = startUp ? 1 : 0;
588     if (startUp == 3)
589       ifValuesPass = 2;
590     // temp
591     if (fabs(this->primalTolerance() - 1.001e-6) < 0.999e-9) {
592       int type = 1;
593       double diff = this->primalTolerance() - 1.001e-6;
594       printf("Diff %g\n", diff);
595       if (fabs(diff - 1.0e-10) < 1.0e-13)
596         type = 2;
597       else if (fabs(diff - 1.0e-11) < 1.0e-13)
598         type = 3;
599 #if 0
600       ClpSimplex * thisModel = static_cast<ClpSimplexOther *> (this)->dualOfModel(1.0,1.0);
601       if (thisModel) {
602 	printf("Dual of model has %d rows and %d columns\n",
603 	       thisModel->numberRows(), thisModel->numberColumns());
604 	thisModel->setOptimizationDirection(1.0);
605 	Idiot info(*thisModel);
606 	info.setStrategy(512 | info.getStrategy());
607 	// Allow for scaling
608 	info.setStrategy(32 | info.getStrategy());
609 	info.setStartingWeight(1.0e3);
610 	info.setReduceIterations(6);
611 	info.crash(50, this->messageHandler(), this->messagesPointer(),false);
612 	// make sure later that primal solution in correct place
613 	// and has correct sign
614 	abcModel2->setupDualValuesPass(thisModel->primalColumnSolution(),
615 				       thisModel->dualRowSolution(),type);
616 	//thisModel->dual();
617 	delete thisModel;
618       }
619 #else
620       if (!solveType) {
621         this->dual(0);
622         abcModel2->setupDualValuesPass(this->dualRowSolution(),
623           this->primalColumnSolution(), type);
624       } else if (solveType == 1) {
625         ifValuesPass = 1;
626         abcModel2->setStateOfProblem(abcModel2->stateOfProblem() | VALUES_PASS);
627         Idiot info(*abcModel2);
628         info.setStrategy(512 | info.getStrategy());
629         // Allow for scaling
630         info.setStrategy(32 | info.getStrategy());
631         info.setStartingWeight(1.0e3);
632         info.setReduceIterations(6);
633         info.crash(200, abcModel2->messageHandler(), abcModel2->messagesPointer(), false);
634         //memcpy(abcModel2->primalColumnSolution(),this->primalColumnSolution(),
635         //     this->numberColumns()*sizeof(double));
636       }
637 #endif
638     }
639     int numberCpu = this->abcState() & 15;
640     if (numberCpu == 9) {
641       numberCpu = 1;
642 #if ABC_PARALLEL == 2
643 #ifndef FAKE_CILK
644       if (number_cilk_workers > 1)
645         numberCpu = CoinMin(2 * number_cilk_workers, 8);
646 #endif
647 #endif
648     } else if (numberCpu == 10) {
649       // maximum
650       numberCpu = 4;
651     } else if (numberCpu == 10) {
652       // decide
653       if (abcModel2->getNumElements() < 5000)
654         numberCpu = 1;
655 #if ABC_PARALLEL == 2
656 #ifndef FAKE_CILK
657       else if (number_cilk_workers > 1)
658         numberCpu = CoinMin(2 * number_cilk_workers, 8);
659 #endif
660 #endif
661       else
662         numberCpu = 1;
663     } else {
664 #if ABC_PARALLEL == 2
665 #ifndef FAKE_CILK
666       char temp[3];
667       sprintf(temp, "%d", numberCpu);
668       __cilkrts_set_param("nworkers", temp);
669       printf("setting cilk workers to %d\n", numberCpu);
670       number_cilk_workers = numberCpu;
671 
672 #endif
673 #endif
674     }
675     char line[200];
676 #if ABC_PARALLEL
677 #if ABC_PARALLEL == 2
678 #ifndef FAKE_CILK
679     if (!number_cilk_workers) {
680       number_cilk_workers = __cilkrts_get_nworkers();
681       sprintf(line, "%d cilk workers", number_cilk_workers);
682       handler_->message(CLP_GENERAL, messages_)
683         << line
684         << CoinMessageEol;
685     }
686 #endif
687 #endif
688     abcModel2->setParallelMode(numberCpu - 1);
689 #endif
690     //if (abcState()==3||abcState()==4) {
691     //abcModel2->setMoreSpecialOptions((131072*2)|abcModel2->moreSpecialOptions());
692     //}
693     //if (processTune>0&&processTune<8)
694     //abcModel2->setMoreSpecialOptions(abcModel2->moreSpecialOptions()|131072*processTune);
695 #if ABC_INSTRUMENT
696     double startTimeCpu = CoinCpuTime();
697     double startTimeElapsed = CoinGetTimeOfDay();
698 #if ABC_INSTRUMENT > 1
699     memset(abcPricing, 0, sizeof(abcPricing));
700     memset(abcPricingDense, 0, sizeof(abcPricing));
701     instrument_initialize(abcModel2->numberRows());
702 #endif
703 #endif
704     if (!solveType) {
705       abcModel2->ClpSimplex::doAbcDual();
706     } else if (solveType == 1) {
707       int saveOptions = abcModel2->specialOptions();
708       //if (startUp==2)
709       //abcModel2->setSpecialOptions(8192|saveOptions);
710       abcModel2->ClpSimplex::doAbcPrimal(ifValuesPass);
711       abcModel2->setSpecialOptions(saveOptions);
712     }
713 #if ABC_INSTRUMENT
714     if (solveType < 2) {
715       double timeCpu = CoinCpuTime() - startTimeCpu;
716       double timeElapsed = CoinGetTimeOfDay() - startTimeElapsed;
717       sprintf(line, "Cpu time for %s (%d rows, %d columns %d elements) %g elapsed %g ratio %g - %d iterations",
718         this->problemName().c_str(), this->numberRows(), this->numberColumns(),
719         this->getNumElements(),
720         timeCpu, timeElapsed, timeElapsed ? timeCpu / timeElapsed : 1.0, abcModel2->numberIterations());
721       handler_->message(CLP_GENERAL, messages_)
722         << line
723         << CoinMessageEol;
724 #if ABC_INSTRUMENT > 1
725       {
726         int n;
727         n = 0;
728         for (int i = 0; i < 20; i++)
729           n += abcPricing[i];
730         printf("CCSparse pricing done %d times", n);
731         int n2 = 0;
732         for (int i = 0; i < 20; i++)
733           n2 += abcPricingDense[i];
734         if (n2)
735           printf(" and dense pricing done %d times\n", n2);
736         else
737           printf("\n");
738         n = 0;
739         printf("CCS");
740         for (int i = 0; i < 19; i++) {
741           if (abcPricing[i]) {
742             if (n == 5) {
743               n = 0;
744               printf("\nCCS");
745             }
746             n++;
747             printf("(%d els,%d times) ", i, abcPricing[i]);
748           }
749         }
750         if (abcPricing[19]) {
751           if (n == 5) {
752             n = 0;
753             printf("\nCCS");
754           }
755           n++;
756           printf("(>=19 els,%d times) ", abcPricing[19]);
757         }
758         if (n2) {
759           printf("CCD");
760           for (int i = 0; i < 19; i++) {
761             if (abcPricingDense[i]) {
762               if (n == 5) {
763                 n = 0;
764                 printf("\nCCD");
765               }
766               n++;
767               int k1 = (numberRows_ / 16) * i;
768               ;
769               int k2 = CoinMin(numberRows_, k1 + (numberRows_ / 16) - 1);
770               printf("(%d-%d els,%d times) ", k1, k2, abcPricingDense[i]);
771             }
772           }
773         }
774         printf("\n");
775       }
776       instrument_print();
777 #endif
778     }
779 #endif
780     abcModel2->moveStatusToClp(this);
781 #if 1
782     if (!problemStatus_) {
783       double offset;
784       CoinMemcpyN(this->objectiveAsObject()->gradient(this,
785                     this->primalColumnSolution(), offset, true),
786         numberColumns_, this->dualColumnSolution());
787       this->clpMatrix()->transposeTimes(-1.0,
788         this->dualRowSolution(),
789         this->dualColumnSolution());
790       memset(this->primalRowSolution(), 0, numberRows_ * sizeof(double));
791       this->clpMatrix()->times(1.0,
792         this->primalColumnSolution(),
793         this->primalRowSolution());
794       this->checkSolutionInternal();
795       if (sumDualInfeasibilities_ > 100.0 * dualTolerance_) {
796 #if CBC_USEFUL_PRINTING > 0
797         printf("internal check on duals failed %d %g\n",
798           numberDualInfeasibilities_, sumDualInfeasibilities_);
799 #endif
800       } else {
801         sumDualInfeasibilities_ = 0.0;
802         numberDualInfeasibilities_ = 0;
803       }
804       if (sumPrimalInfeasibilities_ > 100.0 * primalTolerance_) {
805 #if CBC_USEFUL_PRINTING > 0
806         printf("internal check on primals failed %d %g\n",
807           numberPrimalInfeasibilities_, sumPrimalInfeasibilities_);
808 #endif
809       } else {
810         sumPrimalInfeasibilities_ = 0.0;
811         numberPrimalInfeasibilities_ = 0;
812       }
813       problemStatus_ = 0;
814     }
815 #endif
816     //ClpModel::stopPermanentArrays();
817     this->setSpecialOptions(this->specialOptions() & ~65536);
818 #if 0
819     this->writeBasis("a.bas",true);
820     for (int i=0;i<this->numberRows();i++)
821       printf("%d %g\n",i,this->dualRowSolution()[i]);
822     this->dual();
823     this->writeBasis("b.bas",true);
824     for (int i=0;i<this->numberRows();i++)
825       printf("%d %g\n",i,this->dualRowSolution()[i]);
826 #endif
827     // switch off initialSolve flag
828     moreSpecialOptions_ &= ~16384;
829     //this->setNumberIterations(abcModel2->numberIterations()+this->numberIterations());
830     if (!keepAbc) {
831       delete abcModel2;
832       abcModel2 = NULL;
833     }
834   }
835   return abcModel2;
836 }
837 #endif
838 /** General solve algorithm which can do presolve
839     special options (bits)
840     1 - do not perturb
841     2 - do not scale
842     4 - use crash (default allslack in dual, idiot in primal)
843     8 - all slack basis in primal
844     16 - switch off interrupt handling
845     32 - do not try and make plus minus one matrix
846     64 - do not use sprint even if problem looks good
847  */
initialSolve(ClpSolve & options)848 int ClpSimplex::initialSolve(ClpSolve &options)
849 {
850   ClpSolve::SolveType method = options.getSolveType();
851   //ClpSolve::SolveType originalMethod=method;
852   ClpSolve::PresolveType presolve = options.getPresolveType();
853   int saveMaxIterations = maximumIterations();
854   int finalStatus = -1;
855   int numberIterations = 0;
856   double time1 = CoinCpuTime();
857   double timeX = time1;
858   double time2 = 0.0;
859   ClpMatrixBase *saveMatrix = NULL;
860   ClpObjective *savedObjective = NULL;
861   int idiotOptions = 0;
862   if (options.getSpecialOption(6))
863     idiotOptions = options.getExtraInfo(6) * 32768;
864 #ifdef CLP_USEFUL_PRINTOUT
865   debugInt[0] = numberRows();
866   debugInt[1] = numberColumns();
867   debugInt[2] = matrix()->getNumElements();
868 #endif
869   if (!objective_ || !matrix_) {
870     // totally empty
871     handler_->message(CLP_EMPTY_PROBLEM, messages_)
872       << 0
873       << 0
874       << 0
875       << CoinMessageEol;
876     return -1;
877   } else if (!numberRows_ || !numberColumns_ || !getNumElements()) {
878     presolve = ClpSolve::presolveOff;
879   }
880   if (objective_->type() >= 2 && optimizationDirection_ == 0) {
881     // pretend linear
882     savedObjective = objective_;
883     // make up objective
884     double *obj = new double[numberColumns_];
885     for (int i = 0; i < numberColumns_; i++) {
886       double l = fabs(columnLower_[i]);
887       double u = fabs(columnUpper_[i]);
888       obj[i] = 0.0;
889       if (CoinMin(l, u) < 1.0e20) {
890         if (l < u)
891           obj[i] = 1.0 + randomNumberGenerator_.randomDouble() * 1.0e-2;
892         else
893           obj[i] = -1.0 - randomNumberGenerator_.randomDouble() * 1.0e-2;
894       }
895     }
896     objective_ = new ClpLinearObjective(obj, numberColumns_);
897     delete[] obj;
898   }
899   ClpSimplex *model2 = this;
900   bool interrupt = (options.getSpecialOption(2) == 0);
901   CoinSighandler_t saveSignal = static_cast< CoinSighandler_t >(0);
902   if (interrupt) {
903     currentModel = model2;
904     // register signal handler
905     saveSignal = signal(SIGINT, signal_handler);
906   }
907   // If no status array - set up basis
908   if (!status_)
909     allSlackBasis();
910   ClpPresolve *pinfo = new ClpPresolve();
911   pinfo->setSubstitution(options.substitution());
912   int presolveOptions = options.presolveActions();
913   bool presolveToFile = (presolveOptions & 0x40000000) != 0;
914   presolveOptions &= ~0x40000000;
915   if ((presolveOptions & 0xffffff) != 0)
916     pinfo->setPresolveActions(presolveOptions);
917   // switch off singletons to slacks
918   //pinfo->setDoSingletonColumn(false); // done by bits
919   int printOptions = options.getSpecialOption(5);
920   if ((printOptions & 1) != 0)
921     pinfo->statistics();
922   double timePresolve = 0.0;
923   double timeIdiot = 0.0;
924   double timeCore = 0.0;
925   eventHandler()->event(ClpEventHandler::presolveStart);
926   int savePerturbation = perturbation_;
927   int saveScaling = scalingFlag_;
928 #ifndef SLIM_CLP
929 #ifndef NO_RTTI
930   if (dynamic_cast< ClpNetworkMatrix * >(matrix_)) {
931     // network - switch off stuff
932     presolve = ClpSolve::presolveOff;
933   }
934 #else
935   if (matrix_->type() == 11) {
936     // network - switch off stuff
937     presolve = ClpSolve::presolveOff;
938   }
939 #endif
940 #endif
941 #ifndef CLPSOLVE_ACTIONS
942 #define CLPSOLVE_ACTIONS 2
943 #endif
944 #if CLPSOLVE_ACTIONS
945   bool wasAutomatic = (method == ClpSolve::automatic);
946 #endif
947   if (presolve != ClpSolve::presolveOff) {
948     bool costedSlacks = false;
949 #if CLP_INHERIT_MODE > 1
950     int numberPasses = 20;
951 #else
952     int numberPasses = 5;
953 #endif
954     if (presolve == ClpSolve::presolveNumber) {
955       numberPasses = options.getPresolvePasses();
956       presolve = ClpSolve::presolveOn;
957     } else if (presolve == ClpSolve::presolveNumberCost) {
958       numberPasses = options.getPresolvePasses();
959       presolve = ClpSolve::presolveOn;
960       costedSlacks = true;
961       // switch on singletons to slacks
962       pinfo->setDoSingletonColumn(true);
963       // gub stuff for testing
964       //pinfo->setDoGubrow(true);
965     }
966 #ifndef CLP_NO_STD
967     if (presolveToFile) {
968       // PreSolve to file - not fully tested
969       printf("Presolving to file - presolve.save\n");
970       pinfo->presolvedModelToFile(*this, "presolve.save", dblParam_[ClpPresolveTolerance],
971         false, numberPasses);
972       model2 = this;
973     } else {
974 #endif
975       model2 = pinfo->presolvedModel(*this, dblParam_[ClpPresolveTolerance],
976         false, numberPasses, true, costedSlacks);
977 #ifndef CLP_NO_STD
978     }
979 #endif
980     time2 = CoinCpuTime();
981     timePresolve = time2 - timeX;
982     handler_->message(CLP_INTERVAL_TIMING, messages_)
983       << "Presolve" << timePresolve << time2 - time1
984       << CoinMessageEol;
985     timeX = time2;
986     if (!model2) {
987       handler_->message(CLP_INFEASIBLE, messages_)
988         << CoinMessageEol;
989       model2 = this;
990       eventHandler()->event(ClpEventHandler::presolveInfeasible);
991       problemStatus_ = pinfo->presolveStatus();
992       if (options.infeasibleReturn() || (moreSpecialOptions_ & 1) != 0) {
993         delete pinfo;
994         return -1;
995       }
996       presolve = ClpSolve::presolveOff;
997     } else {
998 #if 0 //def ABC_INHERIT
999 	    {
1000 	      AbcSimplex * abcModel2=new AbcSimplex(*model2);
1001 	      delete model2;
1002 	      model2=abcModel2;
1003 	      pinfo->setPresolvedModel(model2);
1004 	    }
1005 #else
1006       //ClpModel::stopPermanentArrays();
1007       //setSpecialOptions(specialOptions()&~65536);
1008       // try setting tolerances up
1009 #if CLPSOLVE_ACTIONS
1010       bool changeTolerances = wasAutomatic;
1011 #if CLPSOLVE_ACTIONS > 1
1012       changeTolerances = true;
1013 #endif
1014       if (changeTolerances && model2 != this) {
1015 #define CLP_NEW_TOLERANCE 1.0e-6
1016         if (model2->primalTolerance() == 1.0e-7 && model2->dualTolerance() == 1.0e-7) {
1017           model2->setPrimalTolerance(CLP_NEW_TOLERANCE);
1018           model2->setDualTolerance(CLP_NEW_TOLERANCE);
1019         }
1020       }
1021 #endif
1022 #endif
1023       model2->eventHandler()->setSimplex(model2);
1024       int rcode = model2->eventHandler()->event(ClpEventHandler::presolveSize);
1025       // see if too big or small
1026       if (rcode == 2) {
1027         delete model2;
1028         delete pinfo;
1029         return -2;
1030       } else if (rcode == 3) {
1031         delete model2;
1032         delete pinfo;
1033         return -3;
1034       }
1035     }
1036     model2->setMoreSpecialOptions(model2->moreSpecialOptions() & (~1024));
1037     model2->eventHandler()->setSimplex(model2);
1038     // We may be better off using original (but if dual leave because of bounds)
1039     if (presolve != ClpSolve::presolveOff && numberRows_ < 1.01 * model2->numberRows_ && numberColumns_ < 1.01 * model2->numberColumns_
1040       && model2 != this) {
1041       if (method != ClpSolve::useDual || (numberRows_ == model2->numberRows_ && numberColumns_ == model2->numberColumns_)) {
1042         delete model2;
1043         model2 = this;
1044         presolve = ClpSolve::presolveOff;
1045       }
1046     }
1047   }
1048 #ifdef CLP_USEFUL_PRINTOUT
1049   debugInt[3] = model2->numberRows();
1050   debugInt[4] = model2->numberColumns();
1051   debugInt[5] = model2->matrix()->getNumElements();
1052   // analyze
1053   {
1054     double time1 = CoinCpuTime();
1055     int numberColumns = model2->numberColumns();
1056     const double *columnLower = model2->columnLower();
1057     const double *columnUpper = model2->columnUpper();
1058     int numberRows = model2->numberRows();
1059     const double *rowLower = model2->rowLower();
1060     const double *rowUpper = model2->rowUpper();
1061     const double *objective = model2->objective();
1062     CoinPackedMatrix *matrix = model2->matrix();
1063     CoinBigIndex numberElements = matrix->getNumElements();
1064     const int *columnLength = matrix->getVectorLengths();
1065     //const CoinBigIndex * columnStart = matrix->getVectorStarts();
1066     const double *elementByColumn = matrix->getElements();
1067     const int *row = matrix->getIndices();
1068     int *rowCount = new int[numberRows];
1069     memset(rowCount, 0, numberRows * sizeof(int));
1070     int n = CoinMax(2 * numberRows, numberElements);
1071     n = CoinMax(2 * numberColumns, n);
1072     double *check = new double[n];
1073     memcpy(check, elementByColumn, numberElements * sizeof(double));
1074     for (int i = 0; i < numberElements; i++) {
1075       check[i] = fabs(check[i]);
1076       rowCount[row[i]]++;
1077     }
1078     int largestIndex = 0;
1079     for (int i = 0; i < numberColumns; i++) {
1080       largestIndex = CoinMax(largestIndex, columnLength[i]);
1081     }
1082     debugInt[12] = largestIndex;
1083     largestIndex = 0;
1084     for (int i = 0; i < numberRows; i++) {
1085       largestIndex = CoinMax(largestIndex, rowCount[i]);
1086     }
1087     n = numberElements;
1088     delete[] rowCount;
1089     debugInt[11] = largestIndex;
1090     std::sort(check, check + n);
1091     debugDouble[4] = check[0];
1092     debugDouble[5] = check[n - 1];
1093     int nAtOne = 0;
1094     int nDifferent = 0;
1095     double last = -COIN_DBL_MAX;
1096     for (int i = 0; i < n; i++) {
1097       if (fabs(last - check[i]) > 1.0e-12) {
1098         nDifferent++;
1099         last = check[i];
1100       }
1101       if (check[i] == 1.0)
1102         nAtOne++;
1103     }
1104     debugInt[10] = nDifferent;
1105     debugInt[15] = nAtOne;
1106     int nInf = 0;
1107     int nZero = 0;
1108     n = 0;
1109     for (int i = 0; i < numberRows; i++) {
1110       double value = fabs(rowLower[i]);
1111       if (!value)
1112         nZero++;
1113       else if (value != COIN_DBL_MAX)
1114         check[n++] = value;
1115       else
1116         nInf++;
1117     }
1118     for (int i = 0; i < numberRows; i++) {
1119       double value = fabs(rowUpper[i]);
1120       if (!value)
1121         nZero++;
1122       else if (value != COIN_DBL_MAX)
1123         check[n++] = value;
1124       else
1125         nInf++;
1126     }
1127     debugInt[16] = nInf;
1128     debugInt[20] = nZero;
1129     if (n) {
1130       std::sort(check, check + n);
1131       debugDouble[0] = check[0];
1132       debugDouble[1] = check[n - 1];
1133     } else {
1134       debugDouble[0] = 0.0;
1135       debugDouble[1] = 0.0;
1136     }
1137     nAtOne = 0;
1138     nDifferent = 0;
1139     last = -COIN_DBL_MAX;
1140     for (int i = 0; i < n; i++) {
1141       if (fabs(last - check[i]) > 1.0e-12) {
1142         nDifferent++;
1143         last = check[i];
1144       }
1145       if (check[i] == 1.0)
1146         nAtOne++;
1147     }
1148     debugInt[8] = nDifferent;
1149     debugInt[13] = nAtOne;
1150     nZero = 0;
1151     n = 0;
1152     for (int i = 0; i < numberColumns; i++) {
1153       double value = fabs(objective[i]);
1154       if (value)
1155         check[n++] = value;
1156       else
1157         nZero++;
1158     }
1159     debugInt[21] = nZero;
1160     if (n) {
1161       std::sort(check, check + n);
1162       debugDouble[2] = check[0];
1163       debugDouble[3] = check[n - 1];
1164     } else {
1165       debugDouble[2] = 0.0;
1166       debugDouble[3] = 0.0;
1167     }
1168     nAtOne = 0;
1169     nDifferent = 0;
1170     last = -COIN_DBL_MAX;
1171     for (int i = 0; i < n; i++) {
1172       if (fabs(last - check[i]) > 1.0e-12) {
1173         nDifferent++;
1174         last = check[i];
1175       }
1176       if (check[i] == 1.0)
1177         nAtOne++;
1178     }
1179     debugInt[9] = nDifferent;
1180     debugInt[14] = nAtOne;
1181     nInf = 0;
1182     nZero = 0;
1183     n = 0;
1184     for (int i = 0; i < numberColumns; i++) {
1185       double value = fabs(columnLower[i]);
1186       if (!value)
1187         nZero++;
1188       else if (value != COIN_DBL_MAX)
1189         check[n++] = value;
1190       else
1191         nInf++;
1192     }
1193     for (int i = 0; i < numberColumns; i++) {
1194       double value = fabs(columnUpper[i]);
1195       if (!value)
1196         nZero++;
1197       else if (value != COIN_DBL_MAX)
1198         check[n++] = value;
1199       else
1200         nInf++;
1201     }
1202     debugInt[17] = nInf;
1203     double smallestColBound;
1204     double largestColBound;
1205     if (n) {
1206       std::sort(check, check + n);
1207       smallestColBound = check[0];
1208       largestColBound = check[n - 1];
1209     } else {
1210       smallestColBound = 0.0;
1211       largestColBound = 0.0;
1212     }
1213     nAtOne = 0;
1214     nDifferent = 0;
1215     last = -COIN_DBL_MAX;
1216     for (int i = 0; i < n; i++) {
1217       if (fabs(last - check[i]) > 1.0e-12) {
1218         nDifferent++;
1219         last = check[i];
1220       }
1221       if (check[i] == 1.0)
1222         nAtOne++;
1223     }
1224     //debugInt[8]=nDifferent;
1225     //debugInt[13]=nAtOne;
1226     printf("BENCHMARK_STATS rhs %d different - %g -> %g (%d at one, %d infinite, %d zero)\n",
1227       debugInt[8], debugDouble[0], debugDouble[1], debugInt[13], debugInt[16], debugInt[20]);
1228     printf("BENCHMARK_STATS col %d different - %g -> %g (%d at one, %d infinite, %d zero)\n",
1229       nDifferent, smallestColBound, largestColBound, nAtOne, nInf, nZero);
1230     printf("BENCHMARK_STATS els %d different - %g -> %g (%d at one) - longest r,c %d,%d\n",
1231       debugInt[10], debugDouble[4], debugDouble[5], debugInt[15],
1232       debugInt[11], debugInt[12]);
1233     printf("BENCHMARK_STATS obj %d different - %g -> %g (%d at one, %d zero) - time %g\n",
1234       debugInt[9], debugDouble[2], debugDouble[3], debugInt[14], debugInt[21],
1235       CoinCpuTime() - time1);
1236     delete[] check;
1237   }
1238 #endif
1239   if (interrupt)
1240     currentModel = model2;
1241   int saveMoreOptions = moreSpecialOptions_;
1242   // For below >0 overrides
1243   // 0 means no, -1 means maybe
1244   int doIdiot = 0;
1245   int doCrash = 0;
1246   int doSprint = 0;
1247   int doSlp = 0;
1248   int primalStartup = 1;
1249   model2->eventHandler()->event(ClpEventHandler::presolveBeforeSolve);
1250 #if CLP_POOL_MATRIX
1251   if (vectorMode() >= 10) {
1252     ClpPoolMatrix *poolMatrix = new ClpPoolMatrix(*model2->matrix());
1253     char output[80];
1254     int numberDifferent = poolMatrix->getNumDifferentElements();
1255     if (numberDifferent > 0) {
1256       sprintf(output, "Pool matrix has %d different values",
1257         numberDifferent);
1258       model2->replaceMatrix(poolMatrix, true);
1259     } else {
1260       delete poolMatrix;
1261       sprintf(output, "Pool matrix has more than %d different values - no good",
1262         -numberDifferent);
1263     }
1264     handler_->message(CLP_GENERAL, messages_) << output
1265                                               << CoinMessageEol;
1266   }
1267 #endif
1268   int tryItSave = 0;
1269 #if CLPSOLVE_ACTIONS
1270   if (method == ClpSolve::automatic)
1271     model2->moreSpecialOptions_ |= 8192; // stop switch over
1272 #endif
1273   // switch to primal from automatic if just one cost entry
1274   if (method == ClpSolve::automatic && model2->numberColumns() > 5000
1275 #ifndef CLPSOLVE_ACTIONS
1276     && (specialOptions_ & 1024) != 0
1277 #endif
1278   ) {
1279     // look at original model for objective
1280     int numberColumns = model2->numberColumns();
1281     int numberRows = model2->numberRows();
1282     int numberColumnsOrig = this->numberColumns();
1283     const double *obj = this->objective();
1284     int nNon = 0;
1285     bool allOnes = true;
1286     for (int i = 0; i < numberColumnsOrig; i++) {
1287       if (obj[i]) {
1288         nNon++;
1289         if (fabs(obj[i]) != 1.0)
1290           allOnes = false;
1291       }
1292     }
1293     if (nNon <= 1 || allOnes || (options.getExtraInfo(1) > 0 && options.getSpecialOption(1) == 2)) {
1294 #ifdef COIN_DEVELOP
1295       printf("Forcing primal\n");
1296 #endif
1297       method = ClpSolve::usePrimal;
1298 #ifndef CLPSOLVE_ACTIONS
1299       tryItSave = (numberRows > 200 && numberColumns > 2000 && (numberColumns > 2 * numberRows || (specialOptions_ & 1024) != 0)) ? 3 : 0;
1300 #else
1301       if (numberRows > 200 && numberColumns > 2000 && numberColumns > 2 * numberRows) {
1302         tryItSave = 3;
1303       } else {
1304         // If rhs also rubbish then maybe
1305         int numberRowsOrig = this->numberRows();
1306         const double *rowLower = this->rowLower();
1307         const double *rowUpper = this->rowUpper();
1308         double last = COIN_DBL_MAX;
1309         int nDifferent = 0;
1310         for (int i = 0; i < numberRowsOrig; i++) {
1311           double value = fabs(rowLower[i]);
1312           if (value && value != COIN_DBL_MAX) {
1313             if (value != last) {
1314               nDifferent++;
1315               last = value;
1316             }
1317           }
1318           value = fabs(rowUpper[i]);
1319           if (value && value != COIN_DBL_MAX) {
1320             if (value != last) {
1321               nDifferent++;
1322               last = value;
1323             }
1324           }
1325         }
1326         if (nDifferent < 2)
1327           tryItSave = 1;
1328       }
1329 #endif
1330     }
1331   }
1332   if (method != ClpSolve::useDual && method != ClpSolve::useBarrier
1333     && method != ClpSolve::tryBenders && method != ClpSolve::tryDantzigWolfe
1334     && method != ClpSolve::useBarrierNoCross) {
1335     switch (options.getSpecialOption(1)) {
1336     case 0:
1337       doIdiot = -1;
1338       doCrash = -1;
1339       doSprint = -1;
1340       break;
1341     case 1:
1342       doIdiot = 0;
1343       doCrash = 1;
1344       if (options.getExtraInfo(1) > 0)
1345         doCrash = options.getExtraInfo(1);
1346       doSprint = 0;
1347       break;
1348     case 2:
1349       doIdiot = 1;
1350       if (options.getExtraInfo(1) > 0)
1351         doIdiot = options.getExtraInfo(1);
1352       doCrash = 0;
1353       doSprint = 0;
1354       break;
1355     case 3:
1356       doIdiot = 0;
1357       doCrash = 0;
1358       doSprint = 1;
1359       break;
1360     case 4:
1361       doIdiot = 0;
1362       doCrash = 0;
1363       doSprint = 0;
1364       break;
1365     case 5:
1366       doIdiot = 0;
1367       doCrash = -1;
1368       doSprint = -1;
1369       break;
1370     case 6:
1371       doIdiot = -1;
1372       doCrash = -1;
1373       doSprint = 0;
1374       break;
1375     case 7:
1376       doIdiot = -1;
1377       doCrash = 0;
1378       doSprint = -1;
1379       break;
1380     case 8:
1381       doIdiot = -1;
1382       doCrash = 0;
1383       doSprint = 0;
1384       break;
1385     case 9:
1386       doIdiot = 0;
1387       doCrash = 0;
1388       doSprint = -1;
1389       break;
1390     case 10:
1391       doIdiot = 0;
1392       doCrash = 0;
1393       doSprint = 0;
1394       if (options.getExtraInfo(1))
1395         doSlp = options.getExtraInfo(1);
1396       break;
1397     case 11:
1398       doIdiot = 0;
1399       doCrash = 0;
1400       doSprint = 0;
1401       primalStartup = 0;
1402       break;
1403     default:
1404       abort();
1405     }
1406   } else if (method != ClpSolve::tryBenders && method != ClpSolve::tryDantzigWolfe) {
1407     // Dual
1408     switch (options.getSpecialOption(0)) {
1409     case 0:
1410       doIdiot = 0;
1411       doCrash = 0;
1412       doSprint = 0;
1413       break;
1414     case 1:
1415       doIdiot = 0;
1416       doCrash = 1;
1417       if (options.getExtraInfo(0) > 0)
1418         doCrash = options.getExtraInfo(0);
1419       doSprint = 0;
1420       break;
1421     case 2:
1422       doIdiot = -1;
1423       if (options.getExtraInfo(0) > 0)
1424         doIdiot = options.getExtraInfo(0);
1425       doCrash = 0;
1426       doSprint = 0;
1427       break;
1428     default:
1429       abort();
1430     }
1431   } else {
1432     // decomposition
1433   }
1434 #ifndef NO_RTTI
1435   ClpQuadraticObjective *quadraticObj = (dynamic_cast< ClpQuadraticObjective * >(objectiveAsObject()));
1436 #else
1437   ClpQuadraticObjective *quadraticObj = NULL;
1438   if (objective_->type() == 2)
1439     quadraticObj = (static_cast< ClpQuadraticObjective * >(objective_));
1440 #endif
1441   // If quadratic then primal or barrier or slp
1442   if (quadraticObj) {
1443     doSprint = 0;
1444     //doIdiot = 0;
1445     // off
1446     if (method == ClpSolve::useBarrier)
1447       method = ClpSolve::useBarrierNoCross;
1448     else if (method != ClpSolve::useBarrierNoCross)
1449       method = ClpSolve::usePrimal;
1450   }
1451 #ifdef COIN_HAS_VOL
1452   // Save number of idiot
1453   int saveDoIdiot = doIdiot;
1454 #endif
1455   // Just do this number of passes in Sprint
1456   int maxSprintPass = 100;
1457   // See if worth trying +- one matrix
1458   bool plusMinus = false;
1459   CoinBigIndex numberElements = model2->getNumElements();
1460 #ifndef SLIM_CLP
1461 #ifndef NO_RTTI
1462   if (dynamic_cast< ClpNetworkMatrix * >(matrix_)) {
1463     // network - switch off stuff
1464     doIdiot = 0;
1465     if (doSprint < 0)
1466       doSprint = 0;
1467   }
1468 #else
1469   if (matrix_->type() == 11) {
1470     // network - switch off stuff
1471     doIdiot = 0;
1472     //doSprint=0;
1473   }
1474 #endif
1475 #endif
1476   int numberColumns = model2->numberColumns();
1477   int numberRows = model2->numberRows();
1478   // If not all slack basis - switch off all except sprint
1479   int numberRowsBasic = 0;
1480   int iRow;
1481   for (iRow = 0; iRow < numberRows; iRow++)
1482     if (model2->getRowStatus(iRow) == basic)
1483       numberRowsBasic++;
1484   if (numberRowsBasic < numberRows && objective_->type() < 2) {
1485     doIdiot = 0;
1486     doCrash = 0;
1487     //doSprint=0;
1488   }
1489   if (options.getSpecialOption(3) == 0) {
1490     if (numberElements > 100000)
1491       plusMinus = true;
1492     if (numberElements > 10000 && (doIdiot || doSprint))
1493       plusMinus = true;
1494   } else if ((specialOptions_ & 1024) != 0) {
1495     plusMinus = true;
1496   }
1497 #ifndef SLIM_CLP
1498   // Statistics (+1,-1, other) - used to decide on strategy if not +-1
1499   CoinBigIndex statistics[3] = { -1, 0, 0 };
1500   if (plusMinus) {
1501     saveMatrix = model2->clpMatrix();
1502 #ifndef NO_RTTI
1503     ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(saveMatrix);
1504 #else
1505     ClpPackedMatrix *clpMatrix = NULL;
1506     if (saveMatrix->type() == 1)
1507       clpMatrix = static_cast< ClpPackedMatrix * >(saveMatrix);
1508 #endif
1509     if (clpMatrix) {
1510       ClpPlusMinusOneMatrix *newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
1511       if (newMatrix->getIndices()) {
1512         // CHECKME This test of specialOptions and the one above
1513         // don't seem compatible.
1514 #ifndef ABC_INHERIT
1515         if ((specialOptions_ & 1024) == 0) {
1516           model2->replaceMatrix(newMatrix);
1517         } else {
1518 #endif
1519           // in integer (or abc) - just use for sprint/idiot
1520           saveMatrix = NULL;
1521           delete newMatrix;
1522 #ifndef ABC_INHERIT
1523         }
1524 #endif
1525       } else {
1526         handler_->message(CLP_MATRIX_CHANGE, messages_)
1527           << "+- 1"
1528           << CoinMessageEol;
1529         CoinMemcpyN(newMatrix->startPositive(), 3, statistics);
1530         saveMatrix = NULL;
1531         plusMinus = false;
1532         delete newMatrix;
1533       }
1534     } else {
1535       saveMatrix = NULL;
1536       plusMinus = false;
1537     }
1538   }
1539 #endif
1540   if (this->factorizationFrequency() == 200) {
1541     // User did not touch preset
1542     model2->defaultFactorizationFrequency();
1543   } else if (model2 != this) {
1544     // make sure model2 has correct value
1545     model2->setFactorizationFrequency(this->factorizationFrequency());
1546   }
1547   if (method == ClpSolve::automatic) {
1548     if (doSprint == 0 && doIdiot == 0) {
1549       // off
1550       method = ClpSolve::useDual;
1551     } else {
1552       // only do primal if sprint or idiot
1553       if (doSprint > 0) {
1554         method = ClpSolve::usePrimalorSprint;
1555       } else if (doIdiot > 0) {
1556         method = ClpSolve::usePrimal;
1557       } else {
1558         if (numberElements < 500000) {
1559           // Small problem
1560           if (numberRows * 10 > numberColumns || numberColumns < 6000
1561             || (numberRows * 20 > numberColumns && !plusMinus))
1562             doSprint = 0; // switch off sprint
1563         } else {
1564           // larger problem
1565           if (numberRows * 8 > numberColumns)
1566             doSprint = 0; // switch off sprint
1567         }
1568         // switch off idiot or sprint if any free variable
1569         // switch off sprint if very few with costs
1570         // or great variation in cost
1571         int iColumn;
1572         const double *columnLower = model2->columnLower();
1573         const double *columnUpper = model2->columnUpper();
1574         const double *objective = model2->objective();
1575         int nObj = 0;
1576         int nFree = 0;
1577         double smallestObj = COIN_DBL_MAX;
1578         double largestObj = 0.0;
1579         for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1580           if (columnLower[iColumn] < -1.0e10 && columnUpper[iColumn] > 1.0e10) {
1581             nFree++;
1582           } else if (objective[iColumn]) {
1583             nObj++;
1584             smallestObj = CoinMin(smallestObj, objective[iColumn]);
1585             largestObj = CoinMax(largestObj, objective[iColumn]);
1586           }
1587         }
1588         if (nObj * 10 < numberColumns || smallestObj * 10.0 < largestObj)
1589           doSprint = 0;
1590         if (nFree)
1591           doIdiot = 0;
1592         if (nFree * 10 > numberRows)
1593           doSprint = 0;
1594         int nPasses = 0;
1595         // look at rhs
1596         int iRow;
1597         double largest = 0.0;
1598         double smallest = 1.0e30;
1599         double largestGap = 0.0;
1600         int numberNotE = 0;
1601         bool notInteger = false;
1602         for (iRow = 0; iRow < numberRows; iRow++) {
1603           double value1 = model2->rowLower_[iRow];
1604           if (value1 && value1 > -1.0e31) {
1605             largest = CoinMax(largest, fabs(value1));
1606             smallest = CoinMin(smallest, fabs(value1));
1607             if (fabs(value1 - floor(value1 + 0.5)) > 1.0e-8) {
1608               notInteger = true;
1609               break;
1610             }
1611           }
1612           double value2 = model2->rowUpper_[iRow];
1613           if (value2 && value2 < 1.0e31) {
1614             largest = CoinMax(largest, fabs(value2));
1615             smallest = CoinMin(smallest, fabs(value2));
1616             if (fabs(value2 - floor(value2 + 0.5)) > 1.0e-8) {
1617               notInteger = true;
1618               break;
1619             }
1620           }
1621           // CHECKME This next bit can't be right...
1622           if (value2 > value1) {
1623             numberNotE++;
1624             //if (value2 > 1.0e31 || value1 < -1.0e31)
1625             //   largestGap = COIN_DBL_MAX;
1626             //else
1627             //   largestGap = value2 - value1;
1628           }
1629         }
1630         int tryIt = (numberRows > 200 && numberColumns > 2000 && (numberColumns > 2 * numberRows || (method != ClpSolve::useDual && (specialOptions_ & 1024) != 0))) ? 3 : 0;
1631         tryItSave = tryIt;
1632         if (numberRows < 1000 && numberColumns < 3000)
1633           tryIt = 0;
1634         if (notInteger)
1635           tryIt = 0;
1636         if (largest / smallest > 10 || (largest / smallest > 2.0 && largest > 50))
1637           tryIt = 0;
1638         if (tryIt) {
1639           if (largest / smallest > 2.0) {
1640             nPasses = 10 + numberColumns / 100000;
1641             nPasses = CoinMin(nPasses, 50);
1642             nPasses = CoinMax(nPasses, 15);
1643             if (numberRows > 20000 && nPasses > 5) {
1644               // Might as well go for it
1645               nPasses = CoinMax(nPasses, 71);
1646             } else if (numberRows > 2000 && nPasses > 5) {
1647               nPasses = CoinMax(nPasses, 50);
1648             } else if (numberElements < 3 * numberColumns) {
1649               nPasses = CoinMin(nPasses, 10); // probably not worh it
1650             }
1651           } else if (largest / smallest > 1.01 || numberElements <= 3 * numberColumns) {
1652             nPasses = 10 + numberColumns / 1000;
1653             nPasses = CoinMin(nPasses, 100);
1654             nPasses = CoinMax(nPasses, 30);
1655             if (numberRows > 25000) {
1656               // Might as well go for it
1657               nPasses = CoinMax(nPasses, 71);
1658             }
1659             if (!largestGap)
1660               nPasses *= 2;
1661           } else {
1662             nPasses = 10 + numberColumns / 1000;
1663             nPasses = CoinMax(nPasses, 100);
1664             if (!largestGap)
1665               nPasses *= 2;
1666             nPasses = CoinMin(nPasses, 200);
1667           }
1668         }
1669         //printf("%d rows %d cols plus %c tryIt %c largest %g smallest %g largestGap %g npasses %d sprint %c\n",
1670         //     numberRows,numberColumns,plusMinus ? 'Y' : 'N',
1671         //     tryIt ? 'Y' :'N',largest,smallest,largestGap,nPasses,doSprint ? 'Y' :'N');
1672         //exit(0);
1673         if (!tryIt || nPasses <= 5)
1674           doIdiot = 0;
1675 #if CLPSOLVE_ACTIONS
1676         if (doIdiot && doSprint < 0 && wasAutomatic && 20 * model2->numberRows() > model2->numberColumns())
1677           doSprint = 0; // switch off sprint
1678 #endif
1679         if (doSprint) {
1680           method = ClpSolve::usePrimalorSprint;
1681         } else if (doIdiot) {
1682           method = ClpSolve::usePrimal;
1683         } else {
1684           method = ClpSolve::useDual;
1685         }
1686       }
1687     }
1688   }
1689   if (method == ClpSolve::tryBenders) {
1690     // Now build model
1691     int lengthNames = model2->lengthNames();
1692     model2->setLengthNames(0);
1693     CoinModel *build = model2->createCoinModel();
1694     model2->setLengthNames(lengthNames);
1695     CoinStructuredModel benders;
1696     build->convertMatrix();
1697     int numberBlocks = options.independentOption(0);
1698     benders.setMessageHandler(handler_);
1699     numberBlocks = benders.decompose(*build, 2, numberBlocks, NULL);
1700     delete build;
1701     //exit(0);
1702     if (numberBlocks) {
1703       options.setIndependentOption(1, 1); // don't do final clean up
1704       model2->solveBenders(&benders, options);
1705       //move solution
1706       method = ClpSolve::notImplemented;
1707       time2 = CoinCpuTime();
1708       timeCore = time2 - timeX;
1709       handler_->message(CLP_INTERVAL_TIMING, messages_)
1710         << "Crossover" << timeCore << time2 - time1
1711         << CoinMessageEol;
1712       timeX = time2;
1713     } else {
1714       printf("No structure\n");
1715       method = ClpSolve::useDual;
1716     }
1717   } else if (method == ClpSolve::tryDantzigWolfe) {
1718     abort();
1719   }
1720   if (method == ClpSolve::usePrimalorSprint) {
1721     if (doSprint < 0) {
1722       if (numberElements < 500000) {
1723         // Small problem
1724         if (numberRows * 10 > numberColumns || numberColumns < 6000
1725           || (numberRows * 20 > numberColumns && !plusMinus))
1726           method = ClpSolve::usePrimal; // switch off sprint
1727       } else {
1728         // larger problem
1729         if (numberRows * 8 > numberColumns)
1730           method = ClpSolve::usePrimal; // switch off sprint
1731         // but make lightweight
1732         if (numberRows * 10 > numberColumns || numberColumns < 6000
1733           || (numberRows * 20 > numberColumns && !plusMinus))
1734           maxSprintPass = 10;
1735       }
1736     } else if (doSprint == 0) {
1737       method = ClpSolve::usePrimal; // switch off sprint
1738     }
1739   }
1740   if (method == ClpSolve::useDual) {
1741 #ifdef CLP_USEFUL_PRINTOUT
1742     debugInt[6] = 1;
1743 #endif
1744     double *saveLower = NULL;
1745     double *saveUpper = NULL;
1746     if (presolve == ClpSolve::presolveOn) {
1747       int numberInfeasibilities = model2->tightenPrimalBounds(0.0, 0);
1748       if (numberInfeasibilities) {
1749         handler_->message(CLP_INFEASIBLE, messages_)
1750           << CoinMessageEol;
1751         delete model2;
1752         model2 = this;
1753         presolve = ClpSolve::presolveOff;
1754       }
1755     } else if (numberRows_ + numberColumns_ > 5000) {
1756       // do anyway
1757       saveLower = new double[numberRows_ + numberColumns_];
1758       CoinMemcpyN(model2->columnLower(), numberColumns_, saveLower);
1759       CoinMemcpyN(model2->rowLower(), numberRows_, saveLower + numberColumns_);
1760       saveUpper = new double[numberRows_ + numberColumns_];
1761       CoinMemcpyN(model2->columnUpper(), numberColumns_, saveUpper);
1762       CoinMemcpyN(model2->rowUpper(), numberRows_, saveUpper + numberColumns_);
1763       int numberInfeasibilities = model2->tightenPrimalBounds();
1764       if (numberInfeasibilities) {
1765         handler_->message(CLP_INFEASIBLE, messages_)
1766           << CoinMessageEol;
1767         CoinMemcpyN(saveLower, numberColumns_, model2->columnLower());
1768         CoinMemcpyN(saveLower + numberColumns_, numberRows_, model2->rowLower());
1769         delete[] saveLower;
1770         saveLower = NULL;
1771         CoinMemcpyN(saveUpper, numberColumns_, model2->columnUpper());
1772         CoinMemcpyN(saveUpper + numberColumns_, numberRows_, model2->rowUpper());
1773         delete[] saveUpper;
1774         saveUpper = NULL;
1775         // return if wanted
1776         if (options.infeasibleReturn() || (moreSpecialOptions_ & 1) != 0)
1777           return -1;
1778       }
1779     }
1780 #ifndef COIN_HAS_VOL
1781     // switch off idiot and volume for now
1782     doIdiot = 0;
1783 #endif
1784     // pick up number passes
1785     int nPasses = 0;
1786     int numberNotE = 0;
1787 #ifndef SLIM_CLP
1788     if ((doIdiot < 0 && plusMinus) || doIdiot > 0) {
1789       // See if candidate for idiot
1790       nPasses = 0;
1791       Idiot info(*model2);
1792       info.setStrategy(idiotOptions | info.getStrategy());
1793       // Get average number of elements per column
1794       double ratio = static_cast< double >(numberElements) / static_cast< double >(numberColumns);
1795       // look at rhs
1796       int iRow;
1797       double largest = 0.0;
1798       double smallest = 1.0e30;
1799       for (iRow = 0; iRow < numberRows; iRow++) {
1800         double value1 = model2->rowLower_[iRow];
1801         if (value1 && value1 > -1.0e31) {
1802           largest = CoinMax(largest, fabs(value1));
1803           smallest = CoinMin(smallest, fabs(value1));
1804         }
1805         double value2 = model2->rowUpper_[iRow];
1806         if (value2 && value2 < 1.0e31) {
1807           largest = CoinMax(largest, fabs(value2));
1808           smallest = CoinMin(smallest, fabs(value2));
1809         }
1810         if (value2 > value1) {
1811           numberNotE++;
1812         }
1813       }
1814       if (doIdiot < 0) {
1815         if (numberRows > 200 && numberColumns > 5000 && ratio >= 3.0 && largest / smallest < 1.1 && !numberNotE) {
1816           nPasses = 71;
1817         }
1818       }
1819       if (doIdiot > 0) {
1820         nPasses = CoinMax(nPasses, doIdiot);
1821         if (nPasses > 70) {
1822           info.setStartingWeight(1.0e3);
1823           info.setDropEnoughFeasibility(0.01);
1824         }
1825       }
1826       if (nPasses > 20) {
1827 #ifdef COIN_HAS_VOL
1828         int returnCode = solveWithVolume(model2, nPasses, saveDoIdiot);
1829         if (!returnCode) {
1830           time2 = CoinCpuTime();
1831           timeIdiot = time2 - timeX;
1832           handler_->message(CLP_INTERVAL_TIMING, messages_)
1833             << "Idiot Crash" << timeIdiot << time2 - time1
1834             << CoinMessageEol;
1835           timeX = time2;
1836         } else {
1837           nPasses = 0;
1838         }
1839 #else
1840         nPasses = 0;
1841 #endif
1842       } else {
1843         nPasses = 0;
1844       }
1845     }
1846 #endif
1847     if (doCrash) {
1848 #ifdef ABC_INHERIT
1849       if (!model2->abcState()) {
1850 #endif
1851         switch (doCrash) {
1852           // standard
1853         case 1:
1854           model2->crash(1000, 1);
1855           break;
1856           // As in paper by Solow and Halim (approx)
1857         case 2:
1858         case 3:
1859           model2->crash(model2->dualBound(), 0);
1860           break;
1861           // Just put free in basis
1862         case 4:
1863           model2->crash(0.0, 3);
1864           break;
1865         }
1866 #ifdef ABC_INHERIT
1867       } else if (doCrash >= 0) {
1868         model2->setAbcState(model2->abcState() | 256 * doCrash);
1869       }
1870 #endif
1871     }
1872     if (!nPasses) {
1873       int saveOptions = model2->specialOptions();
1874       if (model2->numberRows() > 100)
1875         model2->setSpecialOptions(saveOptions | 64); // go as far as possible
1876       //int numberRows = model2->numberRows();
1877       //int numberColumns = model2->numberColumns();
1878       if (dynamic_cast< ClpPackedMatrix * >(matrix_)) {
1879         // See if original wanted vector
1880         ClpPackedMatrix *clpMatrixO = dynamic_cast< ClpPackedMatrix * >(matrix_);
1881         ClpMatrixBase *matrix = model2->clpMatrix();
1882         if (dynamic_cast< ClpPackedMatrix * >(matrix) && clpMatrixO->wantsSpecialColumnCopy()) {
1883           ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix);
1884           clpMatrix->makeSpecialColumnCopy();
1885           //model2->setSpecialOptions(model2->specialOptions()|256); // to say no row copy for comparisons
1886           model2->dual(0);
1887           clpMatrix->releaseSpecialColumnCopy();
1888         } else {
1889 #ifndef ABC_INHERIT
1890           model2->dual(0);
1891 #else
1892           model2->dealWithAbc(0, 0, interrupt);
1893 #endif
1894         }
1895       } else {
1896         model2->dual(0);
1897       }
1898     } else if (!numberNotE && 0) {
1899       // E so we can do in another way
1900       double *pi = model2->dualRowSolution();
1901       int i;
1902       int numberColumns = model2->numberColumns();
1903       int numberRows = model2->numberRows();
1904       double *saveObj = new double[numberColumns];
1905       CoinMemcpyN(model2->objective(), numberColumns, saveObj);
1906       CoinMemcpyN(model2->objective(),
1907         numberColumns, model2->dualColumnSolution());
1908       model2->clpMatrix()->transposeTimes(-1.0, pi, model2->dualColumnSolution());
1909       CoinMemcpyN(model2->dualColumnSolution(),
1910         numberColumns, model2->objective());
1911       const double *rowsol = model2->primalRowSolution();
1912       double offset = 0.0;
1913       for (i = 0; i < numberRows; i++) {
1914         offset += pi[i] * rowsol[i];
1915       }
1916       double value2;
1917       model2->getDblParam(ClpObjOffset, value2);
1918       //printf("Offset %g %g\n",offset,value2);
1919       model2->setDblParam(ClpObjOffset, value2 - offset);
1920       model2->setPerturbation(51);
1921       //model2->setRowObjective(pi);
1922       // zero out pi
1923       //memset(pi,0,numberRows*sizeof(double));
1924       // Could put some in basis - only partially tested
1925       model2->allSlackBasis();
1926       //model2->factorization()->maximumPivots(200);
1927       //model2->setLogLevel(63);
1928       // solve
1929       model2->dual(0);
1930       model2->setDblParam(ClpObjOffset, value2);
1931       CoinMemcpyN(saveObj, numberColumns, model2->objective());
1932       // zero out pi
1933       //memset(pi,0,numberRows*sizeof(double));
1934       //model2->setRowObjective(pi);
1935       delete[] saveObj;
1936       //model2->dual(0);
1937       model2->setPerturbation(50);
1938       model2->primal();
1939     } else {
1940       // solve
1941       model2->setPerturbation(100);
1942       model2->dual(2);
1943       model2->setPerturbation(50);
1944       model2->dual(0);
1945     }
1946     if (saveLower) {
1947       CoinMemcpyN(saveLower, numberColumns_, model2->columnLower());
1948       CoinMemcpyN(saveLower + numberColumns_, numberRows_, model2->rowLower());
1949       delete[] saveLower;
1950       saveLower = NULL;
1951       CoinMemcpyN(saveUpper, numberColumns_, model2->columnUpper());
1952       CoinMemcpyN(saveUpper + numberColumns_, numberRows_, model2->rowUpper());
1953       delete[] saveUpper;
1954       saveUpper = NULL;
1955     }
1956     time2 = CoinCpuTime();
1957     timeCore = time2 - timeX;
1958     handler_->message(CLP_INTERVAL_TIMING, messages_)
1959       << "Dual" << timeCore << time2 - time1
1960       << CoinMessageEol;
1961     timeX = time2;
1962   } else if (method == ClpSolve::usePrimal) {
1963 #ifdef CLP_USEFUL_PRINTOUT
1964     debugInt[6] = 2;
1965 #endif
1966 #ifndef SLIM_CLP
1967     if (doIdiot) {
1968       int nPasses = 0;
1969       Idiot info(*model2);
1970       info.setStrategy(idiotOptions | info.getStrategy());
1971       // Get average number of elements per column
1972       double ratio = static_cast< double >(numberElements) / static_cast< double >(numberColumns);
1973       // look at rhs
1974       int iRow;
1975       double largest = 0.0;
1976       double smallest = 1.0e30;
1977       double largestGap = 0.0;
1978       int numberNotE = 0;
1979       for (iRow = 0; iRow < numberRows; iRow++) {
1980         double value1 = model2->rowLower_[iRow];
1981         if (value1 && value1 > -1.0e31) {
1982           largest = CoinMax(largest, fabs(value1));
1983           smallest = CoinMin(smallest, fabs(value1));
1984         }
1985         double value2 = model2->rowUpper_[iRow];
1986         if (value2 && value2 < 1.0e31) {
1987           largest = CoinMax(largest, fabs(value2));
1988           smallest = CoinMin(smallest, fabs(value2));
1989         }
1990         if (value2 > value1) {
1991           numberNotE++;
1992           if (value2 > 1.0e31 || value1 < -1.0e31)
1993             largestGap = COIN_DBL_MAX;
1994           else
1995             largestGap = value2 - value1;
1996         }
1997       }
1998       bool increaseSprint = plusMinus;
1999       if ((specialOptions_ & 1024) != 0)
2000         increaseSprint = false;
2001       if (!plusMinus) {
2002         // If 90% +- 1 then go for sprint
2003         if (statistics[0] >= 0 && 10 * statistics[2] < statistics[0] + statistics[1])
2004           increaseSprint = true;
2005       }
2006       int tryIt = tryItSave;
2007       if (numberRows < 1000 && numberColumns < 3000)
2008         tryIt = 0;
2009       if (tryIt) {
2010         if (increaseSprint) {
2011           info.setStartingWeight(1.0e3);
2012           info.setReduceIterations(6);
2013           // also be more lenient on infeasibilities
2014           info.setDropEnoughFeasibility(0.5 * info.getDropEnoughFeasibility());
2015           info.setDropEnoughWeighted(-2.0);
2016           if (largest / smallest > 2.0) {
2017             nPasses = 10 + numberColumns / 100000;
2018             nPasses = CoinMin(nPasses, 50);
2019             nPasses = CoinMax(nPasses, 15);
2020             if (numberRows > 20000 && nPasses > 5) {
2021               // Might as well go for it
2022               nPasses = CoinMax(nPasses, 71);
2023             } else if (numberRows > 2000 && nPasses > 5) {
2024               nPasses = CoinMax(nPasses, 50);
2025             } else if (numberElements < 3 * numberColumns) {
2026               nPasses = CoinMin(nPasses, 10); // probably not worh it
2027               if (doIdiot < 0)
2028                 info.setLightweight(1); // say lightweight idiot
2029             } else {
2030               if (doIdiot < 0)
2031                 info.setLightweight(1); // say lightweight idiot
2032             }
2033           } else if (largest / smallest > 1.01 || numberElements <= 3 * numberColumns) {
2034             nPasses = 10 + numberColumns / 1000;
2035             nPasses = CoinMin(nPasses, 100);
2036             nPasses = CoinMax(nPasses, 30);
2037             if (numberRows > 25000) {
2038               // Might as well go for it
2039               nPasses = CoinMax(nPasses, 71);
2040             }
2041             if (!largestGap)
2042               nPasses *= 2;
2043           } else {
2044             nPasses = 10 + numberColumns / 1000;
2045             nPasses = CoinMin(nPasses, 200);
2046             nPasses = CoinMax(nPasses, 100);
2047             info.setStartingWeight(1.0e-1);
2048             info.setReduceIterations(6);
2049             if (!largestGap && nPasses <= 50)
2050               nPasses *= 2;
2051             //info.setFeasibilityTolerance(1.0e-7);
2052           }
2053           // If few passes - don't bother
2054           if (nPasses <= 5 && !plusMinus)
2055             nPasses = 0;
2056         } else {
2057           if (doIdiot < 0)
2058             info.setLightweight(1); // say lightweight idiot
2059           if (largest / smallest > 1.01 || numberNotE || statistics[2] > statistics[0] + statistics[1]) {
2060             if (numberRows > 25000 || numberColumns > 5 * numberRows) {
2061               nPasses = 50;
2062             } else if (numberColumns > 4 * numberRows) {
2063               nPasses = 20;
2064             } else {
2065               nPasses = 5;
2066             }
2067           } else {
2068             if (numberRows > 25000 || numberColumns > 5 * numberRows) {
2069               nPasses = 50;
2070               info.setLightweight(0); // say not lightweight idiot
2071             } else if (numberColumns > 4 * numberRows) {
2072               nPasses = 20;
2073             } else {
2074               nPasses = 15;
2075             }
2076           }
2077           if (ratio < 3.0) {
2078             nPasses = static_cast< int >(ratio * static_cast< double >(nPasses) / 4.0); // probably not worth it
2079           } else {
2080             nPasses = CoinMax(nPasses, 5);
2081           }
2082           if (numberRows > 25000 && nPasses > 5) {
2083             // Might as well go for it
2084             nPasses = CoinMax(nPasses, 71);
2085           } else if (increaseSprint) {
2086             nPasses *= 2;
2087             nPasses = CoinMin(nPasses, 71);
2088           } else if (nPasses == 5 && ratio > 5.0) {
2089             nPasses = static_cast< int >(static_cast< double >(nPasses) * (ratio / 5.0)); // increase if lots of elements per column
2090           }
2091           if (nPasses <= 5 && !plusMinus)
2092             nPasses = 0;
2093           //info.setStartingWeight(1.0e-1);
2094         }
2095         if (tryIt == 1) {
2096           idiotOptions |= 262144;
2097           info.setStrategy(idiotOptions | info.getStrategy());
2098           //model2->setSpecialOptions(model2->specialOptions()
2099           //			|8388608);
2100         }
2101       }
2102       if (doIdiot > 0) {
2103         // pick up number passes
2104         nPasses = options.getExtraInfo(1) % 1000000;
2105 #ifdef COIN_HAS_VOL
2106         int returnCode = solveWithVolume(model2, nPasses, saveDoIdiot);
2107         nPasses = 0;
2108         if (!returnCode) {
2109           time2 = CoinCpuTime();
2110           timeIdiot = time2 - timeX;
2111           handler_->message(CLP_INTERVAL_TIMING, messages_)
2112             << "Idiot Crash" << timeIdiot << time2 - time1
2113             << CoinMessageEol;
2114           timeX = time2;
2115         }
2116 #endif
2117 #ifdef CLP_USEFUL_PRINTOUT
2118         debugInt[6] = 4;
2119         debugInt[7] = nPasses;
2120 #endif
2121         if (nPasses > 70) {
2122           info.setStartingWeight(1.0e3);
2123           info.setReduceIterations(6);
2124           //if (nPasses > 200)
2125           //info.setFeasibilityTolerance(1.0e-9);
2126           //if (nPasses > 1900)
2127           //info.setWeightFactor(0.93);
2128           if (nPasses > 900) {
2129             double reductions = nPasses / 6.0;
2130             if (nPasses < 5000) {
2131               reductions /= 12.0;
2132             } else {
2133               reductions /= 13.0;
2134               info.setStartingWeight(1.0e4);
2135             }
2136             double ratio = 1.0 / std::pow(10.0, (1.0 / reductions));
2137             printf("%d passes reduction factor %g\n", nPasses, ratio);
2138             info.setWeightFactor(ratio);
2139           } else if (nPasses > 500) {
2140             info.setWeightFactor(0.7);
2141           } else if (nPasses > 200) {
2142             info.setWeightFactor(0.5);
2143           }
2144           if (maximumIterations() < nPasses) {
2145             printf("Presuming maximumIterations is just for Idiot\n");
2146             nPasses = maximumIterations();
2147             setMaximumIterations(COIN_INT_MAX);
2148             model2->setMaximumIterations(COIN_INT_MAX);
2149           }
2150           if (nPasses >= 10000 && nPasses < 100000) {
2151             int k = nPasses % 100;
2152             nPasses /= 200;
2153             info.setReduceIterations(3);
2154             if (k)
2155               info.setStartingWeight(1.0e2);
2156           }
2157           // also be more lenient on infeasibilities
2158           info.setDropEnoughFeasibility(0.5 * info.getDropEnoughFeasibility());
2159           info.setDropEnoughWeighted(-2.0);
2160         } else if (nPasses >= 50) {
2161           info.setStartingWeight(1.0e3);
2162           //info.setReduceIterations(6);
2163         }
2164         // For experimenting
2165         if (nPasses < 70 && (nPasses % 10) > 0 && (nPasses % 10) < 4) {
2166           info.setStartingWeight(1.0e3);
2167           info.setLightweight(nPasses % 10); // special testing
2168 #ifdef COIN_DEVELOP
2169           printf("warning - odd lightweight %d\n", nPasses % 10);
2170           //info.setReduceIterations(6);
2171 #endif
2172         }
2173       }
2174       if (options.getExtraInfo(1) > 1000000)
2175         nPasses += 1000000;
2176       if (nPasses) {
2177         doCrash = 0;
2178 #if 0
2179                     double * solution = model2->primalColumnSolution();
2180                     int iColumn;
2181                     double * saveLower = new double[numberColumns];
2182                     CoinMemcpyN(model2->columnLower(), numberColumns, saveLower);
2183                     double * saveUpper = new double[numberColumns];
2184                     CoinMemcpyN(model2->columnUpper(), numberColumns, saveUpper);
2185                     printf("doing tighten before idiot\n");
2186                     model2->tightenPrimalBounds();
2187                     // Move solution
2188                     double * columnLower = model2->columnLower();
2189                     double * columnUpper = model2->columnUpper();
2190                     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2191                          if (columnLower[iColumn] > 0.0)
2192                               solution[iColumn] = columnLower[iColumn];
2193                          else if (columnUpper[iColumn] < 0.0)
2194                               solution[iColumn] = columnUpper[iColumn];
2195                          else
2196                               solution[iColumn] = 0.0;
2197                     }
2198                     CoinMemcpyN(saveLower, numberColumns, columnLower);
2199                     CoinMemcpyN(saveUpper, numberColumns, columnUpper);
2200                     delete [] saveLower;
2201                     delete [] saveUpper;
2202 #else
2203         // Allow for crossover
2204         //#define LACI_TRY
2205 #ifndef LACI_TRY
2206         //if (doIdiot>0)
2207 #if 0 //def ABC_INHERIT
2208 		    if (!model2->abcState())
2209 #endif
2210         info.setStrategy(512 | info.getStrategy());
2211 #endif
2212         // Allow for scaling
2213         info.setStrategy(32 | info.getStrategy());
2214         int saveScalingFlag = model2->scalingFlag();
2215         bool linearObjective = objective_->type() < 2;
2216         if (!linearObjective)
2217           model2->scaling(0);
2218 #define CLP_DUAL_IDIOT
2219 #ifdef CLP_DUAL_IDIOT
2220         bool doubleIdiot = false;
2221         if (nPasses == 99 && linearObjective)
2222           doubleIdiot = true;
2223         if (doubleIdiot) {
2224           ClpSimplex *dualModel2 = static_cast< ClpSimplexOther * >(model2)->dualOfModel(1.0, 1.0);
2225           if (dualModel2) {
2226             printf("Dual of model has %d rows and %d columns\n",
2227               dualModel2->numberRows(), dualModel2->numberColumns());
2228             dualModel2->setOptimizationDirection(1.0);
2229             Idiot infoDual(info);
2230             infoDual.setModel(dualModel2);
2231 #if 0
2232 			info.setStrategy(512 | info.getStrategy());
2233 			// Allow for scaling
2234 			info.setStrategy(32 | info.getStrategy());
2235 			info.setStartingWeight(1.0e3);
2236 			info.setReduceIterations(6);
2237 #endif
2238             info.crash(nPasses, model2->messageHandler(),
2239               model2->messagesPointer(), false);
2240             infoDual.crash(nPasses, model2->messageHandler(),
2241               model2->messagesPointer(), false);
2242             // two copies of solutions
2243             ClpSimplex temp(*model2);
2244 #if 0
2245 			static_cast<ClpSimplexOther *> (&temp)->restoreFromDual(dualModel2);
2246 #else
2247             // move duals and just copy primal
2248             memcpy(temp.dualRowSolution(), dualModel2->primalColumnSolution(),
2249               numberRows * sizeof(double));
2250             memcpy(temp.primalColumnSolution(), model2->primalColumnSolution(),
2251               numberColumns * sizeof(double));
2252 #endif
2253             delete dualModel2;
2254             int numberRows = model2->numberRows();
2255             int numberColumns = model2->numberColumns();
2256             ClpSimplex *tempModel[2];
2257             tempModel[0] = model2;
2258             tempModel[1] = &temp;
2259             const double *primalColumn[2];
2260             const double *dualRow[2];
2261             double *dualColumn[2];
2262             double *primalRow[2];
2263             for (int i = 0; i < 2; i++) {
2264               primalColumn[i] = tempModel[i]->primalColumnSolution();
2265               dualRow[i] = tempModel[i]->dualRowSolution();
2266               dualColumn[i] = tempModel[i]->dualColumnSolution();
2267               primalRow[i] = tempModel[i]->primalRowSolution();
2268               memcpy(dualColumn[i], model2->objective(),
2269                 numberColumns * sizeof(double));
2270               memset(primalRow[i], 0, numberRows * sizeof(double));
2271               tempModel[i]->clpMatrix()->transposeTimes(-1.0,
2272                 dualRow[i],
2273                 dualColumn[i]);
2274               tempModel[i]->clpMatrix()->times(1.0,
2275                 primalColumn[i],
2276                 primalRow[i]);
2277               tempModel[i]->checkSolutionInternal();
2278               printf("model %d - dual inf %g primal inf %g\n",
2279                 i, tempModel[i]->sumDualInfeasibilities(),
2280                 tempModel[i]->sumPrimalInfeasibilities());
2281             }
2282             printf("What now\n");
2283           } else {
2284             doubleIdiot = false;
2285           }
2286         }
2287         if (!doubleIdiot)
2288           info.crash(nPasses, model2->messageHandler(), model2->messagesPointer(),
2289             (objective_->type() < 2));
2290 #else
2291         info.crash(nPasses, model2->messageHandler(), model2->messagesPointer(), (objective_->type() < 2));
2292 #endif
2293         model2->scaling(saveScalingFlag);
2294 #endif
2295         time2 = CoinCpuTime();
2296         timeIdiot = time2 - timeX;
2297         handler_->message(CLP_INTERVAL_TIMING, messages_)
2298           << "Idiot Crash" << timeIdiot << time2 - time1
2299           << CoinMessageEol;
2300         timeX = time2;
2301         if (nPasses > 100000 && nPasses < 100500) {
2302           // make sure no status left
2303           model2->createStatus();
2304           // solve
2305           if (model2->factorizationFrequency() == 200) {
2306             // User did not touch preset
2307             model2->defaultFactorizationFrequency();
2308           }
2309           //int numberRows = model2->numberRows();
2310           int numberColumns = model2->numberColumns();
2311           // save duals
2312           //double * saveDuals = CoinCopyOfArray(model2->dualRowSolution(),numberRows);
2313           // for moment this only works on nug etc (i.e. all ==)
2314           // needs row objective
2315           double *saveObj = CoinCopyOfArray(model2->objective(), numberColumns);
2316           double *pi = model2->dualRowSolution();
2317           model2->clpMatrix()->transposeTimes(-1.0, pi, model2->objective());
2318           // just primal values pass
2319           double saveScale = model2->objectiveScale();
2320           model2->setObjectiveScale(1.0e-3);
2321           model2->primal(2);
2322           model2->writeMps("xx.mps");
2323           double *solution = model2->primalColumnSolution();
2324           double *upper = model2->columnUpper();
2325           for (int i = 0; i < numberColumns; i++) {
2326             if (solution[i] < 100.0)
2327               upper[i] = 1000.0;
2328           }
2329           model2->setProblemStatus(-1);
2330           model2->setObjectiveScale(saveScale);
2331 #ifdef ABC_INHERIT
2332           AbcSimplex *abcModel2 = new AbcSimplex(*model2);
2333           if (interrupt)
2334             currentAbcModel = abcModel2;
2335           if (abcSimplex_) {
2336             // move factorization stuff
2337             abcModel2->factorization()->synchronize(model2->factorization(), abcModel2);
2338           }
2339           abcModel2->startPermanentArrays();
2340           abcModel2->setAbcState(CLP_ABC_WANTED);
2341 #if ABC_PARALLEL
2342           int parallelMode = 1;
2343           printf("Parallel mode %d\n", parallelMode);
2344           abcModel2->setParallelMode(parallelMode);
2345 #endif
2346           //if (processTune>0&&processTune<8)
2347           //abcModel2->setMoreSpecialOptions(abcModel2->moreSpecialOptions()|65536*processTune);
2348           abcModel2->doAbcDual();
2349           abcModel2->moveStatusToClp(model2);
2350           //ClpModel::stopPermanentArrays();
2351           model2->setSpecialOptions(model2->specialOptions() & ~65536);
2352           //model2->dual();
2353           //model2->setNumberIterations(abcModel2->numberIterations()+model2->numberIterations());
2354           delete abcModel2;
2355 #endif
2356           memcpy(model2->objective(), saveObj, numberColumns * sizeof(double));
2357           //delete [] saveDuals;
2358           delete[] saveObj;
2359           model2->dual(2);
2360         } // end dubious idiot
2361       }
2362     }
2363 #endif
2364     // ?
2365     if (doCrash) {
2366       switch (doCrash) {
2367         // standard
2368       case 1:
2369         model2->crash(1000, 1);
2370         break;
2371         // As in paper by Solow and Halim (approx)
2372       case 2:
2373         model2->crash(model2->dualBound(), 0);
2374         break;
2375         // My take on it
2376       case 3:
2377         model2->crash(model2->dualBound(), -1);
2378         break;
2379         // Just put free in basis
2380       case 4:
2381         model2->crash(0.0, 3);
2382         break;
2383       }
2384     }
2385 #ifndef SLIM_CLP
2386     if (doSlp && objective_->type() == 2) {
2387       model2->nonlinearSLP(doSlp, 1.0e-5);
2388     }
2389 #endif
2390 #ifndef LACI_TRY
2391     if (options.getSpecialOption(1) != 2 || options.getExtraInfo(1) < 1000000) {
2392       if (dynamic_cast< ClpPackedMatrix * >(matrix_)) {
2393         // See if original wanted vector
2394         ClpPackedMatrix *clpMatrixO = dynamic_cast< ClpPackedMatrix * >(matrix_);
2395         ClpMatrixBase *matrix = model2->clpMatrix();
2396         if (dynamic_cast< ClpPackedMatrix * >(matrix) && clpMatrixO->wantsSpecialColumnCopy()) {
2397           ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix);
2398           clpMatrix->makeSpecialColumnCopy();
2399           //model2->setSpecialOptions(model2->specialOptions()|256); // to say no row copy for comparisons
2400           model2->primal(primalStartup);
2401           clpMatrix->releaseSpecialColumnCopy();
2402         } else {
2403 #ifndef ABC_INHERIT
2404           model2->primal(primalStartup);
2405 #else
2406           model2->dealWithAbc(1, primalStartup, interrupt);
2407 #endif
2408         }
2409       } else {
2410 #ifndef ABC_INHERIT
2411         model2->primal(primalStartup);
2412 #else
2413         model2->dealWithAbc(1, primalStartup, interrupt);
2414 #endif
2415       }
2416     }
2417 #endif
2418     time2 = CoinCpuTime();
2419     timeCore = time2 - timeX;
2420     handler_->message(CLP_INTERVAL_TIMING, messages_)
2421       << "Primal" << timeCore << time2 - time1
2422       << CoinMessageEol;
2423     timeX = time2;
2424   } else if (method == ClpSolve::usePrimalorSprint) {
2425     // Sprint
2426     /*
2427             This driver implements what I called Sprint when I introduced the idea
2428             many years ago.  Cplex calls it "sifting" which I think is just as silly.
2429             When I thought of this trivial idea
2430             it reminded me of an LP code of the 60's called sprint which after
2431             every factorization took a subset of the matrix into memory (all
2432             64K words!) and then iterated very fast on that subset.  On the
2433             problems of those days it did not work very well, but it worked very
2434             well on aircrew scheduling problems where there were very large numbers
2435             of columns all with the same flavor.
2436           */
2437 
2438     /* The idea works best if you can get feasible easily.  To make it
2439              more general we can add in costed slacks */
2440 
2441     int originalNumberColumns = model2->numberColumns();
2442     int numberRows = model2->numberRows();
2443     ClpSimplex *originalModel2 = model2;
2444 
2445     // We will need arrays to choose variables.  These are too big but ..
2446     double *weight = new double[numberRows + originalNumberColumns];
2447     int *sort = new int[numberRows + originalNumberColumns];
2448     int numberSort = 0;
2449     // We are going to add slacks to get feasible.
2450     // initial list will just be artificials
2451     int iColumn;
2452     const double *columnLower = model2->columnLower();
2453     const double *columnUpper = model2->columnUpper();
2454     double *columnSolution = model2->primalColumnSolution();
2455 
2456     // See if we have costed slacks
2457     int *negSlack = new int[numberRows + numberColumns];
2458     int *posSlack = new int[numberRows + numberColumns];
2459     int *nextNegSlack = negSlack + numberRows;
2460     int *nextPosSlack = posSlack + numberRows;
2461     int iRow;
2462     for (iRow = 0; iRow < numberRows + numberColumns; iRow++) {
2463       negSlack[iRow] = -1;
2464       posSlack[iRow] = -1;
2465     }
2466     const double *element = model2->matrix()->getElements();
2467     const int *row = model2->matrix()->getIndices();
2468     const CoinBigIndex *columnStart = model2->matrix()->getVectorStarts();
2469     const int *columnLength = model2->matrix()->getVectorLengths();
2470     //bool allSlack = (numberRowsBasic==numberRows);
2471     for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
2472       if (!columnSolution[iColumn] || fabs(columnSolution[iColumn]) > 1.0e20) {
2473         double value = 0.0;
2474         if (columnLower[iColumn] > 0.0)
2475           value = columnLower[iColumn];
2476         else if (columnUpper[iColumn] < 0.0)
2477           value = columnUpper[iColumn];
2478         columnSolution[iColumn] = value;
2479       }
2480       if (columnLength[iColumn] == 1) {
2481         int jRow = row[columnStart[iColumn]];
2482         if (!columnLower[iColumn]) {
2483           if (element[columnStart[iColumn]] > 0.0) {
2484             if (posSlack[jRow] < 0) {
2485               posSlack[jRow] = iColumn;
2486             } else {
2487               int jColumn = posSlack[jRow];
2488               while (nextPosSlack[jColumn] >= 0)
2489                 jColumn = nextPosSlack[jColumn];
2490               nextPosSlack[jColumn] = iColumn;
2491             }
2492           } else if (element[columnStart[iColumn]] < 0.0) {
2493             if (negSlack[jRow] < 0) {
2494               negSlack[jRow] = iColumn;
2495             } else {
2496               int jColumn = negSlack[jRow];
2497               while (nextNegSlack[jColumn] >= 0)
2498                 jColumn = nextNegSlack[jColumn];
2499               nextNegSlack[jColumn] = iColumn;
2500             }
2501           }
2502         } else if (!columnUpper[iColumn] && false) { // out for testing
2503           if (element[columnStart[iColumn]] < 0.0 && posSlack[jRow] < 0)
2504             posSlack[jRow] = iColumn;
2505           else if (element[columnStart[iColumn]] > 0.0 && negSlack[jRow] < 0)
2506             negSlack[jRow] = iColumn;
2507         }
2508       }
2509     }
2510     // now see what that does to row solution
2511     const double *objective = model2->objective();
2512     double *rowSolution = model2->primalRowSolution();
2513     CoinZeroN(rowSolution, numberRows);
2514     model2->clpMatrix()->times(1.0, columnSolution, rowSolution);
2515     // See if we can adjust using costed slacks
2516     double penalty = CoinMax(1.0e5, CoinMin(infeasibilityCost_ * 0.01, 1.0e10)) * optimizationDirection_;
2517     const double *lower = model2->rowLower();
2518     const double *upper = model2->rowUpper();
2519     for (iRow = 0; iRow < numberRows; iRow++) {
2520       if (lower[iRow] > rowSolution[iRow] + 1.0e-8) {
2521         int jColumn = posSlack[iRow];
2522         if (jColumn >= 0) {
2523           // sort if more than one
2524           int nPos = 1;
2525           sort[0] = jColumn;
2526           weight[0] = objective[jColumn];
2527           while (nextPosSlack[jColumn] >= 0) {
2528             jColumn = nextPosSlack[jColumn];
2529             sort[nPos] = jColumn;
2530             weight[nPos++] = objective[jColumn];
2531           }
2532           if (nPos > 1) {
2533             CoinSort_2(weight, weight + nPos, sort);
2534             for (int i = 0; i < nPos; i++) {
2535               double difference = lower[iRow] - rowSolution[iRow];
2536               jColumn = sort[i];
2537               double elementValue = element[columnStart[jColumn]];
2538               assert(elementValue > 0.0);
2539               double value = columnSolution[jColumn];
2540               double movement = CoinMin(difference / elementValue, columnUpper[jColumn] - value);
2541               columnSolution[jColumn] += movement;
2542               rowSolution[iRow] += movement * elementValue;
2543             }
2544             continue;
2545           }
2546           if (jColumn < 0 || columnSolution[jColumn])
2547             continue;
2548           double difference = lower[iRow] - rowSolution[iRow];
2549           double elementValue = element[columnStart[jColumn]];
2550           if (elementValue > 0.0) {
2551             double movement = CoinMin(difference / elementValue, columnUpper[jColumn]);
2552             columnSolution[jColumn] = movement;
2553             rowSolution[iRow] += movement * elementValue;
2554           } else {
2555             double movement = CoinMax(difference / elementValue, columnLower[jColumn]);
2556             columnSolution[jColumn] = movement;
2557             rowSolution[iRow] += movement * elementValue;
2558           }
2559         }
2560       } else if (upper[iRow] < rowSolution[iRow] - 1.0e-8) {
2561         int jColumn = negSlack[iRow];
2562         if (jColumn >= 0) {
2563           // sort if more than one
2564           int nNeg = 1;
2565           sort[0] = jColumn;
2566           weight[0] = objective[jColumn];
2567           while (nextNegSlack[jColumn] >= 0) {
2568             jColumn = nextNegSlack[jColumn];
2569             sort[nNeg] = jColumn;
2570             weight[nNeg++] = objective[jColumn];
2571           }
2572           if (nNeg > 1) {
2573             CoinSort_2(weight, weight + nNeg, sort);
2574             for (int i = 0; i < nNeg; i++) {
2575               double difference = rowSolution[iRow] - upper[iRow];
2576               jColumn = sort[i];
2577               double elementValue = element[columnStart[jColumn]];
2578               assert(elementValue < 0.0);
2579               double value = columnSolution[jColumn];
2580               double movement = CoinMin(difference / -elementValue, columnUpper[jColumn] - value);
2581               columnSolution[jColumn] += movement;
2582               rowSolution[iRow] += movement * elementValue;
2583             }
2584             continue;
2585           }
2586           if (jColumn < 0 || columnSolution[jColumn])
2587             continue;
2588           double difference = upper[iRow] - rowSolution[iRow];
2589           double elementValue = element[columnStart[jColumn]];
2590           if (elementValue < 0.0) {
2591             double movement = CoinMin(difference / elementValue, columnUpper[jColumn]);
2592             columnSolution[jColumn] = movement;
2593             rowSolution[iRow] += movement * elementValue;
2594           } else {
2595             double movement = CoinMax(difference / elementValue, columnLower[jColumn]);
2596             columnSolution[jColumn] = movement;
2597             rowSolution[iRow] += movement * elementValue;
2598           }
2599         }
2600       }
2601     }
2602     delete[] negSlack;
2603     delete[] posSlack;
2604     int nRow = numberRows;
2605     bool network = false;
2606     if (dynamic_cast< ClpNetworkMatrix * >(matrix_)) {
2607       network = true;
2608       nRow *= 2;
2609     }
2610     CoinBigIndex *addStarts = new CoinBigIndex[nRow + 1];
2611     int *addRow = new int[nRow];
2612     double *addElement = new double[nRow];
2613     addStarts[0] = 0;
2614     int numberArtificials = 0;
2615     int numberAdd = 0;
2616     double *addCost = new double[numberRows];
2617     for (iRow = 0; iRow < numberRows; iRow++) {
2618       if (lower[iRow] > rowSolution[iRow] + 1.0e-8) {
2619         addRow[numberAdd] = iRow;
2620         addElement[numberAdd++] = 1.0;
2621         if (network) {
2622           addRow[numberAdd] = numberRows;
2623           addElement[numberAdd++] = -1.0;
2624         }
2625         addCost[numberArtificials] = penalty;
2626         numberArtificials++;
2627         addStarts[numberArtificials] = numberAdd;
2628       } else if (upper[iRow] < rowSolution[iRow] - 1.0e-8) {
2629         addRow[numberAdd] = iRow;
2630         addElement[numberAdd++] = -1.0;
2631         if (network) {
2632           addRow[numberAdd] = numberRows;
2633           addElement[numberAdd++] = 1.0;
2634         }
2635         addCost[numberArtificials] = penalty;
2636         numberArtificials++;
2637         addStarts[numberArtificials] = numberAdd;
2638       }
2639     }
2640     if (numberArtificials) {
2641       // need copy so as not to disturb original
2642       model2 = new ClpSimplex(*model2);
2643       if (network) {
2644         // network - add a null row
2645         model2->addRow(0, NULL, NULL, -COIN_DBL_MAX, COIN_DBL_MAX);
2646         numberRows++;
2647       }
2648       model2->addColumns(numberArtificials, NULL, NULL, addCost,
2649         addStarts, addRow, addElement);
2650     }
2651     delete[] addStarts;
2652     delete[] addRow;
2653     delete[] addElement;
2654     delete[] addCost;
2655     // look at rhs to see if to perturb
2656     double largest = 0.0;
2657     double smallest = 1.0e30;
2658     for (iRow = 0; iRow < numberRows; iRow++) {
2659       double value;
2660       value = fabs(model2->rowLower_[iRow]);
2661       if (value && value < 1.0e30) {
2662         largest = CoinMax(largest, value);
2663         smallest = CoinMin(smallest, value);
2664       }
2665       value = fabs(model2->rowUpper_[iRow]);
2666       if (value && value < 1.0e30) {
2667         largest = CoinMax(largest, value);
2668         smallest = CoinMin(smallest, value);
2669       }
2670     }
2671     double *saveLower = NULL;
2672     double *saveUpper = NULL;
2673     if (largest < -2.01 * smallest) { // switch off for now
2674       // perturb - so switch off standard
2675       model2->setPerturbation(100);
2676       saveLower = new double[numberRows];
2677       CoinMemcpyN(model2->rowLower_, numberRows, saveLower);
2678       saveUpper = new double[numberRows];
2679       CoinMemcpyN(model2->rowUpper_, numberRows, saveUpper);
2680       double *lower = model2->rowLower();
2681       double *upper = model2->rowUpper();
2682       for (iRow = 0; iRow < numberRows; iRow++) {
2683         double lowerValue = lower[iRow], upperValue = upper[iRow];
2684         double value = randomNumberGenerator_.randomDouble();
2685         if (upperValue > lowerValue + primalTolerance_) {
2686           if (lowerValue > -1.0e20 && lowerValue)
2687             lowerValue -= value * 1.0e-4 * fabs(lowerValue);
2688           if (upperValue < 1.0e20 && upperValue)
2689             upperValue += value * 1.0e-4 * fabs(upperValue);
2690         } else if (upperValue > 0.0) {
2691           upperValue -= value * 1.0e-4 * fabs(lowerValue);
2692           lowerValue -= value * 1.0e-4 * fabs(lowerValue);
2693         } else if (upperValue < 0.0) {
2694           upperValue += value * 1.0e-4 * fabs(lowerValue);
2695           lowerValue += value * 1.0e-4 * fabs(lowerValue);
2696         } else {
2697         }
2698         lower[iRow] = lowerValue;
2699         upper[iRow] = upperValue;
2700       }
2701     }
2702     int i;
2703     // Just do this number of passes in Sprint
2704     if (doSprint > 0)
2705       maxSprintPass = options.getExtraInfo(1);
2706     // but if big use to get ratio
2707     double ratio = 3;
2708 #ifdef CLP_USEFUL_PRINTOUT
2709     debugInt[6] = 3;
2710     debugInt[7] = maxSprintPass;
2711 #endif
2712     if (maxSprintPass > 1000) {
2713       ratio = static_cast< double >(maxSprintPass) * 0.0001;
2714       ratio = CoinMax(ratio, 1.1);
2715       maxSprintPass = maxSprintPass % 1000;
2716 #ifdef COIN_DEVELOP
2717       printf("%d passes wanted with ratio of %g\n", maxSprintPass, ratio);
2718 #endif
2719     }
2720     // Just take this number of columns in small problem
2721     int smallNumberColumns = static_cast< int >(CoinMin(ratio * numberRows, static_cast< double >(numberColumns)));
2722     smallNumberColumns = CoinMax(smallNumberColumns, 3000);
2723     smallNumberColumns = CoinMin(smallNumberColumns, numberColumns);
2724     int saveSmallNumber = smallNumberColumns;
2725     bool emergencyMode = false;
2726     //int smallNumberColumns = CoinMin(12*numberRows/10,numberColumns);
2727     //smallNumberColumns = CoinMax(smallNumberColumns,3000);
2728     //smallNumberColumns = CoinMax(smallNumberColumns,numberRows+1000);
2729     // redo as may have changed
2730     columnLower = model2->columnLower();
2731     columnUpper = model2->columnUpper();
2732     columnSolution = model2->primalColumnSolution();
2733     // Set up initial list
2734     numberSort = 0;
2735     if (numberArtificials) {
2736       numberSort = numberArtificials;
2737       for (i = 0; i < numberSort; i++)
2738         sort[i] = i + originalNumberColumns;
2739     }
2740     // put in free
2741     // maybe a solution there already
2742     for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
2743       if (model2->getColumnStatus(iColumn) == basic || (columnLower[iColumn] < -1.0e30 && columnUpper[iColumn] > 1.0e30))
2744         sort[numberSort++] = iColumn;
2745     }
2746     for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
2747       if (model2->getColumnStatus(iColumn) != basic) {
2748         if (columnSolution[iColumn] > columnLower[iColumn] && columnSolution[iColumn] < columnUpper[iColumn] && columnSolution[iColumn])
2749           sort[numberSort++] = iColumn;
2750       }
2751     }
2752     numberSort = CoinMin(numberSort, smallNumberColumns);
2753 
2754     int numberColumns = model2->numberColumns();
2755     double *fullSolution = model2->primalColumnSolution();
2756 
2757     int iPass;
2758     double lastObjective[] = { 1.0e31, 1.0e31 };
2759     // It will be safe to allow dense
2760     model2->setInitialDenseFactorization(true);
2761 
2762     // We will be using all rows
2763     int *whichRows = new int[numberRows];
2764     for (iRow = 0; iRow < numberRows; iRow++)
2765       whichRows[iRow] = iRow;
2766     double originalOffset;
2767     model2->getDblParam(ClpObjOffset, originalOffset);
2768     int totalIterations = 0;
2769     double lastSumArtificials = COIN_DBL_MAX;
2770     int originalMaxSprintPass = maxSprintPass;
2771     maxSprintPass = 20; // so we do that many if infeasible
2772     for (iPass = 0; iPass < maxSprintPass; iPass++) {
2773       //printf("Bug until submodel new version\n");
2774       //CoinSort_2(sort,sort+numberSort,weight);
2775       // Create small problem
2776       ClpSimplex small(model2, numberRows, whichRows, numberSort, sort);
2777       small.setPerturbation(model2->perturbation());
2778       small.setInfeasibilityCost(model2->infeasibilityCost());
2779       if (model2->factorizationFrequency() == 200) {
2780         // User did not touch preset
2781         small.defaultFactorizationFrequency();
2782       }
2783       // now see what variables left out do to row solution
2784       double *rowSolution = model2->primalRowSolution();
2785       double *sumFixed = new double[numberRows];
2786       CoinZeroN(sumFixed, numberRows);
2787       int iRow, iColumn;
2788       // zero out ones in small problem
2789       for (iColumn = 0; iColumn < numberSort; iColumn++) {
2790         int kColumn = sort[iColumn];
2791         fullSolution[kColumn] = 0.0;
2792       }
2793       // Get objective offset
2794       const double *objective = model2->objective();
2795       double offset = 0.0;
2796       for (iColumn = 0; iColumn < originalNumberColumns; iColumn++)
2797         offset += fullSolution[iColumn] * objective[iColumn];
2798 #if 0
2799 	       // Set artificials to zero if first time close to zero
2800                for (iColumn = originalNumberColumns; iColumn < numberColumns; iColumn++) {
2801 		 if (fullSolution[iColumn]<primalTolerance_&&objective[iColumn]==penalty) {
2802 		   model2->objective()[iColumn]=2.0*penalty;
2803 		   fullSolution[iColumn]=0.0;
2804 		 }
2805 	       }
2806 #endif
2807       small.setDblParam(ClpObjOffset, originalOffset - offset);
2808       model2->clpMatrix()->times(1.0, fullSolution, sumFixed);
2809 
2810       double *lower = small.rowLower();
2811       double *upper = small.rowUpper();
2812       for (iRow = 0; iRow < numberRows; iRow++) {
2813         if (lower[iRow] > -1.0e50)
2814           lower[iRow] -= sumFixed[iRow];
2815         if (upper[iRow] < 1.0e50)
2816           upper[iRow] -= sumFixed[iRow];
2817         rowSolution[iRow] -= sumFixed[iRow];
2818       }
2819       delete[] sumFixed;
2820       // Solve
2821       if (interrupt)
2822         currentModel = &small;
2823       small.defaultFactorizationFrequency();
2824       if (emergencyMode) {
2825         // not much happening so big model
2826         int options = small.moreSpecialOptions();
2827         small.setMoreSpecialOptions(options | 1048576);
2828         small.setMaximumIterations(1000400);
2829         small.setPerturbation(100);
2830       }
2831       if (dynamic_cast< ClpPackedMatrix * >(matrix_)) {
2832         // See if original wanted vector
2833         ClpPackedMatrix *clpMatrixO = dynamic_cast< ClpPackedMatrix * >(matrix_);
2834         ClpMatrixBase *matrix = small.clpMatrix();
2835         if (dynamic_cast< ClpPackedMatrix * >(matrix) && clpMatrixO->wantsSpecialColumnCopy()) {
2836           ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix);
2837           clpMatrix->makeSpecialColumnCopy();
2838           small.primal(1);
2839           clpMatrix->releaseSpecialColumnCopy();
2840         } else {
2841 #if 1
2842 #ifdef ABC_INHERIT
2843           //small.writeMps("try.mps");
2844           if (iPass || !numberArtificials)
2845             small.dealWithAbc(1, 1);
2846           else
2847             small.dealWithAbc(0, 0);
2848 #else
2849           if (iPass || !numberArtificials)
2850             small.primal(1);
2851           else
2852             small.dual(0);
2853 #endif
2854           if (emergencyMode) {
2855             if (small.problemStatus() == 3)
2856               small.setProblemStatus(0);
2857             smallNumberColumns = saveSmallNumber;
2858             emergencyMode = false;
2859             double *temp = new double[numberRows];
2860             memset(temp, 0, numberRows * sizeof(double));
2861             double *solution = small.primalColumnSolution();
2862             small.matrix()->times(solution, temp);
2863             double sumInf = 0.0;
2864             double *lower = small.rowLower();
2865             double *upper = small.rowUpper();
2866             for (int iRow = 0; iRow < numberRows; iRow++) {
2867               if (temp[iRow] > upper[iRow])
2868                 sumInf += temp[iRow] - upper[iRow];
2869               else if (temp[iRow] < lower[iRow])
2870                 sumInf += lower[iRow] - temp[iRow];
2871             }
2872             printf("row inf %g\n", sumInf);
2873             sumInf = 0.0;
2874             lower = small.columnLower();
2875             upper = small.columnUpper();
2876             for (int iColumn = 0; iColumn < small.numberColumns(); iColumn++) {
2877               if (solution[iColumn] > upper[iColumn])
2878                 sumInf += solution[iColumn] - upper[iColumn];
2879               else if (solution[iColumn] < lower[iColumn])
2880                 sumInf += lower[iColumn] - solution[iColumn];
2881             }
2882             printf("column inf %g\n", sumInf);
2883             delete[] temp;
2884           }
2885           if (small.problemStatus()) {
2886             int numberIterations = small.numberIterations();
2887             small.dual(0);
2888             small.setNumberIterations(small.numberIterations() + numberIterations);
2889           }
2890 #else
2891           int numberColumns = small.numberColumns();
2892           int numberRows = small.numberRows();
2893           // Use dual region
2894           double *rhs = small.dualRowSolution();
2895           int *whichRow = new int[3 * numberRows];
2896           int *whichColumn = new int[2 * numberColumns];
2897           int nBound;
2898           ClpSimplex *small2 = ((ClpSimplexOther *)(&small))->crunch(rhs, whichRow, whichColumn, nBound, false, false);
2899           if (small2) {
2900 #ifdef ABC_INHERIT
2901             small2->dealWithAbc(1, 1);
2902 #else
2903             small.primal(1);
2904 #endif
2905             if (small2->problemStatus() == 0) {
2906               small.setProblemStatus(0);
2907               ((ClpSimplexOther *)(&small))->afterCrunch(*small2, whichRow, whichColumn, nBound);
2908             } else {
2909 #ifdef ABC_INHERIT
2910               small2->dealWithAbc(1, 1);
2911 #else
2912               small.primal(1);
2913 #endif
2914               if (small2->problemStatus())
2915                 small.primal(1);
2916             }
2917             delete small2;
2918           } else {
2919             small.primal(1);
2920           }
2921           delete[] whichRow;
2922           delete[] whichColumn;
2923 #endif
2924         }
2925       } else {
2926         small.primal(1);
2927       }
2928       int smallIterations = small.numberIterations();
2929       totalIterations += smallIterations;
2930       if (2 * smallIterations < CoinMin(numberRows, 1000) && iPass) {
2931         int oldNumber = smallNumberColumns;
2932         if (smallIterations < 100)
2933           smallNumberColumns *= 1.2;
2934         else
2935           smallNumberColumns *= 1.1;
2936         smallNumberColumns = CoinMin(smallNumberColumns, numberColumns);
2937         if (smallIterations < 200 && smallNumberColumns > 2 * saveSmallNumber) {
2938           // try kicking it
2939           emergencyMode = true;
2940           smallNumberColumns = numberColumns;
2941         }
2942         //		 smallNumberColumns = CoinMin(smallNumberColumns, 3*saveSmallNumber);
2943         char line[100];
2944         sprintf(line, "sample size increased from %d to %d",
2945           oldNumber, smallNumberColumns);
2946         handler_->message(CLP_GENERAL, messages_)
2947           << line
2948           << CoinMessageEol;
2949       }
2950       // move solution back
2951       const double *solution = small.primalColumnSolution();
2952       for (iColumn = 0; iColumn < numberSort; iColumn++) {
2953         int kColumn = sort[iColumn];
2954         model2->setColumnStatus(kColumn, small.getColumnStatus(iColumn));
2955         fullSolution[kColumn] = solution[iColumn];
2956       }
2957       for (iRow = 0; iRow < numberRows; iRow++)
2958         model2->setRowStatus(iRow, small.getRowStatus(iRow));
2959       CoinMemcpyN(small.primalRowSolution(),
2960         numberRows, model2->primalRowSolution());
2961       double sumArtificials = 0.0;
2962       for (i = 0; i < numberArtificials; i++)
2963         sumArtificials += fullSolution[i + originalNumberColumns];
2964       if (sumArtificials && iPass > 5 && sumArtificials >= lastSumArtificials) {
2965         // increase costs
2966         double *cost = model2->objective() + originalNumberColumns;
2967         double newCost = CoinMin(1.0e10, cost[0] * 1.5);
2968         for (i = 0; i < numberArtificials; i++)
2969           cost[i] = newCost;
2970       }
2971       lastSumArtificials = sumArtificials;
2972       // get reduced cost for large problem
2973       double *djs = model2->dualColumnSolution();
2974       CoinMemcpyN(model2->objective(), numberColumns, djs);
2975       model2->clpMatrix()->transposeTimes(-1.0, small.dualRowSolution(), djs);
2976       int numberNegative = 0;
2977       double sumNegative = 0.0;
2978       // now massage weight so all basic in plus good djs
2979       // first count and do basic
2980       numberSort = 0;
2981       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2982         double dj = djs[iColumn] * optimizationDirection_;
2983         double value = fullSolution[iColumn];
2984         if (model2->getColumnStatus(iColumn) == ClpSimplex::basic) {
2985           sort[numberSort++] = iColumn;
2986         } else if (dj < -dualTolerance_ && value < columnUpper[iColumn]) {
2987           numberNegative++;
2988           sumNegative -= dj;
2989         } else if (dj > dualTolerance_ && value > columnLower[iColumn]) {
2990           numberNegative++;
2991           sumNegative += dj;
2992         }
2993       }
2994       handler_->message(CLP_SPRINT, messages_)
2995         << iPass + 1 << small.numberIterations() << small.objectiveValue() << sumNegative
2996         << numberNegative
2997         << CoinMessageEol;
2998       if (sumArtificials < 1.0e-8 && originalMaxSprintPass >= 0) {
2999         maxSprintPass = iPass + originalMaxSprintPass;
3000         originalMaxSprintPass = -1;
3001       }
3002       if (iPass > 20)
3003         sumArtificials = 0.0;
3004       if ((small.objectiveValue() * optimizationDirection_ > lastObjective[1] - 1.0e-7 && iPass > 15 && sumArtificials < 1.0e-8 && maxSprintPass < 200) || (!small.numberIterations() && iPass) || iPass == maxSprintPass - 1 || small.status() == 3) {
3005 
3006         break; // finished
3007       } else {
3008         lastObjective[1] = lastObjective[0];
3009         lastObjective[0] = small.objectiveValue() * optimizationDirection_;
3010         double tolerance;
3011         double averageNegDj = sumNegative / static_cast< double >(numberNegative + 1);
3012         if (numberNegative + numberSort > smallNumberColumns && false)
3013           tolerance = -dualTolerance_;
3014         else
3015           tolerance = 10.0 * averageNegDj;
3016         if (emergencyMode)
3017           tolerance = 1.0e100;
3018         int saveN = numberSort;
3019         for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3020           double dj = djs[iColumn] * optimizationDirection_;
3021           double value = fullSolution[iColumn];
3022           if (model2->getColumnStatus(iColumn) != ClpSimplex::basic) {
3023             if (dj < -dualTolerance_ && value < columnUpper[iColumn])
3024               dj = dj;
3025             else if (dj > dualTolerance_ && value > columnLower[iColumn])
3026               dj = -dj;
3027             else if (columnUpper[iColumn] > columnLower[iColumn])
3028               dj = fabs(dj);
3029             else
3030               dj = 1.0e50;
3031             if (dj < tolerance) {
3032               weight[numberSort] = dj;
3033               sort[numberSort++] = iColumn;
3034             }
3035           }
3036         }
3037         // sort
3038         CoinSort_2(weight + saveN, weight + numberSort, sort + saveN);
3039         if (numberSort < smallNumberColumns)
3040           printf("using %d columns not %d\n", numberSort, smallNumberColumns);
3041         numberSort = CoinMin(smallNumberColumns, numberSort);
3042         // try singletons
3043         char *markX = new char[numberColumns];
3044         memset(markX, 0, numberColumns);
3045         for (int i = 0; i < numberSort; i++)
3046           markX[sort[i]] = 1;
3047         int n = numberSort;
3048         for (int i = 0; i < numberColumns; i++) {
3049           if (columnLength[i] == 1 && !markX[i])
3050             sort[numberSort++] = i;
3051         }
3052         if (n < numberSort)
3053           printf("%d slacks added\n", numberSort - n);
3054         delete[] markX;
3055       }
3056     }
3057     if (interrupt)
3058       currentModel = model2;
3059     for (i = 0; i < numberArtificials; i++)
3060       sort[i] = i + originalNumberColumns;
3061     model2->deleteColumns(numberArtificials, sort);
3062     if (network) {
3063       int iRow = numberRows - 1;
3064       model2->deleteRows(1, &iRow);
3065     }
3066     delete[] weight;
3067     delete[] sort;
3068     delete[] whichRows;
3069     if (saveLower) {
3070       // unperturb and clean
3071       for (iRow = 0; iRow < numberRows; iRow++) {
3072         model2->rowLower_[iRow] = saveLower[iRow];
3073         model2->rowUpper_[iRow] = saveUpper[iRow];
3074       }
3075       delete[] saveLower;
3076       delete[] saveUpper;
3077     }
3078 #ifdef ABC_INHERIT
3079     model2->dealWithAbc(1, 1);
3080 #else
3081     model2->primal(1);
3082 #endif
3083     model2->setPerturbation(savePerturbation);
3084     if (model2 != originalModel2) {
3085       originalModel2->moveInfo(*model2);
3086       delete model2;
3087       model2 = originalModel2;
3088     }
3089     time2 = CoinCpuTime();
3090     timeCore = time2 - timeX;
3091     handler_->message(CLP_INTERVAL_TIMING, messages_)
3092       << "Sprint" << timeCore << time2 - time1
3093       << CoinMessageEol;
3094     timeX = time2;
3095     model2->setNumberIterations(model2->numberIterations() + totalIterations);
3096   } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) {
3097     if (presolve == ClpSolve::presolveOn) {
3098       int numberInfeasibilities = model2->tightenPrimalBounds(0.0, 0);
3099       if (numberInfeasibilities) {
3100         handler_->message(CLP_INFEASIBLE, messages_)
3101           << CoinMessageEol;
3102         delete model2;
3103         model2 = this;
3104         presolve = ClpSolve::presolveOff;
3105       }
3106     }
3107 #ifndef SLIM_CLP
3108     //printf("***** experimental pretty crude barrier\n");
3109     //#define SAVEIT 2
3110 #ifndef SAVEIT
3111 #define BORROW
3112 #endif
3113 #ifdef BORROW
3114     ClpInterior barrier;
3115     barrier.borrowModel(*model2);
3116 #else
3117     ClpInterior barrier(*model2);
3118 #endif
3119     barrier.eventHandler()->setSimplex(NULL);
3120     if (interrupt)
3121       currentModel2 = &barrier;
3122     if (barrier.numberRows() + barrier.numberColumns() > 10000)
3123       barrier.setMaximumBarrierIterations(1000);
3124     int barrierOptions = options.getSpecialOption(4);
3125     int aggressiveGamma = 0;
3126     bool presolveInCrossover = false;
3127     bool scale = false;
3128     bool doKKT = false;
3129     bool forceFixing = false;
3130     int speed = 0;
3131     if (barrierOptions & 16) {
3132       barrierOptions &= ~16;
3133       doKKT = true;
3134     }
3135     if (barrierOptions & (32 + 64 + 128)) {
3136       aggressiveGamma = (barrierOptions & (32 + 64 + 128)) >> 5;
3137       barrierOptions &= ~(32 + 64 + 128);
3138     }
3139     if (barrierOptions & 256) {
3140       barrierOptions &= ~256;
3141       presolveInCrossover = true;
3142     }
3143     if (barrierOptions & 512) {
3144       barrierOptions &= ~512;
3145       forceFixing = true;
3146     }
3147     if (barrierOptions & 1024) {
3148       barrierOptions &= ~1024;
3149       barrier.setProjectionTolerance(1.0e-9);
3150     }
3151     if (barrierOptions & (2048 | 4096)) {
3152       speed = (barrierOptions & (2048 | 4096)) >> 11;
3153       barrierOptions &= ~(2048 | 4096);
3154     }
3155     if (barrierOptions & 8) {
3156       barrierOptions &= ~8;
3157       scale = true;
3158     }
3159     // If quadratic force KKT
3160     if (quadraticObj) {
3161       doKKT = true;
3162     }
3163     switch (barrierOptions) {
3164     case 0:
3165     default:
3166       if (!doKKT) {
3167         ClpCholeskyBase *cholesky = new ClpCholeskyBase(options.getExtraInfo(1));
3168         cholesky->setIntegerParameter(0, speed);
3169         barrier.setCholesky(cholesky);
3170       } else {
3171         ClpCholeskyBase *cholesky = new ClpCholeskyBase();
3172         cholesky->setKKT(true);
3173         barrier.setCholesky(cholesky);
3174       }
3175       break;
3176     case 1:
3177       if (!doKKT) {
3178         ClpCholeskyDense *cholesky = new ClpCholeskyDense();
3179         barrier.setCholesky(cholesky);
3180       } else {
3181         ClpCholeskyDense *cholesky = new ClpCholeskyDense();
3182         cholesky->setKKT(true);
3183         barrier.setCholesky(cholesky);
3184       }
3185       break;
3186 #ifdef COIN_HAS_WSMP
3187     case 2: {
3188       if (!doKKT) {
3189         ClpCholeskyWssmp *cholesky = new ClpCholeskyWssmp(CoinMax(100, model2->numberRows() / 10));
3190         barrier.setCholesky(cholesky);
3191       } else {
3192         ClpCholeskyWssmpKKT *cholesky = new ClpCholeskyWssmpKKT(CoinMax(100, model2->numberRows() / 10));
3193         barrier.setCholesky(cholesky);
3194       }
3195     } break;
3196     case 3:
3197       if (!doKKT) {
3198         ClpCholeskyWssmp *cholesky = new ClpCholeskyWssmp();
3199         barrier.setCholesky(cholesky);
3200       } else {
3201         ClpCholeskyWssmpKKT *cholesky = new ClpCholeskyWssmpKKT(CoinMax(100, model2->numberRows() / 10));
3202         barrier.setCholesky(cholesky);
3203       }
3204       break;
3205 #endif
3206 #ifdef UFL_BARRIER
3207     case 4:
3208       if (!doKKT) {
3209         ClpCholeskyUfl *cholesky = new ClpCholeskyUfl(options.getExtraInfo(1));
3210         barrier.setCholesky(cholesky);
3211       } else {
3212         ClpCholeskyUfl *cholesky = new ClpCholeskyUfl();
3213         cholesky->setKKT(true);
3214         barrier.setCholesky(cholesky);
3215       }
3216       break;
3217 #endif
3218 #ifdef TAUCS_BARRIER
3219     case 5: {
3220       ClpCholeskyTaucs *cholesky = new ClpCholeskyTaucs();
3221       barrier.setCholesky(cholesky);
3222       assert(!doKKT);
3223     } break;
3224 #endif
3225 #ifdef COIN_HAS_MUMPS
3226     case 6: {
3227       if (!doKKT) {
3228         int logLevel = 0;
3229         if (barrier.logLevel() > 3) {
3230           logLevel = (barrier.logLevel() > 4) ? 2 : 1;
3231         }
3232         ClpCholeskyMumps *cholesky = new ClpCholeskyMumps(-1, logLevel);
3233         barrier.setCholesky(cholesky);
3234       } else {
3235         ClpCholeskyMumps *cholesky = new ClpCholeskyMumps();
3236         cholesky->setKKT(true);
3237         barrier.setCholesky(cholesky);
3238       }
3239     } break;
3240 #endif
3241 #ifdef PARDISO_BARRIER
3242     case 7: {
3243       ClpCholeskyPardiso *cholesky = new ClpCholeskyPardiso();
3244       barrier.setCholesky(cholesky);
3245       assert(!doKKT);
3246     } break;
3247 #endif
3248     }
3249     int numberRows = model2->numberRows();
3250     int numberColumns = model2->numberColumns();
3251     int saveMaxIts = model2->maximumIterations();
3252     if (saveMaxIts < 1000) {
3253       barrier.setMaximumBarrierIterations(saveMaxIts);
3254       model2->setMaximumIterations(10000000);
3255     }
3256 #ifndef SAVEIT
3257     //barrier.setDiagonalPerturbation(1.0e-25);
3258     if (aggressiveGamma) {
3259       switch (aggressiveGamma) {
3260       case 1:
3261         barrier.setGamma(1.0e-5);
3262         barrier.setDelta(1.0e-5);
3263         break;
3264       case 2:
3265         barrier.setGamma(1.0e-7);
3266         break;
3267       case 3:
3268         barrier.setDelta(1.0e-5);
3269         break;
3270       case 4:
3271         barrier.setGamma(1.0e-3);
3272         barrier.setDelta(1.0e-3);
3273         break;
3274       case 5:
3275         barrier.setGamma(1.0e-3);
3276         break;
3277       case 6:
3278         barrier.setDelta(1.0e-3);
3279         break;
3280       }
3281     }
3282     if (scale)
3283       barrier.scaling(1);
3284     else
3285       barrier.scaling(0);
3286     barrier.primalDual();
3287 #elif SAVEIT == 1
3288     barrier.primalDual();
3289 #else
3290     model2->restoreModel("xx.save");
3291     // move solutions
3292     CoinMemcpyN(model2->primalRowSolution(),
3293       numberRows, barrier.primalRowSolution());
3294     CoinMemcpyN(model2->dualRowSolution(),
3295       numberRows, barrier.dualRowSolution());
3296     CoinMemcpyN(model2->primalColumnSolution(),
3297       numberColumns, barrier.primalColumnSolution());
3298     CoinMemcpyN(model2->dualColumnSolution(),
3299       numberColumns, barrier.dualColumnSolution());
3300 #endif
3301     time2 = CoinCpuTime();
3302     timeCore = time2 - timeX;
3303     handler_->message(CLP_INTERVAL_TIMING, messages_)
3304       << "Barrier" << timeCore << time2 - time1
3305       << CoinMessageEol;
3306     timeX = time2;
3307     int maxIts = barrier.maximumBarrierIterations();
3308     int barrierStatus = barrier.status();
3309     double gap = barrier.complementarityGap();
3310     // get which variables are fixed
3311     double *saveLower = NULL;
3312     double *saveUpper = NULL;
3313     ClpPresolve pinfo2;
3314     ClpSimplex *saveModel2 = NULL;
3315     bool extraPresolve = false;
3316     int numberFixed = barrier.numberFixed();
3317     if (numberFixed) {
3318       int numberRows = barrier.numberRows();
3319       int numberColumns = barrier.numberColumns();
3320       int numberTotal = numberRows + numberColumns;
3321       saveLower = new double[numberTotal];
3322       saveUpper = new double[numberTotal];
3323       CoinMemcpyN(barrier.columnLower(), numberColumns, saveLower);
3324       CoinMemcpyN(barrier.rowLower(), numberRows, saveLower + numberColumns);
3325       CoinMemcpyN(barrier.columnUpper(), numberColumns, saveUpper);
3326       CoinMemcpyN(barrier.rowUpper(), numberRows, saveUpper + numberColumns);
3327     }
3328     if (((numberFixed * 20 > barrier.numberRows() && numberFixed > 5000) || forceFixing) && presolveInCrossover) {
3329       // may as well do presolve
3330       if (!forceFixing) {
3331         barrier.fixFixed();
3332       } else {
3333         // Fix
3334         int n = barrier.numberColumns();
3335         double *lower = barrier.columnLower();
3336         double *upper = barrier.columnUpper();
3337         double *solution = barrier.primalColumnSolution();
3338         int nFix = 0;
3339         for (int i = 0; i < n; i++) {
3340           if (barrier.fixedOrFree(i) && lower[i] < upper[i]) {
3341             double value = solution[i];
3342             if (value < lower[i] + 1.0e-6 && value - lower[i] < upper[i] - value) {
3343               solution[i] = lower[i];
3344               upper[i] = lower[i];
3345               nFix++;
3346             } else if (value > upper[i] - 1.0e-6 && value - lower[i] > upper[i] - value) {
3347               solution[i] = upper[i];
3348               lower[i] = upper[i];
3349               nFix++;
3350             }
3351           }
3352         }
3353 #ifdef CLP_INVESTIGATE
3354         printf("%d columns fixed\n", nFix);
3355 #endif
3356         int nr = barrier.numberRows();
3357         lower = barrier.rowLower();
3358         upper = barrier.rowUpper();
3359         solution = barrier.primalRowSolution();
3360         nFix = 0;
3361         for (int i = 0; i < nr; i++) {
3362           if (barrier.fixedOrFree(i + n) && lower[i] < upper[i]) {
3363             double value = solution[i];
3364             if (value < lower[i] + 1.0e-6 && value - lower[i] < upper[i] - value) {
3365               solution[i] = lower[i];
3366               upper[i] = lower[i];
3367               nFix++;
3368             } else if (value > upper[i] - 1.0e-6 && value - lower[i] > upper[i] - value) {
3369               solution[i] = upper[i];
3370               lower[i] = upper[i];
3371               nFix++;
3372             }
3373           }
3374         }
3375 #ifdef CLP_INVESTIGATE
3376         printf("%d row slacks fixed\n", nFix);
3377 #endif
3378       }
3379       saveModel2 = model2;
3380       extraPresolve = true;
3381     } else if (numberFixed) {
3382       // Set fixed to bounds (may have restored earlier solution)
3383       if (!forceFixing) {
3384         barrier.fixFixed(false);
3385       } else {
3386         // Fix
3387         int n = barrier.numberColumns();
3388         double *lower = barrier.columnLower();
3389         double *upper = barrier.columnUpper();
3390         double *solution = barrier.primalColumnSolution();
3391         int nFix = 0;
3392         for (int i = 0; i < n; i++) {
3393           if (barrier.fixedOrFree(i) && lower[i] < upper[i]) {
3394             double value = solution[i];
3395             if (value < lower[i] + 1.0e-8 && value - lower[i] < upper[i] - value) {
3396               solution[i] = lower[i];
3397               upper[i] = lower[i];
3398               nFix++;
3399             } else if (value > upper[i] - 1.0e-8 && value - lower[i] > upper[i] - value) {
3400               solution[i] = upper[i];
3401               lower[i] = upper[i];
3402               nFix++;
3403             } else {
3404               //printf("fixcol %d %g <= %g <= %g\n",
3405               //     i,lower[i],solution[i],upper[i]);
3406             }
3407           }
3408         }
3409 #ifdef CLP_INVESTIGATE
3410         printf("%d columns fixed\n", nFix);
3411 #endif
3412         int nr = barrier.numberRows();
3413         lower = barrier.rowLower();
3414         upper = barrier.rowUpper();
3415         solution = barrier.primalRowSolution();
3416         nFix = 0;
3417         for (int i = 0; i < nr; i++) {
3418           if (barrier.fixedOrFree(i + n) && lower[i] < upper[i]) {
3419             double value = solution[i];
3420             if (value < lower[i] + 1.0e-5 && value - lower[i] < upper[i] - value) {
3421               solution[i] = lower[i];
3422               upper[i] = lower[i];
3423               nFix++;
3424             } else if (value > upper[i] - 1.0e-5 && value - lower[i] > upper[i] - value) {
3425               solution[i] = upper[i];
3426               lower[i] = upper[i];
3427               nFix++;
3428             } else {
3429               //printf("fixrow %d %g <= %g <= %g\n",
3430               //     i,lower[i],solution[i],upper[i]);
3431             }
3432           }
3433         }
3434 #ifdef CLP_INVESTIGATE
3435         printf("%d row slacks fixed\n", nFix);
3436 #endif
3437       }
3438     }
3439 #ifdef BORROW
3440     int saveNumberIterations = barrier.numberIterations();
3441     barrier.returnModel(*model2);
3442     double *rowPrimal = new double[numberRows];
3443     double *columnPrimal = new double[numberColumns];
3444     double *rowDual = new double[numberRows];
3445     double *columnDual = new double[numberColumns];
3446     // move solutions other way
3447     CoinMemcpyN(model2->primalRowSolution(),
3448       numberRows, rowPrimal);
3449     CoinMemcpyN(model2->dualRowSolution(),
3450       numberRows, rowDual);
3451     CoinMemcpyN(model2->primalColumnSolution(),
3452       numberColumns, columnPrimal);
3453     CoinMemcpyN(model2->dualColumnSolution(),
3454       numberColumns, columnDual);
3455 #else
3456     double *rowPrimal = barrier.primalRowSolution();
3457     double *columnPrimal = barrier.primalColumnSolution();
3458     double *rowDual = barrier.dualRowSolution();
3459     double *columnDual = barrier.dualColumnSolution();
3460     // move solutions
3461     CoinMemcpyN(rowPrimal,
3462       numberRows, model2->primalRowSolution());
3463     CoinMemcpyN(rowDual,
3464       numberRows, model2->dualRowSolution());
3465     CoinMemcpyN(columnPrimal,
3466       numberColumns, model2->primalColumnSolution());
3467     CoinMemcpyN(columnDual,
3468       numberColumns, model2->dualColumnSolution());
3469 #endif
3470     if (saveModel2) {
3471       // do presolve
3472       model2 = pinfo2.presolvedModel(*model2, dblParam_[ClpPresolveTolerance],
3473         false, 5, true);
3474       if (!model2) {
3475         model2 = saveModel2;
3476         saveModel2 = NULL;
3477         int numberRows = model2->numberRows();
3478         int numberColumns = model2->numberColumns();
3479         CoinMemcpyN(saveLower, numberColumns, model2->columnLower());
3480         CoinMemcpyN(saveLower + numberColumns, numberRows, model2->rowLower());
3481         delete[] saveLower;
3482         CoinMemcpyN(saveUpper, numberColumns, model2->columnUpper());
3483         CoinMemcpyN(saveUpper + numberColumns, numberRows, model2->rowUpper());
3484         delete[] saveUpper;
3485         saveLower = NULL;
3486         saveUpper = NULL;
3487       }
3488     }
3489     if (method == ClpSolve::useBarrier || barrierStatus < 0) {
3490       if (maxIts && barrierStatus < 4 && !quadraticObj) {
3491         //printf("***** crossover - needs more thought on difficult models\n");
3492 #if SAVEIT == 1
3493         model2->ClpSimplex::saveModel("xx.save");
3494 #endif
3495         // make sure no status left
3496         model2->createStatus();
3497         // solve
3498         if (!forceFixing)
3499           model2->setPerturbation(100);
3500         if (model2->factorizationFrequency() == 200) {
3501           // User did not touch preset
3502           model2->defaultFactorizationFrequency();
3503         }
3504 #if 1 //ndef ABC_INHERIT
3505   // throw some into basis
3506         if (!forceFixing) {
3507           int numberRows = model2->numberRows();
3508           int numberColumns = model2->numberColumns();
3509           double *dsort = new double[numberColumns];
3510           int *sort = new int[numberColumns];
3511           int n = 0;
3512           const double *columnLower = model2->columnLower();
3513           const double *columnUpper = model2->columnUpper();
3514           double *primalSolution = model2->primalColumnSolution();
3515           const double *dualSolution = model2->dualColumnSolution();
3516           double tolerance = 10.0 * primalTolerance_;
3517           int i;
3518           for (i = 0; i < numberRows; i++)
3519             model2->setRowStatus(i, superBasic);
3520           for (i = 0; i < numberColumns; i++) {
3521             double distance = CoinMin(columnUpper[i] - primalSolution[i],
3522               primalSolution[i] - columnLower[i]);
3523             if (distance > tolerance) {
3524               if (fabs(dualSolution[i]) < 1.0e-5)
3525                 distance *= 100.0;
3526               dsort[n] = -distance;
3527               sort[n++] = i;
3528               model2->setStatus(i, superBasic);
3529             } else if (distance > primalTolerance_) {
3530               model2->setStatus(i, superBasic);
3531             } else if (primalSolution[i] <= columnLower[i] + primalTolerance_) {
3532               model2->setStatus(i, atLowerBound);
3533               primalSolution[i] = columnLower[i];
3534             } else {
3535               model2->setStatus(i, atUpperBound);
3536               primalSolution[i] = columnUpper[i];
3537             }
3538           }
3539           CoinSort_2(dsort, dsort + n, sort);
3540           n = CoinMin(numberRows, n);
3541           for (i = 0; i < n; i++) {
3542             int iColumn = sort[i];
3543             model2->setStatus(iColumn, basic);
3544           }
3545           delete[] sort;
3546           delete[] dsort;
3547           // model2->allSlackBasis();
3548           if (gap < 1.0e-3 * static_cast< double >(numberRows + numberColumns)) {
3549             if (saveUpper) {
3550               int numberRows = model2->numberRows();
3551               int numberColumns = model2->numberColumns();
3552               CoinMemcpyN(saveLower, numberColumns, model2->columnLower());
3553               CoinMemcpyN(saveLower + numberColumns, numberRows, model2->rowLower());
3554               CoinMemcpyN(saveUpper, numberColumns, model2->columnUpper());
3555               CoinMemcpyN(saveUpper + numberColumns, numberRows, model2->rowUpper());
3556               delete[] saveLower;
3557               delete[] saveUpper;
3558               saveLower = NULL;
3559               saveUpper = NULL;
3560             }
3561             //int numberRows = model2->numberRows();
3562             //int numberColumns = model2->numberColumns();
3563 #ifdef ABC_INHERIT
3564             model2->checkSolution(0);
3565             printf("%d primal infeasibilities summing to %g\n",
3566               model2->numberPrimalInfeasibilities(),
3567               model2->sumPrimalInfeasibilities());
3568             model2->dealWithAbc(1, 1);
3569           }
3570         }
3571 #else
3572             // just primal values pass
3573             double saveScale = model2->objectiveScale();
3574             model2->setObjectiveScale(1.0e-3);
3575             model2->primal(2);
3576             model2->setObjectiveScale(saveScale);
3577             // save primal solution and copy back dual
3578             CoinMemcpyN(model2->primalRowSolution(),
3579               numberRows, rowPrimal);
3580             CoinMemcpyN(rowDual,
3581               numberRows, model2->dualRowSolution());
3582             CoinMemcpyN(model2->primalColumnSolution(),
3583               numberColumns, columnPrimal);
3584             CoinMemcpyN(columnDual,
3585               numberColumns, model2->dualColumnSolution());
3586             //model2->primal(1);
3587             // clean up reduced costs and flag variables
3588             {
3589               double *dj = model2->dualColumnSolution();
3590               double *cost = model2->objective();
3591               double *saveCost = new double[numberColumns];
3592               CoinMemcpyN(cost, numberColumns, saveCost);
3593               double *saveLower = new double[numberColumns];
3594               double *lower = model2->columnLower();
3595               CoinMemcpyN(lower, numberColumns, saveLower);
3596               double *saveUpper = new double[numberColumns];
3597               double *upper = model2->columnUpper();
3598               CoinMemcpyN(upper, numberColumns, saveUpper);
3599               int i;
3600               double tolerance = 10.0 * dualTolerance_;
3601               for (i = 0; i < numberColumns; i++) {
3602                 if (model2->getStatus(i) == basic) {
3603                   dj[i] = 0.0;
3604                 } else if (model2->getStatus(i) == atLowerBound) {
3605                   if (optimizationDirection_ * dj[i] < tolerance) {
3606                     if (optimizationDirection_ * dj[i] < 0.0) {
3607                       //if (dj[i]<-1.0e-3)
3608                       //printf("bad dj at lb %d %g\n",i,dj[i]);
3609                       cost[i] -= dj[i];
3610                       dj[i] = 0.0;
3611                     }
3612                   } else {
3613                     upper[i] = lower[i];
3614                   }
3615                 } else if (model2->getStatus(i) == atUpperBound) {
3616                   if (optimizationDirection_ * dj[i] > tolerance) {
3617                     if (optimizationDirection_ * dj[i] > 0.0) {
3618                       //if (dj[i]>1.0e-3)
3619                       //printf("bad dj at ub %d %g\n",i,dj[i]);
3620                       cost[i] -= dj[i];
3621                       dj[i] = 0.0;
3622                     }
3623                   } else {
3624                     lower[i] = upper[i];
3625                   }
3626                 }
3627               }
3628               // just dual values pass
3629               //model2->setLogLevel(63);
3630               //model2->setFactorizationFrequency(1);
3631               if (!gap)
3632                 model2->dual(2);
3633               CoinMemcpyN(saveCost, numberColumns, cost);
3634               delete[] saveCost;
3635               CoinMemcpyN(saveLower, numberColumns, lower);
3636               delete[] saveLower;
3637               CoinMemcpyN(saveUpper, numberColumns, upper);
3638               delete[] saveUpper;
3639             }
3640           }
3641           // and finish
3642           // move solutions
3643           CoinMemcpyN(rowPrimal,
3644             numberRows, model2->primalRowSolution());
3645           CoinMemcpyN(columnPrimal,
3646             numberColumns, model2->primalColumnSolution());
3647         }
3648         double saveScale = model2->objectiveScale();
3649         model2->setObjectiveScale(1.0e-3);
3650         model2->primal(2);
3651         model2->setObjectiveScale(saveScale);
3652         model2->primal(1);
3653 #endif
3654 #else
3655         // just primal
3656 #ifdef ABC_INHERIT
3657         model2->checkSolution(0);
3658         printf("%d primal infeasibilities summing to %g\n",
3659           model2->numberPrimalInfeasibilities(),
3660           model2->sumPrimalInfeasibilities());
3661         model2->dealWithAbc(1, 1);
3662 #else
3663         model2->primal(1);
3664 #endif
3665         //model2->primal(1);
3666 #endif
3667       } else if (barrierStatus == 4) {
3668         // memory problems
3669         model2->setPerturbation(savePerturbation);
3670         model2->createStatus();
3671         model2->dual();
3672       } else if (maxIts && quadraticObj) {
3673         // make sure no status left
3674         model2->createStatus();
3675         // solve
3676         model2->setPerturbation(100);
3677         model2->reducedGradient(1);
3678       }
3679     }
3680 
3681     //model2->setMaximumIterations(saveMaxIts);
3682 #ifdef BORROW
3683     model2->setNumberIterations(model2->numberIterations() + saveNumberIterations);
3684     delete[] rowPrimal;
3685     delete[] columnPrimal;
3686     delete[] rowDual;
3687     delete[] columnDual;
3688 #endif
3689     if (extraPresolve) {
3690       pinfo2.postsolve(true);
3691       delete model2;
3692       model2 = saveModel2;
3693     }
3694     if (saveUpper) {
3695       if (!forceFixing) {
3696         int numberRows = model2->numberRows();
3697         int numberColumns = model2->numberColumns();
3698         CoinMemcpyN(saveLower, numberColumns, model2->columnLower());
3699         CoinMemcpyN(saveLower + numberColumns, numberRows, model2->rowLower());
3700         CoinMemcpyN(saveUpper, numberColumns, model2->columnUpper());
3701         CoinMemcpyN(saveUpper + numberColumns, numberRows, model2->rowUpper());
3702       }
3703       delete[] saveLower;
3704       delete[] saveUpper;
3705       saveLower = NULL;
3706       saveUpper = NULL;
3707       if (method != ClpSolve::useBarrierNoCross)
3708         model2->primal(1);
3709     }
3710     model2->setPerturbation(savePerturbation);
3711     time2 = CoinCpuTime();
3712     timeCore = time2 - timeX;
3713     handler_->message(CLP_INTERVAL_TIMING, messages_)
3714       << "Crossover" << timeCore << time2 - time1
3715       << CoinMessageEol;
3716     timeX = time2;
3717 #else
3718     abort();
3719 #endif
3720   } else if (method == ClpSolve::notImplemented) {
3721     printf("done decomposition\n");
3722   } else {
3723     assert(method != ClpSolve::automatic); // later
3724     time2 = 0.0;
3725   }
3726   if (saveMatrix) {
3727     if (model2 == this) {
3728       // delete and replace
3729       delete model2->clpMatrix();
3730       model2->replaceMatrix(saveMatrix);
3731     } else {
3732       delete saveMatrix;
3733     }
3734   }
3735   numberIterations = model2->numberIterations();
3736   finalStatus = model2->status();
3737   int finalSecondaryStatus = model2->secondaryStatus();
3738   if (presolve == ClpSolve::presolveOn) {
3739     int saveLevel = logLevel();
3740     if ((specialOptions_ & 1024) == 0)
3741       setLogLevel(CoinMin(1, saveLevel));
3742     else
3743       setLogLevel(CoinMin(0, saveLevel));
3744     pinfo->postsolve(true);
3745     numberIterations_ = 0;
3746     delete pinfo;
3747     pinfo = NULL;
3748     factorization_->areaFactor(model2->factorization()->adjustedAreaFactor());
3749     time2 = CoinCpuTime();
3750     timePresolve += time2 - timeX;
3751     handler_->message(CLP_INTERVAL_TIMING, messages_)
3752       << "Postsolve" << time2 - timeX << time2 - time1
3753       << CoinMessageEol;
3754     timeX = time2;
3755     if (!presolveToFile) {
3756 #if 1 //ndef ABC_INHERIT
3757       delete model2;
3758 #else
3759       if (model2->abcSimplex())
3760         delete model2->abcSimplex();
3761       else
3762         delete model2;
3763 #endif
3764     }
3765     if (interrupt)
3766       currentModel = this;
3767     // checkSolution(); already done by postSolve
3768     setLogLevel(saveLevel);
3769     int oldStatus = problemStatus_;
3770     setProblemStatus(finalStatus);
3771     setSecondaryStatus(finalSecondaryStatus);
3772     /* Code modified so rcode -1 as normal, >0 clean up, 0 say optimal */
3773     int rcode = eventHandler()->event(ClpEventHandler::presolveAfterFirstSolve);
3774     //#define TREAT_AS_OPTIMAL_TOLERANCE 1.0e-4
3775 #ifdef TREAT_AS_OPTIMAL_TOLERANCE
3776     if (rcode == -1 && sumPrimalInfeasibilities_ < TREAT_AS_OPTIMAL_TOLERANCE && sumDualInfeasibilities_ < TREAT_AS_OPTIMAL_TOLERANCE)
3777       rcode = 0;
3778 #endif
3779     if (finalStatus != 3 && rcode < 0 && (finalStatus || oldStatus == -1)) {
3780       double sumPrimal = sumPrimalInfeasibilities_;
3781       double sumDual = sumDualInfeasibilities_;
3782       if (sumDual > 1.0e-6 && sumPrimal > 1.0e-6)
3783         moreSpecialOptions_ &= ~2; // be safe and do final solve
3784       // ignore some parts of solution
3785       if (finalStatus == 1) {
3786         // infeasible
3787         sumDual = 0.0;
3788       } else if (finalStatus == 2) {
3789         sumPrimal = 0.0;
3790       }
3791       int savePerturbation = perturbation();
3792       if (savePerturbation == 50)
3793         setPerturbation(51); // small
3794       if (!finalStatus || finalStatus == 2 || (moreSpecialOptions_ & 2) == 0 || fabs(sumDual) + fabs(sumPrimal) < 1.0e-3) {
3795         if (finalStatus == 2) {
3796           if (sumDual > 1.0e-4) {
3797             // unbounded - get feasible first
3798             double save = optimizationDirection_;
3799             optimizationDirection_ = 0.0;
3800             primal(1);
3801             optimizationDirection_ = save;
3802           }
3803           primal(1);
3804         } else if (finalStatus == 1) {
3805           dual();
3806         } else {
3807           if ((moreSpecialOptions_ & 65536) == 0) {
3808             if (numberRows_ < 10000 || true)
3809               setPerturbation(100); // probably better to perturb after n its
3810             else if (savePerturbation < 100)
3811               setPerturbation(51); // probably better to perturb after n its
3812           }
3813 #ifndef ABC_INHERIT
3814           // use method thought suitable
3815           int numberSuperBasic = 0;
3816           for (int i = 0; i < numberColumns_; i++) {
3817             if (getColumnStatus(i) == superBasic)
3818               numberSuperBasic++;
3819           }
3820           if (sumDual > 1000.0 * sumPrimal || numberSuperBasic) {
3821             primal(1);
3822           } else if (sumPrimal > 1000.0 * sumDual) {
3823             dual();
3824           } else {
3825             if (method != ClpSolve::useDual)
3826               primal(1);
3827             else
3828               dual();
3829           }
3830 #else
3831           dealWithAbc(1, 2, interrupt);
3832 #endif
3833         }
3834       } else {
3835         // just set status
3836         problemStatus_ = finalStatus;
3837       }
3838       setPerturbation(savePerturbation);
3839       numberIterations += numberIterations_;
3840       numberIterations_ = numberIterations;
3841       finalStatus = status();
3842       time2 = CoinCpuTime();
3843       handler_->message(CLP_INTERVAL_TIMING, messages_)
3844         << "Cleanup" << time2 - timeX << time2 - time1
3845         << CoinMessageEol;
3846       timeX = time2;
3847     } else if (rcode > 0) { // was >= 0
3848 #ifdef ABC_INHERIT
3849       dealWithAbc(1, 2, true);
3850 #else
3851       primal(1);
3852 #endif
3853     } else {
3854       secondaryStatus_ = finalSecondaryStatus;
3855     }
3856   } else if (model2 != this) {
3857     // not presolved - but different model used (sprint probably)
3858     CoinMemcpyN(model2->primalRowSolution(),
3859       numberRows_, this->primalRowSolution());
3860     CoinMemcpyN(model2->dualRowSolution(),
3861       numberRows_, this->dualRowSolution());
3862     CoinMemcpyN(model2->primalColumnSolution(),
3863       numberColumns_, this->primalColumnSolution());
3864     CoinMemcpyN(model2->dualColumnSolution(),
3865       numberColumns_, this->dualColumnSolution());
3866     CoinMemcpyN(model2->statusArray(),
3867       numberColumns_ + numberRows_, this->statusArray());
3868     objectiveValue_ = model2->objectiveValue_;
3869     numberIterations_ = model2->numberIterations_;
3870     problemStatus_ = model2->problemStatus_;
3871     secondaryStatus_ = model2->secondaryStatus_;
3872     delete model2;
3873   }
3874   if (method != ClpSolve::useBarrierNoCross && method != ClpSolve::useBarrier)
3875     setMaximumIterations(saveMaxIterations);
3876   std::string statusMessage[] = { "Unknown", "Optimal", "PrimalInfeasible", "DualInfeasible", "Stopped",
3877     "Errors", "User stopped" };
3878   assert(finalStatus >= -1 && finalStatus <= 5);
3879   numberIterations_ = numberIterations;
3880   handler_->message(CLP_TIMING, messages_)
3881     << statusMessage[finalStatus + 1] << objectiveValue() << numberIterations << time2 - time1;
3882   handler_->printing(presolve == ClpSolve::presolveOn)
3883     << timePresolve;
3884   handler_->printing(timeIdiot != 0.0)
3885     << timeIdiot;
3886   handler_->message() << CoinMessageEol;
3887   if (interrupt)
3888     signal(SIGINT, saveSignal);
3889   perturbation_ = savePerturbation;
3890   scalingFlag_ = saveScaling;
3891   // If faking objective - put back correct one
3892   if (savedObjective) {
3893     delete objective_;
3894     objective_ = savedObjective;
3895   }
3896   if (options.getSpecialOption(1) == 2 && options.getExtraInfo(1) > 1000000) {
3897     ClpObjective *savedObjective = objective_;
3898     // make up zero objective
3899     double *obj = new double[numberColumns_];
3900     for (int i = 0; i < numberColumns_; i++)
3901       obj[i] = 0.0;
3902     objective_ = new ClpLinearObjective(obj, numberColumns_);
3903     delete[] obj;
3904     primal(1);
3905     delete objective_;
3906     objective_ = savedObjective;
3907     finalStatus = status();
3908   }
3909   eventHandler()->event(ClpEventHandler::presolveEnd);
3910   delete pinfo;
3911   moreSpecialOptions_ = saveMoreOptions;
3912 #ifdef CLP_USEFUL_PRINTOUT
3913   debugInt[23] = numberIterations_;
3914 #endif
3915   return finalStatus;
3916 }
3917 // General solve
initialSolve()3918 int ClpSimplex::initialSolve()
3919 {
3920   // Default so use dual
3921   ClpSolve options;
3922   return initialSolve(options);
3923 }
3924 // General dual solve
initialDualSolve()3925 int ClpSimplex::initialDualSolve()
3926 {
3927   ClpSolve options;
3928   // Use dual
3929   options.setSolveType(ClpSolve::useDual);
3930   return initialSolve(options);
3931 }
3932 // General primal solve
initialPrimalSolve()3933 int ClpSimplex::initialPrimalSolve()
3934 {
3935   ClpSolve options;
3936   // Use primal
3937   options.setSolveType(ClpSolve::usePrimal);
3938   return initialSolve(options);
3939 }
3940 // barrier solve, not to be followed by crossover
initialBarrierNoCrossSolve()3941 int ClpSimplex::initialBarrierNoCrossSolve()
3942 {
3943   ClpSolve options;
3944   // Use primal
3945   options.setSolveType(ClpSolve::useBarrierNoCross);
3946   return initialSolve(options);
3947 }
3948 
3949 // General barrier solve
initialBarrierSolve()3950 int ClpSimplex::initialBarrierSolve()
3951 {
3952   ClpSolve options;
3953   // Use primal
3954   options.setSolveType(ClpSolve::useBarrier);
3955   return initialSolve(options);
3956 }
3957 
3958 // Default constructor
ClpSolve()3959 ClpSolve::ClpSolve()
3960 {
3961   method_ = automatic;
3962   presolveType_ = presolveOn;
3963   numberPasses_ = 5;
3964   int i;
3965   for (i = 0; i < 7; i++)
3966     options_[i] = 0;
3967   // say no +-1 matrix
3968   options_[3] = 1;
3969   for (i = 0; i < 7; i++)
3970     extraInfo_[i] = -1;
3971   independentOptions_[0] = 0;
3972   // But switch off slacks
3973   independentOptions_[1] = 512;
3974   // Substitute up to 3
3975   independentOptions_[2] = 3;
3976 }
3977 // Constructor when you really know what you are doing
ClpSolve(SolveType method,PresolveType presolveType,int numberPasses,int options[6],int extraInfo[6],int independentOptions[3])3978 ClpSolve::ClpSolve(SolveType method, PresolveType presolveType,
3979   int numberPasses, int options[6],
3980   int extraInfo[6], int independentOptions[3])
3981 {
3982   method_ = method;
3983   presolveType_ = presolveType;
3984   numberPasses_ = numberPasses;
3985   int i;
3986   for (i = 0; i < 6; i++)
3987     options_[i] = options[i];
3988   options_[6] = 0;
3989   for (i = 0; i < 6; i++)
3990     extraInfo_[i] = extraInfo[i];
3991   extraInfo_[6] = 0;
3992   for (i = 0; i < 3; i++)
3993     independentOptions_[i] = independentOptions[i];
3994 }
3995 
3996 // Copy constructor.
ClpSolve(const ClpSolve & rhs)3997 ClpSolve::ClpSolve(const ClpSolve &rhs)
3998 {
3999   method_ = rhs.method_;
4000   presolveType_ = rhs.presolveType_;
4001   numberPasses_ = rhs.numberPasses_;
4002   int i;
4003   for (i = 0; i < 7; i++)
4004     options_[i] = rhs.options_[i];
4005   for (i = 0; i < 7; i++)
4006     extraInfo_[i] = rhs.extraInfo_[i];
4007   for (i = 0; i < 3; i++)
4008     independentOptions_[i] = rhs.independentOptions_[i];
4009 }
4010 // Assignment operator. This copies the data
4011 ClpSolve &
operator =(const ClpSolve & rhs)4012 ClpSolve::operator=(const ClpSolve &rhs)
4013 {
4014   if (this != &rhs) {
4015     method_ = rhs.method_;
4016     presolveType_ = rhs.presolveType_;
4017     numberPasses_ = rhs.numberPasses_;
4018     int i;
4019     for (i = 0; i < 7; i++)
4020       options_[i] = rhs.options_[i];
4021     for (i = 0; i < 7; i++)
4022       extraInfo_[i] = rhs.extraInfo_[i];
4023     for (i = 0; i < 3; i++)
4024       independentOptions_[i] = rhs.independentOptions_[i];
4025   }
4026   return *this;
4027 }
4028 // Destructor
~ClpSolve()4029 ClpSolve::~ClpSolve()
4030 {
4031 }
4032 // See header file for details
setSpecialOption(int which,int value,int extraInfo)4033 void ClpSolve::setSpecialOption(int which, int value, int extraInfo)
4034 {
4035   options_[which] = value;
4036   extraInfo_[which] = extraInfo;
4037 }
getSpecialOption(int which) const4038 int ClpSolve::getSpecialOption(int which) const
4039 {
4040   return options_[which];
4041 }
4042 
4043 // Solve types
setSolveType(SolveType method,int)4044 void ClpSolve::setSolveType(SolveType method, int /*extraInfo*/)
4045 {
4046   method_ = method;
4047 }
4048 
4049 ClpSolve::SolveType
getSolveType()4050 ClpSolve::getSolveType()
4051 {
4052   return method_;
4053 }
4054 
4055 // Presolve types
setPresolveType(PresolveType amount,int extraInfo)4056 void ClpSolve::setPresolveType(PresolveType amount, int extraInfo)
4057 {
4058   presolveType_ = amount;
4059   numberPasses_ = extraInfo;
4060 }
4061 ClpSolve::PresolveType
getPresolveType()4062 ClpSolve::getPresolveType()
4063 {
4064   return presolveType_;
4065 }
4066 // Extra info for idiot (or sprint)
getExtraInfo(int which) const4067 int ClpSolve::getExtraInfo(int which) const
4068 {
4069   return extraInfo_[which];
4070 }
getPresolvePasses() const4071 int ClpSolve::getPresolvePasses() const
4072 {
4073   return numberPasses_;
4074 }
4075 /* Say to return at once if infeasible,
4076    default is to solve */
setInfeasibleReturn(bool trueFalse)4077 void ClpSolve::setInfeasibleReturn(bool trueFalse)
4078 {
4079   independentOptions_[0] = trueFalse ? 1 : 0;
4080 }
4081 #include <string>
4082 // Generates code for above constructor
generateCpp(FILE * fp)4083 void ClpSolve::generateCpp(FILE *fp)
4084 {
4085   std::string solveType[] = {
4086     "ClpSolve::useDual",
4087     "ClpSolve::usePrimal",
4088     "ClpSolve::usePrimalorSprint",
4089     "ClpSolve::useBarrier",
4090     "ClpSolve::useBarrierNoCross",
4091     "ClpSolve::automatic",
4092     "ClpSolve::notImplemented"
4093   };
4094   std::string presolveType[] = {
4095     "ClpSolve::presolveOn",
4096     "ClpSolve::presolveOff",
4097     "ClpSolve::presolveNumber",
4098     "ClpSolve::presolveNumberCost"
4099   };
4100   fprintf(fp, "3  ClpSolve::SolveType method = %s;\n", solveType[method_].c_str());
4101   fprintf(fp, "3  ClpSolve::PresolveType presolveType = %s;\n",
4102     presolveType[presolveType_].c_str());
4103   fprintf(fp, "3  int numberPasses = %d;\n", numberPasses_);
4104   fprintf(fp, "3  int options[] = {%d,%d,%d,%d,%d,%d};\n",
4105     options_[0], options_[1], options_[2],
4106     options_[3], options_[4], options_[5]);
4107   fprintf(fp, "3  int extraInfo[] = {%d,%d,%d,%d,%d,%d};\n",
4108     extraInfo_[0], extraInfo_[1], extraInfo_[2],
4109     extraInfo_[3], extraInfo_[4], extraInfo_[5]);
4110   fprintf(fp, "3  int independentOptions[] = {%d,%d,%d};\n",
4111     independentOptions_[0], independentOptions_[1], independentOptions_[2]);
4112   fprintf(fp, "3  ClpSolve clpSolve(method,presolveType,numberPasses,\n");
4113   fprintf(fp, "3                    options,extraInfo,independentOptions);\n");
4114 }
4115 //#############################################################################
4116 #include "ClpNonLinearCost.hpp"
4117 
ClpSimplexProgress()4118 ClpSimplexProgress::ClpSimplexProgress()
4119 {
4120   int i;
4121   for (i = 0; i < CLP_PROGRESS; i++) {
4122     objective_[i] = COIN_DBL_MAX * 1.0e-50;
4123     infeasibility_[i] = -1.0; // set to an impossible value
4124     realInfeasibility_[i] = COIN_DBL_MAX * 1.0e-50;
4125     numberInfeasibilities_[i] = -1;
4126     iterationNumber_[i] = -1;
4127   }
4128 #ifdef CLP_PROGRESS_WEIGHT
4129   for (i = 0; i < CLP_PROGRESS_WEIGHT; i++) {
4130     objectiveWeight_[i] = COIN_DBL_MAX * 1.0e-50;
4131     infeasibilityWeight_[i] = -1.0; // set to an impossible value
4132     realInfeasibilityWeight_[i] = COIN_DBL_MAX * 1.0e-50;
4133     numberInfeasibilitiesWeight_[i] = -1;
4134     iterationNumberWeight_[i] = -1;
4135   }
4136   drop_ = 0.0;
4137   best_ = 0.0;
4138 #endif
4139   initialWeight_ = 0.0;
4140   for (i = 0; i < CLP_CYCLE; i++) {
4141     //obj_[i]=COIN_DBL_MAX*1.0e-50;
4142     in_[i] = -1;
4143     out_[i] = -1;
4144     way_[i] = 0;
4145   }
4146   numberTimes_ = 0;
4147   numberBadTimes_ = 0;
4148   numberReallyBadTimes_ = 0;
4149   numberTimesFlagged_ = 0;
4150   model_ = NULL;
4151   oddState_ = 0;
4152 }
4153 
4154 //-----------------------------------------------------------------------------
4155 
~ClpSimplexProgress()4156 ClpSimplexProgress::~ClpSimplexProgress()
4157 {
4158 }
4159 // Copy constructor.
ClpSimplexProgress(const ClpSimplexProgress & rhs)4160 ClpSimplexProgress::ClpSimplexProgress(const ClpSimplexProgress &rhs)
4161 {
4162   int i;
4163   for (i = 0; i < CLP_PROGRESS; i++) {
4164     objective_[i] = rhs.objective_[i];
4165     infeasibility_[i] = rhs.infeasibility_[i];
4166     realInfeasibility_[i] = rhs.realInfeasibility_[i];
4167     numberInfeasibilities_[i] = rhs.numberInfeasibilities_[i];
4168     iterationNumber_[i] = rhs.iterationNumber_[i];
4169   }
4170 #ifdef CLP_PROGRESS_WEIGHT
4171   for (i = 0; i < CLP_PROGRESS_WEIGHT; i++) {
4172     objectiveWeight_[i] = rhs.objectiveWeight_[i];
4173     infeasibilityWeight_[i] = rhs.infeasibilityWeight_[i];
4174     realInfeasibilityWeight_[i] = rhs.realInfeasibilityWeight_[i];
4175     numberInfeasibilitiesWeight_[i] = rhs.numberInfeasibilitiesWeight_[i];
4176     iterationNumberWeight_[i] = rhs.iterationNumberWeight_[i];
4177   }
4178   drop_ = rhs.drop_;
4179   best_ = rhs.best_;
4180 #endif
4181   initialWeight_ = rhs.initialWeight_;
4182   for (i = 0; i < CLP_CYCLE; i++) {
4183     //obj_[i]=rhs.obj_[i];
4184     in_[i] = rhs.in_[i];
4185     out_[i] = rhs.out_[i];
4186     way_[i] = rhs.way_[i];
4187   }
4188   numberTimes_ = rhs.numberTimes_;
4189   numberBadTimes_ = rhs.numberBadTimes_;
4190   numberReallyBadTimes_ = rhs.numberReallyBadTimes_;
4191   numberTimesFlagged_ = rhs.numberTimesFlagged_;
4192   model_ = rhs.model_;
4193   oddState_ = rhs.oddState_;
4194 }
4195 // Copy constructor.from model
ClpSimplexProgress(ClpSimplex * model)4196 ClpSimplexProgress::ClpSimplexProgress(ClpSimplex *model)
4197 {
4198   model_ = model;
4199   reset();
4200   initialWeight_ = 0.0;
4201 }
4202 // Fill from model
fillFromModel(ClpSimplex * model)4203 void ClpSimplexProgress::fillFromModel(ClpSimplex *model)
4204 {
4205   model_ = model;
4206   reset();
4207   initialWeight_ = 0.0;
4208 }
4209 // Assignment operator. This copies the data
4210 ClpSimplexProgress &
operator =(const ClpSimplexProgress & rhs)4211 ClpSimplexProgress::operator=(const ClpSimplexProgress &rhs)
4212 {
4213   if (this != &rhs) {
4214     int i;
4215     for (i = 0; i < CLP_PROGRESS; i++) {
4216       objective_[i] = rhs.objective_[i];
4217       infeasibility_[i] = rhs.infeasibility_[i];
4218       realInfeasibility_[i] = rhs.realInfeasibility_[i];
4219       numberInfeasibilities_[i] = rhs.numberInfeasibilities_[i];
4220       iterationNumber_[i] = rhs.iterationNumber_[i];
4221     }
4222 #ifdef CLP_PROGRESS_WEIGHT
4223     for (i = 0; i < CLP_PROGRESS_WEIGHT; i++) {
4224       objectiveWeight_[i] = rhs.objectiveWeight_[i];
4225       infeasibilityWeight_[i] = rhs.infeasibilityWeight_[i];
4226       realInfeasibilityWeight_[i] = rhs.realInfeasibilityWeight_[i];
4227       numberInfeasibilitiesWeight_[i] = rhs.numberInfeasibilitiesWeight_[i];
4228       iterationNumberWeight_[i] = rhs.iterationNumberWeight_[i];
4229     }
4230     drop_ = rhs.drop_;
4231     best_ = rhs.best_;
4232 #endif
4233     initialWeight_ = rhs.initialWeight_;
4234     for (i = 0; i < CLP_CYCLE; i++) {
4235       //obj_[i]=rhs.obj_[i];
4236       in_[i] = rhs.in_[i];
4237       out_[i] = rhs.out_[i];
4238       way_[i] = rhs.way_[i];
4239     }
4240     numberTimes_ = rhs.numberTimes_;
4241     numberBadTimes_ = rhs.numberBadTimes_;
4242     numberReallyBadTimes_ = rhs.numberReallyBadTimes_;
4243     numberTimesFlagged_ = rhs.numberTimesFlagged_;
4244     model_ = rhs.model_;
4245     oddState_ = rhs.oddState_;
4246   }
4247   return *this;
4248 }
4249 // Seems to be something odd about exact comparison of doubles on linux
equalDouble(double value1,double value2)4250 static bool equalDouble(double value1, double value2)
4251 {
4252 
4253   union {
4254     double d;
4255     int i[2];
4256   } v1, v2;
4257   v1.d = value1;
4258   v2.d = value2;
4259   if (sizeof(int) * 2 == sizeof(double))
4260     return (v1.i[0] == v2.i[0] && v1.i[1] == v2.i[1]);
4261   else
4262     return (v1.i[0] == v2.i[0]);
4263 }
looping()4264 int ClpSimplexProgress::looping()
4265 {
4266   if (!model_)
4267     return -1;
4268   double objective;
4269   if (model_->algorithm() < 0) {
4270     objective = model_->rawObjectiveValue();
4271     objective -= model_->bestPossibleImprovement();
4272   } else {
4273     objective = model_->nonLinearCost()->feasibleReportCost();
4274   }
4275   double infeasibility;
4276   double realInfeasibility = 0.0;
4277   int numberInfeasibilities;
4278   int iterationNumber = model_->numberIterations();
4279   //numberTimesFlagged_ = 0;
4280   if (model_->algorithm() < 0) {
4281     // dual
4282     infeasibility = model_->sumPrimalInfeasibilities();
4283     numberInfeasibilities = model_->numberPrimalInfeasibilities();
4284   } else {
4285     //primal
4286     infeasibility = model_->sumDualInfeasibilities();
4287     realInfeasibility = model_->nonLinearCost()->sumInfeasibilities();
4288     numberInfeasibilities = model_->numberDualInfeasibilities();
4289   }
4290   int i;
4291   int numberMatched = 0;
4292   int matched = 0;
4293   int nsame = 0;
4294   for (i = 0; i < CLP_PROGRESS; i++) {
4295     bool matchedOnObjective = equalDouble(objective, objective_[i]);
4296     bool matchedOnInfeasibility = equalDouble(infeasibility, infeasibility_[i]);
4297     bool matchedOnInfeasibilities = (numberInfeasibilities == numberInfeasibilities_[i]);
4298 
4299     if (matchedOnObjective && matchedOnInfeasibility && matchedOnInfeasibilities) {
4300       matched |= (1 << i);
4301       // Check not same iteration
4302       if (iterationNumber != iterationNumber_[i]) {
4303         numberMatched++;
4304         // here mainly to get over compiler bug?
4305         if (model_->messageHandler()->logLevel() > 10)
4306           printf("%d %d %d %d %d loop check\n", i, numberMatched,
4307             matchedOnObjective, matchedOnInfeasibility,
4308             matchedOnInfeasibilities);
4309       } else {
4310         // stuck but code should notice
4311         nsame++;
4312       }
4313     }
4314     if (i) {
4315       objective_[i - 1] = objective_[i];
4316       infeasibility_[i - 1] = infeasibility_[i];
4317       realInfeasibility_[i - 1] = realInfeasibility_[i];
4318       numberInfeasibilities_[i - 1] = numberInfeasibilities_[i];
4319       iterationNumber_[i - 1] = iterationNumber_[i];
4320     }
4321   }
4322   objective_[CLP_PROGRESS - 1] = objective;
4323   infeasibility_[CLP_PROGRESS - 1] = infeasibility;
4324   realInfeasibility_[CLP_PROGRESS - 1] = realInfeasibility;
4325   numberInfeasibilities_[CLP_PROGRESS - 1] = numberInfeasibilities;
4326   iterationNumber_[CLP_PROGRESS - 1] = iterationNumber;
4327   if (nsame == CLP_PROGRESS)
4328     numberMatched = CLP_PROGRESS; // really stuck
4329   if (model_->progressFlag())
4330     numberMatched = 0;
4331   numberTimes_++;
4332   if (numberTimes_ < 10)
4333     numberMatched = 0;
4334   // skip if just last time as may be checking something
4335   if (matched == (1 << (CLP_PROGRESS - 1)))
4336     numberMatched = 0;
4337   if (numberMatched && model_->clpMatrix()->type() < 15) {
4338     model_->messageHandler()->message(CLP_POSSIBLELOOP, model_->messages())
4339       << numberMatched
4340       << matched
4341       << numberTimes_
4342       << CoinMessageEol;
4343     numberBadTimes_++;
4344     if (numberBadTimes_ < 10) {
4345       // make factorize every iteration
4346       model_->forceFactorization(1);
4347       if (numberBadTimes_ < 2) {
4348         startCheck(); // clear other loop check
4349         if (model_->algorithm() < 0) {
4350           // dual - change tolerance
4351           model_->setCurrentDualTolerance(model_->currentDualTolerance() * 1.05);
4352           // if infeasible increase dual bound
4353           if (model_->dualBound() < 1.0e17) {
4354             model_->setDualBound(model_->dualBound() * 1.1);
4355             static_cast< ClpSimplexDual * >(model_)->resetFakeBounds(0);
4356           }
4357         } else {
4358           // primal - change tolerance
4359           if (numberBadTimes_ > 3)
4360             model_->setCurrentPrimalTolerance(model_->currentPrimalTolerance() * 1.05);
4361           // if infeasible increase infeasibility cost
4362           if (model_->nonLinearCost()->numberInfeasibilities() && model_->infeasibilityCost() < 1.0e17) {
4363             model_->setInfeasibilityCost(model_->infeasibilityCost() * 1.1);
4364           }
4365         }
4366       } else {
4367         // flag
4368         int iSequence;
4369         if (model_->algorithm() < 0) {
4370           // dual
4371           if (model_->dualBound() > 1.0e14)
4372             model_->setDualBound(1.0e14);
4373           iSequence = in_[CLP_CYCLE - 1];
4374         } else {
4375           // primal
4376           //if (model_->infeasibilityCost() > 1.0e14)
4377           //   model_->setInfeasibilityCost(1.0e14);
4378           iSequence = out_[CLP_CYCLE - 1];
4379         }
4380         if (iSequence >= 0) {
4381           char x = model_->isColumn(iSequence) ? 'C' : 'R';
4382           if (model_->messageHandler()->logLevel() >= 63)
4383             model_->messageHandler()->message(CLP_SIMPLEX_FLAG, model_->messages())
4384               << x << model_->sequenceWithin(iSequence)
4385               << CoinMessageEol;
4386           // if Gub then needs to be sequenceIn_
4387           int save = model_->sequenceIn();
4388           model_->setSequenceIn(iSequence);
4389           model_->setFlagged(iSequence);
4390           model_->setSequenceIn(save);
4391           //printf("flagging %d from loop\n",iSequence);
4392           startCheck();
4393         } else {
4394           // Give up
4395           if (model_->messageHandler()->logLevel() >= 63)
4396             printf("***** All flagged?\n");
4397           return 4;
4398         }
4399         // reset
4400         numberBadTimes_ = 2;
4401       }
4402       return -2;
4403     } else {
4404       // look at solution and maybe declare victory
4405       if (infeasibility < 1.0e-4) {
4406         return 0;
4407       } else {
4408         model_->messageHandler()->message(CLP_LOOP, model_->messages())
4409           << CoinMessageEol;
4410 #ifndef NDEBUG
4411         printf("debug loop ClpSimplex A\n");
4412         abort();
4413 #endif
4414         return 3;
4415       }
4416     }
4417   }
4418   return -1;
4419 }
4420 // Resets as much as possible
reset()4421 void ClpSimplexProgress::reset()
4422 {
4423   int i;
4424   for (i = 0; i < CLP_PROGRESS; i++) {
4425     if (model_->algorithm() >= 0)
4426       objective_[i] = COIN_DBL_MAX * 1.0e-50;
4427     else
4428       objective_[i] = -COIN_DBL_MAX * 1.0e-50;
4429     infeasibility_[i] = -1.0; // set to an impossible value
4430     realInfeasibility_[i] = COIN_DBL_MAX * 1.0e-50;
4431     numberInfeasibilities_[i] = -1;
4432     iterationNumber_[i] = -1;
4433   }
4434 #ifdef CLP_PROGRESS_WEIGHT
4435   for (i = 0; i < CLP_PROGRESS_WEIGHT; i++) {
4436     objectiveWeight_[i] = COIN_DBL_MAX * 1.0e-50;
4437     infeasibilityWeight_[i] = -1.0; // set to an impossible value
4438     realInfeasibilityWeight_[i] = COIN_DBL_MAX * 1.0e-50;
4439     numberInfeasibilitiesWeight_[i] = -1;
4440     iterationNumberWeight_[i] = -1;
4441   }
4442   drop_ = 0.0;
4443   best_ = 0.0;
4444 #endif
4445   for (i = 0; i < CLP_CYCLE; i++) {
4446     //obj_[i]=COIN_DBL_MAX*1.0e-50;
4447     in_[i] = -1;
4448     out_[i] = -1;
4449     way_[i] = 0;
4450   }
4451   numberTimes_ = 0;
4452   numberBadTimes_ = 0;
4453   numberReallyBadTimes_ = 0;
4454   numberTimesFlagged_ = 0;
4455   oddState_ = 0;
4456 }
4457 // Returns previous objective (if -1) - current if (0)
4458 double
lastObjective(int back) const4459 ClpSimplexProgress::lastObjective(int back) const
4460 {
4461   return objective_[CLP_PROGRESS - 1 - back];
4462 }
4463 // Returns previous infeasibility (if -1) - current if (0)
4464 double
lastInfeasibility(int back) const4465 ClpSimplexProgress::lastInfeasibility(int back) const
4466 {
4467   return realInfeasibility_[CLP_PROGRESS - 1 - back];
4468 }
4469 // Sets real primal infeasibility
setInfeasibility(double value)4470 void ClpSimplexProgress::setInfeasibility(double value)
4471 {
4472   for (int i = 1; i < CLP_PROGRESS; i++)
4473     realInfeasibility_[i - 1] = realInfeasibility_[i];
4474   realInfeasibility_[CLP_PROGRESS - 1] = value;
4475 }
4476 // Returns number of primal infeasibilities (if -1) - current if (0)
numberInfeasibilities(int back) const4477 int ClpSimplexProgress::numberInfeasibilities(int back) const
4478 {
4479   return numberInfeasibilities_[CLP_PROGRESS - 1 - back];
4480 }
4481 // Modify objective e.g. if dual infeasible in dual
modifyObjective(double value)4482 void ClpSimplexProgress::modifyObjective(double value)
4483 {
4484   objective_[CLP_PROGRESS - 1] = value;
4485 }
4486 // Returns previous iteration number (if -1) - current if (0)
lastIterationNumber(int back) const4487 int ClpSimplexProgress::lastIterationNumber(int back) const
4488 {
4489   return iterationNumber_[CLP_PROGRESS - 1 - back];
4490 }
4491 // clears iteration numbers (to switch off panic)
clearIterationNumbers()4492 void ClpSimplexProgress::clearIterationNumbers()
4493 {
4494   for (int i = 0; i < CLP_PROGRESS; i++)
4495     iterationNumber_[i] = -1;
4496 }
4497 // Start check at beginning of whileIterating
startCheck()4498 void ClpSimplexProgress::startCheck()
4499 {
4500   int i;
4501   for (i = 0; i < CLP_CYCLE; i++) {
4502     //obj_[i]=COIN_DBL_MAX*1.0e-50;
4503     in_[i] = -1;
4504     out_[i] = -1;
4505     way_[i] = 0;
4506   }
4507 }
4508 // Returns cycle length in whileIterating
cycle(int in,int out,int wayIn,int wayOut)4509 int ClpSimplexProgress::cycle(int in, int out, int wayIn, int wayOut)
4510 {
4511   int i;
4512 #if 0
4513      if (model_->numberIterations() > 206571) {
4514           printf("in %d out %d\n", in, out);
4515           for (i = 0; i < CLP_CYCLE; i++)
4516                printf("cy %d in %d out %d\n", i, in_[i], out_[i]);
4517      }
4518 #endif
4519   int matched = 0;
4520   // first see if in matches any out
4521   for (i = 1; i < CLP_CYCLE; i++) {
4522     if (in == out_[i]) {
4523       // even if flip then suspicious
4524       matched = -1;
4525       break;
4526     }
4527   }
4528 #if 0
4529      if (!matched || in_[0] < 0) {
4530           // can't be cycle
4531           for (i = 0; i < CLP_CYCLE - 1; i++) {
4532                //obj_[i]=obj_[i+1];
4533                in_[i] = in_[i+1];
4534                out_[i] = out_[i+1];
4535                way_[i] = way_[i+1];
4536           }
4537      } else {
4538           // possible cycle
4539           matched = 0;
4540           for (i = 0; i < CLP_CYCLE - 1; i++) {
4541                int k;
4542                char wayThis = way_[i];
4543                int inThis = in_[i];
4544                int outThis = out_[i];
4545                //double objThis = obj_[i];
4546                for(k = i + 1; k < CLP_CYCLE; k++) {
4547                     if (inThis == in_[k] && outThis == out_[k] && wayThis == way_[k]) {
4548                          int distance = k - i;
4549                          if (k + distance < CLP_CYCLE) {
4550                               // See if repeats
4551                               int j = k + distance;
4552                               if (inThis == in_[j] && outThis == out_[j] && wayThis == way_[j]) {
4553                                    matched = distance;
4554                                    break;
4555                               }
4556                          } else {
4557                               matched = distance;
4558                               break;
4559                          }
4560                     }
4561                }
4562                //obj_[i]=obj_[i+1];
4563                in_[i] = in_[i+1];
4564                out_[i] = out_[i+1];
4565                way_[i] = way_[i+1];
4566           }
4567      }
4568 #else
4569   if (matched && in_[0] >= 0) {
4570     // possible cycle - only check [0] against all
4571     matched = 0;
4572     int nMatched = 0;
4573     char way0 = way_[0];
4574     int in0 = in_[0];
4575     int out0 = out_[0];
4576     //double obj0 = obj_[i];
4577     for (int k = 1; k < CLP_CYCLE - 4; k++) {
4578       if (in0 == in_[k] && out0 == out_[k] && way0 == way_[k]) {
4579         nMatched++;
4580         // See if repeats
4581         int end = CLP_CYCLE - k;
4582         int j;
4583         for (j = 1; j < end; j++) {
4584           if (in_[j + k] != in_[j] || out_[j + k] != out_[j] || way_[j + k] != way_[j])
4585             break;
4586         }
4587         if (j == end) {
4588           matched = k;
4589           break;
4590         }
4591       }
4592     }
4593     // If three times then that is too much even if not regular
4594     if (matched <= 0 && nMatched > 1)
4595       matched = 100;
4596   }
4597   for (i = 0; i < CLP_CYCLE - 1; i++) {
4598     //obj_[i]=obj_[i+1];
4599     in_[i] = in_[i + 1];
4600     out_[i] = out_[i + 1];
4601     way_[i] = way_[i + 1];
4602   }
4603 #endif
4604   int way = 1 - wayIn + 4 * (1 - wayOut);
4605   //obj_[i]=model_->objectiveValue();
4606   in_[CLP_CYCLE - 1] = in;
4607   out_[CLP_CYCLE - 1] = out;
4608   way_[CLP_CYCLE - 1] = static_cast< char >(way);
4609   return matched;
4610 }
4611 #include "CoinStructuredModel.hpp"
4612 // Solve using structure of model and maybe in parallel
solve(CoinStructuredModel * model)4613 int ClpSimplex::solve(CoinStructuredModel *model)
4614 {
4615   // analyze structure
4616   int numberRowBlocks = model->numberRowBlocks();
4617   int numberColumnBlocks = model->numberColumnBlocks();
4618   int numberElementBlocks = model->numberElementBlocks();
4619   if (numberElementBlocks == 1) {
4620     loadProblem(*model, false);
4621     return dual();
4622   }
4623   // For now just get top level structure
4624   CoinModelBlockInfo *blockInfo = new CoinModelBlockInfo[numberElementBlocks];
4625   for (int i = 0; i < numberElementBlocks; i++) {
4626     CoinStructuredModel *subModel = dynamic_cast< CoinStructuredModel * >(model->block(i));
4627     CoinModel *thisBlock;
4628     if (subModel) {
4629       thisBlock = subModel->coinModelBlock(blockInfo[i]);
4630       model->setCoinModel(thisBlock, i);
4631     } else {
4632       thisBlock = dynamic_cast< CoinModel * >(model->block(i));
4633       assert(thisBlock);
4634       // just fill in info
4635       CoinModelBlockInfo info = CoinModelBlockInfo();
4636       int whatsSet = thisBlock->whatIsSet();
4637       info.matrix = static_cast< char >(((whatsSet & 1) != 0) ? 1 : 0);
4638       info.rhs = static_cast< char >(((whatsSet & 2) != 0) ? 1 : 0);
4639       info.rowName = static_cast< char >(((whatsSet & 4) != 0) ? 1 : 0);
4640       info.integer = static_cast< char >(((whatsSet & 32) != 0) ? 1 : 0);
4641       info.bounds = static_cast< char >(((whatsSet & 8) != 0) ? 1 : 0);
4642       info.columnName = static_cast< char >(((whatsSet & 16) != 0) ? 1 : 0);
4643       // Which block
4644       int iRowBlock = model->rowBlock(thisBlock->getRowBlock());
4645       info.rowBlock = iRowBlock;
4646       int iColumnBlock = model->columnBlock(thisBlock->getColumnBlock());
4647       info.columnBlock = iColumnBlock;
4648       blockInfo[i] = info;
4649     }
4650   }
4651   int *rowCounts = new int[numberRowBlocks];
4652   CoinZeroN(rowCounts, numberRowBlocks);
4653   int *columnCounts = new int[numberColumnBlocks + 1];
4654   CoinZeroN(columnCounts, numberColumnBlocks);
4655   int decomposeType = 0;
4656   for (int i = 0; i < numberElementBlocks; i++) {
4657     int iRowBlock = blockInfo[i].rowBlock;
4658     int iColumnBlock = blockInfo[i].columnBlock;
4659     rowCounts[iRowBlock]++;
4660     columnCounts[iColumnBlock]++;
4661   }
4662   if (numberRowBlocks == numberColumnBlocks || numberRowBlocks == numberColumnBlocks + 1) {
4663     // could be Dantzig-Wolfe
4664     int numberG1 = 0;
4665     for (int i = 0; i < numberRowBlocks; i++) {
4666       if (rowCounts[i] > 1)
4667         numberG1++;
4668     }
4669     bool masterColumns = (numberColumnBlocks == numberRowBlocks);
4670     if ((masterColumns && numberElementBlocks == 2 * numberRowBlocks - 1)
4671       || (!masterColumns && numberElementBlocks == 2 * numberRowBlocks)) {
4672       if (numberG1 < 2)
4673         decomposeType = 1;
4674     }
4675   }
4676   if (!decomposeType && (numberRowBlocks == numberColumnBlocks || numberRowBlocks == numberColumnBlocks - 1)) {
4677     // could be Benders
4678     int numberG1 = 0;
4679     for (int i = 0; i < numberColumnBlocks; i++) {
4680       if (columnCounts[i] > 1)
4681         numberG1++;
4682     }
4683     bool masterRows = (numberColumnBlocks == numberRowBlocks);
4684     if ((masterRows && numberElementBlocks == 2 * numberColumnBlocks - 1)
4685       || (!masterRows && numberElementBlocks == 2 * numberColumnBlocks)) {
4686       if (numberG1 < 2)
4687         decomposeType = 2;
4688     }
4689   }
4690   delete[] rowCounts;
4691   delete[] columnCounts;
4692   delete[] blockInfo;
4693   // decide what to do
4694   ClpSolve options;
4695   options.setIndependentOption(2, 100);
4696   switch (decomposeType) {
4697     // No good
4698   case 0:
4699     loadProblem(*model, false);
4700     return dual();
4701     // DW
4702   case 1:
4703     return solveDW(model, options);
4704     // Benders
4705   case 2:
4706     return solveBenders(model, options);
4707   }
4708   return 0; // to stop compiler warning
4709 }
4710 /* This loads a model from a CoinStructuredModel object - returns number of errors.
4711    If originalOrder then keep to order stored in blocks,
4712    otherwise first column/rows correspond to first block - etc.
4713    If keepSolution true and size is same as current then
4714    keeps current status and solution
4715 */
loadProblem(CoinStructuredModel & coinModel,bool originalOrder,bool keepSolution)4716 int ClpSimplex::loadProblem(CoinStructuredModel &coinModel,
4717   bool originalOrder,
4718   bool keepSolution)
4719 {
4720   unsigned char *status = NULL;
4721   double *psol = NULL;
4722   double *dsol = NULL;
4723   int numberRows = coinModel.numberRows();
4724   int numberColumns = coinModel.numberColumns();
4725   int numberRowBlocks = coinModel.numberRowBlocks();
4726   int numberColumnBlocks = coinModel.numberColumnBlocks();
4727   int numberElementBlocks = coinModel.numberElementBlocks();
4728   if (status_ && numberRows_ && numberRows_ == numberRows && numberColumns_ == numberColumns && keepSolution) {
4729     status = new unsigned char[numberRows_ + numberColumns_];
4730     CoinMemcpyN(status_, numberRows_ + numberColumns_, status);
4731     psol = new double[numberRows_ + numberColumns_];
4732     CoinMemcpyN(columnActivity_, numberColumns_, psol);
4733     CoinMemcpyN(rowActivity_, numberRows_, psol + numberColumns_);
4734     dsol = new double[numberRows_ + numberColumns_];
4735     CoinMemcpyN(reducedCost_, numberColumns_, dsol);
4736     CoinMemcpyN(dual_, numberRows_, dsol + numberColumns_);
4737   }
4738   int returnCode = 0;
4739   double *rowLower = new double[numberRows];
4740   double *rowUpper = new double[numberRows];
4741   double *columnLower = new double[numberColumns];
4742   double *columnUpper = new double[numberColumns];
4743   double *objective = new double[numberColumns];
4744   int *integerType = new int[numberColumns];
4745   CoinBigIndex numberElements = 0;
4746   // Bases for blocks
4747   int *rowBase = new int[numberRowBlocks];
4748   CoinFillN(rowBase, numberRowBlocks, -1);
4749   // And row to put it
4750   int *whichRow = new int[numberRows + numberRowBlocks];
4751   int *columnBase = new int[numberColumnBlocks];
4752   CoinFillN(columnBase, numberColumnBlocks, -1);
4753   // And column to put it
4754   int *whichColumn = new int[numberColumns + numberColumnBlocks];
4755   for (int iBlock = 0; iBlock < numberElementBlocks; iBlock++) {
4756     CoinModel *block = coinModel.coinBlock(iBlock);
4757     numberElements += block->numberElements();
4758     //and set up elements etc
4759     double *associated = block->associatedArray();
4760     // If strings then do copies
4761     if (block->stringsExist())
4762       returnCode += block->createArrays(rowLower, rowUpper, columnLower, columnUpper,
4763         objective, integerType, associated);
4764     const CoinModelBlockInfo &info = coinModel.blockType(iBlock);
4765     int iRowBlock = info.rowBlock;
4766     int iColumnBlock = info.columnBlock;
4767     if (rowBase[iRowBlock] < 0) {
4768       rowBase[iRowBlock] = block->numberRows();
4769       // Save block number
4770       whichRow[numberRows + iRowBlock] = iBlock;
4771     } else {
4772       assert(rowBase[iRowBlock] == block->numberRows());
4773     }
4774     if (columnBase[iColumnBlock] < 0) {
4775       columnBase[iColumnBlock] = block->numberColumns();
4776       // Save block number
4777       whichColumn[numberColumns + iColumnBlock] = iBlock;
4778     } else {
4779       assert(columnBase[iColumnBlock] == block->numberColumns());
4780     }
4781   }
4782   // Fill arrays with defaults
4783   CoinFillN(rowLower, numberRows, -COIN_DBL_MAX);
4784   CoinFillN(rowUpper, numberRows, COIN_DBL_MAX);
4785   CoinFillN(columnLower, numberColumns, 0.0);
4786   CoinFillN(columnUpper, numberColumns, COIN_DBL_MAX);
4787   CoinFillN(objective, numberColumns, 0.0);
4788   CoinFillN(integerType, numberColumns, 0);
4789   int n = 0;
4790   for (int iBlock = 0; iBlock < numberRowBlocks; iBlock++) {
4791     int k = rowBase[iBlock];
4792     rowBase[iBlock] = n;
4793     assert(k >= 0);
4794     // block number
4795     int jBlock = whichRow[numberRows + iBlock];
4796     if (originalOrder) {
4797       memcpy(whichRow + n, coinModel.coinBlock(jBlock)->originalRows(), k * sizeof(int));
4798     } else {
4799       CoinIotaN(whichRow + n, k, n);
4800     }
4801     n += k;
4802   }
4803   assert(n == numberRows);
4804   n = 0;
4805   for (int iBlock = 0; iBlock < numberColumnBlocks; iBlock++) {
4806     int k = columnBase[iBlock];
4807     columnBase[iBlock] = n;
4808     assert(k >= 0);
4809     if (k) {
4810       // block number
4811       int jBlock = whichColumn[numberColumns + iBlock];
4812       if (originalOrder) {
4813         memcpy(whichColumn + n, coinModel.coinBlock(jBlock)->originalColumns(),
4814           k * sizeof(int));
4815       } else {
4816         CoinIotaN(whichColumn + n, k, n);
4817       }
4818       n += k;
4819     }
4820   }
4821   assert(n == numberColumns);
4822   bool gotIntegers = false;
4823   for (int iBlock = 0; iBlock < numberElementBlocks; iBlock++) {
4824     CoinModel *block = coinModel.coinBlock(iBlock);
4825     const CoinModelBlockInfo &info = coinModel.blockType(iBlock);
4826     int iRowBlock = info.rowBlock;
4827     int iRowBase = rowBase[iRowBlock];
4828     int iColumnBlock = info.columnBlock;
4829     int iColumnBase = columnBase[iColumnBlock];
4830     if (info.rhs) {
4831       int nRows = block->numberRows();
4832       const double *lower = block->rowLowerArray();
4833       const double *upper = block->rowUpperArray();
4834       for (int i = 0; i < nRows; i++) {
4835         int put = whichRow[i + iRowBase];
4836         rowLower[put] = lower[i];
4837         rowUpper[put] = upper[i];
4838       }
4839     }
4840     if (info.bounds) {
4841       int nColumns = block->numberColumns();
4842       const double *lower = block->columnLowerArray();
4843       const double *upper = block->columnUpperArray();
4844       const double *obj = block->objectiveArray();
4845       for (int i = 0; i < nColumns; i++) {
4846         int put = whichColumn[i + iColumnBase];
4847         columnLower[put] = lower[i];
4848         columnUpper[put] = upper[i];
4849         objective[put] = obj[i];
4850       }
4851     }
4852     if (info.integer) {
4853       gotIntegers = true;
4854       int nColumns = block->numberColumns();
4855       const int *type = block->integerTypeArray();
4856       for (int i = 0; i < nColumns; i++) {
4857         int put = whichColumn[i + iColumnBase];
4858         integerType[put] = type[i];
4859       }
4860     }
4861   }
4862   gutsOfLoadModel(numberRows, numberColumns,
4863     columnLower, columnUpper, objective, rowLower, rowUpper, NULL);
4864   delete[] rowLower;
4865   delete[] rowUpper;
4866   delete[] columnLower;
4867   delete[] columnUpper;
4868   delete[] objective;
4869   // Do integers if wanted
4870   if (gotIntegers) {
4871     for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
4872       if (integerType[iColumn])
4873         setInteger(iColumn);
4874     }
4875   }
4876   delete[] integerType;
4877   setObjectiveOffset(coinModel.objectiveOffset());
4878   // Space for elements
4879   int *row = new int[numberElements];
4880   int *column = new int[numberElements];
4881   double *element = new double[numberElements];
4882   numberElements = 0;
4883   for (int iBlock = 0; iBlock < numberElementBlocks; iBlock++) {
4884     CoinModel *block = coinModel.coinBlock(iBlock);
4885     const CoinModelBlockInfo &info = coinModel.blockType(iBlock);
4886     int iRowBlock = info.rowBlock;
4887     int iRowBase = rowBase[iRowBlock];
4888     int iColumnBlock = info.columnBlock;
4889     int iColumnBase = columnBase[iColumnBlock];
4890     if (info.rowName) {
4891       int numberItems = block->rowNames()->numberItems();
4892       assert(block->numberRows() >= numberItems);
4893       if (numberItems) {
4894         const char *const *rowNames = block->rowNames()->names();
4895         for (int i = 0; i < numberItems; i++) {
4896           int put = whichRow[i + iRowBase];
4897           std::string name = rowNames[i];
4898           setRowName(put, name);
4899         }
4900       }
4901     }
4902     if (info.columnName) {
4903       int numberItems = block->columnNames()->numberItems();
4904       assert(block->numberColumns() >= numberItems);
4905       if (numberItems) {
4906         const char *const *columnNames = block->columnNames()->names();
4907         for (int i = 0; i < numberItems; i++) {
4908           int put = whichColumn[i + iColumnBase];
4909           std::string name = columnNames[i];
4910           setColumnName(put, name);
4911         }
4912       }
4913     }
4914     if (info.matrix) {
4915       CoinPackedMatrix matrix2;
4916       const CoinPackedMatrix *matrix = block->packedMatrix();
4917       if (!matrix) {
4918         double *associated = block->associatedArray();
4919         block->createPackedMatrix(matrix2, associated);
4920         matrix = &matrix2;
4921       }
4922       // get matrix data pointers
4923       const int *row2 = matrix->getIndices();
4924       const CoinBigIndex *columnStart = matrix->getVectorStarts();
4925       const double *elementByColumn = matrix->getElements();
4926       const int *columnLength = matrix->getVectorLengths();
4927       int n = matrix->getNumCols();
4928       assert(matrix->isColOrdered());
4929       for (int iColumn = 0; iColumn < n; iColumn++) {
4930         CoinBigIndex j;
4931         int jColumn = whichColumn[iColumn + iColumnBase];
4932         for (j = columnStart[iColumn];
4933              j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4934           row[numberElements] = whichRow[row2[j] + iRowBase];
4935           column[numberElements] = jColumn;
4936           element[numberElements++] = elementByColumn[j];
4937         }
4938       }
4939     }
4940   }
4941   delete[] whichRow;
4942   delete[] whichColumn;
4943   delete[] rowBase;
4944   delete[] columnBase;
4945   CoinPackedMatrix *matrix = new CoinPackedMatrix(true, row, column, element, numberElements);
4946   matrix_ = new ClpPackedMatrix(matrix);
4947   matrix_->setDimensions(numberRows, numberColumns);
4948   delete[] row;
4949   delete[] column;
4950   delete[] element;
4951   createStatus();
4952   if (status) {
4953     // copy back
4954     CoinMemcpyN(status, numberRows_ + numberColumns_, status_);
4955     CoinMemcpyN(psol, numberColumns_, columnActivity_);
4956     CoinMemcpyN(psol + numberColumns_, numberRows_, rowActivity_);
4957     CoinMemcpyN(dsol, numberColumns_, reducedCost_);
4958     CoinMemcpyN(dsol + numberColumns_, numberRows_, dual_);
4959     delete[] status;
4960     delete[] psol;
4961     delete[] dsol;
4962   }
4963   optimizationDirection_ = coinModel.optimizationDirection();
4964   return returnCode;
4965 }
4966 /*  If input negative scales objective so maximum <= -value
4967     and returns scale factor used.  If positive unscales and also
4968     redoes dual stuff
4969 */
4970 double
scaleObjective(double value)4971 ClpSimplex::scaleObjective(double value)
4972 {
4973   double *obj = objective();
4974   double largest = 0.0;
4975   if (value < 0.0) {
4976     value = -value;
4977     for (int i = 0; i < numberColumns_; i++) {
4978       largest = CoinMax(largest, fabs(obj[i]));
4979     }
4980     if (largest > value) {
4981       double scaleFactor = value / largest;
4982       for (int i = 0; i < numberColumns_; i++) {
4983         obj[i] *= scaleFactor;
4984         reducedCost_[i] *= scaleFactor;
4985       }
4986       for (int i = 0; i < numberRows_; i++) {
4987         dual_[i] *= scaleFactor;
4988       }
4989       largest /= value;
4990     } else {
4991       // no need
4992       largest = 1.0;
4993     }
4994   } else {
4995     // at end
4996     if (value != 1.0) {
4997       for (int i = 0; i < numberColumns_; i++) {
4998         obj[i] *= value;
4999         reducedCost_[i] *= value;
5000       }
5001       for (int i = 0; i < numberRows_; i++) {
5002         dual_[i] *= value;
5003       }
5004       computeObjectiveValue();
5005     }
5006   }
5007   return largest;
5008 }
5009 #if defined(ABC_INHERIT) || defined(CBC_THREAD) || defined(THREADS_IN_ANALYZE)
clp_parallelManager(void * stuff)5010 void *clp_parallelManager(void *stuff)
5011 {
5012   CoinPthreadStuff *driver = reinterpret_cast< CoinPthreadStuff * >(stuff);
5013   int whichThread = driver->whichThread();
5014   CoinThreadInfo *threadInfo = driver->threadInfoPointer(whichThread);
5015   threadInfo->status = -1;
5016   int *which = threadInfo->stuff;
5017 #ifdef PTHREAD_BARRIER_SERIAL_THREAD
5018   pthread_barrier_wait(driver->barrierPointer());
5019 #endif
5020 #if 0
5021   int status=-1;
5022   while (status!=100)
5023     status=timedWait(driver,1000,2);
5024   pthread_cond_signal(driver->conditionPointer(1));
5025   pthread_mutex_unlock(driver->mutexPointer(1,whichThread));
5026 #endif
5027   // so now mutex_ is locked
5028   int whichLocked = 0;
5029   while (true) {
5030     pthread_mutex_t *mutexPointer = driver->mutexPointer(whichLocked, whichThread);
5031     // wait
5032     //printf("Child waiting for %d - status %d %d %d\n",
5033     //	   whichLocked,lockedX[0],lockedX[1],lockedX[2]);
5034 #ifdef DETAIL_THREAD
5035     printf("thread %d about to lock mutex %d\n", whichThread, whichLocked);
5036 #endif
5037     pthread_mutex_lock(mutexPointer);
5038     whichLocked++;
5039     if (whichLocked == 3)
5040       whichLocked = 0;
5041     int unLock = whichLocked + 1;
5042     if (unLock == 3)
5043       unLock = 0;
5044     //printf("child pointer %x status %d\n",threadInfo,threadInfo->status);
5045     assert(threadInfo->status >= 0);
5046     if (threadInfo->status == 1000)
5047       pthread_exit(NULL);
5048     int type = threadInfo->status;
5049     int &returnCode = which[0];
5050     int iPass = which[1];
5051     ClpSimplex *clpSimplex = reinterpret_cast< ClpSimplex * >(threadInfo->extraInfo);
5052     //CoinIndexedVector * array;
5053     //double dummy;
5054     switch (type) {
5055       // dummy
5056     case 0:
5057       break;
5058     case 1:
5059       if (!clpSimplex->problemStatus() || !iPass)
5060         returnCode = clpSimplex->dual();
5061       else
5062         returnCode = clpSimplex->primal();
5063       break;
5064     case 100:
5065       // initialization
5066       break;
5067     }
5068     threadInfo->status = -1;
5069 #ifdef DETAIL_THREAD
5070     printf("thread %d about to unlock mutex %d\n", whichThread, unLock);
5071 #endif
5072     pthread_mutex_unlock(driver->mutexPointer(unLock, whichThread));
5073   }
5074 }
5075 #endif
5076 // Solve using Dantzig-Wolfe decomposition and maybe in parallel
solveDW(CoinStructuredModel * model,ClpSolve & options)5077 int ClpSimplex::solveDW(CoinStructuredModel *model, ClpSolve &options)
5078 {
5079   double time1 = CoinCpuTime();
5080   int numberColumns = model->numberColumns();
5081   int numberRowBlocks = model->numberRowBlocks();
5082   int numberColumnBlocks = model->numberColumnBlocks();
5083   int numberElementBlocks = model->numberElementBlocks();
5084   // We already have top level structure
5085   CoinModelBlockInfo *blockInfo = new CoinModelBlockInfo[numberElementBlocks];
5086   for (int i = 0; i < numberElementBlocks; i++) {
5087     CoinModel *thisBlock = model->coinBlock(i);
5088     assert(thisBlock);
5089     // just fill in info
5090     CoinModelBlockInfo info = CoinModelBlockInfo();
5091     int whatsSet = thisBlock->whatIsSet();
5092     info.matrix = static_cast< char >(((whatsSet & 1) != 0) ? 1 : 0);
5093     info.rhs = static_cast< char >(((whatsSet & 2) != 0) ? 1 : 0);
5094     info.rowName = static_cast< char >(((whatsSet & 4) != 0) ? 1 : 0);
5095     info.integer = static_cast< char >(((whatsSet & 32) != 0) ? 1 : 0);
5096     info.bounds = static_cast< char >(((whatsSet & 8) != 0) ? 1 : 0);
5097     info.columnName = static_cast< char >(((whatsSet & 16) != 0) ? 1 : 0);
5098     // Which block
5099     int iRowBlock = model->rowBlock(thisBlock->getRowBlock());
5100     info.rowBlock = iRowBlock;
5101     int iColumnBlock = model->columnBlock(thisBlock->getColumnBlock());
5102     info.columnBlock = iColumnBlock;
5103     blockInfo[i] = info;
5104   }
5105   // make up problems
5106   int numberBlocks = numberRowBlocks - 1;
5107   // Find master rows and columns
5108   int *rowCounts = new int[numberRowBlocks];
5109   CoinZeroN(rowCounts, numberRowBlocks);
5110   int *columnCounts = new int[numberColumnBlocks + 1];
5111   CoinZeroN(columnCounts, numberColumnBlocks);
5112   int iBlock;
5113   for (iBlock = 0; iBlock < numberElementBlocks; iBlock++) {
5114     int iRowBlock = blockInfo[iBlock].rowBlock;
5115     rowCounts[iRowBlock]++;
5116     int iColumnBlock = blockInfo[iBlock].columnBlock;
5117     columnCounts[iColumnBlock]++;
5118   }
5119   int *whichBlock = new int[numberElementBlocks];
5120   int masterRowBlock = -1;
5121   for (iBlock = 0; iBlock < numberRowBlocks; iBlock++) {
5122     if (rowCounts[iBlock] > 1) {
5123       if (masterRowBlock == -1) {
5124         masterRowBlock = iBlock;
5125       } else {
5126         // Can't decode
5127         masterRowBlock = -2;
5128         break;
5129       }
5130     }
5131   }
5132   int masterColumnBlock = -1;
5133   int kBlock = 0;
5134   for (iBlock = 0; iBlock < numberColumnBlocks; iBlock++) {
5135     int count = columnCounts[iBlock];
5136     columnCounts[iBlock] = kBlock;
5137     kBlock += count;
5138   }
5139   for (iBlock = 0; iBlock < numberElementBlocks; iBlock++) {
5140     int iColumnBlock = blockInfo[iBlock].columnBlock;
5141     whichBlock[columnCounts[iColumnBlock]] = iBlock;
5142     columnCounts[iColumnBlock]++;
5143   }
5144   for (iBlock = numberColumnBlocks - 1; iBlock >= 0; iBlock--)
5145     columnCounts[iBlock + 1] = columnCounts[iBlock];
5146   columnCounts[0] = 0;
5147   for (iBlock = 0; iBlock < numberColumnBlocks; iBlock++) {
5148     int count = columnCounts[iBlock + 1] - columnCounts[iBlock];
5149     if (count == 1) {
5150       int kBlock = whichBlock[columnCounts[iBlock]];
5151       int iRowBlock = blockInfo[kBlock].rowBlock;
5152       if (iRowBlock == masterRowBlock) {
5153         if (masterColumnBlock == -1) {
5154           masterColumnBlock = iBlock;
5155         } else {
5156           // Can't decode
5157           masterColumnBlock = -2;
5158           break;
5159         }
5160       }
5161     }
5162   }
5163   if (masterRowBlock < 0 || masterColumnBlock == -2) {
5164     // What now
5165     abort();
5166   }
5167   delete[] rowCounts;
5168   // create all data
5169   const CoinPackedMatrix **top = new const CoinPackedMatrix *[numberColumnBlocks];
5170   ClpSimplex *sub = new ClpSimplex[numberBlocks];
5171   ClpSimplex master;
5172   // Set offset
5173   master.setObjectiveOffset(model->objectiveOffset());
5174   bool reducePrint = logLevel() == 7;
5175   if (reducePrint) {
5176     // special
5177     setLogLevel(1);
5178     master.setLogLevel(1);
5179   }
5180   kBlock = 0;
5181   int masterBlock = -1;
5182   for (iBlock = 0; iBlock < numberColumnBlocks; iBlock++) {
5183     top[kBlock] = NULL;
5184     int start = columnCounts[iBlock];
5185     int end = columnCounts[iBlock + 1];
5186     assert(end - start <= 2);
5187     for (int j = start; j < end; j++) {
5188       int jBlock = whichBlock[j];
5189       int iRowBlock = blockInfo[jBlock].rowBlock;
5190       int iColumnBlock = blockInfo[jBlock].columnBlock;
5191       assert(iColumnBlock == iBlock);
5192       if (iColumnBlock != masterColumnBlock && iRowBlock == masterRowBlock) {
5193         // top matrix
5194         top[kBlock] = model->coinBlock(jBlock)->packedMatrix();
5195       } else {
5196         const CoinPackedMatrix *matrix
5197           = model->coinBlock(jBlock)->packedMatrix();
5198         // Get pointers to arrays
5199         const double *rowLower;
5200         const double *rowUpper;
5201         const double *columnLower;
5202         const double *columnUpper;
5203         const double *objective;
5204         model->block(iRowBlock, iColumnBlock, rowLower, rowUpper,
5205           columnLower, columnUpper, objective);
5206         if (iColumnBlock != masterColumnBlock) {
5207           // diagonal block
5208           sub[kBlock].loadProblem(*matrix, columnLower, columnUpper,
5209             objective, rowLower, rowUpper);
5210           if (true) {
5211             double *lower = sub[kBlock].columnLower();
5212             double *upper = sub[kBlock].columnUpper();
5213             int n = sub[kBlock].numberColumns();
5214             for (int i = 0; i < n; i++) {
5215               lower[i] = CoinMax(-1.0e8, lower[i]);
5216               upper[i] = CoinMin(1.0e8, upper[i]);
5217             }
5218           }
5219           if (optimizationDirection_ < 0.0) {
5220             double *obj = sub[kBlock].objective();
5221             int n = sub[kBlock].numberColumns();
5222             for (int i = 0; i < n; i++)
5223               obj[i] = -obj[i];
5224           }
5225           if (this->factorizationFrequency() == 200) {
5226             // User did not touch preset
5227             sub[kBlock].defaultFactorizationFrequency();
5228           } else {
5229             // make sure model has correct value
5230             sub[kBlock].setFactorizationFrequency(this->factorizationFrequency());
5231           }
5232           sub[kBlock].setPerturbation(50);
5233           // Set columnCounts to be diagonal block index for cleanup
5234           columnCounts[kBlock] = jBlock;
5235         } else {
5236           // master
5237           masterBlock = jBlock;
5238           master.loadProblem(*matrix, columnLower, columnUpper,
5239             objective, rowLower, rowUpper);
5240           if (optimizationDirection_ < 0.0) {
5241             double *obj = master.objective();
5242             int n = master.numberColumns();
5243             for (int i = 0; i < n; i++)
5244               obj[i] = -obj[i];
5245           }
5246         }
5247       }
5248     }
5249     if (iBlock != masterColumnBlock)
5250       kBlock++;
5251   }
5252   delete[] whichBlock;
5253   delete[] blockInfo;
5254   // For now master must have been defined (does not have to have columns)
5255   assert(master.numberRows());
5256   assert(masterBlock >= 0);
5257   int numberMasterRows = master.numberRows();
5258   // Overkill in terms of space
5259   int spaceNeeded = CoinMax(numberBlocks * (numberMasterRows + 1),
5260     2 * numberMasterRows);
5261   int *rowAdd = new int[spaceNeeded];
5262   double *elementAdd = new double[spaceNeeded];
5263   spaceNeeded = numberBlocks;
5264   CoinBigIndex *columnAdd = new CoinBigIndex[spaceNeeded + 1];
5265   double *objective = new double[spaceNeeded];
5266   // Add in costed slacks
5267   int firstArtificial = master.numberColumns();
5268   int lastArtificial = firstArtificial;
5269   if (true) {
5270     const double *lower = master.rowLower();
5271     const double *upper = master.rowUpper();
5272     int kCol = 0;
5273     for (int iRow = 0; iRow < numberMasterRows; iRow++) {
5274       if (lower[iRow] > -1.0e10) {
5275         rowAdd[kCol] = iRow;
5276         elementAdd[kCol++] = 1.0;
5277       }
5278       if (upper[iRow] < 1.0e10) {
5279         rowAdd[kCol] = iRow;
5280         elementAdd[kCol++] = -1.0;
5281       }
5282     }
5283     if (kCol > spaceNeeded) {
5284       spaceNeeded = kCol;
5285       delete[] columnAdd;
5286       delete[] objective;
5287       columnAdd = new CoinBigIndex[spaceNeeded + 1];
5288       objective = new double[spaceNeeded];
5289     }
5290     for (int i = 0; i < kCol; i++) {
5291       columnAdd[i] = i;
5292       objective[i] = 1.0e13;
5293     }
5294     columnAdd[kCol] = kCol;
5295     master.addColumns(kCol, NULL, NULL, objective,
5296       columnAdd, rowAdd, elementAdd);
5297     lastArtificial = master.numberColumns();
5298   }
5299   int maxPass = options.independentOption(2);
5300   if (maxPass < 2)
5301     maxPass = 100;
5302   int iPass;
5303   double lastObjective = 1.0e31;
5304   // Create convexity rows for proposals
5305   int numberMasterColumns = master.numberColumns();
5306   master.resize(numberMasterRows + numberBlocks, numberMasterColumns);
5307   if (this->factorizationFrequency() == 200) {
5308     // User did not touch preset
5309     master.defaultFactorizationFrequency();
5310   } else {
5311     // make sure model has correct value
5312     master.setFactorizationFrequency(this->factorizationFrequency());
5313   }
5314   master.setPerturbation(50);
5315   // Arrays to say which block and when created
5316   int maximumColumns = 2 * numberMasterRows + 10 * numberBlocks;
5317   whichBlock = new int[maximumColumns];
5318   int *when = new int[maximumColumns];
5319   int numberColumnsGenerated = numberBlocks;
5320   // fill in rhs and add in artificials
5321   {
5322     double *rowLower = master.rowLower();
5323     double *rowUpper = master.rowUpper();
5324     int iBlock;
5325     columnAdd[0] = 0;
5326     for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
5327       int iRow = iBlock + numberMasterRows;
5328       ;
5329       rowLower[iRow] = 1.0;
5330       rowUpper[iRow] = 1.0;
5331       rowAdd[iBlock] = iRow;
5332       elementAdd[iBlock] = 1.0;
5333       objective[iBlock] = 1.0e13;
5334       columnAdd[iBlock + 1] = iBlock + 1;
5335       when[iBlock] = -1;
5336       whichBlock[iBlock] = iBlock;
5337     }
5338     master.addColumns(numberBlocks, NULL, NULL, objective,
5339       columnAdd, rowAdd, elementAdd);
5340   }
5341   char generalPrint[200];
5342   // and resize matrix to double check clp will be happy
5343   //master.matrix()->setDimensions(numberMasterRows+numberBlocks,
5344   //			 numberMasterColumns+numberBlocks);
5345   sprintf(generalPrint, "Time to decompose %.2f seconds", CoinCpuTime() - time1);
5346   handler_->message(CLP_GENERAL, messages_)
5347     << generalPrint
5348     << CoinMessageEol;
5349 #ifdef ABC_INHERIT
5350   //AbcSimplex abcMaster;
5351   //if (!this->abcState())
5352   //setAbcState(1);
5353   int numberCpu = CoinMin((this->abcState() & 15), 4);
5354   CoinPthreadStuff threadInfo(numberCpu, clp_parallelManager);
5355   master.setAbcState(this->abcState());
5356   //AbcSimplex * tempMaster=master.dealWithAbc(2,10,true);
5357   //abcMaster=*tempMaster;
5358   //delete tempMaster;
5359   //abcMaster.startThreads(numberCpu);
5360   //#define master abcMaster
5361 #endif
5362   for (iPass = 0; iPass < maxPass; iPass++) {
5363     sprintf(generalPrint, "Start of pass %d", iPass);
5364     handler_->message(CLP_GENERAL, messages_)
5365       << generalPrint
5366       << CoinMessageEol;
5367     // Solve master - may be infeasible
5368     //master.scaling(0);
5369     if (0) {
5370       master.writeMps("yy.mps");
5371     }
5372     // Correct artificials
5373     double sumArtificials = 0.0;
5374     if (iPass) {
5375       double *upper = master.columnUpper();
5376       double *solution = master.primalColumnSolution();
5377       double *obj = master.objective();
5378       sumArtificials = 0.0;
5379       for (int i = firstArtificial; i < lastArtificial; i++) {
5380         sumArtificials += solution[i];
5381         //assert (solution[i]>-1.0e-2);
5382         if (solution[i] < 1.0e-6) {
5383 #if 0
5384                          // Could take out
5385                          obj[i] = 0.0;
5386                          upper[i] = 0.0;
5387 #else
5388           obj[i] = 1.0e7;
5389           upper[i] = 1.0e-1;
5390 #endif
5391           solution[i] = 0.0;
5392           master.setColumnStatus(i, isFixed);
5393         } else {
5394           upper[i] = solution[i] + 1.0e-5 * (1.0 + solution[i]);
5395         }
5396       }
5397       sprintf(generalPrint, "Sum of artificials before solve is %g", sumArtificials);
5398       handler_->message(CLP_GENERAL, messages_)
5399         << generalPrint
5400         << CoinMessageEol;
5401     }
5402     // scale objective to be reasonable
5403     double scaleFactor = master.scaleObjective(-1.0e9);
5404     {
5405       double *dual = master.dualRowSolution();
5406       int n = master.numberRows();
5407       memset(dual, 0, n * sizeof(double));
5408       double *solution = master.primalColumnSolution();
5409       master.clpMatrix()->times(1.0, solution, dual);
5410       double sum = 0.0;
5411       double *lower = master.rowLower();
5412       double *upper = master.rowUpper();
5413       for (int iRow = 0; iRow < n; iRow++) {
5414         double value = dual[iRow];
5415         if (value > upper[iRow])
5416           sum += value - upper[iRow];
5417         else if (value < lower[iRow])
5418           sum -= value - lower[iRow];
5419       }
5420       printf("** suminf %g\n", sum);
5421       lower = master.columnLower();
5422       upper = master.columnUpper();
5423       n = master.numberColumns();
5424       for (int iColumn = 0; iColumn < n; iColumn++) {
5425         double value = solution[iColumn];
5426         if (value > upper[iColumn] + 1.0e-5)
5427           sum += value - upper[iColumn];
5428         else if (value < lower[iColumn] - 1.0e-5)
5429           sum -= value - lower[iColumn];
5430       }
5431       printf("** suminf %g\n", sum);
5432     }
5433 #ifdef ABC_INHERIT
5434     master.dealWithAbc(1, 0, true);
5435 #else
5436     master.primal();
5437 #endif
5438     //master.primal(1);
5439     // Correct artificials
5440     sumArtificials = 0.0;
5441     {
5442       double *solution = master.primalColumnSolution();
5443       for (int i = firstArtificial; i < lastArtificial; i++) {
5444         sumArtificials += solution[i];
5445       }
5446       printf("** Sum of artificials after solve is %g\n", sumArtificials);
5447     }
5448     master.scaleObjective(scaleFactor);
5449     int problemStatus = master.status(); // do here as can change (delcols)
5450     if (problemStatus == 2 && master.numberColumns()) {
5451 #ifdef ABC_INHERIT
5452       master.dealWithAbc(1, 1, true);
5453 #else
5454       master.primal(1);
5455 #endif
5456       //master.primal(1);
5457       if (problemStatus == 2) {
5458         int numberColumns = master.numberColumns();
5459         double *lower = master.columnLower();
5460         double *upper = master.columnUpper();
5461         for (int i = 0; i < numberColumns; i++) {
5462           lower[i] = CoinMax(lower[i], -1.0e10);
5463           upper[i] = CoinMin(upper[i], 1.0e10);
5464         }
5465 #ifdef ABC_INHERIT
5466         master.dealWithAbc(1, 1, true);
5467 #else
5468         master.primal(1);
5469 #endif
5470         //master.primal(1);
5471         assert(problemStatus != 2);
5472       }
5473     }
5474     if (master.numberIterations() == 0 && iPass)
5475       break; // finished
5476     if (master.objectiveValue() > lastObjective - 1.0e-7 && iPass > 555)
5477       break; // finished
5478     lastObjective = master.objectiveValue();
5479     // mark basic ones and delete if necessary
5480     int iColumn;
5481     numberColumnsGenerated = master.numberColumns() - numberMasterColumns;
5482     for (iColumn = 0; iColumn < numberColumnsGenerated; iColumn++) {
5483       if (master.getStatus(iColumn + numberMasterColumns) == ClpSimplex::basic)
5484         when[iColumn] = iPass;
5485     }
5486     if (numberColumnsGenerated + numberBlocks > maximumColumns) {
5487       // delete
5488       int numberKeep = 0;
5489       int numberDelete = 0;
5490       int *whichDelete = new int[numberColumnsGenerated];
5491       for (iColumn = 0; iColumn < numberColumnsGenerated; iColumn++) {
5492         if (when[iColumn] > iPass - 7) {
5493           // keep
5494           when[numberKeep] = when[iColumn];
5495           whichBlock[numberKeep++] = whichBlock[iColumn];
5496         } else {
5497           // delete
5498           whichDelete[numberDelete++] = iColumn + numberMasterColumns;
5499         }
5500       }
5501       numberColumnsGenerated -= numberDelete;
5502       master.deleteColumns(numberDelete, whichDelete);
5503       delete[] whichDelete;
5504     }
5505     const double *dual = NULL;
5506     bool deleteDual = false;
5507     if (problemStatus == 0) {
5508       dual = master.dualRowSolution();
5509     } else if (problemStatus == 1) {
5510       // could do composite objective
5511       dual = master.infeasibilityRay();
5512       deleteDual = true;
5513       printf("** The sum of infeasibilities is %g\n",
5514         master.sumPrimalInfeasibilities());
5515     } else if (!master.numberColumns()) {
5516       assert(!iPass);
5517       dual = master.dualRowSolution();
5518       memset(master.dualRowSolution(),
5519         0, (numberMasterRows + numberBlocks) * sizeof(double));
5520     } else {
5521       master.writeMps("unbounded.mps");
5522       abort();
5523     }
5524     // Scale back on first time
5525     if (!iPass) {
5526       double *dual2 = master.dualRowSolution();
5527       for (int i = 0; i < numberMasterRows + numberBlocks; i++) {
5528         dual2[i] *= 1.0e-7;
5529       }
5530       dual = master.dualRowSolution();
5531     }
5532     // Create objective for sub problems and solve
5533     columnAdd[0] = 0;
5534     int numberProposals = 0;
5535     double **saveObj2 = new double *[numberBlocks];
5536     for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
5537       int numberColumns2 = sub[iBlock].numberColumns();
5538       saveObj2[iBlock] = new double[numberColumns2];
5539     }
5540     for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
5541       int numberColumns2 = sub[iBlock].numberColumns();
5542       double *saveObj = saveObj2[iBlock];
5543       double *objective2 = sub[iBlock].objective();
5544       memcpy(saveObj, objective2, numberColumns2 * sizeof(double));
5545       // new objective
5546       top[iBlock]->transposeTimes(dual, objective2);
5547       int i;
5548       if (problemStatus == 0) {
5549         for (i = 0; i < numberColumns2; i++)
5550           objective2[i] = saveObj[i] - objective2[i];
5551       } else {
5552         for (i = 0; i < numberColumns2; i++)
5553           objective2[i] = -objective2[i];
5554       }
5555       // scale objective to be reasonable
5556       //double scaleFactor =
5557       //   sub[iBlock].scaleObjective((sumArtificials > 1.0e-5) ? -1.0e-4 : -1.0e9);
5558 
5559       if (reducePrint)
5560         sub[iBlock].setLogLevel(0);
5561     }
5562 #if defined(ABC_INHERIT) || defined(CBC_THREAD) || defined(THREADS_IN_ANALYZE)
5563     if (numberCpu < 2) {
5564 #endif
5565       for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
5566         if (iPass) {
5567           sub[iBlock].primal();
5568         } else {
5569           sub[iBlock].dual();
5570         }
5571       }
5572 #if defined(ABC_INHERIT) || defined(CBC_THREAD) || defined(THREADS_IN_ANALYZE)
5573     } else {
5574       int iBlock = 0;
5575       while (iBlock < numberBlocks) {
5576         if (sub[iBlock].secondaryStatus() != 99 || true) {
5577           int iThread;
5578           threadInfo.waitParallelTask(1, iThread, true);
5579 #ifdef DETAIL_THREAD
5580           printf("Starting block %d on thread %d\n",
5581             iBlock, iThread);
5582 #endif
5583           threadInfo.startParallelTask(1, iThread, sub + iBlock);
5584         }
5585         iBlock++;
5586       }
5587       threadInfo.waitAllTasks();
5588     }
5589 #endif
5590     for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
5591       int numberColumns2 = sub[iBlock].numberColumns();
5592       double *saveObj = saveObj2[iBlock];
5593       double *objective2 = sub[iBlock].objective();
5594       int i;
5595       sub[iBlock].scaleObjective(scaleFactor);
5596       if (!sub[iBlock].isProvenOptimal() && !sub[iBlock].isProvenDualInfeasible()) {
5597         memset(objective2, 0, numberColumns2 * sizeof(double));
5598         sub[iBlock].primal();
5599         if (problemStatus == 0) {
5600           for (int i = 0; i < numberColumns2; i++)
5601             objective2[i] = saveObj[i] - objective2[i];
5602         } else {
5603           for (i = 0; i < numberColumns2; i++)
5604             objective2[i] = -objective2[i];
5605         }
5606         double scaleFactor = sub[iBlock].scaleObjective(-1.0e9);
5607         sub[iBlock].primal(1);
5608         sub[iBlock].scaleObjective(scaleFactor);
5609       }
5610       memcpy(objective2, saveObj, numberColumns2 * sizeof(double));
5611       // get proposal
5612       if (sub[iBlock].numberIterations() || !iPass) {
5613         double objValue = 0.0;
5614         CoinBigIndex start = columnAdd[numberProposals];
5615         // proposal
5616         if (sub[iBlock].isProvenOptimal()) {
5617           const double *solution = sub[iBlock].primalColumnSolution();
5618           top[iBlock]->times(solution, elementAdd + start);
5619           for (i = 0; i < numberColumns2; i++)
5620             objValue += solution[i] * saveObj[i];
5621           // See if good dj and pack down
5622           CoinBigIndex number = start;
5623           double dj = objValue;
5624           if (problemStatus)
5625             dj = 0.0;
5626           double smallest = 1.0e100;
5627           double largest = 0.0;
5628           for (i = 0; i < numberMasterRows; i++) {
5629             double value = elementAdd[start + i];
5630             if (fabs(value) > 1.0e-15) {
5631               dj -= dual[i] * value;
5632               smallest = CoinMin(smallest, fabs(value));
5633               largest = CoinMax(largest, fabs(value));
5634               rowAdd[number] = i;
5635               elementAdd[number++] = value;
5636             }
5637           }
5638           // and convexity
5639           dj -= dual[numberMasterRows + iBlock];
5640           rowAdd[number] = numberMasterRows + iBlock;
5641           elementAdd[number++] = 1.0;
5642           // if elements large then scale?
5643           //if (largest>1.0e8||smallest<1.0e-8)
5644           sprintf(generalPrint, "For subproblem %d smallest - %g, largest %g - dj %g",
5645             iBlock, smallest, largest, dj);
5646           handler_->message(CLP_GENERAL2, messages_)
5647             << generalPrint
5648             << CoinMessageEol;
5649           if (dj < -1.0e-6 || !iPass) {
5650             // take
5651             objective[numberProposals] = objValue;
5652             columnAdd[++numberProposals] = number;
5653             when[numberColumnsGenerated] = iPass;
5654             whichBlock[numberColumnsGenerated++] = iBlock;
5655           }
5656         } else if (sub[iBlock].isProvenDualInfeasible()) {
5657           // use ray
5658           const double *solution = sub[iBlock].unboundedRay();
5659           top[iBlock]->times(solution, elementAdd + start);
5660           for (i = 0; i < numberColumns2; i++)
5661             objValue += solution[i] * saveObj[i];
5662           // See if good dj and pack down
5663           CoinBigIndex number = start;
5664           double dj = objValue;
5665           double smallest = 1.0e100;
5666           double largest = 0.0;
5667           for (i = 0; i < numberMasterRows; i++) {
5668             double value = elementAdd[start + i];
5669             if (fabs(value) > 1.0e-15) {
5670               dj -= dual[i] * value;
5671               smallest = CoinMin(smallest, fabs(value));
5672               largest = CoinMax(largest, fabs(value));
5673               rowAdd[number] = i;
5674               elementAdd[number++] = value;
5675             }
5676           }
5677           // if elements large or small then scale?
5678           //if (largest>1.0e8||smallest<1.0e-8)
5679           sprintf(generalPrint, "For subproblem ray %d smallest - %g, largest %g - dj %g",
5680             iBlock, smallest, largest, dj);
5681           handler_->message(CLP_GENERAL2, messages_)
5682             << generalPrint
5683             << CoinMessageEol;
5684           if (dj < -1.0e-6) {
5685             // take
5686             objective[numberProposals] = objValue;
5687             columnAdd[++numberProposals] = number;
5688             when[numberColumnsGenerated] = iPass;
5689             whichBlock[numberColumnsGenerated++] = iBlock;
5690           }
5691         } else {
5692           abort();
5693         }
5694       }
5695     }
5696     for (iBlock = 0; iBlock < numberBlocks; iBlock++)
5697       delete[] saveObj2[iBlock];
5698     delete[] saveObj2;
5699     if (deleteDual)
5700       delete[] dual;
5701     if (numberProposals)
5702       master.addColumns(numberProposals, NULL, NULL, objective,
5703         columnAdd, rowAdd, elementAdd);
5704   }
5705   sprintf(generalPrint, "Time at end of D-W %.2f seconds", CoinCpuTime() - time1);
5706   handler_->message(CLP_GENERAL, messages_)
5707     << generalPrint
5708     << CoinMessageEol;
5709   //master.scaling(0);
5710   //master.primal(1);
5711   loadProblem(*model);
5712   // now put back a good solution
5713   double *lower = new double[numberMasterRows + numberBlocks];
5714   double *upper = new double[numberMasterRows + numberBlocks];
5715   numberColumnsGenerated += numberMasterColumns;
5716   double *sol = new double[numberColumnsGenerated];
5717   const double *solution = master.primalColumnSolution();
5718   const double *masterLower = master.rowLower();
5719   const double *masterUpper = master.rowUpper();
5720   double *fullSolution = primalColumnSolution();
5721   const double *fullLower = columnLower();
5722   const double *fullUpper = columnUpper();
5723   const double *rowSolution = master.primalRowSolution();
5724   double *fullRowSolution = primalRowSolution();
5725   const int *rowBack = model->coinBlock(masterBlock)->originalRows();
5726   int numberRows2 = model->coinBlock(masterBlock)->numberRows();
5727   const int *columnBack = model->coinBlock(masterBlock)->originalColumns();
5728   int numberColumns2 = model->coinBlock(masterBlock)->numberColumns();
5729   for (int iRow = 0; iRow < numberRows2; iRow++) {
5730     int kRow = rowBack[iRow];
5731     setRowStatus(kRow, master.getRowStatus(iRow));
5732     fullRowSolution[kRow] = rowSolution[iRow];
5733   }
5734   for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
5735     int kColumn = columnBack[iColumn];
5736     setStatus(kColumn, master.getStatus(iColumn));
5737     fullSolution[kColumn] = solution[iColumn];
5738   }
5739   for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
5740     // move basis
5741     int kBlock = columnCounts[iBlock];
5742     const int *rowBack = model->coinBlock(kBlock)->originalRows();
5743     int numberRows2 = model->coinBlock(kBlock)->numberRows();
5744     const int *columnBack = model->coinBlock(kBlock)->originalColumns();
5745     int numberColumns2 = model->coinBlock(kBlock)->numberColumns();
5746     for (int iRow = 0; iRow < numberRows2; iRow++) {
5747       int kRow = rowBack[iRow];
5748       setRowStatus(kRow, sub[iBlock].getRowStatus(iRow));
5749     }
5750     for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
5751       int kColumn = columnBack[iColumn];
5752       setStatus(kColumn, sub[iBlock].getStatus(iColumn));
5753     }
5754     // convert top bit to by rows
5755     CoinPackedMatrix topMatrix = *top[iBlock];
5756     topMatrix.reverseOrdering();
5757     // zero solution
5758     memset(sol, 0, numberColumnsGenerated * sizeof(double));
5759 
5760     for (int i = numberMasterColumns; i < numberColumnsGenerated; i++) {
5761       if (whichBlock[i - numberMasterColumns] == iBlock)
5762         sol[i] = solution[i];
5763     }
5764     memset(lower, 0, (numberMasterRows + numberBlocks) * sizeof(double));
5765     master.clpMatrix()->times(1.0, sol, lower);
5766     for (int iRow = 0; iRow < numberMasterRows; iRow++) {
5767       double value = lower[iRow];
5768       if (masterUpper[iRow] < 1.0e20)
5769         upper[iRow] = value;
5770       else
5771         upper[iRow] = COIN_DBL_MAX;
5772       if (masterLower[iRow] > -1.0e20)
5773         lower[iRow] = value;
5774       else
5775         lower[iRow] = -COIN_DBL_MAX;
5776     }
5777     sub[iBlock].addRows(numberMasterRows, lower, upper,
5778       topMatrix.getVectorStarts(),
5779       topMatrix.getVectorLengths(),
5780       topMatrix.getIndices(),
5781       topMatrix.getElements());
5782     sub[iBlock].primal(1);
5783     const double *subSolution = sub[iBlock].primalColumnSolution();
5784     const double *subRowSolution = sub[iBlock].primalRowSolution();
5785     // move solution
5786     for (int iRow = 0; iRow < numberRows2; iRow++) {
5787       int kRow = rowBack[iRow];
5788       fullRowSolution[kRow] = subRowSolution[iRow];
5789     }
5790     for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
5791       int kColumn = columnBack[iColumn];
5792       fullSolution[kColumn] = subSolution[iColumn];
5793     }
5794   }
5795   for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
5796     if (fullSolution[iColumn] < fullUpper[iColumn] - 1.0e-8 && fullSolution[iColumn] > fullLower[iColumn] + 1.0e-8) {
5797       if (getStatus(iColumn) != ClpSimplex::basic) {
5798         if (columnLower_[iColumn] > -1.0e30 || columnUpper_[iColumn] < 1.0e30)
5799           setStatus(iColumn, ClpSimplex::superBasic);
5800         else
5801           setStatus(iColumn, ClpSimplex::isFree);
5802       }
5803     } else if (fullSolution[iColumn] >= fullUpper[iColumn] - 1.0e-8) {
5804       // may help to make rest non basic
5805       if (getStatus(iColumn) != ClpSimplex::basic)
5806         setStatus(iColumn, ClpSimplex::atUpperBound);
5807     } else if (fullSolution[iColumn] <= fullLower[iColumn] + 1.0e-8) {
5808       // may help to make rest non basic
5809       if (getStatus(iColumn) != ClpSimplex::basic)
5810         setStatus(iColumn, ClpSimplex::atLowerBound);
5811     }
5812   }
5813   //int numberRows=model->numberRows();
5814   //for (int iRow=0;iRow<numberRows;iRow++)
5815   //setRowStatus(iRow,ClpSimplex::superBasic);
5816   sprintf(generalPrint, "Time before cleanup of full model %.2f seconds", CoinCpuTime() - time1);
5817   handler_->message(CLP_GENERAL, messages_)
5818     << generalPrint
5819     << CoinMessageEol;
5820   primal(1);
5821   sprintf(generalPrint, "Total time %.2f seconds", CoinCpuTime() - time1);
5822   handler_->message(CLP_GENERAL, messages_)
5823     << generalPrint
5824     << CoinMessageEol;
5825   delete[] columnCounts;
5826   delete[] sol;
5827   delete[] lower;
5828   delete[] upper;
5829   delete[] whichBlock;
5830   delete[] when;
5831   delete[] columnAdd;
5832   delete[] rowAdd;
5833   delete[] elementAdd;
5834   delete[] objective;
5835   delete[] top;
5836   delete[] sub;
5837   return 0;
5838 }
deBound(ClpSimplex * oldModel)5839 static ClpSimplex *deBound(ClpSimplex *oldModel)
5840 {
5841   ClpSimplex *model = new ClpSimplex(*oldModel);
5842   int numberRows = model->numberRows();
5843   CoinPackedMatrix *matrix = model->matrix();
5844   const int *row = matrix->getIndices();
5845   const int *columnLength = matrix->getVectorLengths();
5846   const CoinBigIndex *columnStart = matrix->getVectorStarts();
5847   double *elementByColumn = matrix->getMutableElements();
5848   int numberColumns = model->numberColumns();
5849   double *rowLower = model->rowLower();
5850   double *rowUpper = model->rowUpper();
5851   double *columnLower = model->columnLower();
5852   double *columnUpper = model->columnUpper();
5853   double *objective = model->objective();
5854   double *change = new double[CoinMax(numberRows, numberColumns) + numberColumns];
5855   CoinBigIndex *rowStart = new CoinBigIndex[2 * numberColumns + 1];
5856   memset(change, 0, numberRows * sizeof(double));
5857   // first swap ones with infinite lower bounds
5858   for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
5859     if (columnLower[iColumn] == -COIN_DBL_MAX && columnUpper[iColumn] != COIN_DBL_MAX) {
5860       for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn]
5861              + columnLength[iColumn];
5862            j++)
5863         elementByColumn[j] *= -1.0;
5864       objective[iColumn] *= -1.0;
5865       columnLower[iColumn] = -columnUpper[iColumn];
5866       columnUpper[iColumn] = COIN_DBL_MAX;
5867     }
5868   }
5869   // Out nonzero LB's
5870   for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
5871     if (columnLower[iColumn]) {
5872       double value = columnLower[iColumn];
5873       for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn]
5874              + columnLength[iColumn];
5875            j++) {
5876         int iRow = row[j];
5877         change[iRow] -= value * elementByColumn[j];
5878       }
5879     }
5880   }
5881   for (int iRow = 0; iRow < numberRows; iRow++) {
5882     double value = change[iRow];
5883     if (rowLower[iRow] > -COIN_DBL_MAX)
5884       rowLower[iRow] -= value;
5885     if (rowUpper[iRow] < COIN_DBL_MAX)
5886       rowUpper[iRow] -= value;
5887   }
5888   int nExtra = 0;
5889   int *columnNew = reinterpret_cast< int * >(rowStart + numberColumns + 1);
5890   for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
5891     if (columnUpper[iColumn] < COIN_DBL_MAX && columnUpper[iColumn]) {
5892       columnNew[nExtra] = iColumn;
5893       change[nExtra++] = columnUpper[iColumn];
5894       columnUpper[iColumn] = COIN_DBL_MAX;
5895     }
5896   }
5897   double *elementNew = change + numberColumns;
5898   for (int i = 0; i < nExtra; i++) {
5899     rowStart[i] = i;
5900     elementNew[i] = 1.0;
5901   }
5902   rowStart[nExtra] = nExtra;
5903   model->addRows(nExtra, NULL, change,
5904     rowStart, columnNew, elementNew);
5905   delete[] rowStart;
5906   delete[] change;
5907   return model;
5908 }
5909 #if defined(ABC_INHERIT) || defined(CBC_THREAD) || defined(THREADS_IN_ANALYZE)
CoinPthreadStuff(int numberThreads,void * parallelManager (void * stuff))5910 CoinPthreadStuff::CoinPthreadStuff(int numberThreads,
5911   void *parallelManager(void *stuff))
5912 {
5913   numberThreads_ = numberThreads;
5914   if (numberThreads > 8)
5915     numberThreads = 1;
5916   // For waking up thread
5917   memset(mutex_, 0, sizeof(mutex_));
5918   for (int iThread = 0; iThread < numberThreads; iThread++) {
5919     for (int i = 0; i < 3; i++) {
5920       pthread_mutex_init(&mutex_[i + 3 * iThread], NULL);
5921       if (i < 2)
5922         pthread_mutex_lock(&mutex_[i + 3 * iThread]);
5923     }
5924     threadInfo_[iThread].status = 100;
5925   }
5926 #ifdef PTHREAD_BARRIER_SERIAL_THREAD
5927   //pthread_barrierattr_t attr;
5928   pthread_barrier_init(&barrier_, /*&attr*/ NULL, numberThreads + 1);
5929 #endif
5930   for (int iThread = 0; iThread < numberThreads; iThread++) {
5931     pthread_create(&abcThread_[iThread], NULL, parallelManager, reinterpret_cast< void * >(this));
5932   }
5933 #ifdef PTHREAD_BARRIER_SERIAL_THREAD
5934   pthread_barrier_wait(&barrier_);
5935   pthread_barrier_destroy(&barrier_);
5936 #endif
5937   for (int iThread = 0; iThread < numberThreads; iThread++) {
5938     threadInfo_[iThread].status = -1;
5939     threadInfo_[iThread].stuff[3] = 1; // idle
5940     locked_[iThread] = 0;
5941   }
5942 }
~CoinPthreadStuff()5943 CoinPthreadStuff::~CoinPthreadStuff()
5944 {
5945   for (int iThread = 0; iThread < numberThreads_; iThread++) {
5946     startParallelTask(1000, iThread);
5947   }
5948   for (int iThread = 0; iThread < numberThreads_; iThread++) {
5949     pthread_join(abcThread_[iThread], NULL);
5950     for (int i = 0; i < 3; i++) {
5951       pthread_mutex_destroy(&mutex_[i + 3 * iThread]);
5952     }
5953   }
5954 }
5955 // so thread can find out which one it is
whichThread() const5956 int CoinPthreadStuff::whichThread() const
5957 {
5958   pthread_t thisThread = pthread_self();
5959   int whichThread;
5960   for (whichThread = 0; whichThread < numberThreads_; whichThread++) {
5961     if (pthread_equal(thisThread, abcThread_[whichThread]))
5962       break;
5963   }
5964   assert(whichThread < NUMBER_THREADS + 1);
5965   return whichThread;
5966 }
startParallelTask(int type,int iThread,void * info)5967 void CoinPthreadStuff::startParallelTask(int type, int iThread, void *info)
5968 {
5969   /*
5970     first time 0,1 owned by main 2 by child
5971     at end of cycle should be 1,2 by main 0 by child then 2,0 by main 1 by child
5972   */
5973   threadInfo_[iThread].status = type;
5974   threadInfo_[iThread].extraInfo = info;
5975   threadInfo_[iThread].stuff[3] = 0; // say not idle
5976 #ifdef DETAIL_THREAD
5977   printf("main doing thread %d about to unlock mutex %d\n", iThread, locked_[iThread]);
5978 #endif
5979   pthread_mutex_unlock(&mutex_[locked_[iThread] + 3 * iThread]);
5980 }
sayIdle(int iThread)5981 void CoinPthreadStuff::sayIdle(int iThread)
5982 {
5983   threadInfo_[iThread].status = -1;
5984   threadInfo_[iThread].stuff[3] = -1;
5985 }
waitParallelTask(int type,int & iThread,bool allowIdle)5986 int CoinPthreadStuff::waitParallelTask(int type, int &iThread, bool allowIdle)
5987 {
5988   bool finished = false;
5989   if (allowIdle) {
5990     for (iThread = 0; iThread < numberThreads_; iThread++) {
5991       if (threadInfo_[iThread].status < 0 && threadInfo_[iThread].stuff[3]) {
5992         finished = true;
5993         break;
5994       }
5995     }
5996     if (finished)
5997       return 0;
5998   }
5999   while (!finished) {
6000     for (iThread = 0; iThread < numberThreads_; iThread++) {
6001       if (threadInfo_[iThread].status < 0 && !threadInfo_[iThread].stuff[3]) {
6002         finished = true;
6003         break;
6004       }
6005     }
6006     if (!finished) {
6007 #ifdef _WIN32
6008       // wait 1 millisecond
6009       Sleep(1);
6010 #else
6011       // wait 0.1 millisecond
6012       usleep(100);
6013 #endif
6014     }
6015   }
6016   int locked = locked_[iThread] + 2;
6017   if (locked >= 3)
6018     locked -= 3;
6019 #ifdef DETAIL_THREAD
6020   printf("Main do thread %d about to lock mutex %d\n", iThread, locked);
6021 #endif
6022   pthread_mutex_lock(&mutex_[locked + iThread * 3]);
6023   locked_[iThread]++;
6024   if (locked_[iThread] == 3)
6025     locked_[iThread] = 0;
6026   threadInfo_[iThread].stuff[3] = 1; // say idle
6027   return threadInfo_[iThread].stuff[0];
6028 }
waitAllTasks()6029 void CoinPthreadStuff::waitAllTasks()
6030 {
6031   int nWait = 0;
6032   for (int iThread = 0; iThread < numberThreads_; iThread++) {
6033     int idle = threadInfo_[iThread].stuff[3];
6034     if (!idle)
6035       nWait++;
6036   }
6037 #ifdef DETAIL_THREAD
6038   printf("Waiting for %d tasks to finish\n", nWait);
6039 #endif
6040   for (int iThread = 0; iThread < nWait; iThread++) {
6041     int jThread;
6042     waitParallelTask(0, jThread, false);
6043 #ifdef DETAIL_THREAD
6044     printf("finished with thread %d\n", jThread);
6045 #endif
6046   }
6047 }
6048 #endif
6049 // Solve using Benders decomposition and maybe in parallel
solveBenders(CoinStructuredModel * model,ClpSolve & options)6050 int ClpSimplex::solveBenders(CoinStructuredModel *model, ClpSolve &options)
6051 {
6052   double time1 = CoinCpuTime();
6053   //ClpSimplex * xxxx = deBound(this);
6054   //xxxx->writeMps("nobounds.mps");
6055   //delete xxxx;
6056   //int numberColumns = model->numberColumns();
6057   int numberRowBlocks = model->numberRowBlocks();
6058   int numberColumnBlocks = model->numberColumnBlocks();
6059   int numberElementBlocks = model->numberElementBlocks();
6060   char generalPrint[200];
6061   // We already have top level structure
6062   CoinModelBlockInfo *blockInfo = new CoinModelBlockInfo[numberElementBlocks];
6063   for (int i = 0; i < numberElementBlocks; i++) {
6064     CoinModel *thisBlock = model->coinBlock(i);
6065     assert(thisBlock);
6066     // just fill in info
6067     CoinModelBlockInfo info = CoinModelBlockInfo();
6068     int whatsSet = thisBlock->whatIsSet();
6069     info.matrix = static_cast< char >(((whatsSet & 1) != 0) ? 1 : 0);
6070     info.rhs = static_cast< char >(((whatsSet & 2) != 0) ? 1 : 0);
6071     info.rowName = static_cast< char >(((whatsSet & 4) != 0) ? 1 : 0);
6072     info.integer = static_cast< char >(((whatsSet & 32) != 0) ? 1 : 0);
6073     info.bounds = static_cast< char >(((whatsSet & 8) != 0) ? 1 : 0);
6074     info.columnName = static_cast< char >(((whatsSet & 16) != 0) ? 1 : 0);
6075     // Which block
6076     int iRowBlock = model->rowBlock(thisBlock->getRowBlock());
6077     info.rowBlock = iRowBlock;
6078     int iColumnBlock = model->columnBlock(thisBlock->getColumnBlock());
6079     info.columnBlock = iColumnBlock;
6080     blockInfo[i] = info;
6081   }
6082   // make up problems
6083   int numberBlocks = numberColumnBlocks - 1;
6084   // Find master columns and rows
6085   int *columnCounts = new int[numberColumnBlocks];
6086   CoinZeroN(columnCounts, numberColumnBlocks);
6087   int *rowCounts = new int[numberRowBlocks + 1];
6088   CoinZeroN(rowCounts, numberRowBlocks);
6089   int iBlock;
6090   for (iBlock = 0; iBlock < numberElementBlocks; iBlock++) {
6091     int iColumnBlock = blockInfo[iBlock].columnBlock;
6092     columnCounts[iColumnBlock]++;
6093     int iRowBlock = blockInfo[iBlock].rowBlock;
6094     rowCounts[iRowBlock]++;
6095   }
6096   int *whichBlock = new int[numberElementBlocks];
6097   int masterColumnBlock = -1;
6098   for (iBlock = 0; iBlock < numberColumnBlocks; iBlock++) {
6099     if (columnCounts[iBlock] > 1) {
6100       if (masterColumnBlock == -1) {
6101         masterColumnBlock = iBlock;
6102       } else {
6103         // Can't decode
6104         masterColumnBlock = -2;
6105         break;
6106       }
6107     }
6108   }
6109   int masterRowBlock = -1;
6110   int kBlock = 0;
6111   for (iBlock = 0; iBlock < numberRowBlocks; iBlock++) {
6112     int count = rowCounts[iBlock];
6113     rowCounts[iBlock] = kBlock;
6114     kBlock += count;
6115   }
6116   for (iBlock = 0; iBlock < numberElementBlocks; iBlock++) {
6117     int iRowBlock = blockInfo[iBlock].rowBlock;
6118     whichBlock[rowCounts[iRowBlock]] = iBlock;
6119     rowCounts[iRowBlock]++;
6120   }
6121   for (iBlock = numberRowBlocks - 1; iBlock >= 0; iBlock--)
6122     rowCounts[iBlock + 1] = rowCounts[iBlock];
6123   rowCounts[0] = 0;
6124   for (iBlock = 0; iBlock < numberRowBlocks; iBlock++) {
6125     int count = rowCounts[iBlock + 1] - rowCounts[iBlock];
6126     if (count == 1) {
6127       int kBlock = whichBlock[rowCounts[iBlock]];
6128       int iColumnBlock = blockInfo[kBlock].columnBlock;
6129       if (iColumnBlock == masterColumnBlock) {
6130         if (masterRowBlock == -1) {
6131           masterRowBlock = iBlock;
6132         } else {
6133           // Can't decode
6134           masterRowBlock = -2;
6135           break;
6136         }
6137       }
6138     }
6139   }
6140   if (masterColumnBlock < 0 || masterRowBlock == -2) {
6141     // What now
6142     abort();
6143   }
6144   delete[] columnCounts;
6145   // create all data
6146   const CoinPackedMatrix **first = new const CoinPackedMatrix *[numberRowBlocks];
6147   ClpSimplex *sub = new ClpSimplex[numberBlocks];
6148   ClpSimplex masterModel;
6149   // Set offset
6150   masterModel.setObjectiveOffset(model->objectiveOffset());
6151   kBlock = 0;
6152 #define ADD_ARTIFICIALS
6153 #ifdef ADD_ARTIFICIALS
6154   int *originalSubColumns = new int[numberBlocks];
6155   for (iBlock = 0; iBlock < numberBlocks; iBlock++)
6156     originalSubColumns[iBlock] = 9999999;
6157 #endif
6158   int masterBlock = -1;
6159   for (iBlock = 0; iBlock < numberRowBlocks; iBlock++) {
6160     first[kBlock] = NULL;
6161     int start = rowCounts[iBlock];
6162     int end = rowCounts[iBlock + 1];
6163     assert(end - start <= 2);
6164     for (int j = start; j < end; j++) {
6165       int jBlock = whichBlock[j];
6166       int iColumnBlock = blockInfo[jBlock].columnBlock;
6167       int iRowBlock = blockInfo[jBlock].rowBlock;
6168       assert(iRowBlock == iBlock);
6169       if (iRowBlock != masterRowBlock && iColumnBlock == masterColumnBlock) {
6170         // first matrix
6171         first[kBlock] = model->coinBlock(jBlock)->packedMatrix();
6172       } else {
6173         const CoinPackedMatrix *matrix
6174           = model->coinBlock(jBlock)->packedMatrix();
6175         // Get pointers to arrays
6176         const double *columnLower;
6177         const double *columnUpper;
6178         const double *rowLower;
6179         const double *rowUpper;
6180         const double *objective;
6181         model->block(iRowBlock, iColumnBlock, rowLower, rowUpper,
6182           columnLower, columnUpper, objective);
6183         if (iRowBlock != masterRowBlock) {
6184           // diagonal block
6185           sub[kBlock].loadProblem(*matrix, columnLower, columnUpper,
6186             objective, rowLower, rowUpper);
6187           if (optimizationDirection_ < 0.0) {
6188             double *obj = sub[kBlock].objective();
6189             int n = sub[kBlock].numberColumns();
6190             for (int i = 0; i < n; i++)
6191               obj[i] = -obj[i];
6192           }
6193           if (this->factorizationFrequency() == 200) {
6194             // User did not touch preset
6195             sub[kBlock].defaultFactorizationFrequency();
6196           } else {
6197             // make sure model has correct value
6198             sub[kBlock].setFactorizationFrequency(this->factorizationFrequency());
6199           }
6200           sub[kBlock].setPerturbation(50);
6201 #ifdef ADD_ARTIFICIALS
6202           originalSubColumns[kBlock] = sub[kBlock].numberColumns();
6203           if (intParam_[0] < 1000000) {
6204             printf("** Adding artificials\n");
6205             int nRow = sub[kBlock].numberRows();
6206             CoinBigIndex *addStarts = new CoinBigIndex[2 * nRow + 1];
6207             int *addRow = new int[2 * nRow];
6208             double *addElement = new double[2 * nRow];
6209             addStarts[0] = 0;
6210             int numberArtificials = 0;
6211             double penalty = 1.0e5;
6212             double *addCost = new double[2 * nRow];
6213             const double *lower = sub[kBlock].rowLower();
6214             const double *upper = sub[kBlock].rowUpper();
6215             for (int iRow = 0; iRow < nRow; iRow++) {
6216               if (lower[iRow] > -1.0e20) {
6217                 addRow[numberArtificials] = iRow;
6218                 addElement[numberArtificials] = 1.0;
6219                 addCost[numberArtificials] = penalty;
6220                 numberArtificials++;
6221                 addStarts[numberArtificials] = numberArtificials;
6222               }
6223               if (upper[iRow] < 1.0e20) {
6224                 addRow[numberArtificials] = iRow;
6225                 addElement[numberArtificials] = -1.0;
6226                 addCost[numberArtificials] = penalty;
6227                 numberArtificials++;
6228                 addStarts[numberArtificials] = numberArtificials;
6229               }
6230             }
6231             if (numberArtificials) {
6232               sub[kBlock].addColumns(numberArtificials, NULL, NULL, addCost,
6233                 addStarts, addRow, addElement);
6234             }
6235             delete[] addStarts;
6236             delete[] addRow;
6237             delete[] addElement;
6238             delete[] addCost;
6239           }
6240 #endif
6241           // Set rowCounts to be diagonal block index for cleanup
6242           rowCounts[kBlock] = jBlock;
6243         } else {
6244           // master
6245           masterBlock = jBlock;
6246           masterModel.loadProblem(*matrix, columnLower, columnUpper,
6247             objective, rowLower, rowUpper);
6248           if (optimizationDirection_ < 0.0) {
6249             double *obj = masterModel.objective();
6250             int n = masterModel.numberColumns();
6251             for (int i = 0; i < n; i++)
6252               obj[i] = -obj[i];
6253           }
6254         }
6255       }
6256     }
6257     if (iBlock != masterRowBlock)
6258       kBlock++;
6259   }
6260   delete[] whichBlock;
6261   delete[] blockInfo;
6262   assert(masterBlock >= 0);
6263   int numberMasterColumns = masterModel.numberColumns();
6264   masterModel.setStrParam(ClpProbName, "Master");
6265   // Overkill in terms of space
6266   int spaceNeeded = CoinMax(numberBlocks * (numberMasterColumns + 1),
6267     2 * numberMasterColumns);
6268   CoinBigIndex *columnAdd = new CoinBigIndex[spaceNeeded];
6269   int *indexColumnAdd = reinterpret_cast< int * >(columnAdd);
6270   double *elementAdd = new double[spaceNeeded];
6271   spaceNeeded = numberBlocks;
6272   CoinBigIndex *rowAdd = new CoinBigIndex[2 * spaceNeeded + 1]; // temp for block info
6273   int *blockPrint = reinterpret_cast< int * >(rowAdd + spaceNeeded + 1);
6274   double *objective = new double[spaceNeeded];
6275   int logLevel = handler_->logLevel();
6276   //#define TEST_MODEL
6277 #ifdef TEST_MODEL
6278   double goodValue = COIN_DBL_MAX;
6279   ClpSimplex goodModel;
6280   if (logLevel > 3) {
6281     // temp - create copy with master at front
6282     const int *columnBack = model->coinBlock(masterBlock)->originalColumns();
6283     int numberColumns2 = model->coinBlock(masterBlock)->numberColumns();
6284     const int *rowBack = model->coinBlock(masterBlock)->originalRows();
6285     int numberRows2 = model->coinBlock(masterBlock)->numberRows();
6286     int *whichColumn = new int[numberColumns_ + numberBlocks];
6287     int *whichRow = new int[numberRows_];
6288     int nColumn = 0;
6289     for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
6290       int kColumn = columnBack[iColumn];
6291       whichColumn[nColumn++] = kColumn;
6292     }
6293     int nRow = 0;
6294     for (int iRow = 0; iRow < numberRows2; iRow++) {
6295       int kRow = rowBack[iRow];
6296       whichRow[nRow++] = kRow;
6297     }
6298     for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
6299       int kBlock = rowCounts[iBlock];
6300       const int *columnBack = model->coinBlock(kBlock)->originalColumns();
6301       int numberColumns2 = model->coinBlock(kBlock)->numberColumns();
6302       const int *rowBack = model->coinBlock(kBlock)->originalRows();
6303       int numberRows2 = model->coinBlock(kBlock)->numberRows();
6304       for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
6305         int kColumn = columnBack[iColumn];
6306         whichColumn[nColumn++] = kColumn;
6307       }
6308       for (int iRow = 0; iRow < numberRows2; iRow++) {
6309         int kRow = rowBack[iRow];
6310         whichRow[nRow++] = kRow;
6311       }
6312     }
6313     ClpSimplex temp(this, nRow, whichRow, nColumn, whichColumn);
6314     temp.writeMps("ordered.mps");
6315     for (int i = numberMasterColumns; i < numberColumns_; i++)
6316       whichColumn[i + numberBlocks] = i;
6317     for (int i = 0; i < numberMasterColumns; i++)
6318       whichColumn[i] = i;
6319     for (int i = 0; i < numberBlocks; i++)
6320       whichColumn[i + numberMasterColumns] = i + numberColumns_;
6321     double *lower = new double[numberBlocks];
6322     // Add extra variables
6323     columnAdd[0] = 0;
6324     for (int iBlock = 0; iBlock < numberBlocks; iBlock++) {
6325       objective[iBlock] = 0.0;
6326       lower[iBlock] = -COIN_DBL_MAX;
6327       columnAdd[iBlock + 1] = 0;
6328     }
6329     temp.addColumns(numberBlocks, lower, NULL, objective,
6330       columnAdd, NULL, NULL);
6331     delete[] lower;
6332     ClpSimplex temp2(&temp, nRow, whichRow, nColumn + numberBlocks, whichColumn);
6333     goodModel = temp2;
6334     goodModel.dual();
6335     goodValue = goodModel.objectiveValue();
6336 #if 0
6337        double * obj = goodModel.objective();
6338        for (int i=numberMasterColumns;i<numberMasterColumns+numberBlocks;i++)
6339 	 obj[i]=0.5;;
6340        for (int i=numberMasterColumns+numberBlocks;i<goodModel.numberColumns();i++)
6341 	 obj[i]*=0.5;
6342        // fix solution
6343        {
6344 	 double * lower = goodModel.columnLower();
6345 	 double * upper = goodModel.columnUpper();
6346 	 double * solution = goodModel.primalColumnSolution();
6347 	 for (int i=0;i<numberMasterColumns;i++) {
6348 	   lower[i]=solution[i];
6349 	   upper[i]=solution[i];
6350 	 }
6351 	 goodModel.scaling(0);
6352 	 goodModel.dual();
6353        }
6354 #endif
6355     delete[] whichColumn;
6356     delete[] whichRow;
6357   }
6358 #endif
6359   int maxPass = options.independentOption(2);
6360   if (maxPass < 2)
6361     maxPass = 100;
6362   int iPass;
6363   double lastObjective = -1.0e31;
6364   // Create columns for proposals
6365   int numberMasterRows = masterModel.numberRows();
6366   //masterModel.resize(numberMasterColumns + numberBlocks, numberMasterRows);
6367   if (this->factorizationFrequency() == 200) {
6368     // User did not touch preset
6369     masterModel.defaultFactorizationFrequency();
6370   } else {
6371     // make sure model has correct value
6372     masterModel.setFactorizationFrequency(this->factorizationFrequency());
6373   }
6374   masterModel.setPerturbation(50);
6375   // temp bounds
6376   if (0) {
6377     printf("temp bounds\n");
6378     double *lower = masterModel.columnLower();
6379     double *upper = masterModel.columnUpper();
6380     for (int i = 0; i < numberMasterColumns; i++) {
6381       lower[i] = CoinMax(lower[i], -1.0e8);
6382       upper[i] = CoinMin(upper[i], 1.0e8);
6383     }
6384   }
6385   //printf("take out debound\n");
6386   //master=*deBound(&master);
6387   // Arrays to say which block and when created
6388   int maximumRows = 2 * numberMasterColumns + 10 * numberBlocks;
6389   whichBlock = new int[maximumRows];
6390   int *when = new int[maximumRows];
6391   // state of each problem (0 first or infeas, 1 feasible, add 2 if extra variables freed)
6392   int *problemState = new int[numberBlocks];
6393   memset(problemState, 0, numberBlocks * sizeof(int));
6394   int numberRowsGenerated = numberBlocks;
6395   // space for rhs modifications
6396   double **modification = new double *[numberBlocks];
6397   // Add extra variables
6398   columnAdd[0] = 0;
6399   for (int iBlock = 0; iBlock < numberBlocks; iBlock++) {
6400     int numberRows2 = sub[iBlock].numberRows();
6401     int numberColumns2 = sub[iBlock].numberColumns();
6402     int numberTotal2 = numberRows2 + numberColumns2;
6403     modification[iBlock] = new double[2 * numberTotal2 + numberRows2];
6404     double *save = modification[iBlock];
6405     memcpy(save, sub[iBlock].rowLower(), numberRows2 * sizeof(double));
6406     save += numberRows2;
6407     memcpy(save, sub[iBlock].columnLower(), numberColumns2 * sizeof(double));
6408     save += numberColumns2;
6409     memcpy(save, sub[iBlock].rowUpper(), numberRows2 * sizeof(double));
6410     save += numberRows2;
6411     memcpy(save, sub[iBlock].columnUpper(), numberColumns2 * sizeof(double));
6412     objective[iBlock] = 1.0;
6413     columnAdd[iBlock + 1] = 0;
6414     when[iBlock] = -1;
6415     whichBlock[iBlock] = iBlock;
6416     if (logLevel < 2) {
6417       // modify printing
6418       sub[iBlock].messagesPointer()->setDetailMessage(2, 6);
6419       sub[iBlock].messagesPointer()->setDetailMessage(2, 14);
6420       sub[iBlock].messagesPointer()->setDetailMessage(2, 0);
6421     }
6422     // scaling
6423     sub[iBlock].scaling(scalingFlag_);
6424     //sub[iBlock].scaling(0);
6425   }
6426   masterModel.addColumns(numberBlocks, NULL, NULL, objective,
6427     columnAdd, NULL, NULL);
6428   sprintf(generalPrint, "Time to decompose %.2f seconds", CoinCpuTime() - time1);
6429   handler_->message(CLP_GENERAL, messages_)
6430     << generalPrint
6431     << CoinMessageEol;
6432   int ixxxxxx = 0;
6433   if (intParam_[0] >= 100000 && intParam_[0] < 100999) {
6434     ixxxxxx = intParam_[0] - 100000;
6435     printf("ixxxxxx %d\n", ixxxxxx);
6436   }
6437 #ifdef ADD_ARTIFICIALS
6438   double **saveObjective = new double *[numberBlocks];
6439   for (int i = 0; i < numberBlocks; i++)
6440     saveObjective[i] = CoinCopyOfArray(sub[i].objective(),
6441       originalSubColumns[i]);
6442   int iFudge = 1;
6443   int lowFudge = 0;
6444   int highFudge = 0;
6445 #endif
6446 #define UNBOUNDED
6447   if (ixxxxxx > 0) {
6448     for (iBlock = 0; iBlock < CoinMin(numberBlocks, ixxxxxx); iBlock++) {
6449       ClpSimplex *temp = deBound(sub + iBlock);
6450       sub[iBlock] = *temp;
6451       delete temp;
6452       delete[] modification[iBlock];
6453       int numberRows2 = sub[iBlock].numberRows();
6454       int numberColumns2 = sub[iBlock].numberColumns();
6455       int numberTotal2 = numberRows2 + numberColumns2;
6456       modification[iBlock] = new double[2 * numberTotal2 + numberRows2];
6457       double *save = modification[iBlock];
6458       memcpy(save, sub[iBlock].rowLower(), numberRows2 * sizeof(double));
6459       save += numberRows2;
6460       memcpy(save, sub[iBlock].columnLower(), numberColumns2 * sizeof(double));
6461       save += numberColumns2;
6462       memcpy(save, sub[iBlock].rowUpper(), numberRows2 * sizeof(double));
6463       save += numberRows2;
6464       memcpy(save, sub[iBlock].columnUpper(), numberColumns2 * sizeof(double));
6465     }
6466   }
6467 #ifdef ABC_INHERIT
6468   //AbcSimplex abcMaster;
6469   //if (!this->abcState())
6470   //setAbcState(1);
6471   int numberCpu = CoinMin((this->abcState() & 15), 4);
6472   CoinPthreadStuff threadInfo(numberCpu, clp_parallelManager);
6473   masterModel.setAbcState(this->abcState());
6474   //AbcSimplex * tempMaster=masterModel.dealWithAbc(2,10,true);
6475   //abcMaster=*tempMaster;
6476   //delete tempMaster;
6477   //abcMaster.startThreads(numberCpu);
6478   //#define masterModel abcMaster
6479 #endif
6480   double treatSubAsFeasible = 1.0e-6;
6481   int numberSubInfeasible = 0;
6482   bool canSkipSubSolve = false;
6483   int numberProposals = 999;
6484   for (iPass = 0; iPass < maxPass; iPass++) {
6485     sprintf(generalPrint, "Start of pass %d", iPass);
6486     handler_->message(CLP_GENERAL, messages_)
6487       << generalPrint
6488       << CoinMessageEol;
6489     // Solve master - may be unbounded
6490     //masterModel.scaling(0);
6491     // get obj for debug
6492     double objSum = masterModel.objectiveValue();
6493     for (int i = 0; i < numberBlocks; i++)
6494       objSum += sub[i].objectiveValue();
6495     //printf("objsum %g\n",objSum);
6496     if (0) {
6497       masterModel.writeMps("yy.mps");
6498       masterModel.writeBasis("yy.bas", true, 2);
6499     }
6500     {
6501       // free up extra variables
6502       double *lower = masterModel.columnLower();
6503       int numberFreed = 0;
6504       for (int i = 0; i < numberBlocks; i++) {
6505         if (problemState[i] == 1) {
6506           // ? need trust region ?
6507           lower[i + numberMasterColumns] = -COIN_DBL_MAX;
6508 #if 0 //1 //ndef UNBOUNDED
6509 		lower[i+numberMasterColumns]=-1.0e10;
6510 #endif
6511           //if (problemState[i]!=2) {
6512           numberFreed++;
6513           problemState[i] = 3;
6514           //}
6515         }
6516       }
6517       if (numberFreed)
6518         lastObjective = -1.0e31;
6519     }
6520 #ifdef TRY_NO_SCALING
6521     masterModel.scaling(0);
6522 #endif
6523 #ifdef ABC_INHERIT
6524     masterModel.dealWithAbc(0, 0, true);
6525 #else
6526     masterModel.dual();
6527 #endif
6528     if ((maxPass == 5000 && scalingFlag_) || (maxPass == 4000 && !scalingFlag_)) {
6529       int n = masterModel.numberIterations();
6530       masterModel.scaling(0);
6531       masterModel.primal();
6532       masterModel.setNumberIterations(n + masterModel.numberIterations());
6533       masterModel.scaling(scalingFlag_);
6534     }
6535     int masterStatus = masterModel.status(); // do here as can change
6536     sprintf(generalPrint, "Pass %d objective %g change %g",
6537       iPass, masterModel.objectiveValue(),
6538       masterModel.objectiveValue() - lastObjective);
6539     handler_->message(CLP_GENERAL, messages_)
6540       << generalPrint
6541       << CoinMessageEol;
6542 #ifndef UNBOUNDED
6543     if (masterStatus == 2) {
6544       // unbounded
6545       masterModel.writeMps("unbounded.mps");
6546       // get primal feasible
6547 #ifdef ABC_INHERIT
6548       masterModel.dealWithAbc(1, 1, true);
6549 #else
6550       masterModel.primal();
6551 #endif
6552       const double *fullLower = columnLower();
6553       const double *fullUpper = columnUpper();
6554       double *lower = masterModel.columnLower();
6555       double *upper = masterModel.columnUpper();
6556       double *solution = masterModel.primalColumnSolution();
6557       const int *columnBack = model->coinBlock(masterBlock)->originalColumns();
6558       if (!numberTimesUnbounded) {
6559         for (int iColumn = 0; iColumn < numberMasterColumns; iColumn++) {
6560           int kColumn = columnBack[iColumn];
6561           double value = solution[iColumn];
6562           double lowerValue = CoinMax(fullLower[kColumn],
6563             CoinMin(value, fullUpper[kColumn]) - trust);
6564           lower[iColumn] = lowerValue;
6565           double upperValue = CoinMin(fullUpper[kColumn],
6566             CoinMax(value, fullLower[kColumn]) + trust);
6567           upper[iColumn] = upperValue;
6568         }
6569 #ifdef TEST_MODEL
6570         if (logLevel > 3) {
6571           //use ones from solved
6572           const double *solutionGood = goodModel.primalColumnSolution();
6573           for (int iColumn = 0; iColumn < numberMasterColumns; iColumn++) {
6574             double value = solutionGood[iColumn];
6575             lower[iColumn] = CoinMin(value, -trust);
6576             upper[iColumn] = CoinMax(value, trust);
6577           }
6578         }
6579 #endif
6580       } else {
6581         abort(); // probably can happen
6582       }
6583       numberTimesUnbounded++;
6584 #ifdef ABC_INHERIT
6585       masterModel.dealWithAbc(0, 0, true);
6586 #else
6587       masterModel.dual();
6588 #endif
6589       masterStatus = masterModel.status();
6590       assert(!masterStatus);
6591       masterModel.setNumberIterations(1); // so will continue
6592     }
6593     if (numberTimesUnbounded > 1 && trust > 0.0) {
6594       assert(!masterStatus);
6595       const double *fullLower = columnLower();
6596       const double *fullUpper = columnUpper();
6597       double *lower = masterModel.columnLower();
6598       double *upper = masterModel.columnUpper();
6599       //double * solution = masterModel.primalColumnSolution();
6600       const int *columnBack = model->coinBlock(masterBlock)->originalColumns();
6601       int nTrusted = 0;
6602       for (int iColumn = 0; iColumn < numberMasterColumns; iColumn++) {
6603         int kColumn = columnBack[iColumn];
6604         if (lower[iColumn] > fullLower[kColumn]) {
6605           if (masterModel.getColumnStatus(iColumn) != atLowerBound) {
6606             lower[iColumn] = fullLower[kColumn];
6607           } else {
6608             nTrusted++;
6609           }
6610         }
6611         if (upper[iColumn] < fullUpper[kColumn]) {
6612           if (masterModel.getColumnStatus(iColumn) != atUpperBound) {
6613             upper[iColumn] = fullUpper[kColumn];
6614           } else {
6615             nTrusted++;
6616           }
6617         }
6618       }
6619       if (nTrusted) {
6620         sprintf(generalPrint, "%d at artificial bound", nTrusted);
6621       } else {
6622         sprintf(generalPrint, "All at natural bounds");
6623         trust = 0.0;
6624       }
6625       handler_->message(CLP_GENERAL2, messages_)
6626         << generalPrint
6627         << CoinMessageEol;
6628     }
6629 #endif
6630     if (!masterStatus) {
6631       if (masterModel.numberIterations() == 0 && iPass) {
6632         if ((!numberSubInfeasible && !numberProposals) || treatSubAsFeasible > 1.0e-2 || iPass > 5555)
6633           break; // finished
6634         if (!numberProposals && numberSubInfeasible) {
6635           treatSubAsFeasible *= 2.0;
6636           printf("Doubling sub primal tolerance to %g\n", treatSubAsFeasible);
6637         } else {
6638           treatSubAsFeasible *= 1.2;
6639           printf("Increasing sub primal tolerance to %g\n", treatSubAsFeasible);
6640         }
6641         canSkipSubSolve = false;
6642       } else if (!numberSubInfeasible) {
6643         if (treatSubAsFeasible > 1.0e-6) {
6644           treatSubAsFeasible = CoinMax(0.9 * treatSubAsFeasible, 1.0e-6);
6645           printf("Reducing sub primal tolerance to %g\n", treatSubAsFeasible);
6646         }
6647       }
6648       if (masterModel.objectiveValue() < lastObjective + 1.0e-7 && iPass > 5555)
6649         break; // finished
6650       lastObjective = masterModel.objectiveValue();
6651     }
6652     // mark non-basic rows and delete if necessary
6653     int iRow;
6654     numberRowsGenerated = masterModel.numberRows() - numberMasterRows;
6655     for (iRow = 0; iRow < numberRowsGenerated; iRow++) {
6656       if (masterModel.getStatus(iRow + numberMasterRows) != ClpSimplex::basic)
6657         when[iRow] = iPass;
6658     }
6659     if (numberRowsGenerated > maximumRows - numberBlocks) {
6660       // delete
6661       int numberKeep = 0;
6662       int numberDelete = 0;
6663       int *whichDelete = new int[numberRowsGenerated];
6664       for (iRow = 0; iRow < numberRowsGenerated; iRow++) {
6665         if (masterModel.getRowStatus(iRow + numberMasterRows) != basic) {
6666           // keep
6667           when[numberKeep] = when[iRow];
6668           whichBlock[numberKeep++] = whichBlock[iRow];
6669         } else {
6670           // delete
6671           whichDelete[numberDelete++] = iRow + numberMasterRows;
6672         }
6673       }
6674       if (numberRowsGenerated - numberDelete > maximumRows - numberBlocks) {
6675         for (iRow = 0; iRow < numberRowsGenerated; iRow++) {
6676           if (when[iRow] > iPass - 7) {
6677             // keep
6678             when[numberKeep] = when[iRow];
6679             whichBlock[numberKeep++] = whichBlock[iRow];
6680           } else {
6681             // delete
6682             whichDelete[numberDelete++] = iRow + numberMasterRows;
6683           }
6684         }
6685       }
6686       numberRowsGenerated -= numberDelete;
6687       masterModel.deleteRows(numberDelete, whichDelete);
6688       delete[] whichDelete;
6689     }
6690     double *primal = NULL;
6691     bool deletePrimal = false;
6692     if (masterStatus == 0) {
6693       primal = masterModel.primalColumnSolution();
6694     } else if (masterStatus == 2 && masterModel.numberRows()) {
6695       // scale back ray (1.0e20?)
6696       primal = masterModel.ray();
6697       //deletePrimal = true;
6698       sprintf(generalPrint, "The sum of dual infeasibilities is %g",
6699         masterModel.sumDualInfeasibilities());
6700       handler_->message(CLP_GENERAL, messages_)
6701         << generalPrint
6702         << CoinMessageEol;
6703 #if 0
6704 	       const double * primal2 = masterModel.primalColumnSolution();
6705 #ifndef UNBOUNDED
6706 	       for (int i=0;i<numberMasterColumns;i++) {
6707 		 primal[i] = 1.0e-10*primal[i]+primal2[i];
6708 	       }
6709 #else
6710 	       double scaleFactor = innerProduct(primal,numberMasterColumns,primal);
6711 	       double scaleFactor2 = innerProduct(primal+numberMasterColumns,
6712 						  numberBlocks,primal+numberMasterColumns);
6713 	       if (scaleFactor&&!scaleFactor2) {
6714 		 scaleFactor = 1.0/sqrt(scaleFactor);
6715 		 for (int i=0;i<numberMasterColumns;i++) {
6716 		   primal[i] *= scaleFactor;
6717 		 }
6718 	       } else {
6719 		 // treat as feasible
6720 		 if (scaleFactor)
6721 		   scaleFactor = 1.0e10/sqrt(scaleFactor);
6722 		 for (int i=0;i<numberMasterColumns;i++) {
6723 		   primal[i] = primal[i]*scaleFactor+primal2[i];
6724 		 }
6725 		 masterStatus=0;
6726 	       }
6727 #endif
6728 #endif
6729     } else if (!masterModel.numberRows()) {
6730       assert(!iPass);
6731       primal = masterModel.primalColumnSolution();
6732       memset(masterModel.primalColumnSolution(),
6733         0, numberMasterColumns * sizeof(double));
6734     } else {
6735       printf("Master infeasible - sum %g\n",
6736         masterModel.sumPrimalInfeasibilities());
6737       masterModel.setProblemStatus(0);
6738       primal = masterModel.primalColumnSolution();
6739       masterModel.writeMps("inf.mps");
6740       //abort();
6741     }
6742 #ifndef UNBOUNDED
6743     if (masterStatus == 2) {
6744       // adjust variables with no elements
6745       const int *columnLength = masterModel.matrix()->getVectorLengths();
6746       const double *lower = masterModel.columnLower();
6747       const double *upper = masterModel.columnUpper();
6748       const double *obj = masterModel.objective();
6749       for (int i = 0; i < numberMasterColumns; i++) {
6750         double value = primal[i];
6751         if (!columnLength[i]) {
6752           if (obj[i] < 0.0)
6753             value += 1.0e10;
6754           else if (obj[i] > 0.0)
6755             value -= 1.0e10;
6756         }
6757         // make sure feasible
6758         primal[i] = CoinMax(-1.0e10, CoinMin(1.0e10, value));
6759         primal[i] = CoinMax(lower[i], CoinMin(upper[i], primal[i]));
6760       }
6761     }
6762 #endif
6763     // Create rhs for sub problems and solve
6764     for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
6765 #ifdef ADD_ARTIFICIALS
6766       {
6767         double *columnUpper2 = sub[iBlock].columnUpper();
6768         double *obj = sub[iBlock].objective();
6769         int start = originalSubColumns[iBlock];
6770         int numberColumns2 = sub[iBlock].numberColumns();
6771         if (iFudge >= lowFudge && iFudge <= abs(highFudge)) {
6772           for (int i = start; i < numberColumns2; i++)
6773             columnUpper2[i] = COIN_DBL_MAX;
6774           memset(obj, 0, originalSubColumns[iBlock] * sizeof(double));
6775         } else {
6776           for (int i = start; i < numberColumns2; i++)
6777             columnUpper2[i] = 0.0;
6778           memcpy(obj, saveObjective[iBlock], originalSubColumns[iBlock] * sizeof(double));
6779           if (highFudge < 0) {
6780             sub[iBlock].allSlackBasis(true);
6781           }
6782         }
6783       }
6784 #endif
6785       int numberRows2 = sub[iBlock].numberRows();
6786       int numberColumns2 = sub[iBlock].numberColumns();
6787       double *saveLower = modification[iBlock];
6788       double *lower2 = sub[iBlock].rowLower();
6789       memcpy(lower2, saveLower, numberRows2 * sizeof(double));
6790       double *saveColumnLower = saveLower + numberRows2;
6791       double *columnLower2 = sub[iBlock].columnLower();
6792       memcpy(columnLower2, saveColumnLower, numberColumns2 * sizeof(double));
6793       double *saveUpper = saveColumnLower + numberColumns2;
6794       double *upper2 = sub[iBlock].rowUpper();
6795       memcpy(upper2, saveUpper, numberRows2 * sizeof(double));
6796       double *saveColumnUpper = saveUpper + numberRows2;
6797       double *columnUpper2 = sub[iBlock].columnUpper();
6798       memcpy(columnUpper2, saveColumnUpper, numberColumns2 * sizeof(double));
6799       double *lastMod = saveColumnUpper + numberColumns2;
6800 #ifdef UNBOUNDED
6801       if (masterStatus == 2) {
6802         for (int i = 0; i < numberRows2; i++) {
6803           if (lower2[i] > -COIN_DBL_MAX)
6804             lower2[i] = 0.0;
6805           if (upper2[i] < COIN_DBL_MAX)
6806             upper2[i] = 0.0;
6807         }
6808         for (int i = 0; i < numberColumns2; i++) {
6809           if (columnLower2[i] > -COIN_DBL_MAX)
6810             columnLower2[i] = 0.0;
6811           if (columnUpper2[i] < COIN_DBL_MAX)
6812             columnUpper2[i] = 0.0;
6813         }
6814       }
6815 #endif
6816       // new rhs
6817       double *rhs = sub[iBlock].dualRowSolution();
6818       CoinZeroN(rhs, numberRows2);
6819       first[iBlock]->times(primal, rhs);
6820       for (int i = 0; i < numberRows2; i++) {
6821         double value = rhs[i];
6822         if (lower2[i] > -1.0e30)
6823           lower2[i] -= value;
6824         if (upper2[i] < 1.0e30)
6825           upper2[i] -= value;
6826       }
6827       bool canSkip = false;
6828       if (canSkipSubSolve) {
6829         canSkip = true;
6830         const double *rowSolution = sub[iBlock].primalRowSolution();
6831         for (int i = 0; i < numberRows2; i++) {
6832           double value = lastMod[i] - rhs[i];
6833           if (fabs(value) > primalTolerance_) {
6834             // see if we can adjust
6835             double rowValue = rowSolution[i];
6836             if (rowValue < lower2[i] - primalTolerance_
6837               || rowValue > upper2[i] + primalTolerance_) {
6838               canSkip = false;
6839               break;
6840             } else if (sub[iBlock].getRowStatus(i) != basic) {
6841               canSkip = false;
6842               break;
6843             }
6844           }
6845         }
6846       }
6847       if (!canSkip) {
6848         memcpy(lastMod, rhs, numberRows2 * sizeof(double));
6849       } else {
6850         // mark
6851         sub[iBlock].setSecondaryStatus(99);
6852       }
6853     }
6854     canSkipSubSolve = true;
6855     if (!iPass) {
6856       // do first and then copy status?
6857 #ifdef TRY_NO_SCALING
6858       sub[0].scaling(0);
6859 #endif
6860 #ifdef ABC_INHERIT
6861       sub[0].setAbcState(numberCpu);
6862       //sub[0].dealWithAbc(0,0,true);
6863       sub[0].dealWithAbc(1, 1, true);
6864       sub[0].setAbcState(0);
6865 #else
6866       sub[0].dual();
6867 #endif
6868       if ((maxPass == 5000 && scalingFlag_) || (maxPass == 4000 && !scalingFlag_)) {
6869         int n = sub[0].numberIterations();
6870         sub[0].scaling(0);
6871         sub[0].primal();
6872         sub[0].setNumberIterations(n + sub[0].numberIterations());
6873         sub[0].scaling(scalingFlag_);
6874       }
6875       int numberIterations = sub[0].numberIterations();
6876       if (sub[0].problemStatus()) {
6877         sub[0].primal();
6878 #if 0
6879 	      sub[0].writeMps("first.mps");
6880 	      sub[0].writeBasis("first.bas",true);
6881 	      sub[0].readBasis("first.bas");
6882 	      sub[0].primal();
6883 #endif
6884         numberIterations += sub[0].numberIterations();
6885       }
6886       sprintf(generalPrint, "First block - initial solve - %d iterations, objective %g",
6887         numberIterations, sub[0].objectiveValue());
6888       handler_->message(CLP_GENERAL, messages_)
6889         << generalPrint
6890         << CoinMessageEol;
6891       // copy status if same size
6892       int numberRows2 = sub[0].numberRows();
6893       int numberColumns2 = sub[0].numberColumns();
6894       for (int iBlock = 1; iBlock < numberBlocks; iBlock++) {
6895         int numberRows2a = sub[iBlock].numberRows();
6896         int numberColumns2a = sub[iBlock].numberColumns();
6897         if (numberRows2 == numberRows2a && numberColumns2 == numberColumns2a) {
6898           memcpy(sub[iBlock].primalColumnSolution(),
6899             sub[0].primalColumnSolution(),
6900             numberColumns2 * sizeof(double));
6901           memcpy(sub[iBlock].statusArray(), sub[0].statusArray(),
6902             numberRows2 + numberColumns2);
6903         }
6904       }
6905       // mark
6906       sub[0].setSecondaryStatus(99);
6907     }
6908 #ifdef ABC_INHERIT
6909     if (numberCpu < 2) {
6910 #endif
6911       numberSubInfeasible = 0;
6912       for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
6913 #ifdef TRY_NO_SCALING
6914         sub[iBlock].scaling(0);
6915 #endif
6916         if (sub[iBlock].secondaryStatus() != 99 || false) {
6917           //int ix=sub[iBlock].secondaryStatus();
6918           int lastStatus = sub[iBlock].problemStatus();
6919           // was do dual unless unbounded
6920           double saveTolerance = sub[iBlock].primalTolerance();
6921           if (lastStatus == 0 || !iPass) {
6922             //if (lastStatus<2||!iPass) {
6923             //sub[iBlock].dual();
6924             sub[iBlock].primal();
6925             if (!sub[iBlock].isProvenOptimal() && sub[iBlock].sumPrimalInfeasibilities() < treatSubAsFeasible) {
6926               printf("Block %d was feasible now has small infeasibility %g\n", iBlock,
6927                 sub[iBlock].sumPrimalInfeasibilities());
6928               sub[iBlock].setPrimalTolerance(CoinMin(treatSubAsFeasible, 1.0e-4));
6929               sub[iBlock].setCurrentPrimalTolerance(CoinMin(treatSubAsFeasible, 1.0e-4));
6930               sub[iBlock].primal();
6931               sub[iBlock].setProblemStatus(0);
6932               problemState[iBlock] |= 4; // force actions
6933             }
6934             if ((maxPass == 5000 && scalingFlag_) || (maxPass == 4000 && !scalingFlag_)) {
6935               int n = sub[iBlock].numberIterations();
6936               sub[iBlock].scaling(0);
6937               sub[iBlock].primal();
6938               sub[iBlock].setNumberIterations(n + sub[iBlock].numberIterations());
6939               sub[iBlock].scaling(scalingFlag_);
6940             }
6941           } else if (lastStatus == 1) {
6942             // zero out objective
6943             double saveScale = sub[iBlock].infeasibilityCost();
6944             ClpObjective *saveObjective = sub[iBlock].objectiveAsObject();
6945             int numberColumns = sub[iBlock].numberColumns();
6946             ClpLinearObjective fake(NULL, numberColumns);
6947             sub[iBlock].setObjectivePointer(&fake);
6948             int saveOptions = sub[iBlock].specialOptions();
6949             sub[iBlock].setSpecialOptions(saveOptions | 8192);
6950             sub[iBlock].primal();
6951             if ((maxPass == 5000 && scalingFlag_) || (maxPass == 4000 && !scalingFlag_)) {
6952               int n = sub[iBlock].numberIterations();
6953               sub[iBlock].scaling(0);
6954               sub[iBlock].primal();
6955               sub[iBlock].setNumberIterations(n + sub[iBlock].numberIterations());
6956               sub[iBlock].scaling(scalingFlag_);
6957             }
6958             sub[iBlock].setObjectivePointer(saveObjective);
6959             sub[iBlock].setInfeasibilityCost(saveScale);
6960             if (!sub[iBlock].isProvenOptimal() && sub[iBlock].sumPrimalInfeasibilities() < treatSubAsFeasible) {
6961               printf("Block %d was infeasible now has small infeasibility %g\n", iBlock,
6962                 sub[iBlock].sumPrimalInfeasibilities());
6963               sub[iBlock].setProblemStatus(0);
6964               sub[iBlock].setPrimalTolerance(CoinMin(treatSubAsFeasible, 1.0e-4));
6965               sub[iBlock].setCurrentPrimalTolerance(CoinMin(treatSubAsFeasible, 1.0e-4));
6966             }
6967             if (sub[iBlock].isProvenOptimal()) {
6968               sub[iBlock].primal();
6969               if ((maxPass == 5000 && scalingFlag_) || (maxPass == 4000 && !scalingFlag_)) {
6970                 int n = sub[iBlock].numberIterations();
6971                 sub[iBlock].scaling(0);
6972                 sub[iBlock].primal();
6973                 sub[iBlock].setNumberIterations(n + sub[iBlock].numberIterations());
6974                 sub[iBlock].scaling(scalingFlag_);
6975               }
6976               if (!sub[iBlock].isProvenOptimal()) {
6977                 printf("Block %d infeasible on second go has small infeasibility %g\n", iBlock,
6978                   sub[iBlock].sumPrimalInfeasibilities());
6979                 sub[iBlock].setProblemStatus(0);
6980               }
6981               problemState[iBlock] |= 4; // force actions
6982             } else {
6983               printf("Block %d still infeasible - sum %g - %d iterations\n", iBlock,
6984                 sub[iBlock].sumPrimalInfeasibilities(),
6985                 sub[iBlock].numberIterations());
6986               numberSubInfeasible++;
6987               if (!sub[iBlock].ray()) {
6988                 printf("Block %d has no ray!\n", iBlock);
6989                 sub[iBlock].primal();
6990                 assert(sub[iBlock].ray()); // otherwise declare optimal
6991               }
6992             }
6993             sub[iBlock].setSpecialOptions(saveOptions);
6994           } else {
6995             sub[iBlock].primal();
6996           }
6997           sub[iBlock].setPrimalTolerance(saveTolerance);
6998           sub[iBlock].setCurrentPrimalTolerance(saveTolerance);
6999           if (!sub[iBlock].isProvenOptimal() && !sub[iBlock].isProvenPrimalInfeasible()) {
7000             printf("!!!Block %d has bad status %d\n", iBlock, sub[iBlock].problemStatus());
7001             sub[iBlock].primal(); // last go
7002           }
7003           //#define WRITE_ALL
7004 #ifdef WRITE_ALL
7005           char name[20];
7006           sprintf(name, "pass_%d_block_%d.mps", iPass, iBlock);
7007           sub[iBlock].writeMps(name);
7008           sprintf(name, "pass_%d_block_%d.bas", iPass, iBlock);
7009           sub[iBlock].writeBasis(name, true);
7010           if (sub[iBlock].problemStatus() == 1) {
7011             sub[iBlock].readBasis(name);
7012             sub[iBlock].primal();
7013           }
7014 #endif
7015           //assert (!sub[iBlock].numberIterations()||ix!=99);
7016         }
7017       }
7018 #ifdef ABC_INHERIT
7019     } else {
7020       int iBlock = 0;
7021       while (iBlock < numberBlocks) {
7022         if (sub[iBlock].secondaryStatus() != 99) {
7023           int iThread;
7024           threadInfo.waitParallelTask(1, iThread, true);
7025 #ifdef DETAIL_THREAD
7026           printf("Starting block %d on thread %d\n",
7027             iBlock, iThread);
7028 #endif
7029           threadInfo.startParallelTask(1, iThread, sub + iBlock);
7030         }
7031         iBlock++;
7032       }
7033       threadInfo.waitAllTasks();
7034     }
7035 #endif
7036     for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
7037       if (!iPass)
7038         problemState[iBlock] |= 4; // force actions
7039       // if state changed then fake number of iterations
7040       if ((problemState[iBlock] & 1) == 0) {
7041         // was infeasible
7042         if (sub[iBlock].isProvenOptimal()) {
7043           // say feasible and changed
7044           problemState[iBlock] |= 1 + 4;
7045         }
7046       } else {
7047         // was feasible
7048         if (sub[iBlock].isProvenPrimalInfeasible()) {
7049           // say infeasible and changed
7050           problemState[iBlock] &= ~1;
7051           problemState[iBlock] |= 4;
7052         }
7053       }
7054       if (sub[iBlock].secondaryStatus() != 99) {
7055         if (logLevel > 1) {
7056           sprintf(generalPrint, "Block %d - %d iterations, objective %g",
7057             iBlock, sub[iBlock].numberIterations(),
7058             sub[iBlock].objectiveValue());
7059           handler_->message(CLP_GENERAL2, messages_)
7060             << generalPrint
7061             << CoinMessageEol;
7062         }
7063         if (sub[iBlock].problemStatus() && sub[iBlock].algorithm() < 0 && false) {
7064           int numberRows2 = sub[iBlock].numberRows();
7065           double *ray = sub[iBlock].infeasibilityRay();
7066           double *saveRay = CoinCopyOfArray(ray, numberRows2);
7067 #if 0
7068 		int directionOut = sub[iBlock].directionOut();
7069 		sub[iBlock].allSlackBasis(true);
7070 		sub[iBlock].dual();
7071 		printf("old dir %d new %d\n",directionOut,sub[iBlock].directionOut());
7072 #else
7073           double *obj = sub[iBlock].objective();
7074           int numberColumns2 = sub[iBlock].numberColumns();
7075           double *saveObj = CoinCopyOfArray(obj, numberColumns2);
7076           memset(obj, 0, numberColumns2 * sizeof(double));
7077           sub[iBlock].allSlackBasis(true);
7078           sub[iBlock].primal();
7079           memcpy(obj, saveObj, numberColumns2 * sizeof(double));
7080           delete[] saveObj;
7081 #endif
7082           ray = sub[iBlock].infeasibilityRay();
7083           for (int i = 0; i < numberRows2; i++) {
7084             if (fabs(ray[i] - saveRay[i]) > 1.0e-4 + 1.0e20)
7085               printf("** diffray block %d row %d first %g second %g\n",
7086                 iBlock, i, saveRay[i], ray[i]);
7087           }
7088           delete[] saveRay;
7089         }
7090       }
7091     }
7092     if (!iPass)
7093       sub[0].setSecondaryStatus(0);
7094     if (logLevel > 2) {
7095       for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
7096         printf("block %d obj %g thetaC %g\n", iBlock, sub[iBlock].objectiveValue(), masterModel.primalColumnSolution()[numberMasterColumns + iBlock]);
7097       }
7098     }
7099     rowAdd[0] = 0;
7100     numberProposals = 0;
7101     for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
7102       int numberRows2 = sub[iBlock].numberRows();
7103       int numberColumns2 = sub[iBlock].numberColumns();
7104       double *saveLower = modification[iBlock];
7105       double *lower2 = sub[iBlock].rowLower();
7106       double *saveUpper = saveLower + numberRows2 + numberColumns2;
7107       double *upper2 = sub[iBlock].rowUpper();
7108       int typeRun = sub[iBlock].secondaryStatus();
7109       sub[iBlock].setSecondaryStatus(0);
7110       if (typeRun != 99) {
7111         if (0) {
7112           double objValue = 0.0;
7113           const double *solution = sub[iBlock].dualRowSolution();
7114           for (int i = 0; i < numberRows2; i++) {
7115             if (solution[i] < -dualTolerance_) {
7116               // at upper
7117               assert(saveUpper[i] < 1.0e30);
7118               objValue += solution[i] * upper2[i];
7119             } else if (solution[i] > dualTolerance_) {
7120               // at lower
7121               assert(saveLower[i] > -1.0e30);
7122               objValue += solution[i] * lower2[i];
7123             }
7124           }
7125           //printf("obj %g\n",objValue);
7126         }
7127         // temp
7128         if (sub[iBlock].isProvenPrimalInfeasible() && !sub[iBlock].numberIterations())
7129           problemState[iBlock] |= 4;
7130         // get proposal
7131         if (sub[iBlock].numberIterations() || (problemState[iBlock] & 4) != 0) {
7132           double objValue = 0.0;
7133           int start = static_cast< int >(rowAdd[numberProposals]);
7134           // proposal
7135           if (sub[iBlock].isProvenOptimal()) {
7136             double *solution = sub[iBlock].dualRowSolution();
7137             first[iBlock]->transposeTimes(solution, elementAdd + start);
7138             for (int i = 0; i < numberRows2; i++) {
7139               if (sub[iBlock].getRowStatus(i) == basic)
7140                 solution[i] = 0.0;
7141               if (saveUpper[i] > saveLower[i]) {
7142                 if (sub[iBlock].getRowStatus(i) == atUpperBound)
7143                   objValue += solution[i] * saveUpper[i];
7144                 else
7145                   objValue += solution[i] * saveLower[i];
7146               } else {
7147                 // fixed
7148                 objValue += solution[i] * saveLower[i];
7149               }
7150             }
7151             const double *dj = sub[iBlock].dualColumnSolution();
7152             const double *columnLower = sub[iBlock].columnLower();
7153             const double *columnUpper = sub[iBlock].columnUpper();
7154             double objValue2 = 0.0;
7155             int numberColumns2 = sub[iBlock].numberColumns();
7156             for (int i = 0; i < numberColumns2; i++) {
7157               if (logLevel > 2) {
7158                 if (sub[iBlock].getColumnStatus(i) != basic && fabs(sub[iBlock].primalColumnSolution()[i]) > 1.0e-5)
7159                   printf("zz %d has value %g\n", i, sub[iBlock].primalColumnSolution()[i]);
7160               }
7161               if (sub[iBlock].getColumnStatus(i) == isFixed) {
7162                 objValue2 += columnLower[i] * dj[i];
7163               } else if (sub[iBlock].getColumnStatus(i) == atLowerBound) {
7164                 objValue2 += columnLower[i] * dj[i];
7165               } else if (sub[iBlock].getColumnStatus(i) == atUpperBound) {
7166                 objValue2 += columnUpper[i] * dj[i];
7167               }
7168             }
7169 #if 1
7170             double objValue3 = 0.0;
7171             const double *cost = sub[iBlock].objective();
7172             for (int i = 0; i < numberColumns2; i++) {
7173               double value = dj[i] - cost[i];
7174               if (sub[iBlock].getColumnStatus(i) == isFixed) {
7175                 objValue3 += columnLower[i] * value;
7176               } else if (sub[iBlock].getColumnStatus(i) == atLowerBound) {
7177                 objValue3 += columnLower[i] * value;
7178               } else if (sub[iBlock].getColumnStatus(i) == atUpperBound) {
7179                 objValue3 += columnUpper[i] * value;
7180               }
7181             }
7182 #endif
7183             // recompute
7184             if (logLevel > 3) {
7185               printf("objValue %g from lp %g, obj2 %g, obj3 %g\n",
7186                 objValue, sub[iBlock].objectiveValue(),
7187                 objValue2, objValue3);
7188             }
7189             objValue += objValue2;
7190             //objValue=sub[iBlock].objectiveValue();
7191             // See if cuts off and pack down
7192             int number = start;
7193             double infeas = -objValue;
7194             double smallest = 1.0e100;
7195             double largest = 0.0;
7196             for (int i = 0; i < numberMasterColumns; i++) {
7197               double value = elementAdd[start + i];
7198               if (fabs(value) > 1.0e-12) {
7199                 infeas += primal[i] * value;
7200                 smallest = CoinMin(smallest, fabs(value));
7201                 largest = CoinMax(largest, fabs(value));
7202                 indexColumnAdd[number] = i;
7203                 elementAdd[number++] = -value;
7204               }
7205             }
7206 
7207             infeas += primal[numberMasterColumns + iBlock];
7208             indexColumnAdd[number] = numberMasterColumns + iBlock;
7209             elementAdd[number++] = -1.0;
7210             // if elements large then scale?
7211             if (largest > 1.0e8 || smallest < 1.0e-8) {
7212               sprintf(generalPrint, "For subproblem %d smallest - %g, largest %g - infeas %g",
7213                 iBlock, smallest, largest, infeas);
7214               handler_->message(CLP_GENERAL2, messages_)
7215                 << generalPrint
7216                 << CoinMessageEol;
7217               if (smallest < 1.0e-12 * largest) {
7218                 sprintf(generalPrint, "Removing small elements");
7219                 handler_->message(CLP_GENERAL2, messages_)
7220                   << generalPrint
7221                   << CoinMessageEol;
7222                 double target = 1.0e-12 * largest;
7223                 smallest = largest;
7224                 int number2 = number - 1;
7225                 number = start;
7226                 for (int i = start; i < number2; i++) {
7227                   double value = elementAdd[i];
7228                   if (fabs(value) > target) {
7229                     smallest = CoinMin(smallest, fabs(value));
7230                     indexColumnAdd[number] = indexColumnAdd[i];
7231                     elementAdd[number++] = value;
7232                   }
7233                 }
7234                 indexColumnAdd[number] = numberMasterColumns + iBlock;
7235                 elementAdd[number++] = -1.0;
7236               }
7237             }
7238             // if smallest >1.0 then scale
7239             if ((smallest > 1.0e6 || fabs(objValue) > 0.01 * largeValue_)
7240               && number > start + 1) {
7241               double scale = 1.0 / smallest;
7242               if (fabs(scale * objValue) > 0.01 * largeValue_) {
7243                 printf("** scale before obj scale %g\n", scale);
7244                 scale = (0.01 * largeValue_) / fabs(objValue);
7245               }
7246               printf("** scale %g infeas %g\n", scale, infeas);
7247               objValue *= scale;
7248               infeas = -objValue;
7249               for (int i = start; i < number - 1; i++) {
7250                 double value = elementAdd[i] * scale;
7251                 elementAdd[i] = value;
7252                 int iColumn = indexColumnAdd[i];
7253                 infeas -= primal[iColumn] * value;
7254               }
7255               elementAdd[number - 1] *= scale;
7256               infeas += primal[numberMasterColumns + iBlock] * scale;
7257               printf("** new infeas %g - scales to %g\n", infeas, infeas / scale);
7258             }
7259             if (infeas < -1.0e-6 || (problemState[iBlock] & 4) != 0) {
7260               // take
7261               // double check infeasibility
7262               if (logLevel > 3)
7263                 printf("objValue %g objectiveValue() %g\n",
7264                   objValue, sub[iBlock].objectiveValue());
7265               double sum = 0.0;
7266               for (int i = start; i < number; i++) {
7267                 int iColumn = indexColumnAdd[i];
7268                 sum += primal[iColumn] * elementAdd[i];
7269               }
7270               if (logLevel > 3)
7271                 printf("Sum %g rhs %g\n", sum, -objValue);
7272               if (logLevel > 1)
7273                 printf("Cut for block %d has %d elements\n", iBlock, number - 1 - start);
7274               blockPrint[numberProposals] = iBlock;
7275               objective[numberProposals] = -objValue;
7276               rowAdd[++numberProposals] = number;
7277               when[numberRowsGenerated] = iPass;
7278               whichBlock[numberRowsGenerated++] = iBlock;
7279             }
7280           } else if (sub[iBlock].isProvenPrimalInfeasible()) {
7281             // use ray
7282             double *solution = sub[iBlock].infeasibilityRay();
7283             if (0) {
7284               double trueOffset = 0.0;
7285               int numberRows = sub[iBlock].numberRows();
7286               int numberColumns = sub[iBlock].numberColumns();
7287               double *farkas = new double[CoinMax(2 * numberColumns + numberRows, numberMasterColumns)];
7288               double *bound = farkas + numberColumns;
7289               double *effectiveRhs = bound + numberColumns;
7290               // get ray as user would
7291               double *ray = solution; //sub[iBlock].infeasibilityRay();
7292               // get farkas row
7293               memset(farkas, 0, (2 * numberColumns + numberRows) * sizeof(double));
7294               // Looks to me as if ray should be flipped according to mosek
7295               sub[iBlock].clpMatrix()->transposeTimes(-1.0, ray, farkas);
7296               // now farkas has A_T_y
7297               // Put nonzero bounds in bound
7298               const double *columnLower = sub[iBlock].columnLower();
7299               const double *columnUpper = sub[iBlock].columnUpper();
7300               int numberBad = 0;
7301               // For sum in mosek
7302               double ySum = 0.0;
7303               for (int i = 0; i < numberColumns; i++) {
7304                 double value = farkas[i];
7305                 double boundValue = 0.0;
7306                 if (sub[iBlock].getStatus(i) == ClpSimplex::basic) {
7307                   // treat as zero if small
7308                   if (fabs(value) < 1.0e-8) {
7309                     value = 0.0;
7310                     farkas[i] = 0.0;
7311                   }
7312                   if (value) {
7313                     //printf("basic %d direction %d farkas %g\n",
7314                     //	   i,sub[iBlock].directionOut(),value);
7315                     if (value < 0.0)
7316                       boundValue = columnLower[i];
7317                     else
7318                       boundValue = columnUpper[i];
7319                   }
7320                 } else if (fabs(value) > 1.0e-8) {
7321                   if (value < 0.0)
7322                     boundValue = columnLower[i];
7323                   else
7324                     boundValue = columnUpper[i];
7325                   if (fabs(boundValue) > 1.0e12 && fabs(value) < 1.0e-8) {
7326                     boundValue = 0.0;
7327                     value = 0.0;
7328                   }
7329                 } else {
7330                   value = 0.0;
7331                 }
7332                 if (fabs(boundValue) > 1.0e20) {
7333                   numberBad++;
7334                   boundValue = 0.0;
7335                   value = 0.0;
7336                   farkas[i] = 0.0;
7337                 }
7338                 // mosek way
7339                 // A_T_y + s_x_l -s_x_u == 0
7340                 // So if value >0 s_x_l->0 s_x_u->value
7341                 // otherwise s_x_l->-value, s_x_u->0
7342                 double s_x_l = 0.0;
7343                 double s_x_u = 0.0;
7344                 if (value > 0)
7345                   s_x_u = value;
7346                 else
7347                   s_x_l = -value;
7348                 ySum += columnLower[i] * s_x_l;
7349                 ySum -= columnUpper[i] * s_x_u;
7350                 bound[i] = boundValue;
7351               }
7352               const double *rowLower = sub[iBlock].rowLower();
7353               const double *rowUpper = sub[iBlock].rowUpper();
7354               //int pivotRow = sub[iBlock].spareIntArray_[3];
7355               //bool badPivot=pivotRow<0;
7356               for (int i = 0; i < numberRows; i++) {
7357                 double value = ray[i];
7358                 double rhsValue = 0.0;
7359                 if (sub[iBlock].getRowStatus(i) == ClpSimplex::basic) {
7360                   // treat as zero if small
7361                   if (fabs(value) < 1.0e-7) {
7362                     value = 0.0;
7363                   }
7364                   if (value) {
7365                     //printf("row basic %d direction %d ray %g\n",
7366                     //	   i,sub[iBlock].directionOut(),value);
7367                     if (value < 0.0)
7368                       rhsValue = rowLower[i];
7369                     else
7370                       rhsValue = rowUpper[i];
7371                   }
7372                 } else if (fabs(value) > 1.0e-10) {
7373                   if (value < 0.0)
7374                     rhsValue = rowLower[i];
7375                   else
7376                     rhsValue = rowUpper[i];
7377                 } else {
7378                   value = 0.0;
7379                 }
7380                 if (fabs(rhsValue) > 1.0e20) {
7381                   numberBad++;
7382                   value = 0.0;
7383                 }
7384                 ray[i] = value;
7385                 if (!value)
7386                   rhsValue = 0.0;
7387                 // for mosek flip value back
7388                 double yvalue = -value;
7389                 // -y + s_c_l - s_c_u==0
7390                 double s_c_l = 0.0;
7391                 double s_c_u = 0.0;
7392                 if (yvalue > 0)
7393                   s_c_l = yvalue;
7394                 else
7395                   s_c_u = -yvalue;
7396                 ySum += rowLower[i] * s_c_l;
7397                 ySum -= rowUpper[i] * s_c_u;
7398                 effectiveRhs[i] = rhsValue;
7399                 if (fabs(effectiveRhs[i]) > 1.0e10)
7400                   printf("Large rhs row %d %g\n",
7401                     i, effectiveRhs[i]);
7402               }
7403               sub[iBlock].clpMatrix()->times(-1.0, bound, effectiveRhs);
7404               double bSum = 0.0;
7405               for (int i = 0; i < numberRows; i++) {
7406                 bSum += effectiveRhs[i] * ray[i];
7407                 if (fabs(effectiveRhs[i]) > 1.0e10)
7408                   printf("Large rhs row %d %g after\n",
7409                     i, effectiveRhs[i]);
7410               }
7411               if (logLevel > 1)
7412                 printf("Block %d Mosek user manual wants %g to be positive so bSum should be negative %g\n",
7413                   iBlock, ySum, bSum);
7414               if (numberBad || bSum > 1.0e-6) {
7415                 printf("Bad infeasibility ray %g  - %d bad\n",
7416                   bSum, numberBad);
7417               } else {
7418                 //printf("Good ray - infeasibility %g\n",
7419                 //     -bSum);
7420               }
7421               /*
7422 		      wanted cut is
7423 		      plus or minus! (temp2 * x - temp2 *x_bar) <= bSum
7424 		      first[iBlock]->transposeTimes(ray, temp2);
7425 		     */
7426               memset(farkas, 0, numberColumns * sizeof(double));
7427               first[iBlock]->transposeTimes(ray, farkas);
7428               double offset = 0.0;
7429               const double *masterSolution = masterModel.primalColumnSolution();
7430               for (int i = 0; i < numberMasterColumns; i++) {
7431                 double value = farkas[i];
7432                 if (fabs(value) > 1.0e-9) {
7433                   offset += value * masterSolution[i];
7434                   if (logLevel > 2)
7435                     printf("(%d,%g) ", i, value);
7436                 } else {
7437                   farkas[i] = 0.0;
7438                 }
7439               }
7440               trueOffset = bSum + offset;
7441               if (sub[iBlock].algorithm() > 0)
7442                 trueOffset *= 1.0e-5;
7443               if (logLevel > 2)
7444                 printf(" - offset %g - ? rhs of %g\n", offset, trueOffset);
7445               //delete [] ray;
7446               delete[] farkas;
7447             }
7448             // if primal then scale
7449             if (sub[iBlock].algorithm() > 0) {
7450               for (int i = 0; i < numberRows2; i++)
7451                 solution[i] = -1.0e-5 * solution[i];
7452             } else {
7453               for (int i = 0; i < numberRows2; i++)
7454                 solution[i] = -solution[i];
7455             }
7456             first[iBlock]->transposeTimes(solution, elementAdd + start);
7457             for (int i = 0; i < numberRows2; i++)
7458               solution[i] = -solution[i];
7459             for (int i = 0; i < numberRows2; i++) {
7460               if (sub[iBlock].getRowStatus(i) == basic && fabs(solution[i]) < 1.0e-7)
7461                 solution[i] = 0.0;
7462               if (solution[i] > dualTolerance_) {
7463                 // at upper
7464                 if (saveUpper[i] > 1.0e20)
7465                   solution[i] = 0.0;
7466                 objValue += solution[i] * saveUpper[i];
7467               } else if (solution[i] < -dualTolerance_) {
7468                 // at lower
7469                 if (saveLower[i] < -1.0e20)
7470                   solution[i] = 0.0;
7471                 objValue += solution[i] * saveLower[i];
7472               } else {
7473                 solution[i] = 0.0;
7474               }
7475             }
7476             //objValue=-objValue;
7477             {
7478               int numberColumns2 = sub[iBlock].numberColumns();
7479               double *temp = new double[numberColumns2];
7480               memset(temp, 0, numberColumns2 * sizeof(double));
7481               sub[iBlock].clpMatrix()->transposeTimes(-1.0, solution, temp);
7482               double loX = 0.0;
7483               double upX = 0.0;
7484               const double *lower = sub[iBlock].columnLower();
7485               const double *upper = sub[iBlock].columnUpper();
7486               const double *primal = sub[iBlock].primalColumnSolution();
7487               for (int i = 0; i < numberColumns2; i++) {
7488                 double value = temp[i];
7489                 if (sub[iBlock].getColumnStatus(i) == basic && fabs(value) < 1.0e-7)
7490                   value = 0.0;
7491                 if (logLevel > 2) {
7492                   //if (sub[iBlock].getColumnStatus(i)!=basic&&
7493                   //  primal[i]>1.0e-5)
7494                   //printf("zz_inf %d has value %g\n",i,primal[i]);
7495                 }
7496                 if (sub[iBlock].getStatus(i) == atLowerBound || sub[iBlock].getStatus(i) == isFixed) {
7497                   loX += lower[i] * value;
7498                 } else if (sub[iBlock].getStatus(i) == atUpperBound) {
7499                   upX += upper[i] * value;
7500                 } else if (sub[iBlock].getStatus(i) == basic) {
7501                   double value2 = primal[i] * value;
7502                   if (logLevel > 2) {
7503                     if (fabs(value2) > 1.0e-3)
7504                       printf("Basic %d arrayval %g primal %g bounds %g %g\n",
7505                         i, value, primal[i],
7506                         lower[i], upper[i]);
7507                   }
7508                   if (value < 0.0) {
7509                     assert(primal[i] < lower[i]);
7510                     value2 = value * lower[i];
7511                   } else if (value > 0.0) {
7512                     assert(primal[i] > upper[i]);
7513                     if (primal[i] - upper[i] < 1.0e-3) {
7514                       if (logLevel > 2)
7515                         printf("small diff %g\n", primal[i] - upper[i]);
7516                       //handler_->message(CLP_GENERAL2, messages_)
7517                       //<< generalPrint
7518                       //<< CoinMessageEol;
7519                       //value=0.0;
7520                       //elementAdd[start+i]=0.0;
7521                     }
7522                     value2 = value * upper[i];
7523                   }
7524                   loX += value2;
7525                 }
7526               }
7527               objValue += loX + upX;
7528               if (logLevel > 2)
7529                 printf("Inf Offsets %g %g - new Objvalue %g\n", loX, upX, objValue);
7530 #define OBJ_OFFSET 0
7531 #if OBJ_OFFSET == 1
7532               objValue -= loX + upX;
7533               objValue -= loX + upX;
7534 #elif OBJ_OFFSET == 2
7535               objValue -= loX + upX;
7536               objValue = -objValue;
7537               objValue += loX + upX;
7538 #elif OBJ_OFFSET == 3
7539               objValue -= loX + upX;
7540               objValue = -objValue;
7541               objValue -= loX + upX;
7542 #endif
7543               if (iBlock == -3) {
7544                 ClpSimplex *temp = deBound(sub + iBlock);
7545                 //temp->allSlackBasis();
7546                 temp->primal();
7547                 // use ray
7548                 double *solution = temp->infeasibilityRay();
7549                 int numberRows2 = temp->numberRows();
7550                 // bug somewhere - if primal then flip
7551                 if (temp->algorithm_ > 0) {
7552                   for (int i = 0; i < numberRows2; i++)
7553                     solution[i] = -1.0e-5 * solution[i];
7554                 }
7555                 double objValue7 = 0.0;
7556                 const double *lower = temp->rowLower();
7557                 const double *upper = temp->rowUpper();
7558                 for (int i = 0; i < numberRows2; i++) {
7559                   if (solution[i] < -dualTolerance_) {
7560                     // at upper
7561                     assert(upper[i] < 1.0e30);
7562                     if (i < sub[iBlock].numberRows())
7563                       objValue7 += solution[i] * saveUpper[i];
7564                     else
7565                       objValue7 += solution[i] * upper[i];
7566                   } else if (solution[i] > dualTolerance_) {
7567                     // at lower
7568                     assert(lower[i] > -1.0e30);
7569                     if (i < sub[iBlock].numberRows())
7570                       objValue7 += solution[i] * saveLower[i];
7571                     else
7572                       objValue7 += solution[i] * lower[i];
7573                   }
7574                 }
7575                 sprintf(generalPrint, "new objValue %g - old %g", objValue7, objValue);
7576                 handler_->message(CLP_GENERAL2, messages_)
7577                   << generalPrint
7578                   << CoinMessageEol;
7579                 //objValue=-objValue7;
7580                 //loX=1.0e-2*objValue;
7581                 //first[iBlock]->transposeTimes(solution, elementAdd + start);
7582                 double *temp2 = new double[numberMasterColumns];
7583                 memset(temp2, 0, numberMasterColumns * sizeof(double));
7584                 first[iBlock]->transposeTimes(solution, temp2);
7585                 double *temp3 = elementAdd + start;
7586                 for (int i = 0; i < numberMasterColumns; i++) {
7587                   if (fabs(temp2[i] - temp3[i]) > 1.0e-4)
7588                     printf("** %d bound el %g nobound %g\n", i, temp3[i], temp2[i]);
7589                 }
7590                 memcpy(temp3, temp2, numberMasterColumns * sizeof(double));
7591                 delete[] temp2;
7592                 delete temp;
7593               }
7594               // relax slightly
7595               objValue += 1.0e-9 * fabs(loX);
7596               delete[] temp;
7597             }
7598             delete[] solution;
7599             // See if good infeas and pack down (signs on infeas,value changed)
7600             int number = start;
7601             //printf("Not changing objValue from %g to %g\n",objValue,trueOffset);
7602             //printf("Changing objValue from %g to %g\n",objValue,trueOffset);
7603             //objValue=trueOffset;
7604             double infeas = objValue;
7605             double smallest = 1.0e100;
7606             double largest = 0.0;
7607             for (int i = 0; i < numberMasterColumns; i++) {
7608               double value = -elementAdd[start + i];
7609               if (fabs(value) > 1.0e-12) {
7610                 infeas -= primal[i] * value;
7611                 smallest = CoinMin(smallest, fabs(value));
7612                 largest = CoinMax(largest, fabs(value));
7613                 indexColumnAdd[number] = i;
7614                 elementAdd[number++] = value;
7615               }
7616             }
7617             // if elements large or small then scale?
7618             if (largest > 1.0e8 || smallest < 1.0e-8) {
7619               sprintf(generalPrint, "For subproblem ray %d smallest - %g, largest %g - infeas %g",
7620                 iBlock, smallest, largest, infeas);
7621               handler_->message(CLP_GENERAL2, messages_)
7622                 << generalPrint
7623                 << CoinMessageEol;
7624             }
7625             if (smallest < 1.0e-12 * largest) {
7626               sprintf(generalPrint, "Removing small elements");
7627               handler_->message(CLP_GENERAL2, messages_)
7628                 << generalPrint
7629                 << CoinMessageEol;
7630               smallest = 1.0e-12 * largest;
7631               int number2 = number - 1;
7632               number = start;
7633               for (int i = start; i < number2; i++) {
7634                 double value = elementAdd[i];
7635                 if (fabs(value) > smallest) {
7636                   indexColumnAdd[number] = indexColumnAdd[i];
7637                   elementAdd[number++] = value;
7638                 }
7639               }
7640               indexColumnAdd[number] = numberMasterColumns + iBlock;
7641               elementAdd[number++] = -1.0;
7642             }
7643             if (infeas < -1.0e-6 || false) {
7644               double sum = 0.0;
7645               for (int i = start; i < number; i++) {
7646                 int iColumn = indexColumnAdd[i];
7647                 sum += primal[iColumn] * elementAdd[i];
7648               }
7649               if (logLevel > 2)
7650                 printf("Sum %g rhs %g\n", sum, objValue);
7651               if (logLevel > 1)
7652                 printf("Cut for block %d has %d elements (infeasibility)\n", iBlock, number - start);
7653               blockPrint[numberProposals] = iBlock;
7654               // take
7655               objective[numberProposals] = objValue;
7656               rowAdd[++numberProposals] = number;
7657               when[numberRowsGenerated] = iPass;
7658               whichBlock[numberRowsGenerated++] = iBlock;
7659             }
7660           } else {
7661             abort();
7662           }
7663         }
7664       } else {
7665         //printf("Can skip\n");
7666       }
7667       problemState[iBlock] &= ~4;
7668     }
7669     if (deletePrimal)
7670       delete[] primal;
7671     if (numberProposals) {
7672       sprintf(generalPrint, "%d cuts added with %d elements",
7673         numberProposals, rowAdd[numberProposals]);
7674       handler_->message(CLP_GENERAL, messages_)
7675         << generalPrint
7676         << CoinMessageEol;
7677       if (logLevel > 2) {
7678         for (int i = 0; i < numberProposals; i++) {
7679           printf("Cut %d block %d thetac %d ", i, blockPrint[i],
7680             blockPrint[i] + numberMasterColumns);
7681           int k = 0;
7682           for (CoinBigIndex j = rowAdd[i]; j < rowAdd[i + 1]; j++) {
7683             if (k == 12) {
7684               printf("\n");
7685               k = 0;
7686             }
7687             k++;
7688             printf("(%d,%g) ", indexColumnAdd[j], elementAdd[j]);
7689           }
7690           printf(" <= %g\n", objective[i]);
7691           //if (k)
7692           //printf("\n");
7693         }
7694       }
7695 #ifdef TEST_MODEL
7696       if (logLevel > 3) {
7697         const double *solution = goodModel.primalColumnSolution();
7698         const double *solution2 = masterModel.primalColumnSolution();
7699         for (int i = 0; i < numberProposals; i++) {
7700           double sum = 0.0;
7701           double sum2 = 0.0;
7702           for (int j = rowAdd[i]; j < rowAdd[i + 1]; j++) {
7703             int iColumn = indexColumnAdd[j];
7704             double value = elementAdd[j];
7705             sum += value * solution[iColumn];
7706             sum2 += value * solution2[iColumn];
7707           }
7708           if (sum2 < objective[i] - 1.0e-4) {
7709             sprintf(generalPrint, "Rhs for cut %d (from block %d) does not cutoff sum2 %g sum %g rhs %g)",
7710               i, blockPrint[i], sum2, sum, objective[i]);
7711             handler_->message(CLP_GENERAL2, messages_)
7712               << generalPrint
7713               << CoinMessageEol;
7714           }
7715 #define FIXUP_RHS 0
7716           if (sum > objective[i] + 1.0e-4) {
7717             sprintf(generalPrint, "Rhs for cut %d (from block %d) is %g too low (rhs is %g)",
7718               i, blockPrint[i], sum - objective[i], objective[i]);
7719             handler_->message(CLP_GENERAL2, messages_)
7720               << generalPrint
7721               << CoinMessageEol;
7722 #if FIXUP_RHS == 1 || FIXUP_RHS == 3
7723             objective[i] = sum;
7724 #endif
7725           } else if (sum < objective[i] - 1.0e-4) {
7726             sprintf(generalPrint, "Rhs for cut %d (from block %d) is %g ineffective (rhs is %g)",
7727               i, blockPrint[i], objective[i] - sum, objective[i]);
7728             handler_->message(CLP_GENERAL2, messages_)
7729               << generalPrint
7730               << CoinMessageEol;
7731 #if FIXUP_RHS == 2 || FIXUP_RHS == 3
7732             objective[i] = sum;
7733 #endif
7734           }
7735         }
7736       }
7737       if (logLevel > 3) {
7738         goodModel.addRows(numberProposals, NULL, objective,
7739           rowAdd, indexColumnAdd, elementAdd);
7740         goodModel.dual();
7741         if (goodModel.problemStatus() == 1 || goodModel.objectiveValue() > goodValue + 1.0e-5 * fabs(goodValue)) {
7742           int numberRows = goodModel.numberRows();
7743           int numberStart = numberRows - numberProposals;
7744           double *upper = goodModel.rowUpper();
7745           for (int iRow = numberStart; iRow < numberRows; iRow++) {
7746             upper[iRow] = COIN_DBL_MAX;
7747           }
7748           for (int iRow = numberStart; iRow < numberRows; iRow++) {
7749             upper[iRow] = objective[iRow - numberStart];
7750             goodModel.allSlackBasis(true);
7751             goodModel.dual();
7752             if (goodModel.problemStatus() == 1) {
7753               sprintf(generalPrint, "Cut %d makes infeasible - upper=%g",
7754                 iRow - numberStart, upper[iRow]);
7755               handler_->message(CLP_GENERAL, messages_)
7756                 << generalPrint
7757                 << CoinMessageEol;
7758             } else if (goodModel.objectiveValue() > goodValue + 1.0e-5 * fabs(goodValue)) {
7759               sprintf(generalPrint, "Cut %d makes too expensive - upper=%g",
7760                 iRow - numberStart, upper[iRow]);
7761               handler_->message(CLP_GENERAL, messages_)
7762                 << generalPrint
7763                 << CoinMessageEol;
7764               int iBlock = blockPrint[iRow - numberStart];
7765               ClpSimplex *temp = deBound(sub + iBlock);
7766               temp->allSlackBasis();
7767               temp->primal();
7768               // use ray
7769               double *solution = temp->infeasibilityRay();
7770               int numberRows2 = temp->numberRows();
7771               // bug somewhere - if primal then flip
7772               if (true) {
7773                 for (int i = 0; i < numberRows2; i++)
7774                   solution[i] = -1.0e-5 * solution[i];
7775               }
7776               double objValue = 0.0;
7777               const double *lower = temp->rowLower();
7778               const double *upper = temp->rowUpper();
7779               for (int i = 0; i < numberRows2; i++) {
7780                 if (solution[i] < -dualTolerance_) {
7781                   // at upper
7782                   assert(upper[i] < 1.0e30);
7783                   objValue += solution[i] * upper[i];
7784                 } else if (solution[i] > dualTolerance_) {
7785                   // at lower
7786                   assert(lower[i] > -1.0e30);
7787                   objValue += solution[i] * lower[i];
7788                 }
7789               }
7790               //printf("new objValue %g\n",objValue);
7791               int numberColumns2 = sub[iBlock].numberColumns();
7792               double *temp2 = new double[numberColumns2];
7793               memset(temp2, 0, numberColumns2 * sizeof(double));
7794               sub[iBlock].clpMatrix()->transposeTimes(1.0, sub[iBlock].infeasibilityRay(), temp2);
7795               double loX = 0.0;
7796               double upX = 0.0;
7797               const double *lower2 = sub[iBlock].columnLower();
7798               const double *upper2 = sub[iBlock].columnUpper();
7799               for (int i = 0; i < numberColumns2; i++) {
7800                 if (sub[iBlock].getColumnStatus(i) != basic && fabs(sub[iBlock].primalColumnSolution()[i]) > 1.0e-5)
7801                   printf("zz_inf %d has value %g\n", i, sub[iBlock].primalColumnSolution()[i]);
7802                 if (sub[iBlock].getStatus(i) == atLowerBound) {
7803                   loX += lower2[i] * temp2[i];
7804                 } else if (sub[iBlock].getStatus(i) == atUpperBound) {
7805                   upX += upper2[i] * temp2[i];
7806                 }
7807               }
7808               printf("Offsets %g %g\n", loX, upX);
7809               memset(temp2, 0, numberColumns2 * sizeof(double));
7810               temp->clpMatrix()->transposeTimes(1.0, solution, temp2);
7811               loX = 0.0;
7812               upX = 0.0;
7813               lower2 = temp->columnLower();
7814               upper2 = temp->columnUpper();
7815               for (int i = 0; i < numberColumns2; i++) {
7816                 if (temp->getColumnStatus(i) != basic && fabs(temp->primalColumnSolution()[i]) > 1.0e-5)
7817                   printf("zz_inf %d has value %g\n", i, temp->primalColumnSolution()[i]);
7818                 if (temp->getStatus(i) == atLowerBound) {
7819                   loX += lower2[i] * temp2[i];
7820                 } else if (temp->getStatus(i) == atUpperBound) {
7821                   upX += upper2[i] * temp2[i];
7822                 }
7823               }
7824               printf("Offsets %g %g\n", loX, upX);
7825               delete[] temp2;
7826               delete temp;
7827             }
7828             upper[iRow] = COIN_DBL_MAX;
7829           }
7830         }
7831         double objValue = goodModel.objectiveValue();
7832         const double *obj = goodModel.objective();
7833         const double *solution = goodModel.primalColumnSolution();
7834         double obj1 = 0.0;
7835         for (int i = 0; i < numberMasterColumns; i++)
7836           obj1 += obj[i] * solution[i];
7837         double obj2 = 0.0;
7838         for (int i = numberMasterColumns; i < numberMasterColumns + numberBlocks; i++)
7839           obj2 += obj[i] * solution[i];
7840         double obj3 = 0.0;
7841         for (int i = numberMasterColumns + numberBlocks; i < goodModel.numberColumns(); i++)
7842           obj3 += obj[i] * solution[i];
7843         //assert (fabs(goodValue-objValue)<1.0e-3+1.0e-7*fabs(goodValue));
7844         printf("XXXX good %g this %g difference %g - objs %g, %g, %g\n",
7845           goodValue, objValue, goodValue - objValue, obj1, obj2, obj3);
7846       }
7847 #endif
7848       masterModel.addRows(numberProposals, NULL, objective,
7849         rowAdd, indexColumnAdd, elementAdd);
7850     }
7851   }
7852   sprintf(generalPrint, "Time at end of Benders %.2f seconds", CoinCpuTime() - time1);
7853   handler_->message(CLP_GENERAL, messages_)
7854     << generalPrint
7855     << CoinMessageEol;
7856   delete[] problemState;
7857   for (int iBlock = 0; iBlock < numberBlocks; iBlock++) {
7858     delete[] modification[iBlock];
7859   }
7860   delete[] modification;
7861 #ifdef ADD_ARTIFICIALS
7862   delete[] originalSubColumns;
7863   for (int i = 0; i < numberBlocks; i++)
7864     delete[] saveObjective[i];
7865   delete[] saveObjective;
7866 #endif
7867   //masterModel.scaling(0);
7868   //masterModel.primal(1);
7869   if (!options.independentOption(1))
7870     loadProblem(*model);
7871   // now put back a good solution
7872   const double *columnSolution = masterModel.primalColumnSolution();
7873   double *fullColumnSolution = primalColumnSolution();
7874   const int *columnBack = model->coinBlock(masterBlock)->originalColumns();
7875   int numberColumns2 = model->coinBlock(masterBlock)->numberColumns();
7876   const int *rowBack = model->coinBlock(masterBlock)->originalRows();
7877   int numberRows2 = model->coinBlock(masterBlock)->numberRows();
7878 #ifndef NDEBUG
7879   for (int iColumn = 0; iColumn < numberColumns_; iColumn++)
7880     fullColumnSolution[iColumn] = COIN_DBL_MAX;
7881 #endif
7882   for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
7883     int kColumn = columnBack[iColumn];
7884     setColumnStatus(kColumn, masterModel.getColumnStatus(iColumn));
7885     fullColumnSolution[kColumn] = columnSolution[iColumn];
7886   }
7887   for (int iRow = 0; iRow < numberRows2; iRow++) {
7888     int kRow = rowBack[iRow];
7889     setRowStatus(kRow, masterModel.getRowStatus(iRow));
7890     //fullSolution[kRow]=solution[iRow];
7891   }
7892   for (iBlock = 0; iBlock < numberBlocks; iBlock++) {
7893     // move basis
7894     int kBlock = rowCounts[iBlock];
7895     const int *columnBack = model->coinBlock(kBlock)->originalColumns();
7896     int numberColumns2 = model->coinBlock(kBlock)->numberColumns();
7897     const int *rowBack = model->coinBlock(kBlock)->originalRows();
7898     int numberRows2 = model->coinBlock(kBlock)->numberRows();
7899     const double *subColumnSolution = sub[iBlock].primalColumnSolution();
7900     for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
7901       int kColumn = columnBack[iColumn];
7902       setColumnStatus(kColumn, sub[iBlock].getColumnStatus(iColumn));
7903 #ifndef NDEBUG
7904       assert(fullColumnSolution[kColumn] == COIN_DBL_MAX);
7905 #endif
7906       fullColumnSolution[kColumn] = subColumnSolution[iColumn];
7907     }
7908     for (int iRow = 0; iRow < numberRows2; iRow++) {
7909       int kRow = rowBack[iRow];
7910       setRowStatus(kRow, sub[iBlock].getRowStatus(iRow));
7911       //setStatus(kRow, atLowerBound);
7912     }
7913   }
7914 #ifndef NDEBUG
7915   for (int iColumn = 0; iColumn < numberColumns_; iColumn++)
7916     assert(fullColumnSolution[iColumn] != COIN_DBL_MAX);
7917 #endif
7918   double *fullSolution = primalRowSolution();
7919   CoinZeroN(fullSolution, numberRows_);
7920   times(1.0, fullColumnSolution, fullSolution);
7921   int numberRowBasic = 0;
7922 #ifndef NDEBUG
7923   int numberInfeasibilities = 0;
7924   double sumInfeasibilities = 0.0;
7925 #endif
7926   for (int iRow = 0; iRow < numberRows_; iRow++) {
7927     if (getRowStatus(iRow) == ClpSimplex::basic)
7928       numberRowBasic++;
7929 #ifndef NDEBUG
7930     if (fullSolution[iRow] < rowLower_[iRow] - primalTolerance_) {
7931       numberInfeasibilities++;
7932       sumInfeasibilities -= fullSolution[iRow] - rowLower_[iRow];
7933       if (getRowStatus(iRow) != basic)
7934         setRowStatus(iRow, superBasic);
7935     } else if (fullSolution[iRow] > rowUpper_[iRow] + primalTolerance_) {
7936       numberInfeasibilities++;
7937       sumInfeasibilities += fullSolution[iRow] - rowUpper_[iRow];
7938       if (getRowStatus(iRow) != basic)
7939         setRowStatus(iRow, superBasic);
7940     }
7941 #endif
7942   }
7943   int numberColumnBasic = 0;
7944   for (int iColumn = 0; iColumn < numberColumns_; iColumn++)
7945     if (getColumnStatus(iColumn) == ClpSimplex::basic)
7946       numberColumnBasic++;
7947   sprintf(generalPrint, "%d row basic %d col basic (total %d) - wanted %d",
7948     numberRowBasic, numberColumnBasic,
7949     numberRowBasic + numberColumnBasic, numberRows_);
7950   handler_->message(CLP_GENERAL2, messages_)
7951     << generalPrint
7952     << CoinMessageEol;
7953 #ifndef NDEBUG
7954   sprintf(generalPrint, "%d infeasibilities summing to %g",
7955     numberInfeasibilities, sumInfeasibilities);
7956   handler_->message(CLP_GENERAL2, messages_)
7957     << generalPrint
7958     << CoinMessageEol;
7959 #endif
7960   //for (int i=0;i<numberRows_;i++) setRowStatus(i,basic);
7961   sprintf(generalPrint, "Time before cleanup of full model %.2f seconds", CoinCpuTime() - time1);
7962   handler_->message(CLP_GENERAL, messages_)
7963     << generalPrint
7964     << CoinMessageEol;
7965 #ifdef ABC_INHERIT
7966   this->dealWithAbc(1, 1, true);
7967 #else
7968   this->primal(1);
7969 #endif
7970   sprintf(generalPrint, "Total time %.2f seconds", CoinCpuTime() - time1);
7971   handler_->message(CLP_GENERAL, messages_)
7972     << generalPrint
7973     << CoinMessageEol;
7974   delete[] rowCounts;
7975   //delete [] sol;
7976   //delete [] lower;
7977   //delete [] upper;
7978   delete[] whichBlock;
7979   delete[] when;
7980   delete[] rowAdd;
7981   delete[] columnAdd;
7982   delete[] elementAdd;
7983   delete[] objective;
7984   delete[] first;
7985   delete[] sub;
7986   return 0;
7987 }
7988 
7989 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
7990 */
7991