Scippy

UG

Ubiquity Generator framework

bbParaSolverPool.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and software framework */
4 /* UG --- Ubquity Generator Framework */
5 /* */
6 /* Copyright Written by Yuji Shinano <shinano@zib.de>, */
7 /* Copyright (C) 2021 by Zuse Institute Berlin, */
8 /* licensed under LGPL version 3 or later. */
9 /* Commercial licenses are available through <licenses@zib.de> */
10 /* */
11 /* This code is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 /* */
24 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
25 
26 /**@file paraSolverPool.cpp
27  * @brief Solver pool.
28  * @author Yuji Shinano
29  *
30  *
31  *
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 
37 #include <cassert>
38 #include <string>
39 #include <cstring>
40 #include <sstream>
41 #include <list>
42 #include <map>
43 #include <cmath>
44 #include "ug/paraDef.h"
45 #include "bbParaComm.h"
46 #include "bbParaParamSet.h"
47 #include "bbParaSolverPool.h"
48 
49 using namespace std;
50 using namespace UG;
51 
52 /** constructor of selection heap */
53 SelectionHeap::SelectionHeap(
54  std::size_t size /**< maximum size of this heap */
55  )
56 {
57  maxHeapSize = size;
58  heapSize = 0;
59  heap = new BbParaSolverPoolElementPtr[size+1]; /* index 0 is a sentinel */
60 }
61 
62 /** destructor of selection heap */
63 SelectionHeap::~SelectionHeap(
64  )
65 {
66  delete[] heap;
67 }
68 /** resize selection heap */
69 void
70 SelectionHeap::resize(
71  std::size_t size /**< new heap size */
72  )
73 {
74  BbParaSolverPoolElementPtr *tempHeap =
75  new BbParaSolverPoolElementPtr[size+1]; /* index 0 is a sentinel */
76  std::memcpy(tempHeap, heap, (unsigned long int)(sizeof(BbParaSolverPoolElementPtr) * (maxHeapSize+1)));
77  delete[] heap;
78  heap = tempHeap;
79  maxHeapSize = size;
80 }
81 
82 /** insert BbParaSolverPoolElementPtr to selection heap */
84 SelectionHeap::insert(
85  BbParaSolverPoolElementPtr inSolver /**< BbParaSolverPoolElementPtr to be inserted */
86  )
87 {
88  if( heapSize >= maxHeapSize ) return FAILED_BY_FULL;
89  heap[++heapSize] = inSolver;
90  upHeap(heapSize);
91  return SUCCEEDED;
92 }
93 
94 /** remove the top priority element form selection heap */
96 SelectionHeap::remove(
97  )
98 {
99  BbParaSolverPoolElementPtr solver = heap[1];
100 
101  heap[1] = heap[heapSize];
102  heapSize--;
103  downHeap(1);
104  if( heapSize == 0 )
105  {
106  heap[1] = 0;
107  }
108  solver->setSelectionHeapElement(0);
109  return solver;
110 }
111 
112 
113 /** stringfy selection heap */
114 const std::string
115 SelectionHeap::toString(
116  )
117 {
118  std::ostringstream os;
119  os << "--- selection heap ---" << std::endl;
120  os << "maxHeapSize: " << maxHeapSize << std::endl;
121  os << "heapSize: " << heapSize << std::endl;
122  for( std::size_t i = 1; i <= heapSize; i++ )
123  {
124  os << "heap[" << i << "]->rank: "
125  << heap[i]->getRank() << std::endl
126  << "heap[" << i << "]->status: "
127  << static_cast<int>(heap[i]->getStatus()) << std::endl
128  << "heap[" << i << "]->bestBound: "
129  << heap[i]->getBestDualBoundValue() << std::endl
130  << "heap[" << i << "]->numOfNodesLeft: "
131  << heap[i]->getNumOfNodesLeft() << std::endl
132  << "heap[" << i << "]->numOfDiff: "
133  << heap[i]->getNumOfDiffNodesLeft() << std::endl
134  << "heap[" << i << "]->collectingMode: "
135  << heap[i]->isInCollectingMode() << std::endl;
136  }
137  return os.str();
138 }
139 
140 /** constructor of DescendingSelectionHeap */
141 DescendingSelectionHeap::DescendingSelectionHeap(
142  std::size_t size /**< maximum size of this heap */
143  )
144  : SelectionHeap(size)
145 {
146 }
147 
148 /** update dual bound value of the solver in heap */
149 void
151  BbParaSolverPoolElementPtr solver, /**< pointer to solver pool element whose dual bound is updated */
152  double newDualBoundValue /**< new dual bound value */
153  )
154 {
155  int pos = solver->getSelectionHeapElement() - heap;
156  if( solver->getBestDualBoundValue() < newDualBoundValue )
157  {
158  solver->setBestDualBoundValue(newDualBoundValue);
159  upHeap(pos);
160  }
161  else
162  {
163  solver->setBestDualBoundValue(newDualBoundValue);
164  downHeap(pos);
165  }
166 }
167 
168 /** delete BbParaSolverPoolElement */
169 void
171  BbParaSolverPoolElementPtr solver /**< BbParaSolverPoolElement to be deleted */
172  )
173 {
174  std::size_t pos = (solver->getSelectionHeapElement()) - heap;
175 
176  if( pos == heapSize )
177  {
178  /* no need to rearrange heap element */
179  heap[heapSize--] = 0;
180  }
181  else
182  {
183  if( heap[pos]->getBestDualBoundValue() < heap[heapSize]->getBestDualBoundValue() )
184  {
185  heap[pos] = heap[heapSize];
186  heap[heapSize--] = 0;
187  upHeap(pos);
188  }
189  else
190  {
191  heap[pos] = heap[heapSize];
192  heap[heapSize--] = 0;
193  downHeap(pos);
194  }
195  }
196  solver->setSelectionHeapElement(0);
197 }
198 
199 
200 /** up heap */
201 void
203  std::size_t pos /**< up heap this position element */
204  )
205 {
207 
208  she = heap[pos];
209  heap[0] = NULL;
210  while ( heap[pos/2] != NULL &&
211  ( heap[pos/2]->getBestDualBoundValue()
212  < she->getBestDualBoundValue() ) )
213  {
214  heap[pos] = heap[pos/2];
215  heap[pos]->setSelectionHeapElement(&heap[pos]);
216  pos = pos/2;
217  }
218  heap[pos] = she;
219  heap[pos]->setSelectionHeapElement(&heap[pos]);
220 }
221 
222 /** down heap */
223 void
225  std::size_t pos /**< down heap this position element */
226  )
227 {
228  std::size_t j;
230 
231  she = heap[pos];
232  while ( pos <= (heapSize/2) )
233  {
234  j = pos + pos;
235  if( j < heapSize &&
236  ( heap[j]->getBestDualBoundValue()
237  < heap[j+1]->getBestDualBoundValue() ) ) j++;
238  if( she->getBestDualBoundValue()
239  > heap[j]->getBestDualBoundValue() )
240  break;
241  heap[pos] = heap[j];
242  heap[pos]->setSelectionHeapElement(&heap[pos]);
243  pos = j;
244  }
245  heap[pos] = she;
246  heap[pos]->setSelectionHeapElement(&heap[pos]);
247 }
248 
249 /** constructor of AscendingSelectionHeap */
251  std::size_t size /**< maximum size of this heap */
252  )
253  : SelectionHeap(size)
254 {
255 }
256 
257 /** update dual bound value of the solver in heap */
258 void
260  BbParaSolverPoolElementPtr solver, /**< pointer to solver pool element whose dual bound is updated */
261  double newDualBoundValue /**< new dual bound value */
262  )
263 {
264  int pos = solver->getSelectionHeapElement() - heap;
265  if( solver->getBestDualBoundValue() > newDualBoundValue )
266  {
267  solver->setBestDualBoundValue(newDualBoundValue);
268  upHeap(pos);
269  }
270  else
271  {
272  solver->setBestDualBoundValue(newDualBoundValue);
273  downHeap(pos);
274  }
275 }
276 
277 /** delete BbParaSolverPoolElement */
278 void
280  BbParaSolverPoolElementPtr solver /**< BbParaSolverPoolElement to be deleted */
281  )
282 {
283  std::size_t pos = (solver->getSelectionHeapElement()) - heap;
284 
285  if( pos == heapSize )
286  {
287  /* no need to rearrange heap element */
288  heap[heapSize--] = 0;
289  }
290  else
291  {
292  if( heap[pos]->getBestDualBoundValue() > heap[heapSize]->getBestDualBoundValue() )
293  {
294  heap[pos] = heap[heapSize];
295  heap[heapSize--] = 0;
296  upHeap(pos);
297  }
298  else
299  {
300  heap[pos] = heap[heapSize];
301  heap[heapSize--] = 0;
302  downHeap(pos);
303  }
304  }
305  solver->setSelectionHeapElement(0);
306 }
307 
308 /** up heap */
309 void
311  std::size_t pos /**< up heap this position element */
312 ){
314 
315  she = heap[pos];
316  heap[0] = NULL;
317 
318  while ( heap[pos/2] != NULL &&
319  ( heap[pos/2]->getBestDualBoundValue()
320  > she->getBestDualBoundValue() ) )
321  {
322  heap[pos] = heap[pos/2];
323  heap[pos]->setSelectionHeapElement(&heap[pos]);
324  pos = pos/2;
325  }
326  heap[pos] = she;
327  heap[pos]->setSelectionHeapElement(&heap[pos]);
328 }
329 
330 /** down heap */
331 void
333  std::size_t pos /**< down heap this position element */
334 ){
335  std::size_t j;
337 
338  she = heap[pos];
339  while ( pos <= (heapSize/2) )
340  {
341  j = pos + pos;
342  if( j < heapSize &&
343  ( heap[j]->getBestDualBoundValue()
344  > heap[j+1]->getBestDualBoundValue() ) ) j++;
345  if( she->getBestDualBoundValue()
346  < heap[j]->getBestDualBoundValue() )
347  break;
348  heap[pos] = heap[j];
349  heap[pos]->setSelectionHeapElement(&heap[pos]);
350  pos = j;
351  }
352  heap[pos] = she;
353  heap[pos]->setSelectionHeapElement(&heap[pos]);
354 }
355 
356 /** constructor of selection heap */
358  std::size_t size /**< maximum size of this heap */
359  )
360 {
361  maxHeapSize = size;
362  heapSize = 0;
363  heap = new BbParaSolverPoolElementPtr[size+1]; /* index 0 is a sentinel */
364 }
365 
366 /** destructor of selection heap */
368  )
369 {
370  delete[] heap;
371 }
372 /** resize selection heap */
373 void
375  std::size_t size /**< new heap size */
376  )
377 {
378  BbParaSolverPoolElementPtr *tempHeap =
379  new BbParaSolverPoolElementPtr[size+1]; /* index 0 is a sentinel */
380  std::memcpy(tempHeap, heap, (unsigned long int)(sizeof(BbParaSolverPoolElementPtr) * (maxHeapSize+1)));
381  delete[] heap;
382  heap = tempHeap;
383  maxHeapSize = size;
384 }
385 
386 /** insert BbParaSolverPoolElementPtr to selection heap */
389  BbParaSolverPoolElementPtr inSolver /**< BbParaSolverPoolElementPtr to be inserted */
390  )
391 {
392  if( heapSize >= maxHeapSize ) return FAILED_BY_FULL;
393  heap[++heapSize] = inSolver;
394  upHeap(heapSize);
395  return SUCCEEDED;
396 }
397 
398 /** remove the top priority element form selection heap */
401  )
402 {
403  BbParaSolverPoolElementPtr solver = heap[1];
404 
405  heap[1] = heap[heapSize];
406  heapSize--;
407  downHeap(1);
408  if( heapSize == 0 )
409  {
410  heap[1] = 0;
411  }
413  return solver;
414 }
415 
416 
417 /** stringfy selection heap */
418 const std::string
420  )
421 {
422  std::ostringstream os;
423  os << "--- selection heap ---" << std::endl;
424  os << "maxHeapSize: " << maxHeapSize << std::endl;
425  os << "heapSize: " << heapSize << std::endl;
426  for( std::size_t i = 1; i <= heapSize; i++ )
427  {
428  os << "heap[" << i << "]->rank: "
429  << heap[i]->getRank() << std::endl
430  << "heap[" << i << "]->status: "
431  << static_cast<int>(heap[i]->getStatus()) << std::endl
432  << "heap[" << i << "]->bestBound: "
433  << heap[i]->getBestDualBoundValue() << std::endl
434  << "heap[" << i << "]->numOfNodesLeft: "
435  << heap[i]->getNumOfNodesLeft() << std::endl
436  << "heap[" << i << "]->numOfDiff: "
437  << heap[i]->getNumOfDiffNodesLeft() << std::endl
438  << "heap[" << i << "]->collectingMode: "
439  << heap[i]->isInCollectingMode() << std::endl;
440  }
441  return os.str();
442 }
443 
444 /** constructor of DescendingCollectingModeSolverHeap */
446  std::size_t size /**< maximum size of this heap */
447  )
449 {
450 }
451 
452 /** update dual bound value of the solver in heap */
453 void
455  BbParaSolverPoolElementPtr solver, /**< pointer to solver pool element whose dual bound is updated */
456  double newDualBoundValue /**< new dual bound value */
457  )
458 {
459  int pos = solver->getCollectingModeSolverHeapElement() - heap;
460  if( solver->getBestDualBoundValue() < newDualBoundValue )
461  {
462  solver->setBestDualBoundValue(newDualBoundValue);
463  upHeap(pos);
464  }
465  else
466  {
467  solver->setBestDualBoundValue(newDualBoundValue);
468  downHeap(pos);
469  }
470 }
471 
472 /** delete BbParaSolverPoolElement */
473 void
475  BbParaSolverPoolElementPtr solver /**< BbParaSolverPoolElement to be deleted */
476  )
477 {
478  std::size_t pos = (solver->getCollectingModeSolverHeapElement()) - heap;
479 
480  if( pos == heapSize )
481  {
482  /* no need to rearrange heap element */
483  heap[heapSize--] = 0;
484  }
485  else
486  {
487  if( heap[pos]->getBestDualBoundValue() < heap[heapSize]->getBestDualBoundValue() )
488  {
489  heap[pos] = heap[heapSize];
490  heap[heapSize--] = 0;
491  upHeap(pos);
492  }
493  else
494  {
495  heap[pos] = heap[heapSize];
496  heap[heapSize--] = 0;
497  downHeap(pos);
498  }
499  }
501 }
502 
503 
504 /** up heap */
505 void
507  std::size_t pos /**< up heap this position element */
508  )
509 {
511 
512  she = heap[pos];
513  heap[0] = NULL;
514  while ( heap[pos/2] != NULL &&
515  ( heap[pos/2]->getBestDualBoundValue()
516  < she->getBestDualBoundValue() ) )
517  {
518  heap[pos] = heap[pos/2];
520  pos = pos/2;
521  }
522  heap[pos] = she;
524 }
525 
526 /** down heap */
527 void
529  std::size_t pos /**< down heap this position element */
530  )
531 {
532  std::size_t j;
534 
535  she = heap[pos];
536  while ( pos <= (heapSize/2) )
537  {
538  j = pos + pos;
539  if( j < heapSize &&
540  ( heap[j]->getBestDualBoundValue()
541  < heap[j+1]->getBestDualBoundValue() ) ) j++;
542  if( she->getBestDualBoundValue()
543  > heap[j]->getBestDualBoundValue() )
544  break;
545  heap[pos] = heap[j];
547  pos = j;
548  }
549  heap[pos] = she;
551 }
552 
553 /** constructor of AscendingCollectingModeSolverHeap */
555  std::size_t size /**< maximum size of this heap */
556  )
558 {
559 }
560 
561 /** update dual bound value of the solver in heap */
562 void
564  BbParaSolverPoolElementPtr solver, /**< pointer to solver pool element whose dual bound is updated */
565  double newDualBoundValue /**< new dual bound value */
566  )
567 {
568  int pos = solver->getCollectingModeSolverHeapElement() - heap;
569  if( solver->getBestDualBoundValue() > newDualBoundValue )
570  {
571  solver->setBestDualBoundValue(newDualBoundValue);
572  upHeap(pos);
573  }
574  else
575  {
576  solver->setBestDualBoundValue(newDualBoundValue);
577  downHeap(pos);
578  }
579 }
580 
581 /** delete BbParaSolverPoolElement */
582 void
584  BbParaSolverPoolElementPtr solver /**< BbParaSolverPoolElement to be deleted */
585  )
586 {
587  std::size_t pos = (solver->getCollectingModeSolverHeapElement()) - heap;
588 
589  if( pos == heapSize )
590  {
591  /* no need to rearrange heap element */
592  heap[heapSize--] = 0;
593  }
594  else
595  {
596  if( heap[pos]->getBestDualBoundValue() > heap[heapSize]->getBestDualBoundValue() )
597  {
598  heap[pos] = heap[heapSize];
599  heap[heapSize--] = 0;
600  upHeap(pos);
601  }
602  else
603  {
604  heap[pos] = heap[heapSize];
605  heap[heapSize--] = 0;
606  downHeap(pos);
607  }
608  }
610 }
611 
612 /** up heap */
613 void
615  std::size_t pos /**< up heap this position element */
616 ){
618 
619  she = heap[pos];
620  heap[0] = NULL;
621 
622  while ( heap[pos/2] != NULL &&
623  ( heap[pos/2]->getBestDualBoundValue()
624  > she->getBestDualBoundValue() ) )
625  {
626  heap[pos] = heap[pos/2];
628  pos = pos/2;
629  }
630  heap[pos] = she;
632 }
633 
634 /** down heap */
635 void
637  std::size_t pos /**< down heap this position element */
638 ){
639  std::size_t j;
641 
642  she = heap[pos];
643  while ( pos <= (heapSize/2) )
644  {
645  j = pos + pos;
646  if( j < heapSize &&
647  ( heap[j]->getBestDualBoundValue()
648  > heap[j+1]->getBestDualBoundValue() ) ) j++;
649  if( she->getBestDualBoundValue()
650  < heap[j]->getBestDualBoundValue() )
651  break;
652  heap[pos] = heap[j];
654  pos = j;
655  }
656  heap[pos] = she;
658 }
659 
660 /** activate Solver specified by its rank */
661 void
663  int rank, ///< rank of the solver to be activated
664  BbParaNode *paraNode, ///< paraNode to be solved in the solver
665  int nGoodNodesInNodePool,
666  double averageDualBoundGain
667  )
668 {
669 
670  active = true; // activate this solver pool
671 
672  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
673  {
674  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
675  }
676  map<int, BbParaSolverPoolElementPtr>::iterator p;
677  if( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Inactive )
678  {
679  p = inactiveSolvers.find(rank);
680  if( p != inactiveSolvers.end() )
681  {
682  if( p->second->getRank() != rank ||
683  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
684  {
685  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
686  }
687  inactiveSolvers.erase(p);
688  }
689  else
690  {
691  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
692  }
693  }
694  else
695  {
696  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
697  }
698  activeSolvers.insert(make_pair(rank,pool[SOLVER_POOL_INDEX( rank )]));
699  pool[SOLVER_POOL_INDEX( rank )]->activate(paraNode);
700  if( paraParams->getBoolParamValue(ControlCollectingModeOnSolverSide) )
701  {
702  pool[SOLVER_POOL_INDEX( rank )]->prohibitCollectingMode();
703  }
704  nNodesInSolvers++;
705  selectionHeap->insert(pool[SOLVER_POOL_INDEX( rank )]); // this should be called after activate: dual bound value need to be set
706  if( paraParams->getBoolParamValue(DualBoundGainTest) )
707  {
708  if( ( (nDualBoundGainTesting*2) + nGoodNodesInNodePool ) < getNumInactiveSolvers() +
709  paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes*paraParams->getRealParamValue(MultiplierForCollectingMode) ) // could be doubled
710  {
711  //if( beforeInitialCollect )
712  // {
713  // averageDualBoundGain*=2;
714  //}
716  paraComm->send(&averageDualBoundGain, 1, ParaDOUBLE, rank, TagTestDualBoundGain )
717  );
718  pool[SOLVER_POOL_INDEX( rank )]->setDualBoundGainTesting(true);
719  nDualBoundGainTesting++;
720  // std::cout << "S." << rank << " Test dual bound gain" << std::endl;
721  }
722  else
723  {
725  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoTestDualBoundGain )
726  );
727  // std::cout << "S." << rank << " No test dual bound gain" << std::endl;
728  }
729  }
730  paraNode->send(paraComm, rank);
731 }
732 
733 /** activate Solver specified by its rank and number of nodes left. This is for the racing winner. */
734 void
736  int rank, ///< rank of the solver to be activated */
737  BbParaNode *paraNode, ///< paraNode to be solved in the solver */
738  int nNodesLeft ///< number of nodes left in the Solver */
739  )
740 {
741 
742  active = true; // activate this solver pool
743 
744  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
745  {
746  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
747  }
748  map<int, BbParaSolverPoolElementPtr>::iterator p;
749  if( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Inactive )
750  {
751  p = inactiveSolvers.find(rank);
752  if( p != inactiveSolvers.end() )
753  {
754  if( p->second->getRank() != rank ||
755  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
756  {
757  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
758  }
759  inactiveSolvers.erase(p);
760  }
761  else
762  {
763  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
764  }
765  }
766  else
767  {
768  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
769  }
770  activeSolvers.insert(make_pair(rank,pool[SOLVER_POOL_INDEX( rank )]));
771  pool[SOLVER_POOL_INDEX( rank )]->activate(paraNode);
772  pool[SOLVER_POOL_INDEX( rank )]->setNumOfNodesLeft(nNodesLeft);
773  /** DO NOT PROHIBIT COLLECTING MODE. THIS IS ACTIVATION ROUTIN FOR RACING WIINGER */
774  nNodesInSolvers += nNodesLeft;
775  selectionHeap->insert(pool[SOLVER_POOL_INDEX( rank )]); // this should be called after activate: dual bound value need to be set
776 }
777 
778 
779 /** activate any Solver which is idle */
780 int
782  BbParaNode *paraNode, ///< paraNode to be solved in an activated solver
783  BbParaRacingSolverPool *paraRacingSolverPool,///< paraRacingSolverPool to check if the solver is not solving root node
784  bool rampUpPhase,
785  int nGoodNodesInNodePool,
786  double averageDualBoundGain
787  )
788 {
789  map<int, BbParaSolverPoolElementPtr>::iterator p;
790  int rank;
791 
792  active = true; // activate this solver pool
793 
794  if( !paraRacingSolverPool )
795  {
796  p = inactiveSolvers.begin();
797  if( p == inactiveSolvers.end() )
798  {
799  THROW_LOGICAL_ERROR1("No inactive Solver");
800  }
801  rank = p->second->getRank();
802  }
803  else
804  {
805  for( p = inactiveSolvers.begin(); p != inactiveSolvers.end(); ++p )
806  {
807  if( !paraRacingSolverPool->isSolverActive(p->second->getRank()) )
808  {
809  // at least one notification message is received
810  rank = p->second->getRank();
811  break;
812  }
813  }
814  if( p == inactiveSolvers.end() )
815  {
816  return -1;
817  }
818  }
819  activeSolvers.insert(make_pair(rank,pool[SOLVER_POOL_INDEX( rank )]));
820  pool[SOLVER_POOL_INDEX( rank )]->activate(paraNode);
821  if( paraParams->getBoolParamValue(ControlCollectingModeOnSolverSide) )
822  {
823  pool[SOLVER_POOL_INDEX( rank )]->prohibitCollectingMode();
824  }
825  nNodesInSolvers++;
826  selectionHeap->insert(pool[SOLVER_POOL_INDEX( rank )]); // this should be called after activate: dual bound value need to be set
827  inactiveSolvers.erase(p);
828  if( paraParams->getBoolParamValue(LightWeightRootNodeProcess) &&
829  (!rampUpPhase) && (!paraRacingSolverPool ) && // already ramp-up ( and no racing solvers )
830  inactiveSolvers.size() >
831  ( nSolvers * paraParams->getRealParamValue(RatioToApplyLightWeightRootProcess) )
832  // specified idle solver exists
833  )
834  {
836  paraComm->send(NULL, 0, ParaBYTE, rank, TagLightWeightRootNodeProcess)
837  );
838  }
839  if( paraParams->getBoolParamValue(DualBoundGainTest) )
840  {
841  if( ( (nDualBoundGainTesting*2) + nGoodNodesInNodePool ) < getNumInactiveSolvers() +
842  paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes*paraParams->getRealParamValue(MultiplierForCollectingMode) ) // could be doubled
843  {
844  //if( beforeInitialCollect )
845  // {
846  // averageDualBoundGain*=2;
847  //}
849  paraComm->send(&averageDualBoundGain, 1, ParaDOUBLE, rank, TagTestDualBoundGain )
850  );
851  pool[SOLVER_POOL_INDEX( rank )]->setDualBoundGainTesting(true);
852  nDualBoundGainTesting++;
853  // std::cout << "S." << rank << " Test dual bound gain" << std::endl;
854  }
855  else
856  {
858  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoTestDualBoundGain )
859  );
860  // std::cout << "S." << rank << " No test dual bound gain" << std::endl;
861  }
862  }
863  paraNode->send(paraComm, rank);
864  assert( ( paraNode->getMergingStatus() != 0 && ( !paraNode->getMergeNodeInfo() ) ) ||
865  ( paraNode->getMergingStatus() == 0 && paraNode->getMergeNodeInfo() ) );
866  return rank;
867 }
868 
869 void
871  int rank, ///< rank of the solver, in which the subtree root node is added
872  BbParaNode *paraNode ///< paraNode to be added as the subtree root
873  )
874 {
875  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
876  {
877  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
878  }
879  map<int, BbParaSolverPoolElementPtr>::iterator p;
880  if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active )
881  {
882  p = activeSolvers.find(rank);
883  if( p != activeSolvers.end() )
884  {
885  if( p->second->getRank() != rank ||
886  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
887  {
888  THROW_LOGICAL_ERROR2("Rank = ", rank);
889  }
890  if( collectingMode || p->second->isCandidateOfCollecting() )
891  {
892  THROW_LOGICAL_ERROR3("Rank = ", rank, " should not be in colleting mode and shuould not be a candidate of collecting.");
893  }
894  p->second->addSubtreeRoot(paraNode);
895  // std::cout << "ADD: " << paraNode->toString() << std::endl;
896  }
897  else
898  {
899  THROW_LOGICAL_ERROR2("Rank = ", rank);
900  }
901  }
902  else
903  {
904  if( pool[SOLVER_POOL_INDEX( rank )]->getStatus() != InterruptRequested &&
905  pool[SOLVER_POOL_INDEX( rank )]->getStatus() != TerminateRequested &&
906  pool[SOLVER_POOL_INDEX( rank )]->getStatus() != Terminated )
907  {
908  std::cout << "Status = " << static_cast<int>(pool[SOLVER_POOL_INDEX( rank )]->getStatus()) << std::endl;
909  THROW_LOGICAL_ERROR2("Rank = ", rank);
910  }
911  }
912 }
913 
914 void
916  int rank, ///< rank of the solver, in which the subtree root node is removed
917  BbParaNode *paraNode ///< paraNode to be removed
918  )
919 {
920  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
921  {
922  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
923  }
924  map<int, BbParaSolverPoolElementPtr>::iterator p;
925  if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active )
926  {
927  p = activeSolvers.find(rank);
928  if( p != activeSolvers.end() )
929  {
930  if( p->second->getRank() != rank ||
931  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
932  {
933  THROW_LOGICAL_ERROR2("Rank = ", rank);
934  }
935 
936  // if( collectingMode || p->second->isCandidateOfCollecting() )
937  // {
938  // THROW_LOGICAL_ERROR3("Rank = ", rank, " should not be in colleting mode and shuould not be a candidate of collecting.");
939  // }
940  // std::cout << "REMOVE: " << paraNode->toString() << std::endl;
941  p->second->makeSubtreeRootCurrent(paraNode);
942  }
943  else
944  {
945  THROW_LOGICAL_ERROR2("Rank = ", rank);
946  }
947  }
948  else
949  {
950  if( pool[SOLVER_POOL_INDEX( rank )]->getStatus() != InterruptRequested &&
951  pool[SOLVER_POOL_INDEX( rank )]->getStatus() != TerminateRequested &&
952  pool[SOLVER_POOL_INDEX( rank )]->getStatus() != Terminated )
953  {
954  std::cout << "Status = " << static_cast<int>(pool[SOLVER_POOL_INDEX( rank )]->getStatus()) << std::endl;
955  THROW_LOGICAL_ERROR2("Rank = ", rank);
956  }
957  }
958 }
959 
960 void
962  int rank, ///< rank of the solver, in which the subtree root node is removed
963  BbParaNode *paraNode ///< paraNode to be removed
964  )
965 {
966  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
967  {
968  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
969  }
970  map<int, BbParaSolverPoolElementPtr>::iterator p;
971  if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active )
972  {
973  p = activeSolvers.find(rank);
974  if( p != activeSolvers.end() )
975  {
976  if( p->second->getRank() != rank ||
977  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
978  {
979  THROW_LOGICAL_ERROR2("Rank = ", rank);
980  }
981 
982  // if( collectingMode || p->second->isCandidateOfCollecting() )
983  // {
984  // THROW_LOGICAL_ERROR3("Rank = ", rank, " should not be in colleting mode and shuould not be a candidate of collecting.");
985  // }
986  // std::cout << "REMOVE: " << paraNode->toString() << std::endl;
987  p->second->removeSubtreeRoot(paraNode);
988  }
989  else
990  {
991  THROW_LOGICAL_ERROR2("Rank = ", rank);
992  }
993  }
994  else
995  {
996  if( pool[SOLVER_POOL_INDEX( rank )]->getStatus() != InterruptRequested &&
997  pool[SOLVER_POOL_INDEX( rank )]->getStatus() != TerminateRequested &&
998  pool[SOLVER_POOL_INDEX( rank )]->getStatus() != Terminated )
999  {
1000  std::cout << "Status = " << static_cast<int>(pool[SOLVER_POOL_INDEX( rank )]->getStatus()) << std::endl;
1001  THROW_LOGICAL_ERROR2("Rank = ", rank);
1002  }
1003  }
1004 }
1005 
1006 //BbParaNode *
1007 //BbParaSolverPool::removeAllSubtreeRootNode(
1008 // int rank, ///< rank of the solver, in which the subtree root node is removed
1009 // BbParaNode *paraNode ///< paraNode to be removed
1010 // )
1011 //{
1012 // if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
1013 // {
1014 // THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
1015 // }
1016 // map<int, BbParaSolverPoolElementPtr>::iterator p;
1017 // if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active )
1018 // {
1019 // p = activeSolvers.find(rank);
1020 // if( p != activeSolvers.end() )
1021 // {
1022 // if( p->second->getRank() != rank ||
1023 // pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
1024 // {
1025 // THROW_LOGICAL_ERROR2("Rank = ", rank);
1026 // }
1027 //
1028 // // if( collectingMode || p->second->isCandidateOfCollecting() )
1029 // // {
1030 // // THROW_LOGICAL_ERROR3("Rank = ", rank, " should not be in colleting mode and shuould not be a candidate of collecting.");
1031 // // }
1032 // // std::cout << "REMOVE: " << paraNode->toString() << std::endl;
1033 // p->second->removeSubtreeRoot(paraNode);
1034 // }
1035 // else
1036 // {
1037 // THROW_LOGICAL_ERROR2("Rank = ", rank);
1038 // }
1039 // }
1040 // else
1041 // {
1042 // THROW_LOGICAL_ERROR2("Rank = ", rank);
1043 // }
1044 // BbParaNode *node = pool[SOLVER_POOL_INDEX(rank)]->extractCurrentNodeGeneratedBySelfSplit();
1045 // return node;
1046 //}
1047 
1048 BbParaNode *
1050  int rank, ///< rank of the solver, in which the subtree root node is removed
1051  BbParaNode *paraNode ///< paraNode to be removed
1052  )
1053 {
1054  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
1055  {
1056  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
1057  }
1058  map<int, BbParaSolverPoolElementPtr>::iterator p;
1059  if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active )
1060  {
1061  p = activeSolvers.find(rank);
1062  if( p != activeSolvers.end() )
1063  {
1064  if( p->second->getRank() != rank ||
1065  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
1066  {
1067  THROW_LOGICAL_ERROR2("Rank = ", rank);
1068  }
1069 
1070  // if( collectingMode || p->second->isCandidateOfCollecting() )
1071  // {
1072  // THROW_LOGICAL_ERROR3("Rank = ", rank, " should not be in colleting mode and shuould not be a candidate of collecting.");
1073  // }
1074 
1075  BbParaNode *node = p->second->extractSubtreeRoot(paraNode);
1076  node->next = 0;
1077  // std::cout << "EXTRACT: " << node->toString() << std::endl;
1078  return node;
1079  }
1080  else
1081  {
1082  THROW_LOGICAL_ERROR2("Rank = ", rank);
1083  }
1084  }
1085  else
1086  {
1087  THROW_LOGICAL_ERROR2("Rank = ", rank);
1088  }
1089 }
1090 
1091 BbParaNode *
1093  int rank ///< rank of the solver, in which the subtree root node is removed
1094  )
1095 {
1096  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
1097  {
1098  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
1099  }
1100  map<int, BbParaSolverPoolElementPtr>::iterator p;
1101  if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active )
1102  {
1103  p = activeSolvers.find(rank);
1104  if( p != activeSolvers.end() )
1105  {
1106  if( p->second->getRank() != rank ||
1107  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
1108  {
1109  THROW_LOGICAL_ERROR2("Rank = ", rank);
1110  }
1111 
1112  // if( collectingMode || p->second->isCandidateOfCollecting() )
1113  // {
1114  // THROW_LOGICAL_ERROR3("Rank = ", rank, " should not be in colleting mode and shuould not be a candidate of collecting.");
1115  // }
1116  return p->second->getSelfSplitNodes();
1117  }
1118  else
1119  {
1120  THROW_LOGICAL_ERROR2("Rank = ", rank);
1121  }
1122  }
1123  else
1124  {
1125  THROW_LOGICAL_ERROR2("Rank = ", rank);
1126  }
1127 }
1128 
1129 BbParaNode *
1131  int rank ///< rank of the solver, in which the subtree root node is removed
1132  )
1133 {
1134  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
1135  {
1136  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
1137  }
1138  return pool[SOLVER_POOL_INDEX( rank )]->extractSelfSplitNodes();
1139 }
1140 
1141 void
1143  int rank ///< rank of the solver, in which the subtree root node is removed
1144  )
1145 {
1146  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
1147  {
1148  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
1149  }
1150  map<int, BbParaSolverPoolElementPtr>::iterator p;
1151  if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active )
1152  {
1153  p = activeSolvers.find(rank);
1154  if( p != activeSolvers.end() )
1155  {
1156  if( p->second->getRank() != rank ||
1157  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
1158  {
1159  THROW_LOGICAL_ERROR2("Rank = ", rank);
1160  }
1161 
1162  // if( collectingMode || p->second->isCandidateOfCollecting() )
1163  // {
1164  // THROW_LOGICAL_ERROR3("Rank = ", rank, " should not be in colleting mode and shuould not be a candidate of collecting.");
1165  // }
1166  return p->second->deleteCurrentNode();
1167  }
1168  else
1169  {
1170  THROW_LOGICAL_ERROR2("Rank = ", rank);
1171  }
1172  }
1173  else
1174  {
1175  if( pool[SOLVER_POOL_INDEX( rank )]->getStatus() != InterruptRequested &&
1176  pool[SOLVER_POOL_INDEX( rank )]->getStatus() != TerminateRequested &&
1177  pool[SOLVER_POOL_INDEX( rank )]->getStatus() != Terminated )
1178  {
1179  std::cout << "Status = " << static_cast<int>(pool[SOLVER_POOL_INDEX( rank )]->getStatus()) << std::endl;
1180  THROW_LOGICAL_ERROR2("Rank = ", rank);
1181  }
1182  }
1183 }
1184 
1185 /** inactivate the Solver specified by rank */
1186 void
1188  int rank, ///< rank of the solver to be inactivated
1189  long long numOfNodesSolved, ///< number of nodes solved
1190  BbParaNodePool *paraNodePool ///< pointer to ParaNodePool to change into collecting mode
1191  )
1192 {
1193  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
1194  {
1195  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
1196  }
1197  // if( breakingFirstSubtree && rank == 1 && pool[SOLVER_POOL_INDEX(rank)]->isInCollectingMode() )
1198  if( breakingFirstSubtree && rank == 1 )
1199  {
1200  breakingFirstSubtree = false;
1201  }
1202  sendSwitchOutCollectingModeIfNecessary( rank );
1203  map<int, BbParaSolverPoolElementPtr>::iterator p;
1204  if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active ||
1205  pool[SOLVER_POOL_INDEX( rank )]->getStatus() == InterruptRequested ||
1206  pool[SOLVER_POOL_INDEX( rank )]->getStatus() == TerminateRequested )
1207  {
1208  p = activeSolvers.find(rank);
1209  if( p != activeSolvers.end() )
1210  {
1211  if( p->second->getRank() != rank ||
1212  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
1213  {
1214  THROW_LOGICAL_ERROR2("Rank = ", rank);
1215  }
1216  if( numOfNodesSolved >= 0 )
1217  {
1218  nNodesSolvedInSolvers += numOfNodesSolved - p->second->getNumOfNodesSolved();
1219  // if(nNodesSolvedInSolvers > 999) abort();
1220  }
1221  nNodesInSolvers -= p->second->getNumOfNodesLeft();
1222  if( collectingMode && !pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
1223  {
1224  // Don't have to send this message. Solver should be initialized with out of collecting mode
1225  //
1226  // PARA_COMM_CALL(
1227  // paraComm->send(NULL, 0, ParaBYTE, p->second->getRank(), TagOutCollectingMode)
1228  // );
1229  //
1230  // Should be initialized
1231  // pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(false);
1232  nCollectingModeSolvers--;
1233  if( paraNodePool &&
1234  selectionHeap->top()->getNumOfNodesLeft() > 1 &&
1235  selectionHeap->top()->isGenerator() &&
1236  (!selectionHeap->top()->isCollectingProhibited()) &&
1237  selectionHeap->top()->isOutCollectingMode() )
1238  {
1239  //
1240  // the solver with the best dual bound should always in collecting mode first!
1241  //
1242  switchInCollectingToSolver(selectionHeap->top()->getRank(), paraNodePool);
1243  }
1244  }
1245  if( p->second->isCandidateOfCollecting() )
1246  {
1247  std::multimap< double, BbParaSolverPoolElementPtr >::iterator pCandidate;
1248  for( pCandidate = candidatesOfCollectingModeSolvers.begin();
1249  pCandidate != candidatesOfCollectingModeSolvers.end(); ++pCandidate )
1250  {
1251  if( pCandidate->second->getRank() == rank )
1252  break;
1253  }
1254  assert( pCandidate != candidatesOfCollectingModeSolvers.end() );
1255  pCandidate->second->setCandidateOfCollecting(false);
1256  candidatesOfCollectingModeSolvers.erase(pCandidate);
1257  }
1258  activeSolvers.erase(p);
1259  }
1260  else
1261  {
1262  THROW_LOGICAL_ERROR2("Rank = ", rank);
1263  }
1264  }
1265  else
1266  {
1267  THROW_LOGICAL_ERROR2("Rank = ", rank);
1268  }
1269  selectionHeap->deleteElement(pool[SOLVER_POOL_INDEX( rank )]); /** need to have dual bound, so should be before inactivate() */
1270  if( collectingModeSolverHeap && pool[SOLVER_POOL_INDEX(rank)]->isInCollectingMode() )
1271  {
1272  collectingModeSolverHeap->deleteElement(pool[SOLVER_POOL_INDEX(rank)]);
1273  }
1274  pool[SOLVER_POOL_INDEX( rank )]->inactivate();
1275  if( paraParams->getBoolParamValue(ControlCollectingModeOnSolverSide) )
1276  {
1277  pool[SOLVER_POOL_INDEX( rank )]->setCollectingIsAllowed();
1278  }
1279  inactiveSolvers.insert(make_pair(rank,pool[SOLVER_POOL_INDEX( rank )]));
1280 }
1281 
1282 /** reset counters in the Solver specified by rank */
1283 void
1285  int rank, ///< rank of the solver to be inactivated
1286  long long numOfNodesSolved, ///< number of nodes solved
1287  int numOfSelfSplitNodesLeft, ///< number of self-split nodes left
1288  BbParaNodePool *paraNodePool ///< pointer to ParaNodePool to change into collecting mode
1289  )
1290 {
1291  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
1292  {
1293  THROW_LOGICAL_ERROR2("Invalid rank. Rank = ", rank);
1294  }
1295  // if( breakingFirstSubtree && rank == 1 && pool[SOLVER_POOL_INDEX(rank)]->isInCollectingMode() )
1296  if( breakingFirstSubtree && rank == 1 )
1297  {
1298  breakingFirstSubtree = false;
1299  }
1300  sendSwitchOutCollectingModeIfNecessary( rank );
1301  map<int, BbParaSolverPoolElementPtr>::iterator p;
1302  if ( pool[SOLVER_POOL_INDEX( rank )]->getStatus() == Active )
1303  {
1304  p = activeSolvers.find(rank);
1305  if( p != activeSolvers.end() )
1306  {
1307  if( p->second->getRank() != rank ||
1308  pool[SOLVER_POOL_INDEX( rank )]->getRank() != rank )
1309  {
1310  THROW_LOGICAL_ERROR2("Rank = ", rank);
1311  }
1312  nNodesSolvedInSolvers += numOfNodesSolved - p->second->getNumOfNodesSolved();
1313  // if(nNodesSolvedInSolvers > 999) abort();
1314  nNodesInSolvers -= p->second->getNumOfNodesLeft();
1315  if( collectingMode && !pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
1316  {
1317  // Don't have to send this message. Solver should be initialized with out of collecting mode
1318  //
1319  // PARA_COMM_CALL(
1320  // paraComm->send(NULL, 0, ParaBYTE, p->second->getRank(), TagOutCollectingMode)
1321  // );
1322  //
1323  // Should be initialized
1324  // pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(false);
1325  nCollectingModeSolvers--;
1326  if( selectionHeap->top()->getNumOfNodesLeft() > 1 &&
1327  selectionHeap->top()->isGenerator() &&
1328  (!selectionHeap->top()->isCollectingProhibited()) &&
1329  selectionHeap->top()->isOutCollectingMode() )
1330  {
1331  //
1332  // the solver with the best dual bound should always in collecting mode first!
1333  //
1334  switchInCollectingToSolver(selectionHeap->top()->getRank(), paraNodePool);
1335  }
1336  }
1337  if( p->second->isCandidateOfCollecting() )
1338  {
1339  std::multimap< double, BbParaSolverPoolElementPtr >::iterator pCandidate;
1340  for( pCandidate = candidatesOfCollectingModeSolvers.begin();
1341  pCandidate != candidatesOfCollectingModeSolvers.end(); ++pCandidate )
1342  {
1343  if( pCandidate->second->getRank() == rank )
1344  break;
1345  }
1346  assert( pCandidate != candidatesOfCollectingModeSolvers.end() );
1347  pCandidate->second->setCandidateOfCollecting(false);
1348  candidatesOfCollectingModeSolvers.erase(pCandidate);
1349  }
1350  activeSolvers.erase(p);
1351  }
1352  else
1353  {
1354  THROW_LOGICAL_ERROR2("Rank = ", rank);
1355  }
1356  }
1357  else
1358  {
1359  THROW_LOGICAL_ERROR2("Rank = ", rank);
1360  }
1361  // selectionHeap->deleteElement(pool[SOLVER_POOL_INDEX( rank )]); /** need to have dual bound, so should be before inactivate() */
1362  if( collectingModeSolverHeap && pool[SOLVER_POOL_INDEX(rank)]->isInCollectingMode() )
1363  {
1364  collectingModeSolverHeap->deleteElement(pool[SOLVER_POOL_INDEX(rank)]);
1365  }
1366  BbParaNode *node = pool[SOLVER_POOL_INDEX( rank )]->extractCurrentNode();
1367  // assert( node );
1368  selectionHeap->deleteElement(pool[SOLVER_POOL_INDEX( rank )]); /** need to have dual bound, so should be before inactivate() */
1369  if( collectingModeSolverHeap && pool[SOLVER_POOL_INDEX(rank)]->isInCollectingMode() )
1370  {
1371  collectingModeSolverHeap->deleteElement(pool[SOLVER_POOL_INDEX(rank)]);
1372  }
1373  pool[SOLVER_POOL_INDEX( rank )]->inactivate();
1374  // pool[SOLVER_POOL_INDEX( rank )]->activate(node);
1375  if( paraParams->getBoolParamValue(ControlCollectingModeOnSolverSide) )
1376  {
1377  pool[SOLVER_POOL_INDEX( rank )]->setCollectingIsAllowed();
1378  }
1379  inactiveSolvers.insert(make_pair(rank,pool[SOLVER_POOL_INDEX( rank )]));
1380  if( node )
1381  {
1382  activateSolver(rank, node, numOfSelfSplitNodesLeft);
1383  }
1384 }
1385 
1386 /** solver specified by rank died */
1387 BbParaNode *
1389  int rank /**< rank of the dead solver */
1390  )
1391 {
1392  if( rank < originRank || rank >= (signed)(originRank + nSolvers) )
1393  {
1394  THROW_LOGICAL_ERROR2("Rank = ", rank);
1395  }
1396  map<int, BbParaSolverPoolElementPtr>::iterator p;
1397  if ( pool[SOLVER_POOL_INDEX(rank)]->getStatus() == Active )
1398  {
1399  p = activeSolvers.find(rank);
1400  if( p != activeSolvers.end() )
1401  {
1402  if( p->second->getRank() != rank ||
1403  pool[SOLVER_POOL_INDEX(rank)]->getRank() != rank )
1404  {
1405  THROW_LOGICAL_ERROR2("Rank = ", rank);
1406  }
1407  nNodesSolvedInSolvers -= p->second->getNumOfNodesSolved();
1408  nNodesInSolvers -= p->second->getNumOfNodesLeft();
1409  activeSolvers.erase(p);
1410  }
1411  else
1412  {
1413  THROW_LOGICAL_ERROR2("Rank = ", rank);
1414  }
1415  }
1416  else
1417  {
1418  THROW_LOGICAL_ERROR2("Rank = ", rank);
1419  }
1420  selectionHeap->deleteElement(pool[SOLVER_POOL_INDEX(rank)]); /** need to have dual bound, so should be before died() */
1421  if( collectingModeSolverHeap && pool[SOLVER_POOL_INDEX(rank)]->isInCollectingMode() )
1422  {
1423  collectingModeSolverHeap->deleteElement(pool[SOLVER_POOL_INDEX(rank)]);
1424  }
1425  deadSolvers.insert(make_pair(rank,pool[SOLVER_POOL_INDEX(rank)]));
1426  return pool[SOLVER_POOL_INDEX(rank)]->died();
1427 }
1428 
1429 /** switch out collecting mode */
1430 void
1432  )
1433 {
1434  if( !collectingMode )
1435  {
1436  return;
1437  }
1438  if( activeSolvers.size() > 0 )
1439  {
1440  map<int, BbParaSolverPoolElementPtr>::iterator p;
1441  for( p = activeSolvers.begin(); p != activeSolvers.end(); ++p)
1442  {
1443  int rank = p->second->getRank();
1444  sendSwitchOutCollectingModeIfNecessary(rank);
1445  if ( pool[SOLVER_POOL_INDEX(rank)]->isCandidateOfCollecting() )
1446  {
1447  pool[SOLVER_POOL_INDEX(rank)]->setCandidateOfCollecting(false);
1448  /** clear candidatesOfCollectingModeSolvers in below */
1449  }
1450  if( paraParams->getBoolParamValue(DualBoundGainTest) &&
1451  pool[SOLVER_POOL_INDEX(rank)]->isDualBoundGainTesting() )
1452  {
1454  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoTestDualBoundGain )
1455  );
1456  pool[SOLVER_POOL_INDEX(rank)]->setDualBoundGainTesting(false);
1457  nDualBoundGainTesting--;
1458  }
1459  }
1460  }
1461  assert(nCollectingModeSolvers == 0);
1462  nCollectingModeSolvers = 0;
1463  candidatesOfCollectingModeSolvers.clear();
1464  collectingMode = false;
1465  switchOutTime = paraTimer->getElapsedTime();
1466 }
1467 
1468 /** switch out collecting mode to the specified rank if it is necessary */
1469 void
1471  int rank /**< rank of the solver */
1472  )
1473 {
1474  /** sending TagOutCollectingMode is harmless */
1476  paraComm->send( NULL, 0, ParaBYTE, rank, TagOutCollectingMode )
1477  );
1478  /** pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() should be true */
1479  if ( !pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
1480  {
1481  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(false);
1482  if( collectingModeSolverHeap )
1483  {
1484  collectingModeSolverHeap->deleteElement(pool[SOLVER_POOL_INDEX(rank)]);
1485  }
1486  nCollectingModeSolvers--;
1487  }
1488 }
1489 
1490 /** switch out collecting mode to the specified rank */
1491 void
1493  int rank
1494  )
1495 {
1496  if ( !pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
1497  {
1499  paraComm->send( NULL, 0, ParaBYTE, rank, TagOutCollectingMode )
1500  );
1501  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(false);
1502  if( collectingModeSolverHeap )
1503  {
1504  collectingModeSolverHeap->deleteElement(pool[SOLVER_POOL_INDEX(rank)]);
1505  }
1506  nCollectingModeSolvers--;
1507  }
1508 }
1509 
1510 /** send switch in-collecting mode to a specific solver */
1511 void
1513  int rank,
1514  BbParaNodePool *paraNodePool
1515  )
1516 {
1517  // assert(nLimitCollectingModeSolvers > nCollectingModeSolvers); ** this is not hold anymore **
1518  int nCollect = std::min(pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft()/4,
1519  static_cast<int>(
1520  getNumInactiveSolvers() +
1521  paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes*
1522  paraParams->getRealParamValue(MultiplierForCollectingMode)
1523  - (signed)paraNodePool->getNumOfGoodNodes(getGlobalBestDualBoundValue())));
1524  if( (signed)paraNodePool->getNumOfGoodNodes( getGlobalBestDualBoundValue()) <
1525  (paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes)/4 )
1526  {
1527  nCollect = 0 - (nCollect + 1); // indicate aggressive collecting
1528  }
1529  assert( pool[SOLVER_POOL_INDEX(rank)]->isGenerator() );
1530  assert( !pool[SOLVER_POOL_INDEX(rank)]->isCollectingProhibited() );
1531  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
1532  {
1534  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
1535  );
1536  }
1538  paraComm->send(&nCollect, 1, ParaINT, rank, TagInCollectingMode)
1539  );
1540  if( pool[SOLVER_POOL_INDEX(rank)]->isCandidateOfCollecting() )
1541  {
1542  std::multimap< double, BbParaSolverPoolElementPtr >::iterator pCandidate;
1543  for( pCandidate = candidatesOfCollectingModeSolvers.begin();
1544  pCandidate != candidatesOfCollectingModeSolvers.end(); ++pCandidate )
1545  {
1546  if( pCandidate->second->getRank() == rank )
1547  break;
1548  }
1549  assert( pCandidate != candidatesOfCollectingModeSolvers.end() );
1550  pCandidate->second->setCandidateOfCollecting(false);
1551  candidatesOfCollectingModeSolvers.erase(pCandidate);
1552  }
1553  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(true);
1554  if( collectingModeSolverHeap )
1555  {
1556  collectingModeSolverHeap->insert( pool[SOLVER_POOL_INDEX(rank)] );
1557  }
1558  nCollectingModeSolvers++;
1559 }
1560 
1561 /** send switch in-collecting mode */
1562 void
1564  BbParaNodePool *paraNodePool
1565  )
1566 {
1567  if( paraParams->getBoolParamValue(DualBoundGainTest) &&
1568  ( beforeInitialCollect || (!beforeInitialCollect && beforeFinishingFirstCollect) ) &&
1569  (signed)paraNodePool->getNumOfGoodNodes(getGlobalBestDualBoundValue()) >
1570  paraParams->getIntParamValue(NChangeIntoCollectingMode) * 0.1
1571  )
1572  {
1573  return;
1574  }
1575  if( paraParams->getRealParamValue(CollectingModeInterval) > 0.0 &&
1576  switchOutTime > 0 &&
1577  (paraTimer->getElapsedTime() - switchOutTime) <
1578  paraParams->getRealParamValue(CollectingModeInterval) &&
1579  mCollectingNodes < 100 )
1580  {
1581  if( candidatesOfCollectingModeSolvers.size() > 0 &&
1582  candidatesOfCollectingModeSolvers.begin()->second->getNumOfDiffNodesLeft() < 0 )
1583  {
1584  mCollectingNodes--;
1585  if( mCollectingNodes <= 0 ) mCollectingNodes = 1;
1586  }
1587  else
1588  {
1589  mCollectingNodes++;
1590  if( mCollectingNodes > mMaxCollectingNodes )
1591  {
1592  mMaxCollectingNodes = mCollectingNodes;
1593  }
1594  }
1595  switchOutTime = -1.0;
1596  // std::cout << paraTimer->getElapsedTime() << " mCollectingNodes = " << mCollectingNodes << std::endl;
1597  }
1598  int nCollect = static_cast<int>(
1599  getNumInactiveSolvers() +
1600  paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes*
1601  paraParams->getRealParamValue(MultiplierForCollectingMode)
1602  - (signed)paraNodePool->getNumOfGoodNodes(getGlobalBestDualBoundValue()));
1603  map<int, BbParaSolverPoolElementPtr>::iterator p;
1604  if( activeSolvers.size() > 0 )
1605  {
1606  if( breakingFirstSubtree )
1607  {
1608  for( p = activeSolvers.begin();
1609  p != activeSolvers.end();
1610  ++p)
1611  {
1612  if( p->second->getRank() == 1 )
1613  {
1614  int rank = p->second->getRank();
1615  assert(pool[SOLVER_POOL_INDEX(rank)]->isGenerator());
1616  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
1617  {
1619  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
1620  );
1621  }
1623  paraComm->send(&nCollect, 1, ParaINT, rank, TagInCollectingMode )
1624  );
1625  nCollect = 0;
1626  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(true);
1627  if( collectingModeSolverHeap )
1628  {
1629  collectingModeSolverHeap->insert( pool[SOLVER_POOL_INDEX(rank)] );
1630  }
1631  nCollectingModeSolvers++;
1632  break;
1633  }
1634  }
1635  }
1636  if( nCollect > 0 )
1637  {
1638  double globalBestDualBoundValue = selectionHeap->top()->getBestDualBoundValue();
1639  switch( paraParams->getIntParamValue(SolverOrderInCollectingMode) )
1640  {
1641  case -1: // no ordering
1642  {
1643  for( p = activeSolvers.begin();
1644  p != activeSolvers.end() && nLimitCollectingModeSolvers > nCollectingModeSolvers;
1645  ++p)
1646  {
1647  if( p->second->getNumOfNodesLeft() > 1 && /* Solver should have at least two nodes left */
1648  ( (p->second->getBestDualBoundValue() - globalBestDualBoundValue) /
1649  max( fabs(globalBestDualBoundValue), 1.0 ) ) < bgap )
1650  {
1651  int rank = p->second->getRank();
1652  if ( pool[SOLVER_POOL_INDEX(rank)]->isGenerator() &&
1653  pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
1654  {
1655  int nCollectPerSolver = std::min(
1656  pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft()/4, nCollect );
1657  if( (signed)paraNodePool->getNumOfGoodNodes( getGlobalBestDualBoundValue()) <
1658  (paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes)/4 )
1659  {
1660  nCollectPerSolver = 0 - (nCollectPerSolver + 1); // indicate aggressive collecting
1661  }
1662  assert(pool[SOLVER_POOL_INDEX(rank)]->isGenerator());
1663  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
1664  {
1666  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
1667  );
1668  }
1670  paraComm->send(&nCollectPerSolver, 1, ParaINT, rank, TagInCollectingMode )
1671  );
1672  nCollect -= nCollectPerSolver;
1673  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(true);
1674  nCollectingModeSolvers++;
1675  }
1676  }
1677  else
1678  {
1679  // The following code works, when the number of collecting mode solvers is increased
1680  if( !paraNodePool->isEmpty() &&
1681  ( ( (p->second->getBestDualBoundValue() - globalBestDualBoundValue) /
1682  max( fabs(globalBestDualBoundValue), 1.0 ) ) > ( bgap * mBgap ) ) )
1683  {
1684  int rank = p->second->getRank();
1685  sendSwitchOutCollectingModeIfNecessary( rank );
1686  }
1687  }
1688  }
1689  break;
1690  }
1691  case 0: // ordering by dual bound value
1692  {
1693 
1694  std::multimap< double, int > boundOrderMap;
1695  for( p = activeSolvers.begin(); p != activeSolvers.end(); ++p )
1696  {
1697  boundOrderMap.insert(std::make_pair(p->second->getBestDualBoundValue(),p->second->getRank()));
1698  }
1699  std::multimap< double, int >::iterator pbo;
1700  for( pbo = boundOrderMap.begin();
1701  pbo != boundOrderMap.end() && nLimitCollectingModeSolvers > nCollectingModeSolvers;
1702  ++pbo )
1703  {
1704  int rank = pbo->second;
1705  if( pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft() > 1 ) // Solver should have at least two nodes left
1706  {
1707  if ( pool[SOLVER_POOL_INDEX(rank)]->isGenerator() &&
1708  pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
1709  {
1710  int nCollectPerSolver = std::min(
1711  pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft()/4, nCollect );
1712  if( (signed)paraNodePool->getNumOfGoodNodes( getGlobalBestDualBoundValue()) <
1713  (paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes)/4 )
1714  {
1715  nCollectPerSolver = 0 - (nCollectPerSolver + 1); // indicate aggressive collecting
1716  }
1717  assert(pool[SOLVER_POOL_INDEX(rank)]->isGenerator());
1718  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
1719  {
1721  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
1722  );
1723  }
1725  paraComm->send(&nCollectPerSolver, 1, ParaINT, rank, TagInCollectingMode )
1726  );
1727  nCollect -= nCollectPerSolver;
1728  if( pool[SOLVER_POOL_INDEX(rank)]->isCandidateOfCollecting() )
1729  {
1730  std::multimap< double, BbParaSolverPoolElementPtr >::iterator pCandidate;
1731  for( pCandidate = candidatesOfCollectingModeSolvers.begin();
1732  pCandidate != candidatesOfCollectingModeSolvers.end(); ++pCandidate )
1733  {
1734  if( pCandidate->second->getRank() == rank )
1735  break;
1736  }
1737  assert( pCandidate != candidatesOfCollectingModeSolvers.end() );
1738  pCandidate->second->setCandidateOfCollecting(false);
1739  candidatesOfCollectingModeSolvers.erase(pCandidate);
1740  }
1741  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(true);
1742  assert( collectingModeSolverHeap );
1743  collectingModeSolverHeap->insert( pool[SOLVER_POOL_INDEX(rank)] );
1744  nCollectingModeSolvers++;
1745  }
1746  else // pool[SOLVER_POOL_INDEX(rank)] is in collecting mode
1747  {
1748  if( pool[SOLVER_POOL_INDEX(rank)]->isGenerator() )
1749  {
1750  assert( pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() ); // No collecting mode soler exists. Never comes here.
1751  THROW_LOGICAL_ERROR2("Logical Error. All solvers are not in collecting mode. rank = ", rank);
1752  // The following code works, when the number of collecting mode solvers is increased
1753  if( !paraNodePool->isEmpty() &&
1754  ( ( (pool[SOLVER_POOL_INDEX(rank)]->getBestDualBoundValue() - globalBestDualBoundValue) /
1755  max( fabs(globalBestDualBoundValue), 1.0 ) ) > ( bgap * mBgap ) ) )
1756  {
1757  sendSwitchOutCollectingModeIfNecessary( rank );
1758  }
1759  else // re-boost the collecting mode solver
1760  {
1761  sendSwitchOutCollectingModeIfNecessary( rank );
1762  int nCollectPerSolver = std::min(
1763  pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft()/4, nCollect );
1764  if( (signed)paraNodePool->getNumOfGoodNodes( getGlobalBestDualBoundValue()) <
1765  (paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes)/4 )
1766  {
1767  nCollectPerSolver = 0 - (nCollectPerSolver + 1); // indicate aggressive collecting
1768  }
1769  assert(pool[SOLVER_POOL_INDEX(rank)]->isGenerator());
1770  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
1771  {
1773  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
1774  );
1775  }
1777  paraComm->send(&nCollectPerSolver, 1, ParaINT, rank, TagInCollectingMode )
1778  );
1779  nCollect -= nCollectPerSolver;
1780  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(true);
1781  assert( collectingModeSolverHeap );
1782  collectingModeSolverHeap->insert( pool[SOLVER_POOL_INDEX(rank)] );
1783  // the solvers was already in collecting mode, so do not have to nCollectingModeSolvers++;
1784  }
1785  }
1786  }
1787  }
1788  }
1789  for(; pbo != boundOrderMap.end() &&
1790  static_cast<int>( candidatesOfCollectingModeSolvers.size() )
1791  < std::min((int)nLimitCollectingModeSolvers,
1792  paraParams->getIntParamValue(NMaxCanditatesForCollecting) );
1793  ++pbo )
1794  {
1795  int rank = pbo->second;
1796  if( pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft() > 1 &&
1797  pool[SOLVER_POOL_INDEX(rank)]->isGenerator() &&
1798  ( !pool[SOLVER_POOL_INDEX(rank)]->isCandidateOfCollecting() ) )
1799  {
1800  candidatesOfCollectingModeSolvers.insert(
1801  make_pair(pool[SOLVER_POOL_INDEX(rank)]->getBestDualBoundValue(),pool[SOLVER_POOL_INDEX(rank)])
1802  );
1803  pool[SOLVER_POOL_INDEX(rank)]->setCandidateOfCollecting(true);
1804  }
1805  }
1806  break;
1807  }
1808  case 1: // ordering by number of nodes left
1809  {
1810  std::multimap< int, int > nNodesOrderMap;
1811  for( p = activeSolvers.begin(); p != activeSolvers.end(); ++p )
1812  {
1813  nNodesOrderMap.insert(std::make_pair(p->second->getNumOfNodesLeft(),p->second->getRank()));
1814  }
1815  std::multimap< int, int >::iterator pno;
1816  for( pno = nNodesOrderMap.begin();
1817  pno != nNodesOrderMap.end() && nLimitCollectingModeSolvers > nCollectingModeSolvers;
1818  ++pno )
1819  {
1820  int rank = pno->second;
1821  if( pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft() > 1 && /* Solver should have at least two nodes left */
1822  pool[SOLVER_POOL_INDEX(rank)]->isGenerator() &&
1823  ( (pool[SOLVER_POOL_INDEX(rank)]->getBestDualBoundValue() - globalBestDualBoundValue) /
1824  max( fabs(globalBestDualBoundValue), 1.0 ) ) < bgap )
1825  {
1826  if ( pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
1827  {
1828  int nCollectPerSolver = std::min(
1829  pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft()/4, nCollect );
1830  if( (signed)paraNodePool->getNumOfGoodNodes( getGlobalBestDualBoundValue()) <
1831  (paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes)/4 )
1832  {
1833  nCollectPerSolver = 0 - (nCollectPerSolver + 1); // indicate aggressive collecting
1834  }
1835  assert(pool[SOLVER_POOL_INDEX(rank)]->isGenerator());
1836  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
1837  {
1839  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
1840  );
1841  }
1843  paraComm->send(&nCollectPerSolver, 1, ParaINT, rank, TagInCollectingMode )
1844  );
1845  nCollect -= nCollectPerSolver;
1846  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(true);
1847  nCollectingModeSolvers++;
1848  }
1849  }
1850  else
1851  {
1852  // The following code works, when the number of collecting mode solvers is increased
1853  if( !paraNodePool->isEmpty() &&
1854  ( ( (pool[SOLVER_POOL_INDEX(rank)]->getBestDualBoundValue() - globalBestDualBoundValue) /
1855  max( fabs(globalBestDualBoundValue), 1.0 ) ) > ( bgap * mBgap ) ) )
1856  {
1857  sendSwitchOutCollectingModeIfNecessary( rank );
1858  }
1859  }
1860  }
1861  break;
1862  }
1863  case 2: // choose alternatively the best bound and the number of nodes orders
1864  {
1865  std::multimap< double, int > boundOrderMap;
1866  for( p = activeSolvers.begin(); p != activeSolvers.end(); ++p )
1867  {
1868  boundOrderMap.insert(std::make_pair(p->second->getBestDualBoundValue(),p->second->getRank()));
1869  }
1870  std::multimap< int, int > nNodesOrderMap;
1871  for( p = activeSolvers.begin(); p != activeSolvers.end(); ++p )
1872  {
1873  nNodesOrderMap.insert(std::make_pair(p->second->getNumOfNodesLeft(),p->second->getRank()));
1874  }
1875  std::multimap< double, int >::iterator pbo;
1876  std::multimap< int, int >::iterator pno;
1877  pbo = boundOrderMap.begin();
1878  pno = nNodesOrderMap.begin();
1879  bool boundOrderSection = true;
1880  while( pbo != boundOrderMap.end()
1881  && pno != nNodesOrderMap.end()
1882  && nLimitCollectingModeSolvers > nCollectingModeSolvers )
1883  {
1884  int rank;
1885  if( boundOrderSection )
1886  {
1887  if( pbo != boundOrderMap.end() )
1888  {
1889  rank = pbo->second;
1890  pbo++;
1891  boundOrderSection = false;
1892  }
1893  else
1894  {
1895  boundOrderSection = false;
1896  continue;
1897  }
1898  }
1899  else
1900  {
1901  if( pno != nNodesOrderMap.end() )
1902  {
1903  rank = pno->second;
1904  pno++;
1905  boundOrderSection = true;
1906  } else {
1907  boundOrderSection = true;
1908  continue;
1909  }
1910  }
1911  if( pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft() > 1 && /* Solver should have at least two nodes left */
1912  pool[SOLVER_POOL_INDEX(rank)]->isGenerator() &&
1913  ( (pool[SOLVER_POOL_INDEX(rank)]->getBestDualBoundValue() - globalBestDualBoundValue) /
1914  max( fabs(globalBestDualBoundValue), 1.0 ) ) < bgap )
1915  {
1916  if ( pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
1917  {
1918  int nCollectPerSolver = std::min(
1919  pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft()/4, nCollect );
1920  if( (signed)paraNodePool->getNumOfGoodNodes( getGlobalBestDualBoundValue()) <
1921  (paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes)/4 )
1922  {
1923  nCollectPerSolver = 0 - (nCollectPerSolver + 1); // indicate aggressive collecting
1924  }
1925  assert(pool[SOLVER_POOL_INDEX(rank)]->isGenerator());
1926  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
1927  {
1929  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
1930  );
1931  }
1933  paraComm->send(&nCollectPerSolver, 1, ParaINT, rank, TagInCollectingMode )
1934  );
1935  nCollect -= nCollectPerSolver;
1936  pool[SOLVER_POOL_INDEX(rank)]->setCollectingMode(true);
1937  nCollectingModeSolvers++;
1938  }
1939  }
1940  else
1941  {
1942  // The following code works, when the number of collecting mode solvers is increased
1943  if( !paraNodePool->isEmpty() &&
1944  ( ( (pool[SOLVER_POOL_INDEX(rank)]->getBestDualBoundValue() - globalBestDualBoundValue) /
1945  max( fabs(globalBestDualBoundValue), 1.0 ) ) > ( bgap * mBgap ) ) )
1946  {
1947  sendSwitchOutCollectingModeIfNecessary( rank );
1948  }
1949  }
1950  }
1951  break;
1952  }
1953  default:
1954  THROW_LOGICAL_ERROR2("paraParams->getIntParamValue(SolverOrderInCollectingMode) = ", paraParams->getIntParamValue(SolverOrderInCollectingMode));
1955  }
1956  }
1957  }
1958  collectingMode = true;
1959  if( !beforeInitialCollect ) beforeFinishingFirstCollect = false;
1960  beforeInitialCollect = false;
1961 }
1962 
1963 void
1965  int rank,
1966  long long numOfNodesSolved,
1967  int numOfNodesLeft,
1968  double solverLocalBestDualBound,
1969  BbParaNodePool *paraNodePool
1970  )
1971 {
1972  map<int, BbParaSolverPoolElementPtr>::iterator p;
1973  p = activeSolvers.find(rank);
1974  if( p != activeSolvers.end() )
1975  {
1976  if( (numOfNodesSolved - p->second->getNumOfNodesSolved() ) < 0 )
1977  {
1978  std::cout << "numOfNodesSolved = " << numOfNodesSolved << ", p->second->getNumOfNodesSolved() = " << p->second->getNumOfNodesSolved() << std::endl;
1979  THROW_LOGICAL_ERROR2("Rank = ", rank);
1980  }
1981  // assert( (numOfNodesSolved - p->second->getNumOfNodesSolved() ) >= 0 ); // if solver restart, this is not always true
1982  nNodesSolvedInSolvers += numOfNodesSolved - p->second->getNumOfNodesSolved();
1983  // if(nNodesSolvedInSolvers > 999) abort();
1984  nNodesInSolvers += numOfNodesLeft - p->second->getNumOfNodesLeft();
1985  p->second->setNumOfDiffNodesSolved( numOfNodesSolved - p->second->getNumOfNodesSolved() );
1986  p->second->setNumOfNodesSolved(numOfNodesSolved);
1987  p->second->setNumOfDiffNodesLeft( numOfNodesLeft - p->second->getNumOfNodesLeft() );
1988  p->second->setNumOfNodesLeft(numOfNodesLeft);
1989  if( p->second->getBestDualBoundValue() < solverLocalBestDualBound ) // even in LP solving, solver may notify its status
1990  {
1991  p->second->setDualBoundValue(solverLocalBestDualBound);
1992  selectionHeap->updateDualBoundValue(*(p->second->getSelectionHeapElement()), solverLocalBestDualBound);
1993  if( p->second->isInCollectingMode() )
1994  {
1995  if( collectingModeSolverHeap )
1996  {
1997  collectingModeSolverHeap->updateDualBoundValue(*(p->second->getCollectingModeSolverHeapElement()), solverLocalBestDualBound);
1998  }
1999  }
2000  }
2001  }
2002  else
2003  {
2004  THROW_LOGICAL_ERROR2("Rank = ", rank);
2005  }
2006  double globalBestDualBoundValue = selectionHeap->top()->getBestDualBoundValue();
2007  if( globalBestDualBoundValue > p->second->getBestDualBoundValue() )
2008  {
2009  std::cout << "Top rank = " << selectionHeap->top()->getRank() << std::endl;
2010  std::cout << "Top bound = " << selectionHeap->top()->getBestDualBoundValue() << std::endl;
2011  std::cout << "This bound = " << p->second->getBestDualBoundValue() << std::endl;
2012  std::cout << "myRank = " << rank << std::endl;
2013  std::cout << "solverLocalBestDualBound = " << p->second->getBestDualBoundValue() << std::endl;
2014  std::cout << selectionHeap->toString();
2015  if( collectingModeSolverHeap )
2016  {
2017  std::cout << collectingModeSolverHeap->toString();
2018  }
2019  abort();
2020  }
2021 
2022  if( pool[SOLVER_POOL_INDEX(rank)]->isDualBoundGainTesting()
2023  && numOfNodesSolved > 1 )
2024  {
2025  pool[SOLVER_POOL_INDEX(rank)]->setDualBoundGainTesting(false);
2026  nDualBoundGainTesting--;
2027  }
2028 
2029  if( collectingMode )
2030  {
2031  int nCollect = 0; // assume zero
2032  if( pool[SOLVER_POOL_INDEX(rank)]->isInCollectingMode() )
2033  {
2034  if( !selectionHeap->top()->isInCollectingMode() &&
2035  selectionHeap->top()->isGenerator() &&
2036  (!selectionHeap->top()->isCollectingProhibited()) &&
2037  selectionHeap->top()->getNumOfNodesLeft() > 1 )
2038  {
2039  if( nLimitCollectingModeSolvers > nCollectingModeSolvers )
2040  {
2041  switchInCollectingToSolver(selectionHeap->top()->getRank(), paraNodePool);
2042  }
2043  else // nLimitCollectingModeSolvers == nCollectingModeSolvers
2044  {
2045  if( pool[SOLVER_POOL_INDEX(rank)]->getBestDualBoundValue() - absoluteGap
2046  < selectionHeap->top()->getBestDualBoundValue() )
2047  {
2048  if( !( breakingFirstSubtree && rank == 1 ) )
2049  {
2050  if( !paraNodePool->isEmpty() )
2051  {
2052  sendSwitchOutCollectingModeIfNecessary( rank );
2053  }
2054  switchInCollectingToSolver(selectionHeap->top()->getRank(), paraNodePool);
2055  }
2056  }
2057  }
2058  }
2059  else
2060  {
2061  if( collectingModeSolverHeap &&
2062  !( breakingFirstSubtree && collectingModeSolverHeap->getHeapSize() <= 1 ) &&
2063  ( p->second->getBestDualBoundValue() - collectingModeSolverHeap->top()->getBestDualBoundValue() ) > absoluteGap && // the notified solver is no so good
2064  ( (!candidatesOfCollectingModeSolvers.empty()) &&
2065  ( candidatesOfCollectingModeSolvers.begin()->second->getBestDualBoundValue() + absoluteGap ) // to avoid flip
2066  < p->second->getBestDualBoundValue() ) //promising candidates exists
2067  )
2068  {
2069  assert( p->second->getRank() == rank );
2070  assert( rank != selectionHeap->top()->getRank() );
2071  if( !paraNodePool->isEmpty() )
2072  {
2073  sendSwitchOutCollectingModeIfNecessary( rank );
2074  }
2075 
2076  std::multimap< double, BbParaSolverPoolElementPtr >::iterator pCandidate;
2077  pCandidate = candidatesOfCollectingModeSolvers.begin();
2078  assert( pCandidate->second->isOutCollectingMode() );
2079  // nCollect = std::min(selectionHeap->top()->getNumOfNodesLeft()/4,
2080  nCollect = std::min(pCandidate->second->getNumOfNodesLeft()/4,
2081  static_cast<int>(
2082  getNumInactiveSolvers() +
2083  paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes*
2084  paraParams->getRealParamValue(MultiplierForCollectingMode)
2085  - (signed)paraNodePool->getNumOfGoodNodes(getGlobalBestDualBoundValue())));
2086  if( (signed)paraNodePool->getNumOfGoodNodes( getGlobalBestDualBoundValue()) <
2087  (paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes)/4 )
2088  {
2089  nCollect = 0 - (nCollect + 1); // indicate aggressive collecting
2090  }
2091  assert(pool[SOLVER_POOL_INDEX(pCandidate->second->getRank())]->isGenerator());
2092  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
2093  {
2095  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
2096  );
2097  }
2099  paraComm->send(&nCollect, 1, ParaINT, pCandidate->second->getRank(), TagInCollectingMode)
2100  );
2101  pCandidate->second->setCollectingMode(true);
2102  collectingModeSolverHeap->insert( pCandidate->second );
2103  nCollectingModeSolvers++;
2104  pCandidate->second->setCandidateOfCollecting(false);
2105  candidatesOfCollectingModeSolvers.erase(pCandidate);
2106  }
2107  else
2108  {
2109  if( !paraNodePool->isEmpty() &&
2110  ( ( ( ( p->second->getBestDualBoundValue() - globalBestDualBoundValue ) /
2111  max( fabs(globalBestDualBoundValue), 1.0 ) ) > ( bgap * mBgap ) ) ) )
2112  {
2113  sendSwitchOutCollectingModeIfNecessary( p->second->getRank() );
2114  }
2115  }
2116  }
2117  }
2118  else // current notification solver is out collecting mode
2119  {
2120  if( nLimitCollectingModeSolvers > nCollectingModeSolvers )
2121  {
2122  if( pool[SOLVER_POOL_INDEX(rank)]->getRank() == selectionHeap->top()->getRank() &&
2123  pool[SOLVER_POOL_INDEX(rank)]->isGenerator() &&
2124  (!pool[SOLVER_POOL_INDEX(rank)]->isCollectingProhibited()) &&
2125  selectionHeap->top()->getNumOfNodesLeft() > 1 )
2126  {
2127  switchInCollectingToSolver(rank, paraNodePool);
2128  }
2129  }
2130  else // nLimitCollectingModeSolvers == nCollectingModeSolvers
2131  {
2132  if( !paraNodePool->isEmpty() &&
2133  pool[SOLVER_POOL_INDEX(rank)]->getNumOfDiffNodesLeft() > 1 &&
2134  collectingModeSolverHeap &&
2135  !( breakingFirstSubtree && collectingModeSolverHeap->getHeapSize() <= 1 ) &&
2136  ( pool[SOLVER_POOL_INDEX(rank)]->getBestDualBoundValue() + absoluteGap )
2137  < collectingModeSolverHeap->top()->getBestDualBoundValue() )
2138  {
2139  sendSwitchOutCollectingModeIfNecessary( collectingModeSolverHeap->top()->getRank() );
2140  }
2141  }
2142  }
2143 
2144  bool manyIdleSolversExist = false;
2145  if( getNumInactiveSolvers() > nSolvers/4 ) manyIdleSolversExist = true;
2146  if( nLimitCollectingModeSolvers > nCollectingModeSolvers )
2147  {
2148  if( manyIdleSolversExist )
2149  {
2150  double temp = switchOutTime;
2151  switchOutCollectingMode();
2152  switchOutTime = temp;
2153  switchInCollectingMode(paraNodePool);
2154  }
2155  else
2156  {
2157  if( selectionHeap->top()->getNumOfNodesLeft() > 1 &&
2158  selectionHeap->top()->isGenerator() &&
2159  (!selectionHeap->top()->isCollectingProhibited()) &&
2160  selectionHeap->top()->isOutCollectingMode() )
2161  {
2162  switchInCollectingToSolver(selectionHeap->top()->getRank(), paraNodePool);
2163  }
2164  else
2165  {
2166  if( !candidatesOfCollectingModeSolvers.empty() )
2167  {
2168  std::multimap< double, BbParaSolverPoolElementPtr >::iterator pCandidate;
2169  pCandidate = candidatesOfCollectingModeSolvers.begin();
2170  assert( pCandidate->second->isOutCollectingMode() );
2171  nCollect = std::min(pCandidate->second->getNumOfNodesLeft()/4,
2172  static_cast<int>(
2173  getNumInactiveSolvers() +
2174  paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes*
2175  paraParams->getRealParamValue(MultiplierForCollectingMode)
2176  - (signed)paraNodePool->getNumOfGoodNodes(getGlobalBestDualBoundValue())));
2177  if( (signed)paraNodePool->getNumOfGoodNodes( getGlobalBestDualBoundValue()) <
2178  (paraParams->getIntParamValue(NChangeIntoCollectingMode)*mCollectingNodes)/4 )
2179  {
2180  nCollect = 0 - (nCollect + 1); // indicate aggressive collecting
2181  }
2182  assert(pool[SOLVER_POOL_INDEX(pCandidate->second->getRank())]->isGenerator());
2183  if( paraNodePool->isEmpty() && nLimitCollectingModeSolvers > 10 )
2184  {
2186  paraComm->send(NULL, 0, ParaBYTE, rank, TagNoWaitModeSend )
2187  );
2188  }
2190  paraComm->send(&nCollect, 1, ParaINT, pCandidate->second->getRank(), TagInCollectingMode)
2191  );
2192  pCandidate->second->setCollectingMode(true);
2193  if( collectingModeSolverHeap )
2194  {
2195  collectingModeSolverHeap->insert( pCandidate->second );
2196  }
2197  nCollectingModeSolvers++;
2198  pCandidate->second->setCandidateOfCollecting(false);
2199  candidatesOfCollectingModeSolvers.erase(pCandidate);
2200  }
2201  else
2202  {
2203  assert( rank == p->second->getRank() );
2204  if( p->second->getNumOfNodesLeft() > 1 && // Solver should have at least two nodes left //
2205  p->second->isGenerator() &&
2206  ( !p->second->isCollectingProhibited() ) &&
2207  p->second->isOutCollectingMode() &&
2208  ( paraNodePool->isEmpty() ||
2209  ( ( ( p->second->getBestDualBoundValue() - globalBestDualBoundValue ) /
2210  max( fabs(globalBestDualBoundValue), 1.0 ) ) < bgap ) ) ) // &&
2211  {
2212  switchInCollectingToSolver(rank, paraNodePool);
2213  }
2214  }
2215  }
2216  }
2217  }
2218  else // nLimitCollectingModeSolvers == nCollectingModeSolvers
2219  {
2220  if ( pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
2221  {
2222  if( !candidatesOfCollectingModeSolvers.empty() )
2223  {
2224  std::multimap< double, BbParaSolverPoolElementPtr >::iterator pCandidate;
2225  if( p->second->isCandidateOfCollecting() )
2226  {
2227  for( pCandidate = candidatesOfCollectingModeSolvers.begin();
2228  pCandidate != candidatesOfCollectingModeSolvers.end(); ++pCandidate )
2229  {
2230  if( pCandidate->second->getRank() == rank )
2231  break;
2232  }
2233  if( pCandidate == candidatesOfCollectingModeSolvers.end() )
2234  {
2235  THROW_LOGICAL_ERROR3("rank = ", rank , " is not in candidatesOfCollectingModeSolvers.");
2236  }
2237  /* anyway remove to update dual bound value */
2238  pCandidate->second->setCandidateOfCollecting(false);
2239  candidatesOfCollectingModeSolvers.erase(pCandidate);
2240  }
2241  if( static_cast<int>( candidatesOfCollectingModeSolvers.size() )
2242  == std::min((signed)nLimitCollectingModeSolvers,
2243  paraParams->getIntParamValue(NMaxCanditatesForCollecting) ) )
2244  {
2245  std::multimap< double, BbParaSolverPoolElementPtr >::reverse_iterator prCandidate;
2246  prCandidate = candidatesOfCollectingModeSolvers.rbegin();
2247  if( p->second->getNumOfNodesLeft() > 1 &&
2248  p->second->isGenerator() &&
2249  prCandidate->second->getBestDualBoundValue() > p->second->getBestDualBoundValue() )
2250  {
2251  BbParaSolverPoolElementPtr tCandidate = prCandidate->second;
2252  // prCandidate->second->setCandidateOfCollecting(false);
2253  ++prCandidate;
2254  assert(prCandidate.base()->second == tCandidate);
2255  if( prCandidate.base()->second != tCandidate )
2256  {
2257  THROW_LOGICAL_ERROR4("prCandidate.base()->second != tCandidate, prCandidate.base()->second = ", prCandidate.base()->second, ", tCandidate = ", tCandidate );
2258  }
2259  prCandidate.base()->second->setCandidateOfCollecting(false);
2260  candidatesOfCollectingModeSolvers.erase(prCandidate.base());
2261  candidatesOfCollectingModeSolvers.insert(
2262  make_pair(p->second->getBestDualBoundValue(),p->second)
2263  );
2264  p->second->setCandidateOfCollecting(true);
2265  }
2266  }
2267  else // candidatesOfCollectingModeSolvers.size()
2268  // < std::min(nLimitCollectingModeSolvers,
2269  // paraParams->getIntParamValue(NMaxCanditatesForCollecting)
2270  {
2271  if( collectingModeSolverHeap &&
2272  !( breakingFirstSubtree && collectingModeSolverHeap->getHeapSize() <= 1 ) &&
2273  p->second->getNumOfNodesLeft() > 1 &&
2274  p->second->isGenerator() &&
2275  ( p->second->getBestDualBoundValue() - collectingModeSolverHeap->top()->getBestDualBoundValue() ) < absoluteGap )
2276  {
2277  candidatesOfCollectingModeSolvers.insert(
2278  make_pair(p->second->getBestDualBoundValue(),p->second)
2279  );
2280  p->second->setCandidateOfCollecting(true);
2281  // p->second solver is in collecting mode, when the current collecting mode solver notifies.
2282  }
2283  }
2284  }
2285  else // candidatesOfCollectingModeSolvers is empty
2286  {
2287  if( collectingModeSolverHeap &&
2288  !( breakingFirstSubtree && collectingModeSolverHeap->getHeapSize() <= 1 ) &&
2289  p->second->getNumOfNodesLeft() > 1 &&
2290  p->second->isGenerator() &&
2291  ( p->second->getBestDualBoundValue() - collectingModeSolverHeap->top()->getBestDualBoundValue() ) < absoluteGap )
2292  {
2293  candidatesOfCollectingModeSolvers.insert(
2294  make_pair(p->second->getBestDualBoundValue(),p->second)
2295  );
2296  p->second->setCandidateOfCollecting(true);
2297  // p->second solver is in collecting mode, when the current collecting mode solver notifies.
2298  }
2299  }
2300  }
2301  }
2302 #ifdef _DEBUG_LB
2303  std::cout << "ASBD = " << selectionHeap->top()->getBestDualBoundValue() << "(" << selectionHeap->top()->getRank() << ")";
2304  if( collectingModeSolverHeap && collectingModeSolverHeap->getHeapSize() > 0 )
2305  {
2306  std::cout << ", CMSBD = " << collectingModeSolverHeap->top()->getBestDualBoundValue() << "(" << collectingModeSolverHeap->top()->getRank() << ")";
2307  }
2308  if( !candidatesOfCollectingModeSolvers.empty() )
2309  {
2310  std::cout << ", CCSBD = ";
2311  std::multimap< double, BbParaSolverPoolElementPtr >::iterator pCandidate;
2312  for( pCandidate = candidatesOfCollectingModeSolvers.begin();
2313  pCandidate != candidatesOfCollectingModeSolvers.end(); ++pCandidate )
2314  {
2315  std::cout << ", " << pCandidate->second->getBestDualBoundValue() << "(" << pCandidate->second->getRank() << ")";
2316  }
2317  }
2318  std::cout << std::endl;
2319 #endif
2320  }
2321  else
2322  {
2323  if( !pool[SOLVER_POOL_INDEX(rank)]->isOutCollectingMode() )
2324  {
2325  THROW_LOGICAL_ERROR2("Not Out collecting mode: Rank = ", rank);
2326  }
2327  }
2328 }
2329 
2330 void
2332  int rank,
2333  long long numOfNodesSolved,
2334  int numOfNodesLeft,
2335  double solverLocalBestDualBound
2336  )
2337 {
2338  if( pool[SOLVER_POOL_INDEX(rank)]->getStatus() != Racing &&
2339  pool[SOLVER_POOL_INDEX(rank)]->getStatus() != RacingEvaluation )
2340  {
2341  std::cout << "Tried to update no racing status solver's info." << std::endl;
2342  std::cout << "Update solver rank = " << rank << std::endl;
2343  abort();
2344  }
2345 
2346 
2347  if( paraParams->getIntParamDefaultValue(RacingRampUpTerminationCriteria) == 0 ) // Criterion is the number of nodes
2348  {
2349  if(pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft() < paraParams->getIntParamDefaultValue(StopRacingNumberOfNodesLeft) &&
2350  numOfNodesLeft >= paraParams->getIntParamDefaultValue(StopRacingNumberOfNodesLeft) )
2351  {
2352  pool[SOLVER_POOL_INDEX(rank)]->switchIntoEvaluation();
2353  nEvaluationStage++;
2354  }
2355  if(pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft() >= paraParams->getIntParamDefaultValue(StopRacingNumberOfNodesLeft) &&
2356  numOfNodesLeft < paraParams->getIntParamDefaultValue(StopRacingNumberOfNodesLeft) )
2357  {
2358  pool[SOLVER_POOL_INDEX(rank)]->switchOutEvaluation();
2359  nEvaluationStage--;
2360  }
2361 
2362  } else {
2363  if( !pool[SOLVER_POOL_INDEX(rank)]->isEvaluationStage() )
2364  {
2365  pool[SOLVER_POOL_INDEX(rank)]->switchIntoEvaluation();
2366  nEvaluationStage++;
2367  }
2368  }
2369  pool[SOLVER_POOL_INDEX(rank)]->setNumOfDiffNodesSolved( numOfNodesSolved - pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesSolved() );
2370  pool[SOLVER_POOL_INDEX(rank)]->setNumOfNodesSolved(numOfNodesSolved);
2371  pool[SOLVER_POOL_INDEX(rank)]->setNumOfDiffNodesLeft( numOfNodesLeft - pool[SOLVER_POOL_INDEX(rank)]->getNumOfNodesLeft() );
2372  pool[SOLVER_POOL_INDEX(rank)]->setNumOfNodesLeft(numOfNodesLeft);
2373 // if( rank != originRank ||
2374 // ( paraParams->getIntParamValue(UgCplexRunningMode) != 1 ) )
2375 // if( rank != originRank )
2376 // {
2377 // int prviousTop = selectionHeap->top()->getRank();
2378  selectionHeap->updateDualBoundValue(*(pool[SOLVER_POOL_INDEX(rank)]->getSelectionHeapElement()), solverLocalBestDualBound);
2379 // if( selectionHeap->top()->getRank() == rank || selectionHeap->top()->getRank() != prviousTop )
2380 // {
2381  nNodesInBestSolver = selectionHeap->top()->getNumOfNodesLeft(); // in racing ramp-up, winner nodes should be the number of nodes left
2382  nNodesSolvedInBestSolver = selectionHeap->top()->getNumOfNodesSolved();
2383 // }
2384  if( selectionHeap->getHeapSize() > 0 )
2385  {
2386  if( selectionHeap->top()->getBestDualBoundValue() > bestDualBound )
2387  {
2388  bestDualBound = selectionHeap->top()->getBestDualBoundValue();
2389  }
2390  }
2391 // }
2392 
2393  if( bestDualBoundInSolvers < solverLocalBestDualBound )
2394  {
2395  bestDualBoundInSolvers = solverLocalBestDualBound;
2396  }
2397 
2398 }
2399 
2400 bool
2402  bool feasibleSol
2403  )
2404 {
2405  double solverRatio = paraParams->getRealParamValue(CountingSolverRatioInRacing);
2406  switch( paraParams->getIntParamValue(RacingRampUpTerminationCriteria) )
2407  {
2408  case 0: /** stop racing at the number of nodes left in a solver reached to the value */
2409  {
2410  if( ( paraParams->getIntParamValue(NEvaluationSolversToStopRacing) == -1 && nEvaluationStage == nSolvers ) ||
2411  ( paraParams->getIntParamValue(NEvaluationSolversToStopRacing) == 0 && nEvaluationStage >= ( nSolvers/2 ) ) ||
2412  ( paraParams->getIntParamValue(NEvaluationSolversToStopRacing) > 0 &&
2413  nEvaluationStage >= paraParams->getIntParamValue(NEvaluationSolversToStopRacing) ) )
2414  {
2415 
2416  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2417  {
2418  winnerRank = selectionHeap->top()->getRank();
2419  return true;
2420  }
2421  }
2422  break;
2423  }
2424  case 1: /** stop racing at time limit */
2425  {
2426  if( nEvaluationStage >= static_cast<int>(nSolvers*solverRatio) ) // some solver may not reply at racing
2427  {
2428  if( paraParams->getBoolParamValue(Deterministic) )
2429  {
2430  if( paraDetTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2431  {
2432  winnerRank = selectionHeap->top()->getRank();
2433  return true;
2434  }
2435  }
2436  else
2437  {
2438  if( paraTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2439  {
2440  winnerRank = selectionHeap->top()->getRank();
2441  return true;
2442  }
2443  }
2444  }
2445  break;
2446  }
2447  case 2: /** stop racing at the Solver with the best bound value has a certain number of nodes left */
2448  {
2449  if( nEvaluationStage >= static_cast<int>(nSolvers*solverRatio) ) // some solver may not reply at racing
2450  {
2451  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2452  {
2453  winnerRank = selectionHeap->top()->getRank();
2454  return true;
2455  }
2456  }
2457  break;
2458  }
2459  case 3: /** node left first adaptive */
2460  {
2461  if( selectionHeap->top()->getNumOfNodesLeft() <= nSolvers
2462  && selectionHeap->top()->getNumOfNodesLeft() <= paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2463  {
2464  return false;
2465  }
2466  if( nEvaluationStage >= static_cast<int>(nSolvers*solverRatio) ) // some solver may not reply at racing
2467  {
2468  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2469  {
2470  winnerRank = selectionHeap->top()->getRank();
2471  return true;
2472  }
2473 
2474  if( paraParams->getBoolParamValue(Deterministic) )
2475  {
2476  if( paraDetTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2477  {
2478  winnerRank = selectionHeap->top()->getRank();
2479  return true;
2480  }
2481  }
2482  else
2483  {
2484  if( paraTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2485  {
2486  winnerRank = selectionHeap->top()->getRank();
2487  return true;
2488  }
2489  }
2490  }
2491  break;
2492  }
2493  case 4: /** time limit first adaptive */
2494  {
2495  if( nEvaluationStage >= static_cast<int>(nSolvers*solverRatio) ) // some solver may not reply at racing
2496  {
2497  if( paraParams->getBoolParamValue(Deterministic) )
2498  {
2499  if( paraDetTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2500  {
2501  winnerRank = selectionHeap->top()->getRank();
2502  return true;
2503  }
2504 
2505  if( selectionHeap->top()->getNumOfNodesLeft() <= nSolvers
2506  && selectionHeap->top()->getNumOfNodesLeft() <= paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2507  {
2508  return false;
2509  }
2510  else
2511  {
2512  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2513  {
2514  winnerRank = selectionHeap->top()->getRank();
2515  return true;
2516  }
2517  }
2518  }
2519  else
2520  {
2521  if( paraTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2522  {
2523  winnerRank = selectionHeap->top()->getRank();
2524  return true;
2525  }
2526  if( selectionHeap->top()->getNumOfNodesLeft() <= nSolvers
2527  && selectionHeap->top()->getNumOfNodesLeft() <= paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2528  {
2529  return false;
2530  }
2531  else
2532  {
2533  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2534  {
2535  winnerRank = selectionHeap->top()->getRank();
2536  return true;
2537  }
2538  }
2539  }
2540  }
2541  break;
2542  }
2543  case 5: /** node left first adaptive - adaptive node left (Default settings): this is for FiberSCIP */
2544  {
2545  if( nEvaluationStage >= static_cast<int>(nSolvers*solverRatio) ) // some solver may not reply at racing
2546  {
2547  if( paraParams->getBoolParamValue(KeepRacingUntilToFindFirstSolution) && (!feasibleSol) ) return false; // no feasible solution keeps racing
2548  if( selectionHeap->top()->getNumOfNodesLeft() <= nSolvers )
2549  {
2550  return false;
2551  }
2552 
2553  if( selectionHeap->top()->getNumOfNodesLeft() >
2554  paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2555  {
2556  if( !paraParams->getBoolParamValue(KeepRacingUntilToFindFirstSolution) || feasibleSol )
2557  {
2558  winnerRank = selectionHeap->top()->getRank();
2559  return true;
2560  }
2561  else
2562  {
2563  if( selectionHeap->top()->getNumOfNodesLeft() >
2564  ( paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) * paraParams->getRealParamValue(StopRacingNumberOfNodesLeftMultiplier) ) )
2565  {
2566  winnerRank = selectionHeap->top()->getRank();
2567  return true;
2568  }
2569  if( paraParams->getBoolParamValue(Deterministic) )
2570  {
2571  if( paraDetTimer->getElapsedTime() >
2572  ( paraParams->getRealParamValue(StopRacingTimeLimit) * paraParams->getRealParamValue(StopRacingTimeLimitMultiplier) ) )
2573  {
2574  winnerRank = selectionHeap->top()->getRank();
2575  return true;
2576  }
2577  }
2578  else
2579  {
2580  if( paraTimer->getElapsedTime() >
2581  ( paraParams->getRealParamValue(StopRacingTimeLimit) * paraParams->getRealParamValue(StopRacingTimeLimitMultiplier) ) )
2582  {
2583  winnerRank = selectionHeap->top()->getRank();
2584  return true;
2585  }
2586  }
2587  }
2588  }
2589  else
2590  {
2591  if( paraParams->getBoolParamValue(Deterministic) )
2592  {
2593  if( paraDetTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2594  {
2595  if( selectionHeap->top()->getNumOfNodesLeft() > nSolvers )
2596  {
2597  if( !paraParams->getBoolParamValue(KeepRacingUntilToFindFirstSolution) || feasibleSol )
2598  {
2599  winnerRank = selectionHeap->top()->getRank();
2600  return true;
2601  }
2602  else
2603  {
2604  if( paraDetTimer->getElapsedTime() >
2605  ( paraParams->getRealParamValue(StopRacingTimeLimit) * paraParams->getRealParamValue(StopRacingTimeLimitMultiplier) ) )
2606  {
2607  winnerRank = selectionHeap->top()->getRank();
2608  return true;
2609  }
2610  }
2611  }
2612  }
2613  }
2614  else
2615  {
2616  if( paraTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2617  {
2618  if( selectionHeap->top()->getNumOfNodesLeft() > nSolvers )
2619  {
2620  if( !paraParams->getBoolParamValue(KeepRacingUntilToFindFirstSolution) || feasibleSol )
2621  {
2622  winnerRank = selectionHeap->top()->getRank();
2623  return true;
2624  }
2625  else
2626  {
2627  if( paraTimer->getElapsedTime() >
2628  ( paraParams->getRealParamValue(StopRacingTimeLimit) * paraParams->getRealParamValue(StopRacingTimeLimitMultiplier) ) )
2629  {
2630  winnerRank = selectionHeap->top()->getRank();
2631  return true;
2632  }
2633  }
2634  }
2635  }
2636  }
2637  }
2638  }
2639  break;
2640  }
2641  case 6: /** time limit first adaptive - adaptive node left */
2642  {
2643  if( nEvaluationStage >= static_cast<int>(nSolvers*solverRatio) ) // some solver may not reply at racing
2644  {
2645  if( paraParams->getBoolParamValue(KeepRacingUntilToFindFirstSolution) && (!feasibleSol) ) return false; // no feasible solution keeps racing
2646  if( selectionHeap->top()->getNumOfNodesLeft() <= nSolvers )
2647  {
2648  return false;
2649  }
2650 
2651  if( paraParams->getBoolParamValue(Deterministic) )
2652  {
2653  if( paraDetTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2654  {
2655  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2656  {
2657  winnerRank = selectionHeap->top()->getRank();
2658  return true;
2659  }
2660  else
2661  {
2662  if( paraDetTimer->getElapsedTime() >
2663  ( paraParams->getRealParamValue(StopRacingTimeLimit) * paraParams->getRealParamValue(StopRacingTimeLimitMultiplier) ) )
2664  {
2665  winnerRank = selectionHeap->top()->getRank();
2666  return true;
2667  }
2668  }
2669  }
2670  }
2671  else
2672  {
2673  if( paraTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2674  {
2675  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2676  {
2677  winnerRank = selectionHeap->top()->getRank();
2678  return true;
2679  }
2680  else
2681  {
2682  if( paraTimer->getElapsedTime() >
2683  ( paraParams->getRealParamValue(StopRacingTimeLimit) * paraParams->getRealParamValue(StopRacingTimeLimitMultiplier) ) )
2684  {
2685  winnerRank = selectionHeap->top()->getRank();
2686  return true;
2687  }
2688  }
2689  }
2690  }
2691  }
2692  break;
2693  }
2694  case 7: /** time limit first adaptive and node limit also checked - adaptive node left */
2695  {
2696  if( nEvaluationStage >= static_cast<int>(nSolvers*solverRatio) ) // some solver may not reply at racing
2697  {
2698  if( paraParams->getBoolParamValue(KeepRacingUntilToFindFirstSolution) && (!feasibleSol) ) return false; // no feasible solution keeps racing
2699  if( selectionHeap->top()->getNumOfNodesLeft() <= nSolvers )
2700  {
2701  return false;
2702  }
2703 
2704  if( paraParams->getBoolParamValue(Deterministic) )
2705  {
2706  if( paraDetTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2707  {
2708  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2709  {
2710  winnerRank = selectionHeap->top()->getRank();
2711  return true;
2712  }
2713  else
2714  {
2715  if( paraDetTimer->getElapsedTime() >
2716  ( paraParams->getRealParamValue(StopRacingTimeLimit) * paraParams->getRealParamValue(StopRacingTimeLimitMultiplier) ) )
2717  {
2718  winnerRank = selectionHeap->top()->getRank();
2719  return true;
2720  }
2721  }
2722  }
2723  else
2724  {
2725  if( selectionHeap->top()->getNumOfNodesLeft() >
2726  ( paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) * paraParams->getRealParamValue(StopRacingNumberOfNodesLeftMultiplier) ) )
2727  {
2728  winnerRank = selectionHeap->top()->getRank();
2729  return true;
2730  }
2731  }
2732  }
2733  else
2734  {
2735  if( paraTimer->getElapsedTime() > paraParams->getRealParamValue(StopRacingTimeLimit) )
2736  {
2737  if( selectionHeap->top()->getNumOfNodesLeft() > paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) )
2738  {
2739  winnerRank = selectionHeap->top()->getRank();
2740  return true;
2741  }
2742  else
2743  {
2744  if( paraTimer->getElapsedTime() >
2745  ( paraParams->getRealParamValue(StopRacingTimeLimit) * paraParams->getRealParamValue(StopRacingTimeLimitMultiplier) ) )
2746  {
2747  winnerRank = selectionHeap->top()->getRank();
2748  return true;
2749  }
2750  }
2751  }
2752  else
2753  {
2754  if( selectionHeap->top()->getNumOfNodesLeft() >
2755  ( paraParams->getIntParamValue(StopRacingNumberOfNodesLeft) * paraParams->getRealParamValue(StopRacingNumberOfNodesLeftMultiplier) ) )
2756  {
2757  winnerRank = selectionHeap->top()->getRank();
2758  return true;
2759  }
2760  }
2761  }
2762  }
2763  break;
2764  }
2765  default:
2766  THROW_LOGICAL_ERROR1("invalid racing ramp-up termination criteria");
2767  }
2768  return false;
2769 }
2770 
const std::string toString()
stringfy of this object for debugging
virtual bool isSolverActive(int rank)
check if the specified Solver is active or not
std::size_t heapSize
current used heap size
#define SOLVER_POOL_INDEX(rank)
virtual void removeSubtreeRootNode(int rank, BbParaNode *node)
remove subtree root node from the active solver with the specified rank
virtual void makeSubtreeRootNodeCurrent(int rank, BbParaNode *node)
make subtree root node as current task for the specified rank
#define THROW_LOGICAL_ERROR4(msg1, msg2, msg3, msg4)
Definition: paraDef.h:103
virtual void deleteElement(BbParaSolverPoolElementPtr solver)
delete BbParaSolverPoolElementPtr from Selection Heap
BbParaMergeNodeInfo * getMergeNodeInfo()
get merge node information struct
Definition: bbParaNode.h:658
virtual void deleteElement(BbParaSolverPoolElementPtr solver)
delete BbParaSolverPoolElementPtr from CollectingModeSolver Heap
int getRank()
get rank of the Solver
static const int TagLightWeightRootNodeProcess
Definition: bbParaTagDef.h:54
virtual void downHeap(std::size_t pos)
down heap
static const int RatioToApplyLightWeightRootProcess
virtual void switchInCollectingMode(BbParaNodePool *paraNodePool)
switch in collecting mode
BbParaSolverPoolElementPtr * getSelectionHeapElement()
extract current solving BbParaNode
static const int KeepRacingUntilToFindFirstSolution
static const int TagNoTestDualBoundGain
Definition: bbParaTagDef.h:59
BbParaSolverPoolElementPtr * getCollectingModeSolverHeapElement()
get collecting mode Solver heap element
virtual void deleteElement(BbParaSolverPoolElementPtr solver)
delete BbParaSolverPoolElementPtr from Selection Heap
virtual void switchInCollectingToSolver(int rank, BbParaNodePool *paraNodePool)
switch a Solver to be in collecting mode
virtual void upHeap(std::size_t pos)
up heap
void setCollectingModeSolverHeapElement(BbParaSolverPoolElementPtr *inCollectingModeSolverHeapElement)
set collecting mode Solver heap element
virtual BbParaNode * extractSelfSplitSubtreeRootNode(int rank, BbParaNode *node)
extract self-split subtree root node from the active solver with the specified rank ...
static const int LightWeightRootNodeProcess
static const int NChangeIntoCollectingMode
virtual void updateDualBoundValue(BbParaSolverPoolElementPtr solver, double value)
update selection heap by a new dual bound value of this Solver
virtual void downHeap(std::size_t pos)
down heap
void setSelectionHeapElement(BbParaSolverPoolElementPtr *inSelectionHeapElement)
set selection heap element
static const int SolverOrderInCollectingMode
static const int RacingRampUpTerminationCriteria
virtual void updateDualBoundValue(BbParaSolverPoolElementPtr solver, double value)
update CollectingModeSolver heap by a new dual bound value of this Solver
Defines for UG Framework.
virtual int send(ParaComm *comm, int destination)=0
send this object
static const int ControlCollectingModeOnSolverSide
static const int NMaxCanditatesForCollecting
virtual void downHeap(std::size_t pos)
down heap
class BbParaRacingSolverPool (Racing Solver Pool)
class CollectingModeSolverHeap
virtual void deleteCurrentSubtreeRootNode(int rank)
delete current self-split subtree root node from the active solver with the specified rank ...
int getNumOfDiffNodesLeft()
get number of nodes left difference between current number and that in the previous notification time...
virtual BbParaNode * extractSelfSplitSubtreeRootNodes(int rank)
extract self-split subtree root node from the active solver with the specified rank ...
AscendingCollectingModeSolverHeap(std::size_t size)
constructor
virtual void resetCountersInSolver(int rank, long long numOfNodesSolved, int numOfSelfSplitNodesLeft, BbParaNodePool *paraNodePool)
reset counters in the Solver specified by rank
#define PARA_COMM_CALL(paracommcall)
Definition: paraComm.h:47
static const int Deterministic
Definition: paraParamSet.h:76
static const int StopRacingNumberOfNodesLeftMultiplier
CollectingModeSolverHeap(std::size_t size)
constructor
static const int CountingSolverRatioInRacing
virtual void upHeap(std::size_t pos)
up heap
static const int ParaDOUBLE
Definition: paraComm.h:76
BbParaNode * next
this pointer is used in case of self-split ramp-up in LC this field is not transferred ...
Definition: bbParaNode.h:83
static const int TagInCollectingMode
Definition: bbParaTagDef.h:50
class Selection Heap
AscendingSelectionHeap(std::size_t size)
constructor
std::size_t heapSize
current used heap size
virtual BbParaNode * solverDied(int rank)
kill the Solver specified by rank
DescendingCollectingModeSolverHeap(std::size_t size)
constructor
class BbParaSolverPoolElement (This class includes information about a Solver status) ...
#define THROW_LOGICAL_ERROR1(msg1)
Definition: paraDef.h:52
virtual void deleteElement(BbParaSolverPoolElementPtr solver)
delete BbParaSolverPoolElementPtr from CollectingModeSolver Heap
virtual void updateDualBoundValue(BbParaSolverPoolElementPtr solver, double value)
update CollectingModeSolver heap by a new dual bound value of this Solver
SolverStatus getStatus()
get Solver status
static const int TagTestDualBoundGain
Definition: bbParaTagDef.h:58
static const int StopRacingTimeLimitMultiplier
int getNumOfNodesLeft()
get number of nodes left
virtual void enforcedSwitchOutCollectingMode(int rank)
enforced to switch out collecting mode of the Solver specified by rank if it is necessary ...
virtual void inactivateSolver(int rank, long long numOfNodesSolved, BbParaNodePool *paraNodePool)
inactivate the Solver specified by rank
#define THROW_LOGICAL_ERROR2(msg1, msg2)
Definition: paraDef.h:69
virtual bool isEmpty()=0
check if this pool is empty or not
static const int ParaBYTE
Definition: paraComm.h:79
void resize(std::size_t size)
resize CollectingModeSolver Heap
class BbParaNode
Definition: bbParaNode.h:61
virtual unsigned int getNumOfGoodNodes(double globalBestBound)=0
get number of good (heavy) BbParaNodes in this pool
virtual ~CollectingModeSolverHeap()
destructor
virtual bool isWinnerDecided(bool feasibleSol)
check racing termination criteria
ResultOfInsert
results of insert
static const int StopRacingNumberOfNodesLeft
std::size_t maxHeapSize
maximum size of this heap
virtual void updateSolverStatus(int rank, long long numNodesSolved, int numNodesLeft, double solverLocalBestBound, BbParaNodePool *paraNodePool)
update Solver status
static const int StopRacingTimeLimit
virtual void sendSwitchOutCollectingModeIfNecessary(int rank)
switch out collecting mode of the Solver specified by rank if it is necessary
static int nSolvers
Definition: fscip.cpp:75
virtual void activateSolver(int rank, BbParaNode *node, int nGoodNodesInNodePool, double averageDualBoundGain)
activate the Solver specified by rank with specified node which has been sent
int getMergingStatus()
get merging status
Definition: bbParaNode.h:678
virtual void upHeap(std::size_t pos)
up heap
BbParaSolverPoolElementPtr remove()
remove top priority BbParaSolverPoolElementPtr from CollectingModeSolver Heap */
class BbParaNodePool
void setBestDualBoundValue(double inBestDualBoundValue)
set best dual bound value
static const int TagNoWaitModeSend
Definition: bbParaTagDef.h:60
virtual void updateSolverStatus(int rank, long long numNodesSolved, int numNodesLeft, double solverLocalBestBound)
update Solver status
static const int ParaINT
Definition: paraComm.h:66
double getBestDualBoundValue()
get best dual bound value
virtual void addNewSubtreeRootNode(int rank, BbParaNode *node)
add new subtree root node to the active solver with the specified rank
static const int NEvaluationSolversToStopRacing
static const int MultiplierForCollectingMode
virtual void upHeap(std::size_t pos)
up heap
ResultOfInsert insert(BbParaSolverPoolElementPtr solver)
insert BbParaSolverPoolElementPtr to CollectingModeSolver Heap
static const int CollectingModeInterval
virtual void downHeap(std::size_t pos)
down heap
static const int DualBoundGainTest
bool isInCollectingMode()
check if this Solver is in collecting mode or not
virtual BbParaNode * getSelfSplitSubtreeRootNodes(int rank)
get self-split subtree root node from the active solver with the specified rank
BbParaSolverPoolElementPtr * heap
heap : contents are BbParaSolverPoolElementPtr
virtual void updateDualBoundValue(BbParaSolverPoolElementPtr solver, double value)
update selection heap by a new dual bound value of this Solver
BbParaSolverPoolElementPtr * heap
heap : contents are BbParaSolverPoolElementPtr
static const int TagOutCollectingMode
Definition: bbParaTagDef.h:52
virtual void switchOutCollectingMode()
switch out collecting mode
#define THROW_LOGICAL_ERROR3(msg1, msg2, msg3)
Definition: paraDef.h:86