source: stable/2.7/Cbc/src/CbcThread.cpp @ 1711

Last change on this file since 1711 was 1711, checked in by stefan, 10 years ago

add method to indicate whether Cbc library has been compiled with multithreading support

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