Scippy

SCIP

Solving Constraint Integer Programs

enumeration.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 enumeration.c
17  * @brief includes enumeration algorithms for Steiner tree problems
18  * @author Daniel Rehfeldt
19  *
20  * Methods for enumerating solutions (i.e. trees) to Steiner tree problems.
21  *
22  * A list of all interface methods can be found in enumeration.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 <assert.h>
33 #include "portab.h"
34 #include "solstp.h"
35 #include "enumeration.h"
36 
37 
38 
39 
40 /** Finds maximum two terminals. Terminal for rooted problems is always the maximum. */
41 static
43  const GRAPH* g, /**< graph data structure */
44  int* term_max, /**< pointer to store maximum-prize terminal */
45  int* term_max2 /**< pointer to store second-maximum-prize terminal */
46  )
47 {
48  const int pseudoroot = graph_pc_isRootedPcMw(g) ? -1 : g->source;
49  const int nnodes = graph_get_nNodes(g);
50 
51  SCIP_Real max = -1.0;
52  SCIP_Real max2 = -1.0;
53  *term_max = UNKNOWN;
54  *term_max2 = UNKNOWN;
55 
56  for( int i = 0; i < nnodes; ++i )
57  {
58  if( !Is_term(g->term[i]) || i == pseudoroot )
59  continue;
60 
61  if( g->prize[i] > max || i == g->source )
62  {
63  max2 = max;
64  *term_max2 = *term_max;
65 
66  max = g->prize[i];
67  *term_max = i;
68  }
69  else if( g->prize[i] > max2 )
70  {
71  max2 = g->prize[i];
72  *term_max2 = i;
73  }
74  }
75 }
76 
77 /** builds path and connect if possible */
78 static
80  SCIP* scip, /**< SCIP data structure */
81  const GRAPH* g, /**< graph data structure */
82  int term_start, /**< start vertex, from which to connect */
83  int term_end, /**< vertex to be reached */
84  STP_Bool* RESTRICT nodes_inPath /**< for each node: is in path? */
85 )
86 {
87  PATH* path;
88  const int nnodes = graph_get_nNodes(g);
89  assert(term_start != term_end);
90  assert(term_end != g->source);
91 
92  SCIP_CALL(SCIPallocBufferArray(scip, &path, nnodes));
93  BMSclearMemoryArray(nodes_inPath, nnodes);
94  nodes_inPath[term_start] = TRUE;
95 
96  graph_path_exec(scip, g, FSP_MODE, term_start, g->cost, path);
97 
98  /* profitable to connect 2nd terminal? */
99  if( LT(path[term_end].dist, g->prize[term_end]) )
100  {
101  for( int node = term_end; node != term_start; node = g->tail[path[node].edge] )
102  {
103  nodes_inPath[node] = TRUE;
104  assert(graph_edge_isInRange(g, path[node].edge));
105  }
106  }
107 
108  SCIPfreeBufferArray(scip, &path);
109 
110  return SCIP_OKAY;
111 }
112 
113 
114 /** enumeration of rooted PC/MW */
115 static
117  SCIP* scip, /**< SCIP data structure */
118  GRAPH* g, /**< graph data structure */
119  int* RESTRICT result /**< solution array, indicating whether an edge is in the solution */
120 )
121 {
122  int term_max;
123  int term_min;
124  const int nnodes = graph_get_nNodes(g);
125  STP_Bool* RESTRICT connected;
126 
127  assert(graph_pc_isRootedPcMw(g));
128  assert(graph_isMarked(g));
129 
130  assert(g->terms <= 2);
131 
132  if( g->terms == 1 )
133  return SCIP_OKAY;
134 
135  pcmwFindMax2Terms(g, &term_max, &term_min);
136  assert(term_max != UNKNOWN && term_min != UNKNOWN);
137  assert(term_max == g->source);
138  assert(GE(g->prize[term_max], g->prize[term_min]));
139 
140  SCIP_CALL( SCIPallocBufferArray(scip, &connected, nnodes) );
141 
142  SCIP_CALL( tryPathPcMw(scip, g, term_max, term_min, connected) );
143 
144  assert(connected[term_max]);
145  assert(connected[term_min] || !graph_pc_knotIsFixedTerm(g, term_min));
146 
147  graph_pc_2trans(scip, g);
148  solstp_pruneFromNodes(scip, g, result, connected);
149  graph_pc_2org(scip, g);
150 
151  SCIPfreeBufferArray(scip, &connected);
152 
153  return SCIP_OKAY;
154 }
155 
156 
157 /** enumeration of unrooted PC/MW with one terminal other than the root */
158 static
160  const GRAPH* g, /**< graph data structure */
161  int* RESTRICT result /**< solution array, indicating whether an edge is in the solution */
162 )
163 {
164  int a;
165  const int root = g->source;
166 
167  assert(g->terms == 2);
168 
169  for( a = g->outbeg[root]; a != EAT_LAST; a = g->oeat[a] )
170  {
171  if( !graph_pc_knotIsDummyTerm(g, g->head[a]) )
172  {
173  result[a] = CONNECT;
174  break;
175  }
176  }
177 
178  assert(a != EAT_LAST);
179 }
180 
181 
182 /** enumeration of unrooted PC/MW with one terminal other than the root */
183 static
185  SCIP* scip, /**< SCIP data structure */
186  GRAPH* g, /**< graph data structure */
187  int* RESTRICT result /**< solution array, indicating whether an edge is in the solution */
188 )
189 {
190  int term_max;
191  int term_min;
192  const int nnodes = graph_get_nNodes(g);
193  STP_Bool* RESTRICT connected;
194 
195  assert(g->terms == 3);
196  assert(!g->extended);
197 
198  pcmwFindMax2Terms(g, &term_max, &term_min);
199  assert(term_max != UNKNOWN && term_min != UNKNOWN);
200  assert(term_max != g->source && term_min != g->source);
201  assert(GE(g->prize[term_max], g->prize[term_min]));
202 
203  SCIP_CALL( SCIPallocBufferArray(scip, &connected, nnodes) );
204 
205  SCIP_CALL( tryPathPcMw(scip, g, term_max, term_min, connected) );
206 
207  graph_pc_2trans(scip, g);
208  solstp_pruneFromNodes(scip, g, result, connected);
209  graph_pc_2org(scip, g);
210 
211  SCIPfreeBufferArray(scip, &connected);
212 
213  return SCIP_OKAY;
214 }
215 
216 
217 /** enumeration of unrooted PC/MW */
218 static
220  SCIP* scip, /**< SCIP data structure */
221  GRAPH* g, /**< graph data structure */
222  int* RESTRICT result /**< solution array, indicating whether an edge is in the solution */
223 )
224 {
225  assert(!graph_pc_isRootedPcMw(g));
226  assert(g->terms <= 3);
227  assert(g->terms > 1);
228  assert(graph_isMarked(g));
229 
230  if( g->terms == 2 )
231  {
232  SCIPdebugMessage("finding solution for 1 terminal \n");
233 
234  findSolPcMw1Term(g, result);
235  }
236  else
237  {
238  SCIPdebugMessage("finding solution for 2 terminals \n");
239 
240  SCIP_CALL( findSolPcMw2Term(scip, g, result) );
241  }
242 
243  return SCIP_OKAY;
244 }
245 
246 
247 /*
248  * Interface methods
249  */
250 
251 
252 /** enumeration of PC/MW */
254  SCIP* scip, /**< SCIP data structure */
255  GRAPH* g, /**< graph data structure */
256  int* RESTRICT result /**< solution array, indicating whether an edge is in the solution */
257 )
258 {
259  const int nedges = graph_get_nEdges(g);
260 
261  assert(scip && g && result);
262  assert(graph_pc_isPcMw(g));
263  assert(enumeration_isPossible(g));
264 
265  for( int e = 0; e < nedges; e++ )
266  result[e] = UNKNOWN;
267 
268  graph_mark(g);
269 
270  if( graph_pc_isRootedPcMw(g) )
271  {
272  SCIP_CALL( findSolRPcMw(scip, g, result) );
273  }
274  else
275  {
276  SCIP_CALL( findSolPcMw(scip, g, result) );
277  }
278 
279  return TRUE;
280 }
281 
282 
283 /** enumeration possible? */
285  const GRAPH* g /**< graph data structure */
286 )
287 {
288  assert(g);
289 
290  if( graph_pc_isRootedPcMw(g) )
291  {
292  return (g->terms <= 2);
293  }
294  else if( graph_pc_isPcMw(g) )
295  {
296  return (g->terms <= 3);
297  }
298 
299  return FALSE;
300 
301 }
int graph_get_nEdges(const GRAPH *)
Definition: graph_stats.c:548
SCIP_Bool enumeration_isPossible(const GRAPH *g)
Definition: enumeration.c:284
int *RESTRICT head
Definition: graphdefs.h:224
int source
Definition: graphdefs.h:195
#define FSP_MODE
Definition: graphdefs.h:99
SCIP_Bool graph_pc_isRootedPcMw(const GRAPH *)
#define Is_term(a)
Definition: graphdefs.h:102
signed int edge
Definition: graphdefs.h:287
SCIP_RETCODE solstp_pruneFromNodes(SCIP *scip, const GRAPH *g, int *result, STP_Bool *connected)
Definition: solstp.c:1415
int terms
Definition: graphdefs.h:192
void graph_path_exec(SCIP *, const GRAPH *, int, int, const SCIP_Real *, PATH *)
Definition: graph_path.c:541
void graph_mark(GRAPH *)
Definition: graph_base.c:1130
includes methods for Steiner tree problem solutions
void graph_pc_2org(SCIP *, GRAPH *)
#define FALSE
Definition: def.h:87
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
#define EAT_LAST
Definition: graphdefs.h:58
#define SCIPdebugMessage
Definition: pub_message.h:87
includes enumeration algorithms for Steiner tree problems
SCIP_RETCODE enumeration_findSolPcMw(SCIP *scip, GRAPH *g, int *RESTRICT result)
Definition: enumeration.c:253
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
int *RESTRICT oeat
Definition: graphdefs.h:231
static SCIP_RETCODE tryPathPcMw(SCIP *scip, const GRAPH *g, int term_start, int term_end, STP_Bool *RESTRICT nodes_inPath)
Definition: enumeration.c:79
#define GE(a, b)
Definition: portab.h:85
void graph_pc_2trans(SCIP *, GRAPH *)
SCIP_Bool extended
Definition: graphdefs.h:267
SCIP_Real * prize
Definition: graphdefs.h:210
#define SCIP_CALL(x)
Definition: def.h:384
#define LT(a, b)
Definition: portab.h:81
unsigned char STP_Bool
Definition: portab.h:34
static void pcmwFindMax2Terms(const GRAPH *g, int *term_max, int *term_max2)
Definition: enumeration.c:42
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
#define SCIP_Bool
Definition: def.h:84
SCIP_Bool graph_isMarked(const GRAPH *)
Definition: graph_base.c:1165
int *RESTRICT tail
Definition: graphdefs.h:223
static SCIP_RETCODE findSolPcMw2Term(SCIP *scip, GRAPH *g, int *RESTRICT result)
Definition: enumeration.c:184
int *RESTRICT term
Definition: graphdefs.h:196
#define CONNECT
Definition: graphdefs.h:87
Portable definitions.
static SCIP_RETCODE findSolPcMw(SCIP *scip, GRAPH *g, int *RESTRICT result)
Definition: enumeration.c:219
SCIP_Bool graph_pc_knotIsDummyTerm(const GRAPH *, int)
SCIP_Bool graph_pc_knotIsFixedTerm(const GRAPH *, int)
SCIP_Real * cost
Definition: graphdefs.h:221
SCIP_Bool graph_edge_isInRange(const GRAPH *, int)
Definition: graph_stats.c:110
SCIP_Bool graph_pc_isPcMw(const GRAPH *)
SCIP_VAR * a
Definition: circlepacking.c:57
#define SCIP_Real
Definition: def.h:177
int *RESTRICT outbeg
Definition: graphdefs.h:204
int graph_get_nNodes(const GRAPH *)
Definition: graph_stats.c:536
static SCIP_RETCODE findSolRPcMw(SCIP *scip, GRAPH *g, int *RESTRICT result)
Definition: enumeration.c:116
#define UNKNOWN
Definition: sepa_mcf.c:4095
#define nnodes
Definition: gastrans.c:65
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:123
static void findSolPcMw1Term(const GRAPH *g, int *RESTRICT result)
Definition: enumeration.c:159