Scippy

GCG

Branch-and-Price & Column Generation for Everyone

gcgpqueue.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file gcgpqueue.c
29  * @brief methods for working with priority queue
30  * @author Jonas Witt
31  *
32  * Various methods to work with the priority queue
33  *
34  */
35 
36 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37 
38 #include "gcgpqueue.h"
39 #include "pub_gcgpqueue.h"
40 
41 #include "gcg.h"
42 #include "scip/def.h"
43 #include "scip/scip.h"
44 #include "blockmemshell/memory.h"
45 
46 #include <assert.h>
47 
48 
49 
50 /*
51  * Priority Queue
52  */
53 
54 #define PQ_PARENT(q) (((q)+1)/2-1)
55 #define PQ_LEFTCHILD(p) (2*(p)+1)
56 #define PQ_RIGHTCHILD(p) (2*(p)+2)
57 
58 
59 /** resizes element memory to hold at least the given number of elements */
60 static
61 SCIP_RETCODE pqueueResize(
62  GCG_PQUEUE* pqueue, /**< pointer to a priority queue */
63  int minsize /**< minimal number of storable elements */
64  )
65 {
66  int newsize;
67  assert(pqueue != NULL);
68 
69  if( minsize <= pqueue->size )
70  return SCIP_OKAY;
71 
72  newsize = SCIPcalcMemGrowSize(pqueue->scip, minsize);
73  SCIP_CALL( SCIPreallocBlockMemoryArray(pqueue->scip, &pqueue->slots, pqueue->size, newsize) );
74  pqueue->size = newsize;
75 
76  return SCIP_OKAY;
77 }
78 
79 /** heapifies element at position pos into corresponding subtrees */
80 static
81 SCIP_RETCODE pqueueHeapify(
82  GCG_PQUEUE* pqueue, /**< pointer to a priority queue */
83  int pos /**< heapify element at position pos into corresponding subtrees */
84  )
85 {
86  int childpos;
87  int brotherpos;
88  void* elem;
89 
90  assert(pqueue != NULL);
91  assert(pqueue->len > 0);
92 
93  /* move the better child of elem to its parents position until element
94  * is better than its children
95  */
96  elem = pqueue->slots[pos];
97 
98  while( pos <= PQ_PARENT(pqueue->len-1) )
99  {
100  childpos = PQ_LEFTCHILD(pos);
101  brotherpos = PQ_RIGHTCHILD(pos);
102  if( brotherpos < pqueue->len && (*pqueue->ptrcomp)(pqueue->slots[brotherpos], pqueue->slots[childpos]) < 0 )
103  childpos = brotherpos;
104  if( (*pqueue->ptrcomp)(elem, pqueue->slots[childpos]) < 0 )
105  break;
106  pqueue->slots[pos] = pqueue->slots[childpos];
107  pqueue->slots[childpos] = elem;
108 
109  pos = childpos;
110  }
111  assert(0 <= pos && pos < pqueue->len);
112 
113  return SCIP_OKAY;
114 }
115 
116 
117 /** creates priority queue */
118 SCIP_RETCODE GCGpqueueCreate(
119  SCIP* scip, /**< SCIP data structure */
120  GCG_PQUEUE** pqueue, /**< pointer to a priority queue */
121  int initsize, /**< initial number of available element slots */
122  SCIP_DECL_SORTPTRCOMP((*ptrcomp)) /**< data element comparator */
123  )
124 {
125  assert(pqueue != NULL);
126  assert(ptrcomp != NULL);
127 
128  initsize = MAX(1, initsize);
129 
130  SCIP_CALL( SCIPallocBlockMemory(scip, pqueue) );
131  (*pqueue)->len = 0;
132  (*pqueue)->size = 0;
133  (*pqueue)->scip = scip;
134  (*pqueue)->slots = NULL;
135  (*pqueue)->ptrcomp = ptrcomp;
136  SCIP_CALL( pqueueResize(*pqueue, initsize) );
137 
138  return SCIP_OKAY;
139 }
140 
141 /** frees priority queue, but not the data elements themselves */
143  GCG_PQUEUE** pqueue /**< pointer to a priority queue */
144  )
145 {
146  assert(pqueue != NULL);
147 
148  SCIPfreeBlockMemoryArray((*pqueue)->scip, &(*pqueue)->slots, (*pqueue)->size);
149  SCIPfreeBlockMemory((*pqueue)->scip, pqueue);
150 }
151 
152 /** clears the priority queue, but doesn't free the data elements themselves */
154  GCG_PQUEUE* pqueue /**< priority queue */
155  )
156 {
157  assert(pqueue != NULL);
158 
159  pqueue->len = 0;
160 }
161 
162 /** inserts element into priority queue */
163 SCIP_RETCODE GCGpqueueInsert(
164  GCG_PQUEUE* pqueue, /**< priority queue */
165  void* elem /**< element to be inserted */
166  )
167 {
168  int pos;
169  int parentpos;
170 
171  assert(pqueue != NULL);
172  assert(pqueue->len >= 0);
173  assert(elem != NULL);
174 
175  SCIP_CALL( pqueueResize(pqueue, pqueue->len+1) );
176 
177  /* insert element as leaf in the tree, move it towards the root as long it is better than its parent */
178  pos = pqueue->len;
179  parentpos = PQ_PARENT(pos);
180  pqueue->len++;
181  while( pos > 0 && (*pqueue->ptrcomp)(elem, pqueue->slots[parentpos]) < 0 )
182  {
183  pqueue->slots[pos] = pqueue->slots[parentpos];
184  pos = parentpos;
185  parentpos = PQ_PARENT(pos);
186  }
187  pqueue->slots[pos] = elem;
188 
189  return SCIP_OKAY;
190 }
191 
192 /** removes and returns best element from the priority queue */
194  GCG_PQUEUE* pqueue /**< priority queue */
195  )
196 {
197  void* root;
198  void* last;
199  int pos;
200  int childpos;
201  int brotherpos;
202 
203  assert(pqueue != NULL);
204  assert(pqueue->len >= 0);
205 
206  if( pqueue->len == 0 )
207  return NULL;
208 
209  /* remove root element of the tree, move the better child to its parents position until the last element
210  * of the queue could be placed in the empty slot
211  */
212  root = pqueue->slots[0];
213  last = pqueue->slots[pqueue->len-1];
214  pqueue->len--;
215  pos = 0;
216  while( pos <= PQ_PARENT(pqueue->len-1) )
217  {
218  childpos = PQ_LEFTCHILD(pos);
219  brotherpos = PQ_RIGHTCHILD(pos);
220  if( brotherpos <= pqueue->len && (*pqueue->ptrcomp)(pqueue->slots[brotherpos], pqueue->slots[childpos]) < 0 )
221  childpos = brotherpos;
222  if( (*pqueue->ptrcomp)(last, pqueue->slots[childpos]) <= 0 )
223  break;
224  pqueue->slots[pos] = pqueue->slots[childpos];
225  pos = childpos;
226  }
227  assert(pos <= pqueue->len);
228  pqueue->slots[pos] = last;
229 
230  return root;
231 }
232 
233 /** resorts priority queue after changing the key values */
234 SCIP_RETCODE GCGpqueueResort(
235  GCG_PQUEUE* pqueue /**< priority queue */
236  )
237 {
238  int lastinner;
239  int pos;
240 
241  assert(pqueue != NULL);
242  assert(pqueue->len >= 0);
243 
244  if( pqueue->len == 0 )
245  {
246  return SCIP_OKAY;
247  }
248 
249  lastinner = PQ_PARENT(pqueue->len - 1);
250 
251  for( pos = lastinner; pos >= 0; --pos )
252  {
253  SCIP_CALL( pqueueHeapify(pqueue, pos) );
254  }
255 
256  return SCIP_OKAY;
257 }
258 
259 
260 /** set the comperator of the priority queue */
262  GCG_PQUEUE* pqueue, /**< priority queue */
263  SCIP_DECL_SORTPTRCOMP((*ptrcomp)) /**< data element comparator */
264  )
265 {
266  pqueue->ptrcomp = ptrcomp;
267 
268  return SCIP_OKAY;
269 }
270 
271 /* todo: write method to get comperator */
272 
273 /**< delete item at position pos and insert last item at this position and resort pqueue */
274 SCIP_RETCODE GCGpqueueDelete(
275  GCG_PQUEUE* pqueue, /**< priority queue */
276  int pos, /**< position of item that should be deleted */
277  void** elem /**< pointer to store element that was deleted from pqueue */
278  )
279 {
280  void* last;
281  int childpos;
282  int brotherpos;
283 
284  assert(pqueue != NULL);
285  assert(pqueue->len >= 0);
286 
287  assert(pos < pqueue->len);
288 
289  /* remove element at position pos of the tree, move the better child to its parents position until the last element
290  * of the queue could be placed in the empty slot
291  */
292  *elem = pqueue->slots[pos];
293  last = pqueue->slots[pqueue->len-1];
294  pqueue->len--;
295  while( pos <= PQ_PARENT(pqueue->len-1) )
296  {
297  childpos = PQ_LEFTCHILD(pos);
298  brotherpos = PQ_RIGHTCHILD(pos);
299  if( brotherpos <= pqueue->len && (*pqueue->ptrcomp)(pqueue->slots[brotherpos], pqueue->slots[childpos]) < 0 )
300  childpos = brotherpos;
301  if( (*pqueue->ptrcomp)(last, pqueue->slots[childpos]) <= 0 )
302  break;
303  pqueue->slots[pos] = pqueue->slots[childpos];
304  pos = childpos;
305  }
306  assert(pos <= pqueue->len);
307  pqueue->slots[pos] = last;
308 
309  return SCIP_OKAY;
310 }
311 
312 /** returns the best element of the queue without removing it */
314  GCG_PQUEUE* pqueue /**< priority queue */
315  )
316 {
317  assert(pqueue != NULL);
318  assert(pqueue->len >= 0);
319 
320  if( pqueue->len == 0 )
321  return NULL;
322 
323  return pqueue->slots[0];
324 }
325 
326 /** returns the number of elements in the queue */
328  GCG_PQUEUE* pqueue /**< priority queue */
329  )
330 {
331  assert(pqueue != NULL);
332  assert(pqueue->len >= 0);
333 
334  return pqueue->len;
335 }
336 
337 /** returns the elements of the queue; changing the returned array may destroy the queue's ordering! */
339  GCG_PQUEUE* pqueue /**< priority queue */
340  )
341 {
342  assert(pqueue != NULL);
343  assert(pqueue->len >= 0);
344 
345  return pqueue->slots;
346 }
#define PQ_RIGHTCHILD(p)
Definition: gcgpqueue.c:56
#define PQ_LEFTCHILD(p)
Definition: gcgpqueue.c:55
GCG interface methods.
void * GCGpqueueFirst(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:313
static SCIP_RETCODE pqueueResize(GCG_PQUEUE *pqueue, int minsize)
Definition: gcgpqueue.c:61
priority queue data structure
SCIP_RETCODE GCGpqueueDelete(GCG_PQUEUE *pqueue, int pos, void **elem)
Definition: gcgpqueue.c:274
SCIP_RETCODE GCGpqueueCreate(SCIP *scip, GCG_PQUEUE **pqueue, int initsize, SCIP_DECL_SORTPTRCOMP((*ptrcomp)))
Definition: gcgpqueue.c:118
SCIP_RETCODE GCGpqueueResort(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:234
void GCGpqueueClear(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:153
static SCIP_RETCODE pqueueHeapify(GCG_PQUEUE *pqueue, int pos)
Definition: gcgpqueue.c:81
void GCGpqueueFree(GCG_PQUEUE **pqueue)
Definition: gcgpqueue.c:142
int GCGpqueueNElems(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:327
private methods for working with priority queue
void * GCGpqueueRemove(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:193
SCIP_RETCODE GCGpqueueInsert(GCG_PQUEUE *pqueue, void *elem)
Definition: gcgpqueue.c:163
void ** GCGpqueueElems(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:338
static SCIP_DECL_SORTPTRCOMP(ptrilocomp)
#define PQ_PARENT(q)
Definition: gcgpqueue.c:54
SCIP_RETCODE GCGpqueueSetComperator(GCG_PQUEUE *pqueue, SCIP_DECL_SORTPTRCOMP((*ptrcomp)))
Definition: gcgpqueue.c:261