Scippy

SCIP

Solving Constraint Integer Programs

validate.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 scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file validate.c
17  * @brief Method to validate Steiner problem solutions
18  * @author Thorsten Koch
19  * @author Gerald Gamrath
20  * @author Daniel Rehfeldt
21  *
22  */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
30 #include <assert.h>
31 #include "graph.h"
32 #include "portab.h"
33 
34 
35 static int nail(
36  const GRAPH* g,
37  const double* xval)
38 {
39  double sum;
40  int i;
41  int l;
42  int ind;
43 
44  assert(g != NULL);
45  assert(xval != NULL);
46 
47  if (g->layers == 1)
48  return(TRUE);
49 
50  assert(0 && "currently not used!");
51 
52  for(i = 0; i < g->edges; i += 2)
53  {
54  sum = 0.0;
55 
56  for(l = 0; l < g->layers; l++)
57  {
58  ind = l * g->edges + i;
59  sum += xval[ind] + xval[ind + 1];
60  }
61  assert(sum >= -EPSILON);
62 
63 #ifdef WITH_CAPACITIES
64  assert(g->capa[i] > 0);
65 
66  if (sum - EPSILON > (double)g->capa[i])
67  return(FALSE);
68 #else
69  if (sum - EPSILON > 1.0)
70  return(FALSE);
71 #endif
72  }
73 
74  return(TRUE);
75 }
76 
77 #ifndef NDEBUG
78 /*---------------------------------------------------------------------------*/
79 /*--- Name : Trail ---*/
80 /*--- Function : Durchlaeuft einen Graphen entsprechend einer Loesung und ---*/
81 /*--- stellt fest ob er bei allen Knoten vorbeikommt ---*/
82 /*--- Parameter: Startknoten, Loesung, Herkunft, Schongewesenliste ---*/
83 /*--- Returns : Nichts ---*/
84 /*---------------------------------------------------------------------------*/
85 static void trail_old(
86  const GRAPH* g,
87  int i,
88  const double* xval,
89  int tail,
90  int* visitcount
91  )
92 {
93  /* node visited at most one time so far? */
94  if( visitcount[i] <= 1 )
95  {
96  assert(visitcount[i] == 0 || visitcount[i] == 1);
97 
98  ++(visitcount[i]);
99 
100  /* node visited the first time? */
101  if( visitcount[i] <= 1 )
102  {
103  assert(visitcount[i] == 1);
104 
105  for( int k = g->outbeg[i]; k != EAT_LAST; k = g->oeat[k] )
106  {
107  if( (xval[k] + EPSILON > 1.0) ) // && g->head[k] != tail
108  {
109  trail_old(g, g->head[k], xval, i, visitcount);
110  }
111  }
112  }
113  }
114 }
115 #endif
116 
117 
118 /** traverses the graph from vertex 'start' and marks all reached nodes (counts up to to at most 2) */
119 static
121  SCIP* scip, /**< SCIP */
122  const GRAPH* g, /**< the new graph */
123  const double* xval, /**< (LP) solution */
124  int start, /**< node to start from */
125  int* visitcount /**< marks which node has been visited */
126  )
127 {
128  int* RESTRICT stackarr;
129  int stacksize;
130  const int nnodes = g->knots;
131 
132  for( int i = 0; i < nnodes; i++ )
133  visitcount[i] = 0;
134 
135  visitcount[start] = 1;
136 
137  if( g->grad[start] == 0 )
138  return SCIP_OKAY;
139 
140  stacksize = 0;
141 
142  SCIP_CALL(SCIPallocBufferArray(scip, &stackarr, nnodes));
143 
144  stackarr[stacksize++] = start;
145 
146  /* DFS loop */
147  while( stacksize != 0 )
148  {
149  const int node = stackarr[--stacksize];
150 
151  /* traverse outgoing arcs */
152  for( int a = g->outbeg[node]; a != EAT_LAST; a = g->oeat[a] )
153  {
154  if( (xval[a] > 1.0 - EPSILON) )
155  {
156  const int head = g->head[a];
157 
158  /* not visited yet? */
159  if( visitcount[head] == 0 )
160  stackarr[stacksize++] = head;
161 
162  if( visitcount[head] <= 1 )
163  visitcount[head]++;
164  }
165  }
166  }
167 
168  SCIPfreeBufferArray(scip, &stackarr);
169 
170 #ifndef NDEBUG
171  if( nnodes <= 10000 )
172  {
173  int* visitcount_dbg;
174  SCIP_CALL( SCIPallocClearBufferArray(scip, &visitcount_dbg, nnodes) );
175 
176  trail_old(g, start, xval, -1, visitcount_dbg);
177 
178  for( int i = 0; i < nnodes; i++ )
179  {
180  assert(visitcount_dbg[i] == visitcount[i]);
181  }
182 
183  SCIPfreeBufferArray(scip, &visitcount_dbg);
184  }
185 #endif
186 
187  return SCIP_OKAY;
188 }
189 
190 
191 
192 
193 
194 /*---------------------------------------------------------------------------*/
195 /*--- Name : Validate Solution ---*/
196 /*--- Function : Stellt fuer eine (Teil-)Loesung fest, ob sie zulaessig ---*/
197 /*--- unzulaessig oder schon eine vollstaendige Loesung ist ---*/
198 /*--- Parameter: Graph, Loesung. ---*/
199 /*--- Returns : TRUE / FALSE ---*/
200 /*---------------------------------------------------------------------------*/
201 /** validates whether a (LP) solution is feasible */
203  SCIP* scip, /**< SCIP */
204  const GRAPH* g, /**< the new graph */
205  const double* xval, /**< (LP) solution */
206  SCIP_Bool allow_cyles, /**< allow cycles? */
207  SCIP_Bool* feasible /**< is feasible? */
208 )
209 {
210  int* visitcount;
211  SCIP_Bool isValid = TRUE;
212  const int nnodes = graph_get_nNodes(g);
213 
214  assert(scip && xval && feasible);
215  assert(graph_valid(scip, g));
216 
217  if( nnodes == 1 )
218  {
219  *feasible = TRUE;
220 
221  return SCIP_OKAY;
222  }
223 
224  SCIP_CALL( SCIPallocBufferArray(scip, &visitcount, nnodes) );
225 
226  trail(scip, g, xval, g->source, visitcount);
227 
228  /* check whether solution is feasible */
229  for( int i = 0; i < nnodes; i++ )
230  {
231  if( g->stp_type == STP_DCSTP )
232  {
233  int deg = 0;
234 
235  for( int e = g->outbeg[i]; e != EAT_LAST ; e = g->oeat[e] )
236  {
237  if( GE(xval[e], 1.0) || GE(xval[flipedge(e)], 1.0) )
238  deg++;
239  }
240 
241  if( deg > g->maxdeg[i] )
242  {
243  isValid = FALSE;
244  SCIPdebugMessage("deg condition violated \n");
245 
246  break;
247  }
248  }
249 
250  /* with cycle? */
251  if( !allow_cyles && visitcount[i] >= 2 )
252  {
253  isValid = FALSE;
254  SCIPdebugMessage("cycle found \n");
255 
256  break;
257  }
258 
259  /* terminal not reached? */
260  if ((g->grad[i] > 0) && (g->term[i] == 0) && visitcount[i] == 0 )
261  {
262  isValid = FALSE;
263  SCIPdebugMessage("terminal %d not reached \n", i);
264 
265  break;
266  }
267  }
268 
269  SCIPfreeBufferArray(scip, &visitcount);
270 
271  if( isValid )
272  isValid = nail(g, xval);
273 
274  /* SCIP-Heuristiken können (z.B. durch Runden) Lösungen konstruieren, die einen Kreis aus Steiner-Knoten enthalten, der
275  * nicht zum Baum gehört
276  */
277 #ifndef NDEBUG
278  /* Teste, ob alle Kanten nur in eine Richtung benutzt werden.
279  */
280  if( isValid && !allow_cyles )
281  {
282  for( int e = 0; e < g->edges; e += 2)
283  {
284  assert((xval[e] <= EPSILON) || (xval[e + 1] <= EPSILON));
285  }
286  }
287 #endif
288 
289  *feasible = isValid;
290 
291  return SCIP_OKAY;
292 }
int *RESTRICT head
Definition: graphdefs.h:224
int source
Definition: graphdefs.h:195
#define SCIPallocClearBufferArray(scip, ptr, num)
Definition: scip_mem.h:117
#define EPSILON
Definition: lpi_qso.c:93
SCIP_Bool graph_valid(SCIP *, const GRAPH *)
Definition: graph_base.c:1480
int *RESTRICT maxdeg
Definition: graphdefs.h:206
#define FALSE
Definition: def.h:87
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
includes various files containing graph methods used for Steiner tree problems
#define STP_DCSTP
Definition: graphdefs.h:47
#define EAT_LAST
Definition: graphdefs.h:58
#define SCIPdebugMessage
Definition: pub_message.h:87
static int nail(const GRAPH *g, const double *xval)
Definition: validate.c:35
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
int *RESTRICT oeat
Definition: graphdefs.h:231
#define GE(a, b)
Definition: portab.h:85
int stp_type
Definition: graphdefs.h:264
SCIP_RETCODE SCIPStpValidateSol(SCIP *scip, const GRAPH *g, const double *xval, SCIP_Bool allow_cyles, SCIP_Bool *feasible)
Definition: validate.c:202
int *RESTRICT grad
Definition: graphdefs.h:201
#define NULL
Definition: lpi_spx1.cpp:155
int knots
Definition: graphdefs.h:190
#define SCIP_CALL(x)
Definition: def.h:384
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
#define SCIP_Bool
Definition: def.h:84
#define flipedge(edge)
Definition: graphdefs.h:84
int *RESTRICT term
Definition: graphdefs.h:196
Portable definitions.
int layers
Definition: graphdefs.h:193
SCIP_VAR * a
Definition: circlepacking.c:57
int *RESTRICT outbeg
Definition: graphdefs.h:204
static void trail_old(const GRAPH *g, int i, const double *xval, int tail, int *visitcount)
Definition: validate.c:85
int edges
Definition: graphdefs.h:219
int graph_get_nNodes(const GRAPH *)
Definition: graph_stats.c:536
#define nnodes
Definition: gastrans.c:65
static SCIP_RETCODE trail(SCIP *scip, const GRAPH *g, const double *xval, int start, int *visitcount)
Definition: validate.c:120