Scippy

UG

Ubiquity Generator framework

bbParaNodePool.h
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 paraNodePool.h
27  * @brief BbParaNode 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 #ifndef __BB_PARA_NODE_POOL_H__
38 #define __BB_PARA_NODE_POOL_H__
39 #include <map>
40 #include <queue>
41 #include <cfloat>
42 #include <cmath>
43 #include "bbParaInstance.h"
44 #include "bbParaNodesMerger.h"
45 #include "bbParaNode.h"
46 
47 namespace UG
48 {
49 
50 static const double eps = 1.0e-12;
51 
52 
53 ///
54 /// class BbParaNodeSortCriterion
55 ///
57 {
58 
59 public:
60 
61  ///
62  /// ()operator
63  /// @return true if n1 < n2
64  ///
65  bool operator()(
66  const BbParaNodePtr& n1, ///< BbParaNode pointer n1
67  const BbParaNodePtr& n2 ///< BbParaNode pointer n2
68  ) const
69  {
70 
71  return EPSLT(n1->getDualBoundValue(),n2->getDualBoundValue(),eps) ||
73  n1->getDiffSubproblem() && n2->getDiffSubproblem() &&
75 
76  }
77 };
78 
79 ///
80 /// class BbParaNodeSortCriterionForCleanUp
81 ///
83 {
84 
85 public:
86 
87  ///
88  /// ()operator
89  /// @return true if n1 > n2
90  ///
91  bool operator()(
92  const BbParaNodePtr& n1, ///< BbParaNode pointer n1
93  const BbParaNodePtr& n2 ///< BbParaNode pointer n2
94  ) const
95  {
96 
97  return EPSGT(n1->getDualBoundValue(),n2->getDualBoundValue(),eps) ||
99  n1->getDiffSubproblem() && n2->getDiffSubproblem() &&
101 
102  }
103 };
104 
105 ///
106 /// class BbParaNodePool
107 ///
109 {
110 
111 protected:
112 
113  double bgap; ///< gap which can be considered as good
114  size_t maxUsageOfPool; ///< maximum usage of this pool
115 
116 public:
117 
118  ///
119  /// constructor
120  ///
122  double inBgap ///< gap which can be considered as good
123  )
124  : bgap(inBgap),
125  maxUsageOfPool(0)
126  {
127  }
128 
129  ///
130  /// destructor
131  ///
133  )
134  {
135  }
136 
137  ///
138  /// insert BbParaNode to this pool
139  ///
140  virtual void insert(
141  BbParaNodePtr node ///< pointer to BbParaNode object
142  ) = 0;
143 
144  ///
145  /// check if this pool is empty or not
146  /// @return true if this pool is empty
147  ///
148  virtual bool isEmpty(
149  ) = 0;
150 
151  ///
152  /// extract a BbParaNode object from this pool
153  /// @return pointer to BbParaNode object extracted
154  ///
155  virtual BbParaNodePtr extractNode(
156  ) = 0;
157 
158  ///
159  /// extract a BbParaNode object with the lowest priority from this pool
160  /// @return pointer to BbParaNode object extracted
161  ///
162  virtual BbParaNodePtr extractWorstNode(
163  ) = 0;
164 
165  ///
166  /// extract a BbParaNode object randomly from this pool
167  /// @return pointer to BbParaNode object extracted
168  ///
169  virtual BbParaNodePtr extractNodeRandomly(
170  ) = 0;
171 
172  ///
173  /// get best dual bound value of BbParaNode object in this pool
174  /// @return best dual bound value
175  ///
176  virtual double getBestDualBoundValue(
177  ) = 0;
178 
179  ///
180  /// get number of good (heavy) BbParaNodes in this pool
181  /// @return the number of good BbParaNodes
182  ///
183  virtual unsigned int getNumOfGoodNodes(
184  double globalBestBound ///< global best bound value to evaluate goodness
185  ) = 0;
186 
187  ///
188  /// get number of BbParaNodes in this pool
189  /// @return number of BbParaNodes
190  ///
191  virtual size_t getNumOfNodes(
192  ) = 0;
193 
194  ///
195  /// remove bounded BbParaNodes by given incumbnet value
196  /// @return the number of bounded BbParaNodes
197  ///
198  virtual int removeBoundedNodes(
199  double incumbentValue ///< incumbent value
200  ) = 0;
201 
202  ///
203  /// update dual bound values for saving BbParaNodes to checkpoint file
204  ///
205  virtual void updateDualBoundsForSavingNodes(
206  ) = 0;
207 
208 #ifdef UG_WITH_ZLIB
209 
210  ///
211  /// write BbParaNodes to checkpoint file
212  /// @return number of BbParaNodes written
213  ///
214  virtual int writeBbParaNodesToCheckpointFile(
215  gzstream::ogzstream &out ///< gzstream for output
216  ) = 0;
217 
218 #endif
219 
220  ///
221  /// remove merged BbParaNodes from this pool
222  /// @return
223  ///
224  virtual int removeMergedNodes(
225  BbParaMergedNodeListElement *head ///< head of Merged BbParaNodes list
226  ) = 0;
227 
228  ///
229  /// stringfy this object
230  /// @return string which shows inside of this object as string
231  ///
232  virtual const std::string toString(
233  ) = 0;
234 
235  ///
236  /// get maximum usage of this pool
237  /// @return the maximum number of BbParaNodes that were in this pool
238  ///
240  )
241  {
242  return maxUsageOfPool;
243  }
244 
245 };
246 
247 ///
248 /// class BbParaNodePoolForMinimization
249 /// @note only minimization pool was written, since all problem is converted to minimization problem inside of UG solvers
250 ///
252 {
253 
254  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion > ascendingPool; ///< asnding pool
255 
256 public:
257 
258  ///
259  /// constructor
260  ///
262  double inBgap ///< gap to evaluate a BbParaNode is good or not
263  )
264  : BbParaNodePool(inBgap)
265  {
266  }
267 
268  ///
269  /// destructor
270  ///
272  )
273  {
274  if( ascendingPool.size() > 0 )
275  {
276  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
277  for( p = ascendingPool.begin(); p != ascendingPool.end(); )
278  {
279  if( p->second ) delete p->second;
280  ascendingPool.erase(p++);
281  }
282  }
283  }
284 
285  ///
286  /// insert a BbParaNode object to this pool
287  ///
288  void insert(
289  BbParaNodePtr paraNode ///< pointer to BbParaNode object to insert
290  )
291  {
292  ascendingPool.insert(std::make_pair(paraNode,paraNode));
293  if( maxUsageOfPool < ascendingPool.size() )
294  {
295  maxUsageOfPool = ascendingPool.size();
296  }
297  }
298 
299  ///
300  /// check if this pool is empty or not
301  /// @return true if this pool is empty
302  ///
303  bool isEmpty(
304  )
305  {
306  return ( ascendingPool.size() == 0 );
307  }
308 
309  ///
310  /// extract a BbParaNode from this pool
311  /// @return pointer to BbParaNode object extracted
312  ///
314  )
315  {
316  BbParaNodePtr extracted = 0;
317  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
318  p = ascendingPool.begin();
319  while( p != ascendingPool.end() )
320  {
321  if( p->second->getMergeNodeInfo() )
322  {
323  assert( p->second->getMergeNodeInfo()->status != BbParaMergeNodeInfo::PARA_MERGING );
324  if( p->second->getMergingStatus() == 4 ) // merging representative was already deleted
325  {
326  delete p->second; // this delete is not counted in statistics
327  ascendingPool.erase(p++);
328  }
329  else
330  {
331  if( p->second->getMergeNodeInfo()->status == BbParaMergeNodeInfo::PARA_MERGE_CHECKING_TO_OTHER_NODE )
332  {
333  assert(dynamic_cast<BbParaNodePtr>(p->second)->getMergeNodeInfo()->mergedTo->status == BbParaMergeNodeInfo::PARA_MERGED_RPRESENTATIVE );
334  p++;
335  }
336  else
337  {
338  extracted = p->second;
339  ascendingPool.erase(p);
340  break;
341  }
342  }
343  }
344  else
345  {
346  extracted = p->second;
347  ascendingPool.erase(p);
348  break;
349  }
350  }
351  assert( ( p == ascendingPool.end() && (!extracted) ) || ( p != ascendingPool.end() && extracted ) );
352  return extracted;
353  }
354 
355  ///
356  /// extract a BbParaNode object with the lowest priority from this pool
357  /// @return pointer to BbParaNode object extracted
358  /// TODO: need to debug
360  )
361  {
362  BbParaNodePtr extracted = 0;
363  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::reverse_iterator rp;
364  rp = ascendingPool.rbegin();
365  // while( rp != ascendingPool.rend() )
366  if( rp != ascendingPool.rend() )
367  {
368  assert( !(rp->second->getMergeNodeInfo()) );
369  extracted = rp->second;
370  // ascendingPool.erase(--(rp.base()));
371  ascendingPool.erase((rp.base()));
372  // break;
373  }
374  // assert( ( rp == ascendingPool.rend() && (!extracted) ) || ( rp != ascendingPool.rend() && extracted ) );
375  return extracted;
376  }
377 
378  ///
379  /// get a BbParaNode object, which is expected to extract from this pool
380  /// @return pointer to BbParaNode object, which is expected to extract (Note: the BbParaNode object stays in pool)
381  ///
383  )
384  {
385  BbParaNodePtr node = 0;
386  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
387  p = ascendingPool.begin();
388  while( p != ascendingPool.end() )
389  {
390  assert( !(p->second->getMergeNodeInfo()) ); // should not have this info.
391  node = p->second;
392  break;
393  }
394  assert( ( p == ascendingPool.end() && (!node) ) || ( p != ascendingPool.end() && node ) );
395  return node;
396  }
397 
398 
399  ///
400  /// extract a BbParaNode object randomly from this pool
401  /// @return pointer to BbParaNode object extracted
402  ///
404  )
405  {
406  BbParaNodePtr extracted = 0;
407  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
408  p = ascendingPool.begin();
409  size_t nNodes = ascendingPool.size();
410  if( nNodes == 0 ) return extracted;
411  int pos = 0;
412  if( nNodes > 10 )
413  {
414  // select nodes randomly
415  pos = rand()% static_cast<int>( nNodes * 0.8 ) + static_cast<int>(nNodes*0.1);
416  if( pos < (static_cast<int>(nNodes*0.1)) || pos > nNodes*0.9 )
417  {
418  THROW_LOGICAL_ERROR4("Invalid pos in extractNodeRandomly in BbParaNodePool: pos = ", pos, ", nNodes = ", nNodes);
419  }
420  for( int j = 0; j < pos; j++ )
421  {
422  p++;
423  }
424  }
425  assert( p != ascendingPool.end() );
426  if( p == ascendingPool.end() ) // should not happen
427  {
428  p = ascendingPool.begin();
429  }
430  if( p->second->getMergeNodeInfo() )
431  {
432  assert( p->second->getMergeNodeInfo()->status != BbParaMergeNodeInfo::PARA_MERGING );
433  if( p->second->getMergingStatus() == 4 ) // merging representative was already deleted
434  {
435  delete p->second; // this delete is not counted in statistics
436  ascendingPool.erase(p);
437  }
438  else
439  {
440  if( p->second->getMergeNodeInfo()->status == BbParaMergeNodeInfo::PARA_MERGE_CHECKING_TO_OTHER_NODE )
441  {
442  assert(dynamic_cast<BbParaNodePtr>(p->second)->getMergeNodeInfo()->mergedTo->status == BbParaMergeNodeInfo::PARA_MERGED_RPRESENTATIVE );
443  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator pp;
444  pp = ascendingPool.begin();
445  while( pp != p )
446  {
447  if( dynamic_cast<BbParaNodePtr>(pp->second) == dynamic_cast<BbParaNodePtr>(p->second)->getMergeNodeInfo()->mergedTo->paraNode )
448  {
449  extracted = pp->second;
450  ascendingPool.erase(pp);
451  break;
452  }
453  pp++;
454  }
455  }
456  else
457  {
458  extracted = p->second;
459  ascendingPool.erase(p);
460  }
461  }
462  }
463  else
464  {
465  extracted = p->second;
466  ascendingPool.erase(p);
467  }
468  if( !extracted )
469  {
470  /** check nodes from the head of this pool */
471  p = ascendingPool.begin();
472  while( p != ascendingPool.end() )
473  {
474  if( p->second->getMergeNodeInfo() )
475  {
476  assert( p->second->getMergeNodeInfo()->status != BbParaMergeNodeInfo::PARA_MERGING );
477  if( p->second->getMergingStatus() == 4 ) // merging representative was already deleted
478  {
479  delete p->second; // this delete is not counted in statistics
480  ascendingPool.erase(p++);
481  }
482  else
483  {
484  if( p->second->getMergeNodeInfo()->status == BbParaMergeNodeInfo::PARA_MERGE_CHECKING_TO_OTHER_NODE )
485  {
486  assert(dynamic_cast<BbParaNodePtr>(p->second)->getMergeNodeInfo()->mergedTo->status == BbParaMergeNodeInfo::PARA_MERGED_RPRESENTATIVE );
487  p++;
488  }
489  else
490  {
491  extracted = p->second;
492  ascendingPool.erase(p);
493  break;
494  }
495  }
496  }
497  else
498  {
499  extracted = p->second;
500  ascendingPool.erase(p);
501  break;
502  }
503  }
504  }
505  assert( ( p == ascendingPool.end() && (!extracted) ) || ( p != ascendingPool.end() && extracted ) );
506  return extracted;
507  }
508 
509  ///
510  /// update dual bound values for saving BbParaNodes to checkpoint file
511  ///
513  )
514  {
515  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
516  for( p = ascendingPool.begin(); p != ascendingPool.end(); ++p )
517  {
518  if( p->second->getAncestor() == 0 )
519  {
520  p->second->updateInitialDualBoundToSubtreeDualBound();
521  }
522  }
523  }
524 
525 #ifdef UG_WITH_ZLIB
526 
527  ///
528  /// write BbParaNodes to checkpoint file
529  /// @return number of BbParaNodes written
530  ///
531  int writeBbParaNodesToCheckpointFile(
532  gzstream::ogzstream &out ///< gzstream for output
533  )
534  {
535  int n = 0;
536  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
537  for( p = ascendingPool.begin(); p != ascendingPool.end(); ++p )
538  {
539  if( p->second->getAncestor() == 0 )
540  {
541  p->second->write(out);
542  n++;
543  }
544  }
545  return n;
546  }
547 
548 #endif
549 
550  ///
551  /// get best dual bound value of BbParaNode object in this pool
552  /// @return best dual bound value
553  ///
555  )
556  {
557  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
558  p = ascendingPool.begin();
559  if( p != ascendingPool.end() )
560  {
561  return p->second->getDualBoundValue();
562  }
563  else
564  {
565  return DBL_MAX; // no nodes exist
566  }
567  }
568 
569  ///
570  /// get number of good (heavy) BbParaNodes in this pool
571  /// @return the number of good BbParaNodes
572  ///
573  unsigned int getNumOfGoodNodes(
574  double globalBestBound ///< global best bound value to evaluate goodness
575  )
576  {
577  /** The following code is not a good idea,
578  * because only a node is received from a solver, LC can switch out
579  if( globalBestBound > getBestDualBoundValue() )
580  globalBestBound = getBestDualBoundValue();
581  */
582 //
583 // Old code: we had an issue when Pool size is huge
584 //
585 // int num = 0;
586 // std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
587 // for( p = ascendingPool.begin(); p != ascendingPool.end() &&
588 // ( ( ( p->second->getDualBoundValue() ) - globalBestBound ) /
589 // std::max( fabs(globalBestBound) , 1.0 ) ) < bgap;
590 // ++p )
591 // {
592 // num++;
593 // }
594 
595  int num2 = 0;
596  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::reverse_iterator rp;
597  for( rp = ascendingPool.rbegin(); rp != ascendingPool.rend() &&
598  ( ( ( rp->second->getDualBoundValue() ) - globalBestBound ) /
599  std::max( fabs(globalBestBound) , 1.0 ) ) > bgap;
600  ++rp )
601  {
602  num2++;
603  }
604  int num3 = ascendingPool.size() - num2;
605 // assert( num == num3 );
606 // std::cout << "################### num = " << num << ", num3 = " << num3 << std::endl;
607 
608  return num3;
609  }
610 
611  ///
612  /// get number of BbParaNodes in this pool
613  /// @return number of BbParaNodes
614  ///
616  )
617  {
618  return ascendingPool.size();
619  }
620 
621  ///
622  /// remove bounded BbParaNodes by given incumbnet value
623  /// @return the number of bounded BbParaNodes
624  ///
626  double incumbentValue ///< incumbent value
627  )
628  {
629  int nDeleted = 0;
630  if( ascendingPool.size() > 0 )
631  {
632  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
633  for( p = ascendingPool.begin(); p != ascendingPool.end(); )
634  {
635  assert( p->second );
636  if( !p->second->getMergeNodeInfo() )
637  {
638  if( p->second->getDualBoundValue() > incumbentValue || p->second->getMergingStatus() == 4 )
639  {
640  nDeleted++;
641  delete p->second;
642  ascendingPool.erase(p++);
643  }
644  else
645  {
646  p++;
647  }
648  }
649  else
650  {
651  if( p->second->getMergeNodeInfo()->status == BbParaMergeNodeInfo::PARA_MERGE_CHECKING_TO_OTHER_NODE )
652  {
653  if( p->second->getDualBoundValue() > incumbentValue || p->second->getMergingStatus() == 4 )
654  {
655  nDeleted++;
656  delete p->second;
657  ascendingPool.erase(p++);
658  }
659  else
660  {
661  p++;
662  }
663  }
664  else
665  {
666  p++;
667  }
668  }
669  }
670  }
671  return nDeleted;
672  }
673 
674  ///
675  /// remove merged BbParaNodes from this pool
676  /// @return the number of BbParaNodes removed
677  ///
679  BbParaMergedNodeListElement *head ///< head of Merged BbParaNodes list
680  )
681  {
682  int nDeleted = 0;
683  assert( ascendingPool.size() > 0 );
684  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
685  for( p = ascendingPool.begin(); p != ascendingPool.end() && head; )
686  {
687  assert( p->second );
688  if( p->second->getMergingStatus() == 2 )
689  {
690  BbParaMergedNodeListElement *prev = head;
691  BbParaMergedNodeListElement *cur = head;
692  for( ; cur; cur=cur->next )
693  {
694  if( p->second == cur->node )
695  {
696  break;
697  }
698  prev = cur;
699  }
700  assert(cur);
701  if( prev == head )
702  {
703  if( cur == prev )
704  {
705  head = head->next;
706  }
707  else
708  {
709  assert( cur == prev->next );
710  prev->next = prev->next->next;
711  }
712  }
713  else
714  {
715  assert( cur == prev->next );
716  prev->next = prev->next->next;
717  }
718  assert( p->second == cur->node );
719  assert( cur->node->getMergeNodeInfo() );
720  delete cur;
721  nDeleted++;
722  delete p->second;
723  ascendingPool.erase(p++);
724  }
725  else
726  {
727  p++;
728  }
729  }
730  assert(!head);
731  return nDeleted;
732  }
733 
734  ///
735  /// stringfy this object
736  /// @return string which shows inside of this object as string
737  ///
738  const std::string toString(
739  )
740  {
741  std::ostringstream s;
742  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion >::iterator p;
743  for( p = ascendingPool.begin(); p != ascendingPool.end(); ++p )
744  {
745  s << p->second->toString();
746  }
747  return s.str();
748  }
749 };
750 
751 ///
752 /// class BbParaNodePoolForCleanUp
753 ///
755 {
756  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp > descendingPool;
757 
758 public:
759 
760  ///
761  /// constructor
762  ///
764  double inBgap ///< gap which can be considered as good
765  )
766  : BbParaNodePool(inBgap)
767  {
768  }
769 
770  ///
771  /// destructor
772  ///
774  )
775  {
776  if( descendingPool.size() > 0 )
777  {
778  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::iterator p;
779  for( p = descendingPool.begin(); p != descendingPool.end(); )
780  {
781  if( p->second ) delete p->second;
782  descendingPool.erase(p++);
783  }
784  }
785  }
786 
787  ///
788  /// insert BbParaNode to this pool
789  ///
790  void insert(
791  BbParaNodePtr paraNode ///< pointer to BbParaNode object
792  )
793  {
794  descendingPool.insert(std::make_pair(paraNode,paraNode));
795  if( maxUsageOfPool < descendingPool.size() )
796  {
797  maxUsageOfPool = descendingPool.size();
798  }
799  }
800 
801  ///
802  /// check if this pool is empty or not
803  /// @return true if this pool is empty
804  ///
805  bool isEmpty(
806  )
807  {
808  return ( descendingPool.size() == 0 );
809  }
810 
811  ///
812  /// extract a BbParaNode object from this pool
813  /// @return pointer to BbParaNode object extracted
814  ///
816  )
817  {
818  BbParaNodePtr extracted = 0;
819  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::iterator p;
820  p = descendingPool.begin();
821  while( p != descendingPool.end() )
822  {
823  if( p->second->getMergeNodeInfo() )
824  {
825  THROW_LOGICAL_ERROR1("Nodes merging was used in clean up process!");
826  }
827  extracted = p->second;
828  descendingPool.erase(p);
829  break;
830  }
831  assert( ( p == descendingPool.end() && (!extracted) ) || ( p != descendingPool.end() && extracted ) );
832  return extracted;
833  }
834 
835  ///
836  /// extract a BbParaNode object with the lowest priority from this pool
837  /// @return pointer to BbParaNode object extracted
838  ///
840  )
841  {
842  std::cerr << "***** LOGICAL ERROR : should not be called *****" << std::endl;
843  abort();
844  }
845 
846  ///
847  /// extract a BbParaNode object randomly from this pool
848  /// @return pointer to BbParaNode object extracted
849  ///
851  )
852  {
853  BbParaNodePtr extracted = 0;
854  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::iterator p;
855  p = descendingPool.begin();
856  while( p != descendingPool.end() )
857  {
858  if( p->second->getMergeNodeInfo() )
859  {
860  THROW_LOGICAL_ERROR1("Nodes merging was used in clean up process!");
861  }
862  extracted = p->second;
863  descendingPool.erase(p);
864  break;
865  }
866  assert( ( p == descendingPool.end() && (!extracted) ) || ( p != descendingPool.end() && extracted ) );
867  return extracted;
868  }
869 
870  ///
871  /// update dual bound values for saving BbParaNodes to checkpoint file
872  ///
874  )
875  {
876  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::iterator p;
877  for( p = descendingPool.begin(); p != descendingPool.end(); ++p )
878  {
879  if( p->second->getAncestor() == 0 )
880  {
881  p->second->updateInitialDualBoundToSubtreeDualBound();
882  }
883  }
884  }
885 
886 #ifdef UG_WITH_ZLIB
887 
888  ///
889  /// write BbParaNodes to checkpoint file
890  /// @return number of BbParaNodes written
891  ///
892  int writeBbParaNodesToCheckpointFile(
893  gzstream::ogzstream &out ///< gzstram for output
894  )
895  {
896  int n = 0;
897  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::iterator p;
898  for( p = descendingPool.begin(); p != descendingPool.end(); ++p )
899  {
900  if( p->second->getAncestor() == 0 )
901  {
902  p->second->write(out);
903  n++;
904  }
905  }
906  return n;
907  }
908 
909 #endif
910 
911  ///
912  /// get best dual bound value of BbParaNode object in this pool
913  /// @return best dual bound value
914  ///
916  )
917  {
918  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::reverse_iterator rp;
919  rp = descendingPool.rbegin();
920  if( rp != descendingPool.rend() )
921  {
922  return rp->second->getDualBoundValue();
923  }
924  else
925  {
926  return DBL_MAX; // no nodes exist
927  }
928  }
929 
930  ///
931  /// get number of good (heavy) BbParaNodes in this pool
932  /// @return the number of good BbParaNodes
933  ///
934  unsigned int getNumOfGoodNodes(
935  double globalBestBound ///< global best bound value to evaluate goodness
936  )
937  {
938  /** The following code is not a good idea,
939  * because only a node is received from a solver, LC can switch out
940  if( globalBestBound > getBestDualBoundValue() )
941  globalBestBound = getBestDualBoundValue();
942  */
943  int num = 0;
944  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::reverse_iterator rp;
945  for( rp = descendingPool.rbegin(); rp != descendingPool.rend() &&
946  ( ( ( rp->second->getDualBoundValue() ) - globalBestBound ) /
947  std::max( fabs(globalBestBound) , 1.0 ) ) < bgap;
948  ++rp )
949  {
950  num++;
951  }
952  return num;
953  }
954 
955  ///
956  /// get number of BbParaNodes in this pool
957  /// @return number of BbParaNodes
958  ///
960  )
961  {
962  return descendingPool.size();
963  }
964 
965  ///
966  /// remove bounded BbParaNodes by given incumbnet value
967  /// @return the number of bounded BbParaNodes
968  ///
970  double incumbentValue ///< incumbent value
971  )
972  {
973  int nDeleted = 0;
974  if( descendingPool.size() > 0 )
975  {
976  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::iterator p;
977  for( p = descendingPool.begin(); p != descendingPool.end(); )
978  {
979  assert( p->second );
980  if( !p->second->getMergeNodeInfo() )
981  {
982  if( p->second->getDualBoundValue() > incumbentValue )
983  {
984  nDeleted++;
985  delete p->second;
986  descendingPool.erase(p++);
987  }
988  else
989  {
990  p++;
991  }
992  }
993  else
994  {
995  THROW_LOGICAL_ERROR1("Nodes merging was used in clean up process!");
996  }
997  }
998  }
999  return nDeleted;
1000  }
1001 
1002  ///
1003  /// remove merged BbParaNodes from this pool
1004  /// @return the number of BbParaNodes removed
1005  ///
1007  BbParaMergedNodeListElement *head ///< head of Merged BbParaNodes list
1008  )
1009  {
1010  THROW_LOGICAL_ERROR1("Nodes merging was used in clean up process!");
1011  }
1012 
1013  ///
1014  /// stringfy this object
1015  /// @return string which shows inside of this object as string
1016  ///
1017  const std::string toString(
1018  )
1019  {
1020  std::ostringstream s;
1021  std::multimap<BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp >::iterator p;
1022  for( p = descendingPool.begin(); p != descendingPool.end(); ++p )
1023  {
1024  s << p->second->toString();
1025  }
1026  return s.str();
1027  }
1028 };
1029 
1030 }
1031 
1032 #endif // __BB_PARA_NODE_POOL_H__
void insert(BbParaNodePtr paraNode)
insert a BbParaNode object to this pool
virtual int getNBoundChanges()=0
get the number of bound changes
unsigned int getNumOfGoodNodes(double globalBestBound)
get number of good (heavy) BbParaNodes in this pool
#define THROW_LOGICAL_ERROR4(msg1, msg2, msg3, msg4)
Definition: paraDef.h:103
unsigned int getNumOfGoodNodes(double globalBestBound)
get number of good (heavy) BbParaNodes in this pool
BbParaNodePtr extractWorstNode()
extract a BbParaNode object with the lowest priority from this pool
BbParaMergeNodeInfo * getMergeNodeInfo()
get merge node information struct
Definition: bbParaNode.h:658
int removeBoundedNodes(double incumbentValue)
remove bounded BbParaNodes by given incumbnet value
class BbParaNodeSortCriterionForCleanUp
size_t getNumOfNodes()
get number of BbParaNodes in this pool
int removeMergedNodes(BbParaMergedNodeListElement *head)
remove merged BbParaNodes from this pool
virtual ~BbParaNodePool()
destructor
size_t getMaxUsageOfPool()
get maximum usage of this pool
merged node list element stract
int removeMergedNodes(BbParaMergedNodeListElement *head)
remove merged BbParaNodes from this pool
bool isEmpty()
check if this pool is empty or not
bool operator()(const BbParaNodePtr &n1, const BbParaNodePtr &n2) const
()operator
bool operator()(const BbParaNodePtr &n1, const BbParaNodePtr &n2) const
()operator
BbParaNodePtr extractNode()
extract a BbParaNode object from this pool
BbParaNodePool(double inBgap)
constructor
BbParaNodePtr extractNode()
extract a BbParaNode from this pool
BbParaNodePtr extractNodeRandomly()
extract a BbParaNode object randomly from this pool
double getBestDualBoundValue()
get best dual bound value of BbParaNode object in this pool
std::multimap< BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterion > ascendingPool
asnding pool
bool isEmpty()
check if this pool is empty or not
void updateDualBoundsForSavingNodes()
update dual bound values for saving BbParaNodes to checkpoint file
#define EPSEQ(x, y, eps)
Definition: paraDef.h:166
void updateDualBoundsForSavingNodes()
update dual bound values for saving BbParaNodes to checkpoint file
class BbParaNodeSortCriterion
#define THROW_LOGICAL_ERROR1(msg1)
Definition: paraDef.h:52
double bgap
gap which can be considered as good
std::multimap< BbParaNodePtr, BbParaNodePtr, BbParaNodeSortCriterionForCleanUp > descendingPool
double getBestDualBoundValue()
get best dual bound value of BbParaNode object in this pool
class BbParaNodePoolForMinimization
#define EPSLT(x, y, eps)
Definition: paraDef.h:167
BbParaMergedNodeListElement * next
pointer to the next ParaMergedNodeListElement
BbParaNodePtr extractWorstNode()
extract a BbParaNode object with the lowest priority from this pool
BbParaNode * node
pointer to BbParaNode object
void insert(BbParaNodePtr paraNode)
insert BbParaNode to this pool
const std::string toString()
stringfy this object
size_t maxUsageOfPool
maximum usage of this pool
class BbParaNode
Definition: bbParaNode.h:61
size_t getNumOfNodes()
get number of BbParaNodes in this pool
#define EPSGT(x, y, eps)
Definition: paraDef.h:169
double getDualBoundValue()
getter of dual bound value
Definition: bbParaNode.h:303
~BbParaNodePoolForCleanUp()
destructor
BbParaDiffSubproblem * getDiffSubproblem()
getter of diffSubproblem
Definition: bbParaNode.h:353
BbParaNodePtr extractNodeRandomly()
extract a BbParaNode object randomly from this pool
checking possibility to merge with the other nodes
int removeBoundedNodes(double incumbentValue)
remove bounded BbParaNodes by given incumbnet value
class BbParaNodePoolForCleanUp
class BbParaNodePool
BbParaNodePoolForCleanUp(double inBgap)
constructor
BbParaNodePoolForMinimization(double inBgap)
constructor
const std::string toString()
stringfy this object
static const double eps
BbParaNodePtr getNextNode()
get a BbParaNode object, which is expected to extract from this pool