source: trunk/Cbc/src/CbcThread.cpp

Last change on this file was 2467, checked in by unxusr, 6 months ago

spaces after angles

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