1 /* $Id$ */
2 // Copyright (C) 2002, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #if defined(_MSC_VER)
7 // Turn off compiler warning about long names
8 #pragma warning(disable : 4786)
9 #endif
10 
11 #include "CbcConfig.h"
12 
13 //#define THREAD_DEBUG
14 #include <string>
15 #include <cassert>
16 #include <cmath>
17 #include <cfloat>
18 
19 #include "CbcEventHandler.hpp"
20 
21 #include "OsiSolverInterface.hpp"
22 #include "OsiRowCutDebugger.hpp"
23 #include "CbcThread.hpp"
24 #include "CbcTree.hpp"
25 #include "CbcHeuristic.hpp"
26 #include "CbcCutGenerator.hpp"
27 #include "CbcModel.hpp"
28 #include "CbcFathom.hpp"
29 #include "CbcSimpleIntegerDynamicPseudoCost.hpp"
30 #include "ClpDualRowDantzig.hpp"
31 #include "OsiAuxInfo.hpp"
32 
33 #include "CoinTime.hpp"
34 #ifdef CBC_THREAD
35 /// Thread functions
36 static void *doNodesThread(void *voidInfo);
37 static void *doCutsThread(void *voidInfo);
38 static void *doHeurThread(void *voidInfo);
39 // Default Constructor
CbcSpecificThread()40 CbcSpecificThread::CbcSpecificThread()
41   : basePointer_(NULL)
42   , masterMutex_(NULL)
43   , locked_(false)
44 {
45 #ifdef CBC_PTHREAD
46   pthread_mutex_init(&mutex2_, NULL);
47   pthread_cond_init(&condition2_, NULL);
48   threadId_.status = 0;
49 #else
50 #endif
51 }
52 // Useful Constructor
CbcSpecificThread(CbcSpecificThread * master,pthread_mutex_t * masterMutex)53 CbcSpecificThread::CbcSpecificThread(CbcSpecificThread *master, pthread_mutex_t *masterMutex)
54   : basePointer_(master)
55   , masterMutex_(masterMutex)
56   , locked_(false)
57 
58 {
59 #ifdef CBC_PTHREAD
60   pthread_mutex_init(&mutex2_, NULL);
61   pthread_cond_init(&condition2_, NULL);
62   threadId_.status = 0;
63 #else
64 #endif
65 }
66 // Useful stuff
setUsefulStuff(CbcSpecificThread * master,void * & masterMutex)67 void CbcSpecificThread::setUsefulStuff(CbcSpecificThread *master, void *&masterMutex)
68 
69 {
70 #ifdef CBC_PTHREAD
71   basePointer_ = master;
72   if (masterMutex) {
73     masterMutex_ = reinterpret_cast< pthread_mutex_t * >(masterMutex);
74   } else {
75     // create master mutex
76     masterMutex_ = new pthread_mutex_t;
77     pthread_mutex_init(masterMutex_, NULL);
78     masterMutex = reinterpret_cast< void * >(masterMutex_);
79   }
80 #else
81 #endif
82 }
83 
~CbcSpecificThread()84 CbcSpecificThread::~CbcSpecificThread()
85 {
86 #ifdef CBC_PTHREAD
87   pthread_mutex_destroy(&mutex2_);
88   if (basePointer_ == this) {
89     pthread_mutex_destroy(masterMutex_);
90     delete masterMutex_;
91   }
92 #else
93 #endif
94 }
95 /*
96   Locks a thread if parallel so that stuff like cut pool
97   can be updated and/or used.
98 */
lockThread()99 void CbcSpecificThread::lockThread()
100 {
101 #ifdef CBC_PTHREAD
102   // Use master mutex
103   assert(basePointer_->masterMutex_ == masterMutex_);
104   pthread_mutex_lock(masterMutex_);
105 #else
106 #endif
107 }
108 /*
109   Unlocks a thread if parallel to say cut pool stuff not needed
110 */
unlockThread()111 void CbcSpecificThread::unlockThread()
112 {
113 #ifdef CBC_PTHREAD
114   // Use master mutex
115   pthread_mutex_unlock(masterMutex_);
116 #else
117 #endif
118 }
119 //  Locks a thread for testing whether to start etc
lockThread2(bool doAnyway)120 void CbcSpecificThread::lockThread2(bool doAnyway)
121 {
122   if (!locked_ || doAnyway) {
123 #ifdef CBC_PTHREAD
124     pthread_mutex_lock(&mutex2_);
125 #else
126 #endif
127     locked_ = true;
128   }
129 }
130 //  Unlocks a thread for testing whether to start etc
unlockThread2(bool doAnyway)131 void CbcSpecificThread::unlockThread2(bool doAnyway)
132 {
133   if (locked_ || doAnyway) {
134 #ifdef CBC_PTHREAD
135     pthread_mutex_unlock(&mutex2_);
136 #else
137 #endif
138     locked_ = false;
139   }
140 }
141 #ifdef HAVE_CLOCK_GETTIME
my_gettime(struct timespec * tp)142 inline int my_gettime(struct timespec *tp)
143 {
144   return clock_gettime(CLOCK_REALTIME, tp);
145 }
146 #else
147 #ifndef _MSC_VER
my_gettime(struct timespec * tp)148 inline int my_gettime(struct timespec *tp)
149 {
150   struct timeval tv;
151   int ret = gettimeofday(&tv, NULL);
152   tp->tv_sec = tv.tv_sec;
153   tp->tv_nsec = tv.tv_usec * 1000;
154   return ret;
155 }
156 #else
my_gettime(struct timespec * tp)157 inline int my_gettime(struct timespec *tp)
158 {
159   double t = CoinGetTimeOfDay();
160   tp->tv_sec = (int)floor(t);
161   tp->tv_nsec = (int)((tp->tv_sec - floor(t)) / 1000000.0);
162   return 0;
163 }
164 #endif
165 #endif
166 // Get time
getTime()167 static double getTime()
168 {
169   struct timespec absTime2;
170   my_gettime(&absTime2);
171   double time2 = static_cast<double>(absTime2.tv_sec)
172     + 1.0e-9 * static_cast< double >(absTime2.tv_nsec);
173   return time2;
174 }
175 // Timed wait in nanoseconds - if negative then seconds
timedWait(int time)176 void CbcSpecificThread::timedWait(int time)
177 {
178 
179 #ifdef CBC_PTHREAD
180   struct timespec absTime;
181   my_gettime(&absTime);
182   if (time > 0) {
183     absTime.tv_nsec += time;
184     if (absTime.tv_nsec >= 1000000000) {
185       absTime.tv_nsec -= 1000000000;
186       absTime.tv_sec++;
187     }
188   } else {
189     absTime.tv_sec -= time;
190   }
191   pthread_cond_timedwait(&condition2_, &mutex2_, &absTime);
192 #else
193 #endif
194 }
195 // Signal
signal()196 void CbcSpecificThread::signal()
197 {
198 #ifdef CBC_PTHREAD
199   pthread_cond_signal(&condition2_);
200 #else
201 #endif
202 }
203 // Actually starts a thread
startThread(void * (* routine)(void *),CbcThread * thread)204 void CbcSpecificThread::startThread(void *(*routine)(void *), CbcThread *thread)
205 {
206 #ifdef CBC_PTHREAD
207   pthread_create(&(threadId_.thr), NULL, routine, thread);
208   threadId_.status = 1;
209 #else
210 #endif
211 }
212 // Exits thread (from master)
exit()213 int CbcSpecificThread::exit()
214 {
215 #ifdef CBC_PTHREAD
216   pthread_cond_signal(&condition2_); // unlock
217   return pthread_join(threadId_.thr, NULL);
218 #else
219 #endif
220 }
221 // Exits thread
exitThread()222 void CbcSpecificThread::exitThread()
223 {
224 #ifdef CBC_PTHREAD
225   pthread_mutex_unlock(&mutex2_);
226   pthread_exit(NULL);
227 #else
228 #endif
229 }
230 // Get status
status() const231 int CbcSpecificThread::status() const
232 {
233 #ifdef CBC_PTHREAD
234   return static_cast< int >(threadId_.status);
235 #else
236 #endif
237 }
238 // Set status
setStatus(int value)239 void CbcSpecificThread::setStatus(int value)
240 {
241 #ifdef CBC_PTHREAD
242   threadId_.status = value;
243 #else
244 #endif
245 }
246 // Parallel heuristics
parallelHeuristics(int numberThreads,int sizeOfData,void * argBundle)247 void parallelHeuristics(int numberThreads,
248   int sizeOfData,
249   void *argBundle)
250 {
251   Coin_pthread_t *threadId = new Coin_pthread_t[numberThreads];
252   char *args = reinterpret_cast< char * >(argBundle);
253   for (int i = 0; i < numberThreads; i++) {
254     pthread_create(&(threadId[i].thr), NULL, doHeurThread,
255       args + i * sizeOfData);
256   }
257   // now wait
258   for (int i = 0; i < numberThreads; i++) {
259     pthread_join(threadId[i].thr, NULL);
260   }
261   delete[] threadId;
262 }
263 // End of specific thread stuff
264 
265 /// Default constructor
CbcThread()266 CbcThread::CbcThread()
267   : baseModel_(NULL)
268   , thisModel_(NULL)
269   , node_(NULL)
270   , // filled in every time
271   createdNode_(NULL)
272   , // filled in every time on return
273   returnCode_(-1)
274   , // -1 available, 0 busy, 1 finished , 2??
275   timeLocked_(0.0)
276   , timeWaitingToLock_(0.0)
277   , timeWaitingToStart_(0.0)
278   , timeInThread_(0.0)
279   , numberTimesLocked_(0)
280   , numberTimesUnlocked_(0)
281   , numberTimesWaitingToStart_(0)
282   , dantzigState_(0)
283   , // 0 unset, -1 waiting to be set, 1 set
284   locked_(false)
285   , nDeleteNode_(0)
286   , delNode_(NULL)
287   , maxDeleteNode_(0)
288   , nodesThisTime_(0)
289   , iterationsThisTime_(0)
290   , deterministic_(0)
291 {
292 }
gutsOfDelete()293 void CbcThread::gutsOfDelete()
294 {
295   baseModel_ = NULL;
296   thisModel_ = NULL;
297   node_ = NULL;
298   createdNode_ = NULL;
299   delNode_ = NULL;
300 }
301 // Destructor
~CbcThread()302 CbcThread::~CbcThread()
303 {
304 }
305 // Fills in useful stuff
setUsefulStuff(CbcModel * model,int deterministic,CbcModel * baseModel,CbcThread * master,void * & masterMutex)306 void CbcThread::setUsefulStuff(CbcModel *model, int deterministic, CbcModel *baseModel,
307   CbcThread *master,
308   void *&masterMutex)
309 {
310   baseModel_ = baseModel;
311   thisModel_ = model;
312   deterministic_ = deterministic;
313   threadStuff_.setUsefulStuff(&master->threadStuff_, masterMutex);
314   node_ = NULL;
315   createdNode_ = NULL;
316   master_ = master;
317   returnCode_ = -1;
318   timeLocked_ = 0.0;
319   timeWaitingToLock_ = 0.0;
320   timeWaitingToStart_ = 0.0;
321   timeInThread_ = 0.0;
322   numberTimesLocked_ = 0;
323   numberTimesUnlocked_ = 0;
324   numberTimesWaitingToStart_ = 0;
325   dantzigState_ = 0; // 0 unset, -1 waiting to be set, 1 set
326   locked_ = false;
327   delNode_ = NULL;
328   maxDeleteNode_ = 0;
329   nDeleteNode_ = 0;
330   nodesThisTime_ = 0;
331   iterationsThisTime_ = 0;
332   if (model != baseModel) {
333     // thread
334     thisModel_->setInfoInChild(-3, this);
335     if (deterministic_ >= 0)
336       thisModel_->moveToModel(baseModel, -1);
337     if (deterministic == -1)
338       threadStuff_.startThread(doCutsThread, this);
339     else
340       threadStuff_.startThread(doNodesThread, this);
341   }
342 }
343 /*
344   Locks a thread if parallel so that stuff like cut pool
345   can be updated and/or used.
346 */
lockThread()347 void CbcThread::lockThread()
348 {
349   if (!locked_) {
350     double time2 = getTime();
351     threadStuff_.lockThread();
352     locked_ = true;
353     timeWhenLocked_ = getTime();
354     timeWaitingToLock_ += timeWhenLocked_ - time2;
355     ;
356     numberTimesLocked_++;
357 #ifdef THREAD_DEBUG
358     lockCount_++;
359 #if THREAD_DEBUG > 1
360     if (threadNumber_ == -1)
361       printf("locking master %d\n", lockCount_);
362     else
363       printf("locking thread %d %d\n", threadNumber_, lockCount_);
364 #endif
365   } else {
366     if (threadNumber_ == -1)
367       printf("master already locked %d\n", lockCount_);
368     else
369       printf("thread already locked %d %d\n", threadNumber_, lockCount_);
370 #endif
371   }
372 }
373 /*
374   Unlocks a thread if parallel
375 */
unlockThread()376 void CbcThread::unlockThread()
377 {
378   if (locked_) {
379     locked_ = false;
380     threadStuff_.unlockThread();
381     double time2 = getTime();
382     timeLocked_ += time2 - timeWhenLocked_;
383     numberTimesUnlocked_++;
384 #ifdef THREAD_DEBUG
385 #if THREAD_DEBUG > 1
386     if (threadNumber_ == -1)
387       printf("unlocking master %d\n", lockCount_);
388     else
389       printf("unlocking thread %d %d\n", threadNumber_, lockCount_);
390 #endif
391   } else {
392     if (threadNumber_ == -1)
393       printf("master already unlocked %d\n", lockCount_);
394     else
395       printf("thread already unlocked %d %d\n", threadNumber_, lockCount_);
396 #endif
397   }
398 }
399 /* Wait for child to have return code NOT == to currentCode
400    type - 0 timed wait
401    1 wait
402    returns true if return code changed */
wait(int type,int currentCode)403 bool CbcThread::wait(int type, int currentCode)
404 {
405   if (!type) {
406     // just timed wait
407     master_->threadStuff_.lockThread2();
408     master_->threadStuff_.timedWait(1000000);
409     master_->threadStuff_.unlockThread2();
410   } else {
411     // wait until return code changes
412     while (returnCode_ == currentCode) {
413       threadStuff_.signal();
414       master_->threadStuff_.lockThread2();
415       master_->threadStuff_.timedWait(1000000);
416       master_->threadStuff_.unlockThread2();
417     }
418   }
419   return (returnCode_ != currentCode);
420 }
421 #if 0
422 pthread_cond_signal(&condition2_);
423 -
424 if (!locked_)
425 {
426     pthread_mutex_lock (&mutex2_);
427     locked_ = true;
428 }
429 -
430 pthread_cond_timedwait(&condition2_, &mutex2_, &absTime);
431 -
432 if (locked_)
433 {
434     pthread_mutex_unlock (&mutex2_);
435     locked_ = false;
436 }
437 #endif
438 // Waits until returnCode_ goes to zero
waitThread()439 void CbcThread::waitThread()
440 {
441   double time = getTime();
442   threadStuff_.lockThread2();
443   while (returnCode_) {
444     threadStuff_.timedWait(-10); // 10 seconds
445   }
446   timeWaitingToStart_ += getTime() - time;
447   numberTimesWaitingToStart_++;
448 }
449 // Just wait for so many nanoseconds
waitNano(int time)450 void CbcThread::waitNano(int time)
451 {
452   threadStuff_.lockThread2();
453   threadStuff_.timedWait(time);
454   threadStuff_.unlockThread2();
455 }
456 // Signal child to carry on
signal()457 void CbcThread::signal()
458 {
459   threadStuff_.signal();
460 }
461 // Lock from master with mutex2 and signal before lock
lockFromMaster()462 void CbcThread::lockFromMaster()
463 {
464   threadStuff_.signal();
465   master_->threadStuff_.lockThread2(true);
466 }
467 // Unlock from master with mutex2 and signal after unlock
unlockFromMaster()468 void CbcThread::unlockFromMaster()
469 {
470   master_->threadStuff_.unlockThread2(true); // unlock anyway
471   threadStuff_.signal();
472 }
473 // Lock from thread with mutex2 and signal before lock
lockFromThread()474 void CbcThread::lockFromThread()
475 {
476   master_->threadStuff_.signal();
477   threadStuff_.lockThread2();
478 }
479 // Unlock from thread with mutex2 and signal after unlock
unlockFromThread()480 void CbcThread::unlockFromThread()
481 {
482   master_->threadStuff_.signal();
483   threadStuff_.unlockThread2();
484 }
485 // Exits thread (from master)
exit()486 int CbcThread::exit()
487 {
488   return threadStuff_.exit();
489 }
490 // Exits thread
exitThread()491 void CbcThread::exitThread()
492 {
493   threadStuff_.exitThread();
494 }
495 // Default constructor
CbcBaseModel()496 CbcBaseModel::CbcBaseModel()
497   : numberThreads_(0)
498   , children_(NULL)
499   , type_(0)
500   , threadCount_(NULL)
501   , threadModel_(NULL)
502   , numberObjects_(0)
503   , saveObjects_(NULL)
504   , defaultParallelIterations_(400)
505   , defaultParallelNodes_(2)
506 {
507 }
508 // Constructor with model
CbcBaseModel(CbcModel & model,int type)509 CbcBaseModel::CbcBaseModel(CbcModel &model, int type)
510   : children_(NULL)
511   , type_(type)
512   , threadCount_(NULL)
513   , threadModel_(NULL)
514   , numberObjects_(0)
515   , saveObjects_(NULL)
516   , defaultParallelIterations_(400)
517   , defaultParallelNodes_(2)
518 {
519   numberThreads_ = model.getNumberThreads();
520   if (numberThreads_) {
521     children_ = new CbcThread[numberThreads_ + 1];
522     // Do a partial one for base model
523     void *mutex_main = NULL;
524     children_[numberThreads_].setUsefulStuff(&model, type_, &model,
525       children_ + numberThreads_, mutex_main);
526 #ifdef THREAD_DEBUG
527     children_[numberThreads_].threadNumber_ = -1;
528     children_[numberThreads_].lockCount_ = 0;
529 #endif
530     threadCount_ = new int[numberThreads_];
531     CoinZeroN(threadCount_, numberThreads_);
532     threadModel_ = new CbcModel *[numberThreads_ + 1];
533     memset(threadStats_, 0, sizeof(threadStats_));
534     if (type_ > 0) {
535       // May need for deterministic
536       numberObjects_ = model.numberObjects();
537       saveObjects_ = new OsiObject *[numberObjects_];
538       for (int i = 0; i < numberObjects_; i++) {
539         saveObjects_[i] = model.object(i)->clone();
540       }
541     }
542     // we don't want a strategy object
543     CbcStrategy *saveStrategy = model.strategy();
544     model.setStrategy(NULL);
545     for (int i = 0; i < numberThreads_; i++) {
546       //threadModel_[i] = new CbcModel(model, true);
547       threadModel_[i] = model.clone(true);
548       threadModel_[i]->synchronizeHandlers(1);
549 #ifdef COIN_HAS_CLP
550       // Solver may need to know about model
551       CbcModel *thisModel = threadModel_[i];
552       CbcOsiSolver *solver = dynamic_cast< CbcOsiSolver * >(thisModel->solver());
553       if (solver)
554         solver->setCbcModel(thisModel);
555 #endif
556       children_[i].setUsefulStuff(threadModel_[i], type_, &model,
557         children_ + numberThreads_, mutex_main);
558 #ifdef THREAD_DEBUG
559       children_[i].threadNumber_ = i;
560       children_[i].lockCount_ = 0;
561 #endif
562     }
563     model.setStrategy(saveStrategy);
564   }
565 }
566 // Stop threads
stopThreads(int type)567 void CbcBaseModel::stopThreads(int type)
568 {
569   CbcModel *baseModel = children_[0].baseModel();
570   if (type < 0) {
571     // max nodes ?
572     bool finished = false;
573     while (!finished) {
574       finished = true;
575       for (int i = 0; i < numberThreads_; i++) {
576         if (abs(children_[i].returnCode()) != 1) {
577           children_[i].wait(1, 0);
578           finished = false;
579         }
580       }
581     }
582     for (int i = 0; i < numberThreads_; i++) {
583       baseModel->incrementExtra(threadModel_[i]->getExtraNodeCount(),
584         threadModel_[i]->numberExtraIterations(),
585         threadModel_[i]->getFathomCount());
586       threadModel_[i]->zeroExtra();
587     }
588     return;
589   }
590   for (int i = 0; i < numberThreads_; i++) {
591     children_[i].wait(1, 0);
592     assert(children_[i].returnCode() == -1);
593     baseModel->incrementExtra(threadModel_[i]->getExtraNodeCount(),
594       threadModel_[i]->numberExtraIterations(),
595       threadModel_[i]->getFathomCount());
596     threadModel_[i]->setInfoInChild(-2, NULL);
597     children_[i].setReturnCode(0);
598     children_[i].exit();
599     children_[i].setStatus(0);
600   }
601   // delete models and solvers
602   for (int i = 0; i < numberThreads_; i++) {
603     threadModel_[i]->setInfoInChild(type_, NULL);
604     delete threadModel_[i];
605   }
606   delete[] children_;
607   delete[] threadModel_;
608   for (int i = 0; i < numberObjects_; i++)
609     delete saveObjects_[i];
610   delete[] saveObjects_;
611   children_ = NULL;
612   threadModel_ = NULL;
613   saveObjects_ = NULL;
614   numberObjects_ = 0;
615   numberThreads_ = 0;
616 }
617 // Wait for threads in tree
waitForThreadsInTree(int type)618 int CbcBaseModel::waitForThreadsInTree(int type)
619 {
620   CbcModel *baseModel = children_[0].baseModel();
621   int anyLeft = 0;
622   // May be able to combine parts later
623   if (type == 0) {
624     bool locked = true;
625 #ifdef COIN_DEVELOP
626     printf("empty\n");
627 #endif
628     // may still be outstanding nodes
629     while (true) {
630       int iThread;
631       for (iThread = 0; iThread < numberThreads_; iThread++) {
632         if (children_[iThread].status()) {
633           if (children_[iThread].returnCode() == 0) {
634             break;
635           }
636         }
637       }
638       if (iThread < numberThreads_) {
639 #ifdef COIN_DEVELOP
640         printf("waiting for thread %d code 0\n", iThread);
641 #endif
642         unlockThread();
643         locked = false;
644         children_[iThread].wait(1, 0);
645         assert(children_[iThread].returnCode() == 1);
646         threadModel_[iThread]->moveToModel(baseModel, 1);
647 #ifdef THREAD_PRINT
648         printf("off thread2 %d node %x\n", iThread, children_[iThread].node());
649 #endif
650         children_[iThread].setNode(NULL);
651         anyLeft = 1;
652         assert(children_[iThread].returnCode() == 1);
653         if (children_[iThread].dantzigState() == -1) {
654           // 0 unset, -1 waiting to be set, 1 set
655           children_[iThread].setDantzigState(1);
656           CbcModel *model = children_[iThread].thisModel();
657           OsiClpSolverInterface *clpSolver2
658             = dynamic_cast< OsiClpSolverInterface * >(model->solver());
659           assert(clpSolver2);
660           ClpSimplex *simplex2 = clpSolver2->getModelPtr();
661           ClpDualRowDantzig dantzig;
662           simplex2->setDualRowPivotAlgorithm(dantzig);
663         }
664         // say available
665         children_[iThread].setReturnCode(-1);
666         threadStats_[4]++;
667 #ifdef COIN_DEVELOP
668         printf("thread %d code now -1\n", iThread);
669 #endif
670         break;
671       } else {
672 #ifdef COIN_DEVELOP
673         printf("no threads at code 0 \n");
674 #endif
675         // now check if any have just finished
676         for (iThread = 0; iThread < numberThreads_; iThread++) {
677           if (children_[iThread].status()) {
678             if (children_[iThread].returnCode() == 1)
679               break;
680           }
681         }
682         if (iThread < numberThreads_) {
683           unlockThread();
684           locked = false;
685           threadModel_[iThread]->moveToModel(baseModel, 1);
686 #ifdef THREAD_PRINT
687           printf("off thread3 %d node %x\n", iThread, children_[iThread].node());
688 #endif
689           children_[iThread].setNode(NULL);
690           anyLeft = 1;
691           assert(children_[iThread].returnCode() == 1);
692           // say available
693           children_[iThread].setReturnCode(-1);
694           threadStats_[4]++;
695 #ifdef COIN_DEVELOP
696           printf("thread %d code now -1\n", iThread);
697 #endif
698           break;
699         }
700       }
701       if (!baseModel->tree()->empty()) {
702 #ifdef COIN_DEVELOP
703         printf("tree not empty!!!!!!\n");
704 #endif
705         if (locked)
706           unlockThread();
707         return 1;
708         break;
709       }
710       for (iThread = 0; iThread < numberThreads_; iThread++) {
711         if (children_[iThread].status()) {
712           if (children_[iThread].returnCode() != -1) {
713             printf("bad end of tree\n");
714             abort();
715           }
716         }
717       }
718       break;
719     }
720 #ifdef COIN_DEVELOP
721     printf("finished ************\n");
722 #endif
723     if (locked)
724       unlockThread();
725     return anyLeft;
726   } else if (type == 1) {
727     // normal
728     double cutoff = baseModel->getCutoff();
729     CbcNode *node = baseModel->tree()->bestNode(cutoff);
730     // Possible one on tree worse than cutoff
731     if (!node || node->objectiveValue() > cutoff)
732       return 1;
733     threadStats_[0]++;
734     //need to think
735     int iThread;
736     // Start one off if any available
737     for (iThread = 0; iThread < numberThreads_; iThread++) {
738       if (children_[iThread].returnCode() == -1) {
739         break;
740       }
741     }
742     if (iThread < numberThreads_) {
743       children_[iThread].setNode(node);
744 #ifdef THREAD_PRINT
745       printf("empty thread %d node %x\n", iThread, children_[iThread].node());
746 #endif
747       assert(children_[iThread].returnCode() == -1);
748       // say in use
749       threadModel_[iThread]->moveToModel(baseModel, 0);
750       // This has to be AFTER moveToModel
751       children_[iThread].setReturnCode(0);
752       children_[iThread].signal();
753       threadCount_[iThread]++;
754     }
755     lockThread();
756     // see if any finished
757     for (iThread = 0; iThread < numberThreads_; iThread++) {
758       if (children_[iThread].returnCode() > 0)
759         break;
760     }
761     unlockThread();
762     if (iThread < numberThreads_) {
763       threadModel_[iThread]->moveToModel(baseModel, 1);
764 #ifdef THREAD_PRINT
765       printf("off thread4 %d node %x\n", iThread, children_[iThread].node());
766 #endif
767       children_[iThread].setNode(NULL);
768       anyLeft = 1;
769       assert(children_[iThread].returnCode() == 1);
770       // say available
771       children_[iThread].setReturnCode(-1);
772       // carry on
773       threadStats_[3]++;
774     } else {
775       // Start one off if any available
776       for (iThread = 0; iThread < numberThreads_; iThread++) {
777         if (children_[iThread].returnCode() == -1)
778           break;
779       }
780       if (iThread < numberThreads_) {
781         // If any on tree get
782         if (!baseModel->tree()->empty()) {
783           //node = baseModel->tree()->bestNode(cutoff) ;
784           //assert (node);
785           threadStats_[1]++;
786           return 1; // ** get another node
787         }
788       }
789       // wait (for debug could sleep and use test)
790       bool finished = false;
791       while (!finished) {
792         double time = getTime();
793         children_[numberThreads_].wait(0, 0);
794         children_[numberThreads_].incrementTimeInThread(getTime() - time);
795         for (iThread = 0; iThread < numberThreads_; iThread++) {
796           if (children_[iThread].returnCode() > 0) {
797             finished = true;
798             break;
799           } else if (children_[iThread].returnCode() == 0) {
800             children_[iThread].signal(); // unlock
801           }
802         }
803       }
804       assert(iThread < numberThreads_);
805       // move information to model
806       threadModel_[iThread]->moveToModel(baseModel, 1);
807       anyLeft = 1;
808 #ifdef THREAD_PRINT
809       printf("off thread %d node %x\n", iThread, children_[iThread].node());
810 #endif
811       children_[iThread].setNode(NULL);
812       assert(children_[iThread].returnCode() == 1);
813       // say available
814       children_[iThread].setReturnCode(-1);
815     }
816     // carry on
817     threadStats_[2]++;
818     for (int iThread = 0; iThread < numberThreads_; iThread++) {
819       if (children_[iThread].status()) {
820         if (children_[iThread].returnCode() != -1) {
821           anyLeft = 1;
822           break;
823         }
824       }
825     }
826     return anyLeft;
827   } else if (type == 2) {
828     if (!baseModel->tree()->empty()) {
829       // max nodes ?
830       bool finished = false;
831       while (!finished) {
832         finished = true;
833         for (int iThread = 0; iThread < numberThreads_; iThread++) {
834           if (children_[iThread].returnCode() == 0) {
835             double time = getTime();
836             children_[numberThreads_].wait(0, 0);
837             children_[numberThreads_].incrementTimeInThread(getTime() - time);
838             finished = false;
839             children_[iThread].signal(); // unlock
840           }
841         }
842       }
843     }
844     int i;
845     // do statistics
846     // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation
847     double time = 0.0;
848     for (i = 0; i < numberThreads_; i++)
849       time += children_[i].timeInThread();
850     bool goodTimer = time < (baseModel->getCurrentSeconds());
851     for (i = 0; i < numberThreads_; i++) {
852       while (children_[i].returnCode() == 0) {
853         children_[i].signal();
854         double time = getTime();
855         children_[numberThreads_].wait(0, 0);
856         children_[numberThreads_].incrementTimeInThread(getTime() - time);
857       }
858       children_[i].lockFromMaster();
859       threadModel_[i]->setNumberThreads(0); // say exit
860       if (children_[i].deterministic() > 0)
861         delete[] children_[i].delNode();
862       if (children_[i].node()) {
863         delete children_[i].node();
864         children_[i].setNode(NULL);
865       }
866       children_[i].setReturnCode(0);
867       children_[i].unlockFromMaster();
868 #ifndef NDEBUG
869       int returnCode = children_[i].exit();
870       assert(!returnCode);
871 #else
872       children_[i].exit();
873 #endif
874       children_[i].setStatus(0);
875       //else
876       threadModel_[i]->moveToModel(baseModel, 2);
877       assert(children_[i].numberTimesLocked() == children_[i].numberTimesUnlocked());
878       baseModel->messageHandler()->message(CBC_THREAD_STATS, baseModel->messages())
879         << "Thread";
880       baseModel->messageHandler()->printing(true)
881         << i << threadCount_[i] << children_[i].timeWaitingToStart();
882       baseModel->messageHandler()->printing(goodTimer) << children_[i].timeInThread();
883       baseModel->messageHandler()->printing(false) << 0.0;
884       baseModel->messageHandler()->printing(true) << children_[i].numberTimesLocked()
885                                                   << children_[i].timeLocked() << children_[i].timeWaitingToLock()
886                                                   << CoinMessageEol;
887     }
888     assert(children_[numberThreads_].numberTimesLocked() == children_[numberThreads_].numberTimesUnlocked());
889     baseModel->messageHandler()->message(CBC_THREAD_STATS, baseModel->messages())
890       << "Main thread";
891     baseModel->messageHandler()->printing(false) << 0 << 0 << 0.0;
892     baseModel->messageHandler()->printing(false) << 0.0;
893     baseModel->messageHandler()->printing(true) << children_[numberThreads_].timeInThread();
894     baseModel->messageHandler()->printing(true) << children_[numberThreads_].numberTimesLocked()
895                                                 << children_[numberThreads_].timeLocked() << children_[numberThreads_].timeWaitingToLock()
896                                                 << CoinMessageEol;
897     // delete models (here in case some point to others)
898     for (i = 0; i < numberThreads_; i++) {
899       // make sure handler will be deleted
900       threadModel_[i]->setDefaultHandler(true);
901       //delete threadModel_[i];
902     }
903   } else {
904     abort();
905   }
906   return 0;
907 }
waitForThreadsInCuts(int type,OsiCuts * eachCuts,int whichGenerator)908 void CbcBaseModel::waitForThreadsInCuts(int type, OsiCuts *eachCuts,
909   int whichGenerator)
910 {
911   if (type == 0) {
912     // cuts while doing
913     bool finished = false;
914     int iThread = -1;
915     // see if any available
916     for (iThread = 0; iThread < numberThreads_; iThread++) {
917       if (children_[iThread].returnCode()) {
918         finished = true;
919         break;
920       } else if (children_[iThread].returnCode() == 0) {
921         children_[iThread].signal();
922       }
923     }
924     while (!finished) {
925       children_[numberThreads_].waitNano(1000000);
926       for (iThread = 0; iThread < numberThreads_; iThread++) {
927         if (children_[iThread].returnCode() > 0) {
928           finished = true;
929           break;
930         } else if (children_[iThread].returnCode() == 0) {
931           children_[iThread].signal();
932         }
933       }
934     }
935     assert(iThread < numberThreads_);
936     assert(children_[iThread].returnCode());
937     // Use dantzigState to signal which generator
938     children_[iThread].setDantzigState(whichGenerator);
939     // and delNode for eachCuts
940     children_[iThread].fakeDelNode(reinterpret_cast< CbcNode ** >(eachCuts));
941     // allow to start
942     children_[iThread].setReturnCode(0);
943     children_[iThread].signal();
944   } else if (type == 1) {
945     // cuts - finish up
946     for (int iThread = 0; iThread < numberThreads_; iThread++) {
947       if (children_[iThread].returnCode() == 0) {
948         bool finished = false;
949         while (!finished) {
950           children_[numberThreads_].wait(0, 0);
951           if (children_[iThread].returnCode() > 0) {
952             finished = true;
953             break;
954             //#ifndef NEW_STYLE_PTHREAD
955             //} else if (children_[iThread].returnCode_ == 0) {
956             //pthread_cond_signal(&children_[iThread].threadStuff_.condition2_); // unlock
957             //#endif
958           }
959         }
960       }
961       assert(children_[iThread].returnCode());
962       // say available
963       children_[iThread].setReturnCode(-1);
964       //delete threadModel_[iThread]->solver();
965       //threadModel_[iThread]->setSolver(NULL);
966     }
967   } else {
968     abort();
969   }
970 }
971 // Returns pointer to master thread
972 CbcThread *
masterThread() const973 CbcBaseModel::masterThread() const
974 {
975   return children_ + numberThreads_;
976 }
977 
978 // Split model and do work in deterministic parallel
deterministicParallel()979 void CbcBaseModel::deterministicParallel()
980 {
981   CbcModel *baseModel = children_[0].baseModel();
982   for (int i = 0; i < numberThreads_; i++)
983     threadCount_[i]++;
984   int saveTreeSize = baseModel->tree()->size();
985   // For now create threadModel - later modify splitModel
986   CbcModel **threadModel = new CbcModel *[numberThreads_];
987   int iThread;
988   for (iThread = 0; iThread < numberThreads_; iThread++)
989     threadModel[iThread] = children_[iThread].thisModel();
990 
991   int nAffected = baseModel->splitModel(numberThreads_, threadModel, defaultParallelNodes_);
992   // do all until finished
993   for (iThread = 0; iThread < numberThreads_; iThread++) {
994     // obviously tune
995     children_[iThread].setNDeleteNode(defaultParallelIterations_);
996   }
997   // Save current state
998   int iObject;
999   OsiObject **object = baseModel->objects();
1000   for (iObject = 0; iObject < numberObjects_; iObject++) {
1001     saveObjects_[iObject]->updateBefore(object[iObject]);
1002   }
1003   //#define FAKE_PARALLEL
1004 #ifndef FAKE_PARALLEL
1005   for (iThread = 0; iThread < numberThreads_; iThread++) {
1006     children_[iThread].setReturnCode(0);
1007     children_[iThread].signal();
1008   }
1009   // wait
1010   bool finished = false;
1011   double time = getTime();
1012   while (!finished) {
1013     children_[numberThreads_].waitNano(1000000); // millisecond
1014     finished = true;
1015     for (iThread = 0; iThread < numberThreads_; iThread++) {
1016       if (children_[iThread].returnCode() <= 0) {
1017         finished = false;
1018       }
1019     }
1020   }
1021   for (iThread = 0; iThread < numberThreads_; iThread++)
1022     children_[iThread].setReturnCode(-1);
1023 #else
1024   // wait
1025   bool finished = false;
1026   double time = getTime();
1027   for (iThread = 0; iThread < numberThreads_; iThread++) {
1028     children_[iThread].setReturnCode(0);
1029     children_[iThread].signal();
1030     while (!finished) {
1031       children_[numberThreads_].waitNano(1000000); // millisecond
1032       finished = (children_[iThread].returnCode() > 0);
1033     }
1034     children_[iThread].setReturnCode(-1);
1035     finished = false;
1036   }
1037 #endif
1038   children_[numberThreads_].incrementTimeInThread(getTime() - time);
1039   // Unmark marked
1040   for (int i = 0; i < nAffected; i++) {
1041     baseModel->walkback()[i]->unmark();
1042   }
1043   int iModel;
1044   double scaleFactor = 1.0;
1045   for (iModel = 0; iModel < numberThreads_; iModel++) {
1046     //printf("model %d tree size %d\n",iModel,threadModel[iModel]->baseModel->tree()->size());
1047     if (saveTreeSize > 4 * numberThreads_ * defaultParallelNodes_) {
1048       if (!threadModel[iModel]->tree()->size()) {
1049         scaleFactor *= 1.05;
1050       }
1051     }
1052     threadModel[iModel]->moveToModel(baseModel, 11);
1053     // Update base model
1054     OsiObject **threadObject = threadModel[iModel]->objects();
1055     for (iObject = 0; iObject < numberObjects_; iObject++) {
1056       object[iObject]->updateAfter(threadObject[iObject], saveObjects_[iObject]);
1057     }
1058   }
1059   if (scaleFactor != 1.0) {
1060     int newNumber = static_cast< int >(defaultParallelNodes_ * scaleFactor + 0.5001);
1061     if (newNumber * 2 < defaultParallelIterations_) {
1062       if (defaultParallelNodes_ == 1)
1063         newNumber = 2;
1064       if (newNumber != defaultParallelNodes_) {
1065         char general[200];
1066         sprintf(general, "Changing tree size from %d to %d",
1067           defaultParallelNodes_, newNumber);
1068         baseModel->messageHandler()->message(CBC_GENERAL,
1069           baseModel->messages())
1070           << general << CoinMessageEol;
1071         defaultParallelNodes_ = newNumber;
1072       }
1073     }
1074   }
1075   delete[] threadModel;
1076 }
1077 // Destructor
~CbcBaseModel()1078 CbcBaseModel::~CbcBaseModel()
1079 {
1080   delete[] threadCount_;
1081 #if 1
1082   for (int i = 0; i < numberThreads_; i++)
1083     delete threadModel_[i];
1084   delete[] threadModel_;
1085   delete[] children_;
1086 #endif
1087   for (int i = 0; i < numberObjects_; i++)
1088     delete saveObjects_[i];
1089   delete[] saveObjects_;
1090 }
1091 // Sets Dantzig state in children
setDantzigState()1092 void CbcBaseModel::setDantzigState()
1093 {
1094   for (int i = 0; i < numberThreads_; i++) {
1095     children_[i].setDantzigState(-1);
1096   }
1097 }
doNodesThread(void * voidInfo)1098 static void *doNodesThread(void *voidInfo)
1099 {
1100   CbcThread *stuff = reinterpret_cast< CbcThread * >(voidInfo);
1101   CbcModel *thisModel = stuff->thisModel();
1102   CbcModel *baseModel = stuff->baseModel();
1103   while (true) {
1104     stuff->waitThread();
1105     //printf("start node %x\n",stuff->node);
1106     int mode = thisModel->getNumberThreads();
1107     if (mode) {
1108       // normal
1109       double time2 = CoinCpuTime();
1110       assert(stuff->returnCode() == 0);
1111       if (thisModel->parallelMode() >= 0) {
1112         CbcNode *node = stuff->node();
1113         //assert (node->nodeInfo());
1114         CbcNode *createdNode = stuff->createdNode();
1115         // try and see if this has slipped through
1116         if (node) {
1117           thisModel->doOneNode(baseModel, node, createdNode);
1118         } else {
1119           //printf("null node\n");
1120           createdNode = NULL;
1121         }
1122         stuff->setNode(node);
1123         stuff->setCreatedNode(createdNode);
1124         stuff->setReturnCode(1);
1125       } else {
1126         assert(!stuff->node());
1127         assert(!stuff->createdNode());
1128         int numberIterations = stuff->nDeleteNode();
1129         int nDeleteNode = 0;
1130         int maxDeleteNode = stuff->maxDeleteNode();
1131         CbcNode **delNode = stuff->delNode();
1132         int returnCode = 1;
1133         // this should be updated by heuristics strong branching etc etc
1134         assert(numberIterations > 0);
1135         thisModel->setNumberThreads(0);
1136         int nodesThisTime = thisModel->getNodeCount();
1137         int iterationsThisTime = thisModel->getIterationCount();
1138         int strongThisTime = thisModel->numberStrongIterations();
1139         thisModel->setStopNumberIterations(thisModel->getIterationCount() + numberIterations);
1140         int numberColumns = thisModel->getNumCols();
1141         int *used = CoinCopyOfArray(thisModel->usedInSolution(), numberColumns);
1142         int numberSolutions = thisModel->getSolutionCount();
1143         while (true) {
1144           if (thisModel->tree()->empty()) {
1145             returnCode = 1 + 1;
1146 #ifdef CLP_INVESTIGATE_2
1147             printf("%x tree empty - time %18.6f\n", thisModel, CoinGetTimeOfDay() - 1.2348e9);
1148 #endif
1149             break;
1150           }
1151 #define NODE_ITERATIONS 2
1152           int nodesNow = thisModel->getNodeCount();
1153           int iterationsNow = thisModel->getIterationCount();
1154           int strongNow = thisModel->numberStrongIterations();
1155           bool exit1 = (NODE_ITERATIONS * ((nodesNow - nodesThisTime) + ((strongNow - strongThisTime) >> 1)) + (iterationsNow - iterationsThisTime) > numberIterations);
1156           //bool exit2 =(thisModel->getIterationCount()>thisModel->getStopNumberIterations()) ;
1157           //assert (exit1==exit2);
1158           if (exit1 && nodesNow - nodesThisTime >= 10) {
1159             // out of loop
1160             //printf("out of loop\n");
1161 #ifdef CLP_INVESTIGATE3
1162             printf("%x tree %d nodes left, done %d and %d its - time %18.6f\n", thisModel,
1163               thisModel->tree()->size(), nodesNow - nodesThisTime,
1164               iterationsNow - iterationsThisTime, CoinGetTimeOfDay() - 1.2348e9);
1165 #endif
1166             break;
1167           }
1168           double cutoff = thisModel->getCutoff();
1169           CbcNode *node = thisModel->tree()->bestNode(cutoff);
1170           // Possible one on tree worse than cutoff
1171           if (!node)
1172             continue;
1173           CbcNode *createdNode = NULL;
1174           // Do real work of node
1175           thisModel->doOneNode(NULL, node, createdNode);
1176           assert(createdNode);
1177           if (!createdNode->active()) {
1178             delete createdNode;
1179           } else {
1180             // Say one more pointing to this **** postpone if marked
1181             node->nodeInfo()->increment();
1182             thisModel->tree()->push(createdNode);
1183           }
1184           if (node->active()) {
1185             assert(node->nodeInfo());
1186             if (node->nodeInfo()->numberBranchesLeft()) {
1187               thisModel->tree()->push(node);
1188             } else {
1189               node->setActive(false);
1190             }
1191           } else {
1192             if (node->nodeInfo()) {
1193               if (!node->nodeInfo()->numberBranchesLeft())
1194                 node->nodeInfo()->allBranchesGone(); // can clean up
1195               // So will delete underlying stuff
1196               node->setActive(true);
1197             }
1198             if (nDeleteNode == maxDeleteNode) {
1199               maxDeleteNode = (3 * maxDeleteNode) / 2 + 10;
1200               stuff->setMaxDeleteNode(maxDeleteNode);
1201               stuff->setDelNode(new CbcNode *[maxDeleteNode]);
1202               for (int i = 0; i < nDeleteNode; i++)
1203                 stuff->delNode()[i] = delNode[i];
1204               delete[] delNode;
1205               delNode = stuff->delNode();
1206             }
1207             delNode[nDeleteNode++] = node;
1208           }
1209         }
1210         // end of this sub-tree
1211         int *usedA = thisModel->usedInSolution();
1212         for (int i = 0; i < numberColumns; i++) {
1213           usedA[i] -= used[i];
1214         }
1215         delete[] used;
1216         thisModel->setSolutionCount(thisModel->getSolutionCount() - numberSolutions);
1217         stuff->setNodesThisTime(thisModel->getNodeCount() - nodesThisTime);
1218         stuff->setIterationsThisTime(thisModel->getIterationCount() - iterationsThisTime);
1219         stuff->setNDeleteNode(nDeleteNode);
1220         stuff->setReturnCode(returnCode);
1221         thisModel->setNumberThreads(mode);
1222       }
1223       //printf("end node %x\n",stuff->node);
1224       stuff->unlockFromThread();
1225       stuff->incrementTimeInThread(CoinCpuTime() - time2);
1226     } else {
1227       // exit
1228       break;
1229     }
1230   }
1231   //printf("THREAD exiting\n");
1232   stuff->exitThread();
1233   return NULL;
1234 }
doHeurThread(void * voidInfo)1235 static void *doHeurThread(void *voidInfo)
1236 {
1237   typedef struct {
1238     double solutionValue;
1239     CbcModel *model;
1240     double *solution;
1241     int foundSol;
1242   } argBundle;
1243   argBundle *stuff = reinterpret_cast< argBundle * >(voidInfo);
1244   stuff->foundSol = stuff->model->heuristic(0)->solution(stuff->solutionValue,
1245     stuff->solution);
1246   return NULL;
1247 }
doCutsThread(void * voidInfo)1248 static void *doCutsThread(void *voidInfo)
1249 {
1250   CbcThread *stuff = reinterpret_cast< CbcThread * >(voidInfo);
1251   CbcModel *thisModel = stuff->thisModel();
1252   while (true) {
1253     stuff->waitThread();
1254     //printf("start node %x\n",stuff->node);
1255     int mode = thisModel->getNumberThreads();
1256     if (mode) {
1257       // normal
1258       assert(stuff->returnCode() == 0);
1259       int fullScan = thisModel->getNodeCount() == 0 ? 1 : 0; //? was >0
1260       CbcCutGenerator *generator = thisModel->cutGenerator(stuff->dantzigState());
1261       generator->refreshModel(thisModel);
1262       OsiCuts *cuts = reinterpret_cast< OsiCuts * >(stuff->delNode());
1263       OsiSolverInterface *thisSolver = thisModel->solver();
1264       generator->generateCuts(*cuts, fullScan, thisSolver, NULL);
1265       stuff->setReturnCode(1);
1266       stuff->unlockFromThread();
1267     } else {
1268       // exit
1269       break;
1270     }
1271   }
1272   stuff->exitThread();
1273   return NULL;
1274 }
1275 // Split up nodes - returns number of CbcNodeInfo's affected
splitModel(int numberModels,CbcModel ** model,int numberNodes)1276 int CbcModel::splitModel(int numberModels, CbcModel **model,
1277   int numberNodes)
1278 {
1279   int iModel;
1280   int i;
1281   for (iModel = 0; iModel < numberModels; iModel++) {
1282     CbcModel *otherModel = model[iModel];
1283     otherModel->moveToModel(this, 10);
1284     assert(!otherModel->tree()->size());
1285     otherModel->tree()->resetNodeNumbers();
1286     otherModel->bestPossibleObjective_ = bestPossibleObjective_;
1287     otherModel->sumChangeObjective1_ = sumChangeObjective1_;
1288     otherModel->sumChangeObjective2_ = sumChangeObjective2_;
1289     int numberColumns = solver_->getNumCols();
1290     if (otherModel->bestSolution_) {
1291       assert(bestSolution_);
1292       memcpy(otherModel->bestSolution_, bestSolution_, numberColumns * sizeof(double));
1293     } else if (bestSolution_) {
1294       otherModel->bestSolution_ = CoinCopyOfArray(bestSolution_, numberColumns);
1295     }
1296     otherModel->globalCuts_ = globalCuts_;
1297     otherModel->numberSolutions_ = numberSolutions_;
1298     otherModel->numberHeuristicSolutions_ = numberHeuristicSolutions_;
1299     otherModel->numberNodes_ = numberNodes_;
1300     otherModel->numberIterations_ = numberIterations_;
1301 #ifdef JJF_ZERO
1302     if (maximumNumberCuts_ > otherModel->maximumNumberCuts_) {
1303       otherModel->maximumNumberCuts_ = maximumNumberCuts_;
1304       delete[] otherModel->addedCuts_;
1305       otherModel->addedCuts_ = new CbcCountRowCut *[maximumNumberCuts_];
1306     }
1307     if (maximumDepth_ > otherModel->maximumDepth_) {
1308       otherModel->maximumDepth_ = maximumDepth_;
1309       delete[] otherModel->walkback_;
1310       otherModel->walkback_ = new CbcNodeInfo *[maximumDepth_];
1311     }
1312 #endif
1313     otherModel->currentNumberCuts_ = currentNumberCuts_;
1314     if (otherModel->usedInSolution_) {
1315       assert(usedInSolution_);
1316       memcpy(otherModel->usedInSolution_, usedInSolution_, numberColumns * sizeof(int));
1317     } else if (usedInSolution_) {
1318       otherModel->usedInSolution_ = CoinCopyOfArray(usedInSolution_, numberColumns);
1319     }
1320     /// ??? tree_;
1321     // Need flag (stopNumberIterations_>0?) which says don't update cut etc counts
1322     for (i = 0; i < numberObjects_; i++) {
1323       otherModel->object_[i]->updateBefore(object_[i]);
1324     }
1325     otherModel->maximumDepthActual_ = maximumDepthActual_;
1326     // Real cuts are in node info
1327     otherModel->numberOldActiveCuts_ = numberOldActiveCuts_;
1328     otherModel->numberNewCuts_ = numberNewCuts_;
1329     otherModel->numberStrongIterations_ = numberStrongIterations_;
1330   }
1331   double cutoff = getCutoff();
1332   int nAffected = 0;
1333   while (!tree_->empty()) {
1334     for (iModel = 0; iModel < numberModels; iModel++) {
1335       if (tree_->empty())
1336         break;
1337       CbcModel *otherModel = model[iModel];
1338       CbcNode *node = tree_->bestNode(cutoff);
1339       CbcNodeInfo *nodeInfo = node->nodeInfo();
1340       assert(nodeInfo);
1341       if (!nodeInfo->marked()) {
1342         //while (nodeInfo&&!nodeInfo->marked()) {
1343         if (nAffected == maximumDepth_) {
1344           redoWalkBack();
1345         }
1346         nodeInfo->mark();
1347         //nodeInfo->incrementCuts(1000000);
1348         walkback_[nAffected++] = nodeInfo;
1349         //nodeInfo = nodeInfo->parent() ;
1350         //}
1351       }
1352       // Make node join otherModel
1353       OsiBranchingObject *bobj = node->modifiableBranchingObject();
1354       CbcBranchingObject *cbcobj = dynamic_cast< CbcBranchingObject * >(bobj);
1355       //assert (cbcobj);
1356       if (cbcobj) {
1357         CbcObject *object = cbcobj->object();
1358         assert(object);
1359         int position = object->position();
1360         assert(position >= 0);
1361         assert(object_[position] == object);
1362         CbcObject *objectNew = dynamic_cast< CbcObject * >(otherModel->object_[position]);
1363         cbcobj->setOriginalObject(objectNew);
1364       }
1365       otherModel->tree_->push(node);
1366     }
1367     numberNodes--;
1368     if (!numberNodes)
1369       break;
1370   }
1371   return nAffected;
1372 }
1373 // Start threads
startSplitModel(int)1374 void CbcModel::startSplitModel(int /*numberIterations*/)
1375 {
1376   abort();
1377 }
1378 // Merge models
mergeModels(int,CbcModel **,int)1379 void CbcModel::mergeModels(int /*numberModel*/, CbcModel ** /*model*/,
1380   int /*numberNodes*/)
1381 {
1382   abort();
1383 }
1384 /* Move/copy information from one model to another
1385    -1 - initial setup
1386    0 - from base model
1387    1 - to base model (and reset)
1388    2 - add in final statistics etc (and reset so can do clean destruction)
1389    10 - from base model (deterministic)
1390    11 - to base model (deterministic)
1391 */
moveToModel(CbcModel * baseModel,int mode)1392 void CbcModel::moveToModel(CbcModel *baseModel, int mode)
1393 {
1394 #ifdef THREAD_DEBUG
1395   {
1396     CbcThread *stuff = reinterpret_cast< CbcThread * >(masterThread_);
1397     if (stuff)
1398       printf("mode %d node_ %p createdNode_ %p - stuff %p\n",
1399         mode, stuff->node(), stuff->createdNode(), stuff);
1400     else
1401       printf("mode %d null stuff\n", mode);
1402   }
1403 #endif
1404   if (mode == 0) {
1405     setCutoff(baseModel->getCutoff());
1406     bestObjective_ = baseModel->bestObjective_;
1407     //assert (!baseModel->globalCuts_.sizeRowCuts());
1408     if (numberSolutions_ < baseModel->numberSolutions_ && baseModel->bestSolution_) {
1409       int numberColumns = solver_->getNumCols();
1410       if (!bestSolution_)
1411         bestSolution_ = new double[numberColumns];
1412       memcpy(bestSolution_, baseModel->bestSolution_,
1413         numberColumns * sizeof(double));
1414       numberSolutions_ = baseModel->numberSolutions_;
1415     }
1416     stateOfSearch_ = baseModel->stateOfSearch_;
1417     numberNodes_ = baseModel->numberNodes_;
1418     numberIterations_ = baseModel->numberIterations_;
1419     numberFixedAtRoot_ = numberIterations_; // for statistics
1420     numberSolves_ = 0;
1421     phase_ = baseModel->phase_;
1422     assert(!nextRowCut_);
1423     nodeCompare_ = baseModel->nodeCompare_;
1424     tree_ = baseModel->tree_;
1425     assert(!subTreeModel_);
1426     //branchingMethod_ = NULL; // need something but what
1427     numberOldActiveCuts_ = baseModel->numberOldActiveCuts_;
1428     cutModifier_ = NULL;
1429     assert(!analyzeResults_);
1430     CbcThread *stuff = reinterpret_cast< CbcThread * >(masterThread_);
1431     assert(stuff);
1432     //if (stuff)
1433     stuff->setCreatedNode(NULL);
1434     // ?? searchStrategy_;
1435     searchStrategy_ = baseModel->searchStrategy_;
1436     stuff->saveStuff()[0] = searchStrategy_;
1437     stateOfSearch_ = baseModel->stateOfSearch_;
1438     stuff->saveStuff()[1] = stateOfSearch_;
1439     for (int iObject = 0; iObject < numberObjects_; iObject++) {
1440       CbcSimpleIntegerDynamicPseudoCost *dynamicObject = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[iObject]);
1441       if (dynamicObject) {
1442         CbcSimpleIntegerDynamicPseudoCost *baseObject = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(baseModel->object_[iObject]);
1443         assert(baseObject);
1444         dynamicObject->copySome(baseObject);
1445       }
1446     }
1447     // add new global cuts
1448     CbcRowCuts *baseGlobal = baseModel->globalCuts();
1449     CbcRowCuts *thisGlobal = globalCuts();
1450     int baseNumberCuts = baseGlobal->sizeRowCuts();
1451     int thisNumberCuts = thisGlobal->sizeRowCuts();
1452     for (int i = thisNumberCuts; i < baseNumberCuts; i++) {
1453       thisGlobal->addCutIfNotDuplicate(*baseGlobal->cut(i));
1454     }
1455     numberGlobalCutsIn_ = baseNumberCuts;
1456   } else if (mode == 1) {
1457     lockThread();
1458     CbcThread *stuff = reinterpret_cast< CbcThread * >(masterThread_);
1459     assert(stuff);
1460     // deal with hotstart
1461     static int lastHotDepth = -1;
1462     if (baseModel->hotstartSolution_) {
1463       if (!baseModel->numberNodes_) {
1464         lastHotDepth = -1;
1465       } else if (stuff->node()) {
1466         if (stuff->node()->depth() >= lastHotDepth) {
1467           lastHotDepth = stuff->node()->depth();
1468           //printf("hotdepth %d\n",lastHotDepth);
1469         } else {
1470           // switch off
1471           delete[] hotstartSolution_;
1472           hotstartSolution_ = NULL;
1473           delete[] baseModel->hotstartSolution_;
1474           baseModel->hotstartSolution_ = NULL;
1475           //printf("off hotstart\n");
1476         }
1477       }
1478     }
1479     //stateOfSearch_
1480     if (stuff->saveStuff()[0] != searchStrategy_) {
1481 #ifdef COIN_DEVELOP
1482       printf("changing searchStrategy from %d to %d\n",
1483         baseModel->searchStrategy_, searchStrategy_);
1484 #endif
1485       baseModel->searchStrategy_ = searchStrategy_;
1486     }
1487     if (stuff->saveStuff()[1] != stateOfSearch_) {
1488 #ifdef COIN_DEVELOP
1489       printf("changing stateOfSearch from %d to %d\n",
1490         baseModel->stateOfSearch_, stateOfSearch_);
1491 #endif
1492       baseModel->stateOfSearch_ = stateOfSearch_;
1493     }
1494     if (numberUpdateItems_) {
1495       for (int i = 0; i < numberUpdateItems_; i++) {
1496         CbcObjectUpdateData *update = updateItems_ + i;
1497         int objectNumber = update->objectNumber_;
1498         CbcObject *object = dynamic_cast< CbcObject * >(baseModel->object_[objectNumber]);
1499         if (object)
1500           object->updateInformation(*update);
1501       }
1502       numberUpdateItems_ = 0;
1503     }
1504     if (eventHappened_)
1505       baseModel->eventHappened_ = true;
1506     baseModel->numberNodes_++;
1507     baseModel->numberIterations_ += numberIterations_ - numberFixedAtRoot_;
1508     baseModel->numberSolves_ += numberSolves_;
1509     if (stuff->node())
1510       baseModel->tree_->push(stuff->node());
1511     if (stuff->createdNode())
1512       baseModel->tree_->push(stuff->createdNode());
1513     // add new global cuts to base and take off
1514     CbcRowCuts *baseGlobal = baseModel->globalCuts();
1515     CbcRowCuts *thisGlobal = globalCuts();
1516     int thisNumberCuts = thisGlobal->sizeRowCuts();
1517     for (int i = thisNumberCuts - 1; i >= numberGlobalCutsIn_; i--) {
1518       baseGlobal->addCutIfNotDuplicate(*thisGlobal->cut(i), thisGlobal->cut(i)->whichRow());
1519       thisGlobal->eraseRowCut(i);
1520     }
1521     //thisGlobal->truncate(numberGlobalCutsIn_);
1522     numberGlobalCutsIn_ = 999999;
1523     unlockThread();
1524   } else if (mode == 2) {
1525     baseModel->sumChangeObjective1_ += sumChangeObjective1_;
1526     baseModel->sumChangeObjective2_ += sumChangeObjective2_;
1527     //baseModel->numberIterations_ += numberIterations_;
1528     for (int iGenerator = 0; iGenerator < numberCutGenerators_; iGenerator++) {
1529       CbcCutGenerator *generator = baseModel->generator_[iGenerator];
1530       CbcCutGenerator *generator2 = generator_[iGenerator];
1531       generator->incrementNumberTimesEntered(generator2->numberTimesEntered());
1532       generator->incrementNumberCutsInTotal(generator2->numberCutsInTotal());
1533       generator->incrementNumberCutsActive(generator2->numberCutsActive());
1534       generator->incrementTimeInCutGenerator(generator2->timeInCutGenerator());
1535     }
1536     if (parallelMode() >= 0)
1537       nodeCompare_ = NULL;
1538     baseModel->maximumDepthActual_ = CoinMax(baseModel->maximumDepthActual_, maximumDepthActual_);
1539     baseModel->numberDJFixed_ += numberDJFixed_;
1540     baseModel->numberStrongIterations_ += numberStrongIterations_;
1541     int i;
1542     for (i = 0; i < 3; i++)
1543       baseModel->strongInfo_[i] += strongInfo_[i];
1544     if (parallelMode() >= 0) {
1545       walkback_ = NULL;
1546       lastNodeInfo_ = NULL;
1547       lastNumberCuts_ = NULL;
1548       lastCut_ = NULL;
1549       //addedCuts_ = NULL;
1550       tree_ = NULL;
1551     }
1552     if ((moreSpecialOptions2_ & 32) != 0)
1553       delete eventHandler_;
1554     eventHandler_ = NULL;
1555     delete solverCharacteristics_;
1556     solverCharacteristics_ = NULL;
1557     bool newMethod = (baseModel->branchingMethod_ && baseModel->branchingMethod_->chooseMethod());
1558     if (newMethod) {
1559       // new method - we were using base models
1560       numberObjects_ = 0;
1561       object_ = NULL;
1562     }
1563   } else if (mode == -1) {
1564     delete eventHandler_;
1565     if ((moreSpecialOptions2_ & 32) == 0 || !baseModel->eventHandler_) {
1566       eventHandler_ = baseModel->eventHandler_;
1567     } else {
1568       eventHandler_ = baseModel->eventHandler_->clone();
1569       eventHandler_->setModel(this);
1570     }
1571     assert(!statistics_);
1572     assert(baseModel->solverCharacteristics_);
1573     solverCharacteristics_ = new OsiBabSolver(*baseModel->solverCharacteristics_);
1574     solverCharacteristics_->setSolver(solver_);
1575     setMaximumNodes(COIN_INT_MAX);
1576     if (parallelMode() >= 0) {
1577       delete[] walkback_;
1578       //delete [] addedCuts_;
1579       walkback_ = NULL;
1580       //addedCuts_ = NULL;
1581       delete[] lastNodeInfo_;
1582       lastNodeInfo_ = NULL;
1583       delete[] lastNumberCuts_;
1584       lastNumberCuts_ = NULL;
1585       delete[] lastCut_;
1586       lastCut_ = NULL;
1587       delete tree_;
1588       tree_ = NULL;
1589       delete nodeCompare_;
1590       nodeCompare_ = NULL;
1591     } else {
1592       delete tree_;
1593       tree_ = new CbcTree();
1594       tree_->setComparison(*nodeCompare_);
1595     }
1596     delete continuousSolver_;
1597     continuousSolver_ = baseModel->continuousSolver_->clone();
1598     // make sure solvers have correct message handler
1599     solver_->passInMessageHandler(handler_);
1600     continuousSolver_->passInMessageHandler(handler_);
1601     bool newMethod = (baseModel->branchingMethod_ && baseModel->branchingMethod_->chooseMethod());
1602     if (newMethod) {
1603       // new method uses solver - but point to base model
1604       // We may update an object in wrong order - shouldn't matter?
1605       numberObjects_ = baseModel->numberObjects_;
1606       if (parallelMode() >= 0) {
1607         object_ = baseModel->object_;
1608       } else {
1609         printf("*****WARNING - fix testosi option\n");
1610         object_ = baseModel->object_;
1611       }
1612     }
1613     int i;
1614     for (i = 0; i < numberHeuristics_; i++) {
1615       delete heuristic_[i];
1616       heuristic_[i] = baseModel->heuristic_[i]->clone();
1617       heuristic_[i]->setModelOnly(this);
1618     }
1619     for (i = 0; i < numberCutGenerators_; i++) {
1620       bool generatorTiming = baseModel->generator_[i]->timing();
1621       delete generator_[i];
1622       generator_[i] = new CbcCutGenerator(*baseModel->generator_[i]);
1623       // zero out timing
1624       if (generatorTiming)
1625 	generator_[i]->setTiming(true);
1626       // refreshModel was overkill as thought too many rows
1627       if (generator_[i]->needsRefresh())
1628         generator_[i]->refreshModel(this);
1629       else
1630         generator_[i]->setModel(this);
1631     }
1632   } else if (mode == 10) {
1633     setCutoff(baseModel->getCutoff());
1634     bestObjective_ = baseModel->bestObjective_;
1635     //assert (!baseModel->globalCuts_.sizeRowCuts());
1636     numberSolutions_ = baseModel->numberSolutions_;
1637     assert(usedInSolution_);
1638     assert(baseModel->usedInSolution_);
1639     memcpy(usedInSolution_, baseModel->usedInSolution_, solver_->getNumCols() * sizeof(int));
1640     stateOfSearch_ = baseModel->stateOfSearch_;
1641     //numberNodes_ = baseModel->numberNodes_;
1642     //numberIterations_ = baseModel->numberIterations_;
1643     //numberFixedAtRoot_ = numberIterations_; // for statistics
1644     phase_ = baseModel->phase_;
1645     assert(!nextRowCut_);
1646     delete nodeCompare_;
1647     nodeCompare_ = baseModel->nodeCompare_->clone();
1648     tree_->setComparison(*nodeCompare_);
1649     assert(!subTreeModel_);
1650     //branchingMethod_ = NULL; // need something but what
1651     numberOldActiveCuts_ = baseModel->numberOldActiveCuts_;
1652     cutModifier_ = NULL;
1653     assert(!analyzeResults_);
1654     CbcThread *stuff = reinterpret_cast< CbcThread * >(masterThread_);
1655     assert(stuff);
1656     //if (stuff)
1657     stuff->setCreatedNode(NULL);
1658     // ?? searchStrategy_;
1659     searchStrategy_ = baseModel->searchStrategy_;
1660     stuff->saveStuff()[0] = searchStrategy_;
1661     stateOfSearch_ = baseModel->stateOfSearch_;
1662     stuff->saveStuff()[1] = stateOfSearch_;
1663     OsiObject **baseObject = baseModel->object_;
1664     for (int iObject = 0; iObject < numberObjects_; iObject++) {
1665       object_[iObject]->updateBefore(baseObject[iObject]);
1666     }
1667     //delete [] stuff->nodeCount;
1668     //stuff->nodeCount = new int [baseModel->maximumDepth_+1];
1669   } else if (mode == 11) {
1670     if (parallelMode() < 0) {
1671       // from deterministic
1672       CbcThread *stuff = reinterpret_cast< CbcThread * >(masterThread_);
1673       assert(stuff);
1674       // Move solution etc
1675       // might as well mark all including continuous
1676       int numberColumns = solver_->getNumCols();
1677       for (int i = 0; i < numberColumns; i++) {
1678         baseModel->usedInSolution_[i] += usedInSolution_[i];
1679         //usedInSolution_[i]=0;
1680       }
1681       baseModel->numberSolutions_ += numberSolutions_;
1682       if (bestObjective_ < baseModel->bestObjective_ && bestObjective_ < baseModel->getCutoff()) {
1683         baseModel->bestObjective_ = bestObjective_;
1684         int numberColumns = solver_->getNumCols();
1685         if (!baseModel->bestSolution_)
1686           baseModel->bestSolution_ = new double[numberColumns];
1687         CoinCopyN(bestSolution_, numberColumns, baseModel->bestSolution_);
1688         baseModel->setCutoff(getCutoff());
1689         baseModel->handler_->message(CBC_ROUNDING, messages_)
1690           << bestObjective_
1691           << "heuristic"
1692           << baseModel->numberIterations_
1693           << baseModel->numberNodes_ << getCurrentSeconds()
1694           << CoinMessageEol;
1695       }
1696       //stateOfSearch_
1697       if (stuff->saveStuff()[0] != searchStrategy_) {
1698 #ifdef COIN_DEVELOP
1699         printf("changing searchStrategy from %d to %d\n",
1700           baseModel->searchStrategy_, searchStrategy_);
1701 #endif
1702         baseModel->searchStrategy_ = searchStrategy_;
1703       }
1704       if (stuff->saveStuff()[1] != stateOfSearch_) {
1705 #ifdef COIN_DEVELOP
1706         printf("changing stateOfSearch from %d to %d\n",
1707           baseModel->stateOfSearch_, stateOfSearch_);
1708 #endif
1709         baseModel->stateOfSearch_ = stateOfSearch_;
1710       }
1711       int i;
1712       if (eventHappened_)
1713         baseModel->eventHappened_ = true;
1714       baseModel->numberNodes_ += stuff->nodesThisTime();
1715       baseModel->numberIterations_ += stuff->iterationsThisTime();
1716       double cutoff = baseModel->getCutoff();
1717       while (!tree_->empty()) {
1718         CbcNode *node = tree_->bestNode(COIN_DBL_MAX);
1719         if (node->objectiveValue() < cutoff) {
1720           assert(node->nodeInfo());
1721           // Make node join correctly
1722           OsiBranchingObject *bobj = node->modifiableBranchingObject();
1723           CbcBranchingObject *cbcobj = dynamic_cast< CbcBranchingObject * >(bobj);
1724           if (cbcobj) {
1725             CbcObject *object = cbcobj->object();
1726             assert(object);
1727             int position = object->position();
1728             assert(position >= 0);
1729             assert(object_[position] == object);
1730             CbcObject *objectNew = dynamic_cast< CbcObject * >(baseModel->object_[position]);
1731             cbcobj->setOriginalObject(objectNew);
1732           }
1733           baseModel->tree_->push(node);
1734         } else {
1735           delete node;
1736         }
1737       }
1738       for (i = 0; i < stuff->nDeleteNode(); i++) {
1739         //printf("CbcNode %x stuff delete\n",stuff->delNode[i]);
1740         delete stuff->delNode()[i];
1741       }
1742     }
1743   } else {
1744     abort();
1745   }
1746 }
1747 // Generate one round of cuts - parallel mode
parallelCuts(CbcBaseModel * master,OsiCuts & theseCuts,CbcNode *,OsiCuts & slackCuts,int lastNumberCuts)1748 int CbcModel::parallelCuts(CbcBaseModel *master, OsiCuts &theseCuts,
1749   CbcNode * /*node*/, OsiCuts &slackCuts, int lastNumberCuts)
1750 {
1751   /*
1752       Is it time to scan the cuts in order to remove redundant cuts? If so, set
1753       up to do it.
1754     */
1755   int fullScan = 0;
1756   if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_ & 256) != 0) {
1757     fullScan = 1;
1758     if (!numberNodes_ || (specialOptions_ & 256) != 0)
1759       fullScan = 2;
1760     specialOptions_ &= ~256; // mark as full scan done
1761   }
1762   // do cuts independently
1763   OsiCuts *eachCuts = new OsiCuts[numberCutGenerators_];
1764   ;
1765   int i;
1766   assert(master);
1767   for (i = 0; i < numberThreads_; i++) {
1768     // set solver here after cloning
1769     master->model(i)->solver_ = solver_->clone();
1770     master->model(i)->numberNodes_ = (fullScan) ? 1 : 0;
1771   }
1772   // generate cuts
1773   int status = 0;
1774   const OsiRowCutDebugger *debugger = NULL;
1775   bool onOptimalPath = false;
1776   for (i = 0; i < numberCutGenerators_; i++) {
1777     bool generate = generator_[i]->normal();
1778     // skip if not optimal and should be (maybe a cut generator has fixed variables)
1779     if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable())
1780       generate = false;
1781     if (generator_[i]->switchedOff())
1782       generate = false;
1783     ;
1784     if (generate) {
1785       master->waitForThreadsInCuts(0, eachCuts + i, i);
1786     }
1787   }
1788   // wait
1789   master->waitForThreadsInCuts(1, eachCuts, 0);
1790   // Now put together
1791   for (i = 0; i < numberCutGenerators_; i++) {
1792     // add column cuts
1793     int numberColumnCutsBefore = theseCuts.sizeColCuts();
1794     int numberColumnCuts = eachCuts[i].sizeColCuts();
1795     int numberColumnCutsAfter = numberColumnCutsBefore
1796       + numberColumnCuts;
1797     int j;
1798     for (j = 0; j < numberColumnCuts; j++) {
1799       theseCuts.insert(eachCuts[i].colCut(j));
1800     }
1801     int numberRowCutsBefore = theseCuts.sizeRowCuts();
1802     int numberRowCuts = eachCuts[i].sizeRowCuts();
1803     // insert good cuts
1804     if (numberRowCuts) {
1805       int n = numberRowCuts;
1806       numberRowCuts = 0;
1807       for (j = 0; j < n; j++) {
1808         const OsiRowCut *thisCut = eachCuts[i].rowCutPtr(j);
1809         if (thisCut->lb() <= 1.0e10 && thisCut->ub() >= -1.0e10) {
1810           theseCuts.insert(eachCuts[i].rowCut(j));
1811           numberRowCuts++;
1812         }
1813       }
1814       if (generator_[i]->mustCallAgain() && status >= 0)
1815         status = 1; // say must go round
1816     }
1817     int numberRowCutsAfter = numberRowCutsBefore
1818       + numberRowCuts;
1819     if (numberRowCuts) {
1820       // Check last cut to see if infeasible
1821       const OsiRowCut *thisCut = theseCuts.rowCutPtr(numberRowCutsAfter - 1);
1822       if (thisCut->lb() > thisCut->ub()) {
1823         status = -1; // sub-problem is infeasible
1824         break;
1825       }
1826     }
1827 #ifdef CBC_DEBUG
1828     {
1829       int k;
1830       for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
1831         OsiRowCut thisCut = theseCuts.rowCut(k);
1832         /* check size of elements.
1833                    We can allow smaller but this helps debug generators as it
1834                    is unsafe to have small elements */
1835         int n = thisCut.row().getNumElements();
1836         const int *column = thisCut.row().getIndices();
1837         const double *element = thisCut.row().getElements();
1838         //assert (n);
1839         for (int i = 0; i < n; i++) {
1840           double value = element[i];
1841           assert(fabs(value) > 1.0e-12 && fabs(value) < 1.0e20);
1842         }
1843       }
1844     }
1845 #endif
1846     if ((specialOptions_ & 1) != 0) {
1847       if (onOptimalPath) {
1848         int k;
1849         for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
1850           OsiRowCut thisCut = theseCuts.rowCut(k);
1851           if (debugger->invalidCut(thisCut)) {
1852             solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
1853             solver_->writeMpsNative("badCut.mps", NULL, NULL, 2);
1854 #ifdef NDEBUG
1855             printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n",
1856               i, generator_[i]->cutGeneratorName(), k - numberRowCutsBefore);
1857             const double *lower = getColLower();
1858             const double *upper = getColUpper();
1859             int numberColumns = solver_->getNumCols();
1860             for (int i = 0; i < numberColumns; i++)
1861               printf("%d bounds %g,%g\n", i, lower[i], upper[i]);
1862             abort();
1863 #endif
1864           }
1865           assert(!debugger->invalidCut(thisCut));
1866         }
1867       }
1868     }
1869     /*
1870           The cut generator has done its thing, and maybe it generated some
1871           cuts.  Do a bit of bookkeeping: load
1872           whichGenerator[i] with the index of the generator responsible for a cut,
1873           and place cuts flagged as global in the global cut pool for the model.
1874 
1875           lastNumberCuts is the sum of cuts added in previous iterations; it's the
1876           offset to the proper starting position in whichGenerator.
1877         */
1878     int numberBefore = numberRowCutsBefore + numberColumnCutsBefore + lastNumberCuts;
1879     int numberAfter = numberRowCutsAfter + numberColumnCutsAfter + lastNumberCuts;
1880     // possibly extend whichGenerator
1881     resizeWhichGenerator(numberBefore, numberAfter);
1882 
1883     for (j = numberRowCutsBefore; j < numberRowCutsAfter; j++) {
1884       whichGenerator_[numberBefore++] = i;
1885       const OsiRowCut *thisCut = theseCuts.rowCutPtr(j);
1886       if (thisCut->lb() > thisCut->ub())
1887         status = -1; // sub-problem is infeasible
1888       if (thisCut->globallyValid()) {
1889         // add to global list
1890         OsiRowCut newCut(*thisCut);
1891         newCut.setGloballyValid(true);
1892         newCut.mutableRow().setTestForDuplicateIndex(false);
1893         globalCuts_.addCutIfNotDuplicate(newCut);
1894       }
1895     }
1896     for (j = numberColumnCutsBefore; j < numberColumnCutsAfter; j++) {
1897       //whichGenerator_[numberBefore++] = i ;
1898       const OsiColCut *thisCut = theseCuts.colCutPtr(j);
1899       if (thisCut->globallyValid()) {
1900         // add to global list
1901         makeGlobalCut(thisCut);
1902       }
1903     }
1904   }
1905   // Add in any violated saved cuts
1906   if (!theseCuts.sizeRowCuts() && !theseCuts.sizeColCuts()) {
1907     int numberOld = theseCuts.sizeRowCuts() + lastNumberCuts;
1908     int numberCuts = slackCuts.sizeRowCuts();
1909     int i;
1910     // possibly extend whichGenerator
1911     resizeWhichGenerator(numberOld, numberOld + numberCuts);
1912     double primalTolerance;
1913     solver_->getDblParam(OsiPrimalTolerance, primalTolerance);
1914     for (i = 0; i < numberCuts; i++) {
1915       const OsiRowCut *thisCut = slackCuts.rowCutPtr(i);
1916       if (thisCut->violated(cbcColSolution_) > 100.0 * primalTolerance) {
1917         if (messageHandler()->logLevel() > 2)
1918           printf("Old cut added - violation %g\n",
1919             thisCut->violated(cbcColSolution_));
1920         whichGenerator_[numberOld++] = 999;
1921         theseCuts.insert(*thisCut);
1922       }
1923     }
1924   }
1925   delete[] eachCuts;
1926   return status;
1927 }
1928 /*
1929   Locks a thread if parallel so that stuff like cut pool
1930   can be updated and/or used.
1931 */
lockThread()1932 void CbcModel::lockThread()
1933 {
1934   if (masterThread_ && (threadMode_ & 1) == 0)
1935     masterThread_->lockThread();
1936 }
1937 /*
1938   Unlocks a thread if parallel
1939 */
unlockThread()1940 void CbcModel::unlockThread()
1941 {
1942   if (masterThread_ && (threadMode_ & 1) == 0)
1943     masterThread_->unlockThread();
1944 }
1945 // Returns true if locked
isLocked() const1946 bool CbcModel::isLocked() const
1947 {
1948   if (masterThread_) {
1949     return (masterThread_->locked());
1950   } else {
1951     return true;
1952   }
1953 }
1954 // Stop a child
setInfoInChild(int type,CbcThread * info)1955 void CbcModel::setInfoInChild(int type, CbcThread *info)
1956 {
1957   if (type == -3) {
1958     // set up
1959     masterThread_ = info;
1960   } else if (type == -2) {
1961     numberThreads_ = 0; // signal to stop
1962   } else {
1963     // make sure message handler will be deleted
1964     defaultHandler_ = true;
1965     ownObjects_ = false;
1966     delete solverCharacteristics_;
1967     solverCharacteristics_ = NULL;
1968     if (type >= 0) {
1969       delete[] object_; // may be able to when all over to CbcThread
1970       for (int i = 0; i < numberCutGenerators_; i++) {
1971         delete generator_[i];
1972         generator_[i] = NULL;
1973         //delete virginGenerator_[i];
1974         //virginGenerator_[i]=NULL;
1975       }
1976       //generator_[0] = NULL;
1977       //delete [] generator_;
1978       //generator_ = NULL;
1979       numberCutGenerators_ = 0;
1980     } else {
1981       for (int i = 0; i < numberCutGenerators_; i++) {
1982         generator_[i] = NULL;
1983       }
1984     }
1985     object_ = NULL;
1986   }
1987 }
1988 
1989 /// Indicates whether Cbc library has been compiled with multithreading support
haveMultiThreadSupport()1990 bool CbcModel::haveMultiThreadSupport() { return true; }
1991 
1992 #else
1993 // Default constructor
CbcBaseModel()1994 CbcBaseModel::CbcBaseModel() {}
1995 
haveMultiThreadSupport()1996 bool CbcModel::haveMultiThreadSupport() { return false; }
1997 
isLocked() const1998 bool CbcModel::isLocked() const { return false; }
lockThread()1999 void CbcModel::lockThread() {}
unlockThread()2000 void CbcModel::unlockThread() {}
setInfoInChild(int type,CbcThread * info)2001 void CbcModel::setInfoInChild(int type, CbcThread *info) {}
moveToModel(CbcModel * baseModel,int mode)2002 void CbcModel::moveToModel(CbcModel *baseModel, int mode) {}
splitModel(int numberModels,CbcModel ** model,int numberNodes)2003 int CbcModel::splitModel(int numberModels, CbcModel **model, int numberNodes) { return 0; }
startSplitModel(int numberIterations)2004 void CbcModel::startSplitModel(int numberIterations) {}
mergeModels(int numberModel,CbcModel ** model,int numberNodes)2005 void CbcModel::mergeModels(int numberModel, CbcModel **model, int numberNodes) {}
2006 #endif
2007 
2008 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
2009 */
2010