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