source: releases/2.7.1/Cbc/src/CbcThread.cpp @ 1995

Last change on this file since 1995 was 1573, checked in by lou, 8 years ago

Change to EPL license notice.

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