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

Last change on this file since 1433 was 1432, checked in by bjarni, 10 years ago

Added extra return at end of each source file where needed, to remove possible linefeed conflicts (NightlyBuild? errors)

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
1900
Note: See TracBrowser for help on using the repository browser.