Scippy

SCIP

Solving Constraint Integer Programs

solhistory.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file solhistory.c
17  * @brief includes methods working on the (reduction) history of solutions to Steiner tree problems
18  * @author Daniel Rehfeldt
19  *
20  * This file includes methods working on the (reduction) history of solutions to Steiner tree problems
21  *
22  * A list of all interface methods can be found in solhistory.h
23  *
24  */
25 
26 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
27 
28 /*lint -esym(766,stdlib.h) -esym(766,malloc.h) */
29 /*lint -esym(766,string.h) */
30 //#define SCIP_DEBUG
31 
32 #include "solhistory.h"
33 #include "probdata_stp.h"
34 #include "portab.h"
35 #include "solstp.h"
36 #include "mst.h"
37 #include "shortestpath.h"
38 
39 
40 /*
41  * Local methods
42  */
43 
44 /** updates */
45 static inline
47  const GRAPH* graph, /**< graph data structure */
48  IDX* curr, /**< head of solution edge list */
49  STP_Bool* RESTRICT orgnodes, /**< array to mark whether a node is part of the original solution */
50  STP_Bool* RESTRICT orgedges, /**< array to mark whether an edge is part of the original solution */
51  int* nsolnodes, /**< pointer to store the number of nodes in the original solution */
52  int* nsoledges /**< pointer to store the number of edges in the original solution */
53 )
54 {
55  int e = 0;
56  int k = 0;
57 
58  while( curr != NULL )
59  {
60  const int i = curr->index;
61  assert(i >= 0);
62 
63  if( orgedges[i] == FALSE )
64  {
65  orgedges[i] = TRUE;
66  e++;
67  }
68 
69  if( !(orgnodes[graph->orgtail[i]]) )
70  {
71  k++;
72  orgnodes[graph->orgtail[i]] = TRUE;;
73  }
74 
75  if( !(orgnodes[graph->orghead[i]]) )
76  {
77  k++;
78  orgnodes[graph->orghead[i]] = TRUE;
79  }
80 
81  curr = curr->parent;
82  }
83 
84  (*nsolnodes) += k;
85  (*nsoledges) += e;
86 }
87 
88 
89 /** builds history */
90 static
92  const GRAPH* g, /**< graph structure */
93  SOLHISTORY* solhistory /**< the solution history */
94  )
95 {
96  STP_Bool* const orgnodes = solhistory->orgnodes_isInSol;
97  STP_Bool* const orgedges = solhistory->orgedges_isInSol;
98  const int norgnodes = solhistory->norgnodes;
99  const int norgedges = solhistory->norgedges;
100 
101  assert(norgnodes == g->orgknots);
102  assert(norgedges == g->orgedges);
103 
104  for( int k = 0; k < norgnodes; k++ )
105  orgnodes[k] = FALSE;
106 
107  for( int e = 0; e < norgedges; e++ )
108  orgedges[e] = FALSE;
109 }
110 
111 
112 /** builds history */
113 static
115  SCIP* scip, /**< SCIP data structure */
116  SCIP_SOL* scipsol, /**< solution */
117  const GRAPH* graph, /**< graph structure */
118  SOLHISTORY* solhistory /**< the solution history */
119  )
120 {
121  GRAPH* solgraph = NULL;
122  SCIP_QUEUE* queue = NULL;
123  SCIP_VAR** edgevars = SCIPprobdataGetVars(scip);
124  STP_Bool* const orgnodes = solhistory->orgnodes_isInSol;
125  STP_Bool* const orgedges = solhistory->orgedges_isInSol;
126  int* nodechild = NULL;
127  int* edgeancestor = NULL;
128  int nsolnodes = 0;
129  int nsoledges = 0;
130  int norgnodes = solhistory->norgnodes;
131  const int norgedges = solhistory->norgedges;
132 
133  assert(!graph_pc_isPcMw(graph));
134  assert(graph->ancestors || graph->edges == 0);
135  assert(edgevars || graph->edges == 0);
136 
137  /* iterate through the list of fixed edges */
138  updateorgsol(graph, graph_getFixedges(graph), orgnodes, orgedges, &nsolnodes, &nsoledges);
139 
140  for( int e = 0; e < graph->edges; e++ )
141  {
142  if( !SCIPisZero(scip, SCIPgetSolVal(scip, scipsol, edgevars[e])) )
143  /* iterate through the list of ancestors */
144  updateorgsol(graph, graph_edge_getAncestors(graph, e), orgnodes, orgedges, &nsolnodes, &nsoledges);
145  }
146 
147  if( nsolnodes == 0 )
148  {
149  assert(graph->terms == 1);
150 
151  solhistory->nsolnodes = 1;
152  solhistory->nsoledges = 0;
153  solhistory->norgnodes = norgnodes;
154  solhistory->norgedges = norgedges;
155 
156  return SCIP_OKAY;
157  }
158 
159 
160  assert(nsolnodes > 0);
161 
162  SCIP_CALL( SCIPallocBufferArray(scip, &nodechild, norgnodes) );
163  SCIP_CALL( SCIPallocBufferArray(scip, &edgeancestor, 2 * nsoledges) );
164 
165  /* initialize new graph */
166  SCIP_CALL( graph_init(scip, &solgraph, nsolnodes, 2 * nsoledges, 1) );
167 
168  /* add vertices to new graph */
169  for( int k = 0; k < norgnodes; k++ )
170  {
171  if( orgnodes[k] )
172  {
173  nodechild[k] = solgraph->knots;
174  graph_knot_add(solgraph, -1);
175  }
176  else
177  {
178  nodechild[k] = -1;
179  }
180  }
181 
182  assert(nsolnodes == solgraph->knots);
183  assert(nodechild[graph->orgsource] >= 0);
184 
185  /* set root of new graph */
186  solgraph->source = nodechild[graph->orgsource];
187 
188  /* add edges to new graph */
189  for( int e = 0; e < norgedges; e++ )
190  {
191  int tail;
192  int head;
193 
194  if( !orgedges[e] )
195  continue;
196 
197  tail = nodechild[graph->orgtail[e]];
198  head = nodechild[graph->orghead[e]];
199 
200  assert(tail >= 0);
201  assert(head >= 0);
202 
203  edgeancestor[solgraph->edges] = e;
204  edgeancestor[solgraph->edges + 1] = flipedge(e);
205  graph_edge_add(scip, solgraph, tail, head, 1.0, 1.0);
206  }
207 
208  for( int e = 0; e < norgedges; e++ )
209  orgedges[e] = FALSE;
210 
211  for( int k = 0; k < norgnodes; k++ )
212  orgnodes[k] = FALSE;
213 
214  SCIP_CALL( SCIPqueueCreate(&queue, nsolnodes, 1.1) );
215  SCIP_CALL( SCIPqueueInsert(queue, &(solgraph->source)) );
216  solgraph->mark[solgraph->source] = FALSE;
217 
218  nsolnodes = 1;
219 
220  /* BFS from root */
221  while( !SCIPqueueIsEmpty(queue) )
222  {
223  const int k = *((int*) SCIPqueueRemove(queue));
224 
225  /* traverse outgoing arcs */
226  for( int e = solgraph->outbeg[k]; e != EAT_LAST; e = solgraph->oeat[e] )
227  {
228  const int head = solgraph->head[e];
229 
230  /* vertex not labeled yet? */
231  if( solgraph->mark[head] )
232  {
233  orgedges[edgeancestor[e]] = TRUE;
234  solgraph->mark[head] = FALSE;
235  nsolnodes++;
236  SCIP_CALL(SCIPqueueInsert(queue, &(solgraph->head[e])));
237  }
238  }
239  }
240 
241  nsoledges = nsolnodes - 1;
242 
243  SCIPqueueFree(&queue);
244 
245  graph_free(scip, &solgraph, TRUE);
246 
247  for( int e = 0; e < norgedges; e++ )
248  {
249  if( orgedges[e] )
250  {
251  orgnodes[graph->orgtail[e]] = TRUE;
252  orgnodes[graph->orghead[e]] = TRUE;
253  }
254  }
255 
256  SCIPfreeBufferArray(scip, &edgeancestor);
257  SCIPfreeBufferArray(scip, &nodechild);
258 
259  if( graph->stp_type == STP_GSTP )
260  {
261  assert(graph->norgmodelterms > 0);
262 
263  norgnodes -= graph->norgmodelterms;
264  nsolnodes -= graph->norgmodelterms;
265  nsoledges -= graph->norgmodelterms;
266  assert(nsolnodes >= 0);
267  assert(nsoledges >= 1);
268  }
269 
270  solhistory->nsolnodes = nsolnodes;
271  solhistory->nsoledges = nsoledges;
272  solhistory->norgnodes = norgnodes;
273  solhistory->norgedges = norgedges;
274 
275  return SCIP_OKAY;
276 }
277 
278 
279 /** builds history */
280 static
282  SCIP* scip, /**< SCIP data structure */
283  SCIP_SOL* scipsol, /**< solution */
284  const GRAPH* graph, /**< graph structure */
285  SOLHISTORY* solhistory /**< the solution history */
286  )
287 {
288  SCIP_VAR** edgevars = SCIPprobdataGetVars(scip);
289  int* solnodequeue;
290  STP_Bool* const orgnodes = solhistory->orgnodes_isInSol;
291  STP_Bool* const orgedges = solhistory->orgedges_isInSol;
292  int nsolnodes = 0;
293  int nsoledges = 0;
294  int norgnodes = solhistory->norgnodes;
295  const int norgedges = solhistory->norgedges;
296 
297  assert(graph->ancestors || graph->edges == 0);
298  assert(edgevars || graph->edges == 0);
299  assert(graph_pc_isPcMw(graph));
300  assert(graph->source >= 0);
301 
302  SCIP_CALL( SCIPallocBufferArray(scip, &solnodequeue, norgnodes) );
303 
304  /* cover RPCSPG/RMWCSP with single node solution */
305  if( graph_pc_isRootedPcMw(graph) && graph->orgsource != -1 )
306  {
307  SCIPdebugMessage("graph->orgsource %d \n", graph->orgsource);
308  solnodequeue[nsolnodes++] = graph->orgsource;
309  orgnodes[graph->orgsource] = TRUE;
310  }
311 
312  for( int e = 0; e <= graph->edges; e++ )
313  {
314  if( e == graph->edges || !SCIPisZero(scip, SCIPgetSolVal(scip, scipsol, edgevars[e])) )
315  {
316  IDX* curr;
317 
318  /* iterate through the list of ancestors/fixed edges */
319  if( e < graph->edges )
320  curr = graph_edge_getAncestors(graph, e);
321  else
322  curr = graph_getFixedges(graph);
323 
324  while (curr != NULL)
325  {
326  const int ancestoredge = curr->index;
327  if( e < graph->edges && (graph->stp_type == STP_MWCSP || graph->stp_type == STP_RMWCSP || graph->stp_type == STP_BRMWCSP) )
328  {
329  if( !SCIPisZero(scip, SCIPgetSolVal(scip, scipsol, edgevars[flipedge(e)])) )
330  {
331  curr = curr->parent;
332  continue;
333  }
334  }
335 
336  if( ancestoredge < graph->norgmodeledges )
337  {
338  if( !orgedges[ancestoredge] )
339  {
340  orgedges[ancestoredge] = TRUE;
341  nsoledges++;
342  }
343  if( !orgnodes[graph->orgtail[ancestoredge]] )
344  {
345  orgnodes[graph->orgtail[ancestoredge]] = TRUE;
346  solnodequeue[nsolnodes++] = graph->orgtail[ancestoredge];
347  }
348  if( !orgnodes[graph->orghead[ancestoredge]] )
349  {
350  orgnodes[graph->orghead[ancestoredge]] = TRUE;
351  solnodequeue[nsolnodes++] = graph->orghead[ancestoredge];
352  }
353  }
354  else if( graph->orghead[ancestoredge] < graph->norgmodelknots )
355  {
356  if( !orgnodes[graph->orghead[ancestoredge]])
357  {
358  orgnodes[graph->orghead[ancestoredge]] = TRUE;
359  solnodequeue[nsolnodes++] = graph->orghead[ancestoredge];
360  }
361  }
362  curr = curr->parent;
363  }
364  }
365  }
366 
367  SCIP_CALL( solstp_markPcancestors(scip, graph->pcancestors, graph->orgtail, graph->orghead, norgnodes,
368  orgnodes, orgedges, solnodequeue, &nsolnodes, &nsoledges ) );
369 
370  SCIPfreeBufferArray(scip, &solnodequeue);
371 
372  solhistory->nsolnodes = nsolnodes;
373  solhistory->nsoledges = nsoledges;
374  solhistory->norgnodes = norgnodes;
375  solhistory->norgedges = norgedges;
376 
377  return SCIP_OKAY;
378 }
379 
380 
381 
382 /*
383  * Interface methods
384  */
385 
386 
387 
388 /** initializes */
390  SCIP* scip, /**< SCIP data structure */
391  const GRAPH* graph, /**< graph */
392  SOLHISTORY** solhistory /**< the solution history */
393 )
394 {
395  SOLHISTORY* sol;
396 
397  assert(scip && graph);
398 
399  SCIP_CALL( SCIPallocMemory(scip, solhistory) );
400  sol = *solhistory;
401 
402  sol->nsolnodes = 0;
403  sol->nsoledges = 0;
404  sol->norgedges = graph->orgedges;
405  sol->norgnodes = graph->orgknots;
406  assert(sol->norgedges >= 0);
407  assert(sol->norgnodes >= 1);
408 
410 
411  if( sol->norgedges > 0 )
413 
414  return SCIP_OKAY;
415 }
416 
417 
418 /** frees */
420  SCIP* scip, /**< SCIP data structure */
421  SOLHISTORY** solhistory /**< the solution history */
422  )
423 {
424  SOLHISTORY* sol;
425 
426  assert(scip && solhistory);
427  sol = *solhistory;
428  assert(sol);
429 
431  SCIPfreeMemoryArray(scip, &(sol->orgnodes_isInSol));
432  SCIPfreeMemory(scip, solhistory);
433 }
434 
435 
436 /** builds history */
438  SCIP* scip, /**< SCIP data structure */
439  SCIP_SOL* scipsol, /**< solution */
440  const GRAPH* g, /**< graph structure */
441  SOLHISTORY* solhistory /**< the solution history */
442  )
443 {
444  assert(scip && g && solhistory && scipsol);
445 
446  cleanHistory(g, solhistory);
447 
448  if( graph_pc_isPcMw(g) )
449  {
450  SCIP_CALL( computeHistoryPcMw(scip, scipsol, g, solhistory) );
451  }
452  else
453  {
454  SCIP_CALL( computeHistory(scip, scipsol, g, solhistory) );
455  }
456 
457  return SCIP_OKAY;
458 }
int *RESTRICT head
Definition: graphdefs.h:224
int *RESTRICT orgtail
Definition: graphdefs.h:225
int source
Definition: graphdefs.h:195
SCIP_Bool graph_pc_isRootedPcMw(const GRAPH *)
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip_mem.h:72
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip_mem.h:71
Shortest path based algorithms for Steiner problems.
int terms
Definition: graphdefs.h:192
SCIP_VAR ** SCIPprobdataGetVars(SCIP *scip)
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip_mem.h:55
SCIP_RETCODE SCIPqueueInsert(SCIP_QUEUE *queue, void *elem)
Definition: misc.c:1020
SCIP_RETCODE solstp_markPcancestors(SCIP *scip, IDX **pcancestors, const int *tails, const int *heads, int orgnnodes, STP_Bool *solnodemark, STP_Bool *soledgemark, int *solnodequeue, int *nsolnodes, int *nsoledges)
Definition: solstp.c:2200
includes methods for Steiner tree problem solutions
void graph_free(SCIP *, GRAPH **, SCIP_Bool)
Definition: graph_base.c:796
#define FALSE
Definition: def.h:87
Problem data for stp problem.
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
minimum spanning tree based algorithms for Steiner problems
#define EAT_LAST
Definition: graphdefs.h:58
#define SCIPdebugMessage
Definition: pub_message.h:87
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
Definition: misc.c:1175
int *RESTRICT orghead
Definition: graphdefs.h:226
static void cleanHistory(const GRAPH *g, SOLHISTORY *solhistory)
Definition: solhistory.c:91
int *RESTRICT mark
Definition: graphdefs.h:198
static void updateorgsol(const GRAPH *graph, IDX *curr, STP_Bool *RESTRICT orgnodes, STP_Bool *RESTRICT orgedges, int *nsolnodes, int *nsoledges)
Definition: solhistory.c:46
int *RESTRICT oeat
Definition: graphdefs.h:231
SCIP_RETCODE solhistory_init(SCIP *scip, const GRAPH *graph, SOLHISTORY **solhistory)
Definition: solhistory.c:389
includes methods working on the (reduction) history of solutions to Steiner tree problems ...
int stp_type
Definition: graphdefs.h:264
IDX ** ancestors
Definition: graphdefs.h:234
int orgedges
Definition: graphdefs.h:220
STP_Bool * orgnodes_isInSol
Definition: solhistory.h:42
static SCIP_RETCODE computeHistory(SCIP *scip, SCIP_SOL *scipsol, const GRAPH *graph, SOLHISTORY *solhistory)
Definition: solhistory.c:114
void graph_edge_add(SCIP *, GRAPH *, int, int, double, double)
void graph_knot_add(GRAPH *, int)
Definition: graph_node.c:64
#define NULL
Definition: lpi_spx1.cpp:155
#define STP_RMWCSP
Definition: graphdefs.h:54
int knots
Definition: graphdefs.h:190
#define SCIP_CALL(x)
Definition: def.h:384
IDX ** pcancestors
Definition: graphdefs.h:235
void SCIPqueueFree(SCIP_QUEUE **queue)
Definition: misc.c:958
static SCIP_RETCODE computeHistoryPcMw(SCIP *scip, SCIP_SOL *scipsol, const GRAPH *graph, SOLHISTORY *solhistory)
Definition: solhistory.c:281
int orgknots
Definition: graphdefs.h:191
unsigned char STP_Bool
Definition: portab.h:34
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
SCIP_RETCODE solhistory_computeHistory(SCIP *scip, SCIP_SOL *scipsol, const GRAPH *g, SOLHISTORY *solhistory)
Definition: solhistory.c:437
#define flipedge(edge)
Definition: graphdefs.h:84
IDX * graph_getFixedges(const GRAPH *)
STP_Bool * orgedges_isInSol
Definition: solhistory.h:43
Portable definitions.
#define SCIPfreeMemory(scip, ptr)
Definition: scip_mem.h:69
SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
Definition: misc.c:934
SCIP_Bool graph_pc_isPcMw(const GRAPH *)
int *RESTRICT outbeg
Definition: graphdefs.h:204
#define STP_BRMWCSP
Definition: graphdefs.h:55
int edges
Definition: graphdefs.h:219
#define STP_GSTP
Definition: graphdefs.h:53
void * SCIPqueueRemove(SCIP_QUEUE *queue)
Definition: misc.c:1071
#define SCIPallocMemory(scip, ptr)
Definition: scip_mem.h:51
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_RETCODE graph_init(SCIP *, GRAPH **, int, int, int)
Definition: graph_base.c:607
struct Int_List_Node * parent
Definition: misc_stp.h:91
int norgmodelterms
Definition: graphdefs.h:188
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1352
#define STP_MWCSP
Definition: graphdefs.h:51
void solhistory_free(SCIP *scip, SOLHISTORY **solhistory)
Definition: solhistory.c:419
IDX * graph_edge_getAncestors(const GRAPH *, int)
int norgmodelknots
Definition: graphdefs.h:187
int orgsource
Definition: graphdefs.h:194