source: trunk/Cbc/src/CbcThread.cpp @ 1424

Last change on this file since 1424 was 1412, checked in by forrest, 10 years ago

try and modularize threads

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