Scippy

SCIP

Solving Constraint Integer Programs

prop_stp.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-2015 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file prop_stp.c
17  * @brief propagator for Steiner tree problems, using the LP reduced costs
18  * @author Daniel Rehfeldt
19  *
20  * This propagator makes use of the reduced cost of an optimally solved LP relaxation to propagate the variables
21  *
22  */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 
26 #include <assert.h>
27 #include <string.h>
28 
29 #include "prop_stp.h"
30 
31 
32 /**@name Propagator properties
33  *
34  * @{
35  */
36 
37 #define PROP_NAME "stp"
38 #define PROP_DESC "stp propagator"
39 #define PROP_TIMING SCIP_PROPTIMING_DURINGLPLOOP | SCIP_PROPTIMING_AFTERLPLOOP
40 #define PROP_PRIORITY +1000000 /**< propagator priority */
41 #define PROP_FREQ 1 /**< propagator frequency */
42 #define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found reductions? */
43 
44 /**@} */
45 
46 /**@name Default parameter values
47  *
48  * @{
49  */
50 
51 #define DEFAULT_MAXNWAITINGROUNDS 3 /**< maximal number of rounds to wait until propagating again */
52 
53 
54 /**@} */
55 
56 
57 /*
58  * Data structures
59  */
60 
61 
62 /** propagator data */
64 {
65  SCIP_Longint nfails; /**< number of failures since last successful call */
66  SCIP_Longint ncalls; /**< number of calls */
67  SCIP_Longint nlastcall; /**< number of last call */
68 };
69 
70 /**@name Local methods
71  *
72  * @{
73  */
74 
75 /** fix a variable (corresponding to an edge) to zero */
76 SCIP_RETCODE fixedgevar(
77  SCIP* scip, /**< SCIP data structure */
78  SCIP_VAR* edgevar, /**< the variable to be fixed */
79  int* nfixed /**< counter that is incriminated if variable could be fixed */
80  )
81 {
82  assert(SCIPvarGetLbLocal(edgevar) < 0.5);
83  if( SCIPvarGetUbLocal(edgevar) > 0.5 && SCIPvarGetLbLocal(edgevar) < 0.5 )
84  {
85  SCIP_CALL( SCIPchgVarUb(scip, edgevar, 0.0) );
86  (*nfixed)++;
87  }
88  return SCIP_OKAY;
89 }
90 
91 /**@} */
92 
93 /**@name Callback methods of propagator
94  *
95  * @{
96  */
97 
98 /** copy method for propagator plugins (called when SCIP copies plugins) */
99 static
100 SCIP_DECL_PROPCOPY(propCopyStp)
101 { /*lint --e{715}*/
102  assert(scip != NULL);
103  assert(prop != NULL);
104  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
105 
106  /* call inclusion method of constraint handler */
107  SCIP_CALL( SCIPincludePropStp(scip) );
108 
109  return SCIP_OKAY;
110 }
111 
112 
113 /** destructor of propagator to free user data (called when SCIP is exiting) */
114 static
115 SCIP_DECL_PROPFREE(propFreeStp)
116 { /*lint --e{715}*/
117  SCIP_PROPDATA* propdata;
118 
119  /* free propagator data */
120  propdata = SCIPpropGetData(prop);
121  assert(propdata != NULL);
122 
123  SCIPfreeMemory(scip, &propdata);
124 
125  SCIPpropSetData(prop, NULL);
126 
127  return SCIP_OKAY;
128 }
129 
130 
131 /** reduced cost propagation method for an LP solution */
132 static
133 SCIP_DECL_PROPEXEC(propExecStp)
134 { /*lint --e{715}*/
135  SCIP_PROPDATA* propdata;
136  SCIP_PROBDATA* probdata;
137  SCIP_VAR** vars;
138  SCIP_VAR* edgevar;
139  GRAPH* graph;
140  PATH* vnoi;
141  SCIP_Real* cost;
142  SCIP_Real* costrev;
143  SCIP_Real* pathdist;
144  SCIP_Real lpobjval;
145  SCIP_Real cutoffbound;
146  SCIP_Real minpathcost;
147  int* vbase;
148  int* pathedge;
149  int k;
150  int e;
151  int nedges;
152  int nnodes;
153  int nfixed = 0;
154 
155  *result = SCIP_DIDNOTRUN;
156 
157  /* propagator can only be applied during solving stage */
158  if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING )
159  return SCIP_OKAY;
160 
161  /* only call propagator if current node has an LP */
162  if( !SCIPhasCurrentNodeLP(scip) )
163  return SCIP_OKAY;
164 
165  /* only call propagator if optimal LP solution is at hand */
166  if( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
167  return SCIP_OKAY;
168 
169  /* only call propagator if current LP is valid relaxation */
170  if( !SCIPisLPRelax(scip) )
171  return SCIP_OKAY;
172 
173  /* we cannot apply reduced cost strengthening, if no simplex basis is available */
174  if( !SCIPisLPSolBasic(scip) )
175  return SCIP_OKAY;
176 
177  cutoffbound = SCIPgetCutoffbound(scip);
178 
179  /* reduced cost strengthening can only be applied, if cutoff is finite */
180  if( SCIPisInfinity(scip, cutoffbound) )
181  return SCIP_OKAY;
182 
183  /* get problem data */
184  probdata = SCIPgetProbData(scip);
185  assert(probdata != NULL);
186 
187  graph = SCIPprobdataGetGraph(probdata);
188  assert(graph != NULL);
189 
190  nedges = graph->edges;
191  nnodes = graph->knots;
192 
193  /* get all variables (corresponding to the edges) */
194  vars = SCIPprobdataGetVars(scip);
195 
196  if( vars == NULL )
197  return SCIP_OKAY;
198 
199  /* check if all integral variables are fixed */
200  if( SCIPgetNPseudoBranchCands(scip) == 0 )
201  return SCIP_OKAY;
202 
203  /* get propagator data */
204  propdata = SCIPpropGetData(prop);
205  assert(propdata != NULL);
206 
207  propdata->ncalls++;
208 
209  /* @todo: parameter */
210  if( propdata->nfails > 0 && (propdata->nlastcall + DEFAULT_MAXNWAITINGROUNDS >= propdata->ncalls)
211  && (propdata->nlastcall + propdata->nfails > propdata->ncalls) )
212  return SCIP_OKAY;
213 
214  propdata->nlastcall = propdata->ncalls;
215 
216  /* get LP objective value */
217  lpobjval = SCIPgetLPObjval(scip);
218 #if 0
219  if( SCIPisEQ(scip, lpobjval, 0.0) )
220  return SCIP_OKAY;
221 #endif
222  *result = SCIP_DIDNOTFIND;
223 
224  /* the required reduced path cost to be surpassed */
225  minpathcost = cutoffbound - lpobjval;
226  SCIPdebugMessage("cutoffbound %f, lpobjval %f\n", cutoffbound, lpobjval);
227 
228  SCIP_CALL( SCIPallocBufferArray(scip, &cost, nedges) );
229  SCIP_CALL( SCIPallocBufferArray(scip, &costrev, nedges) );
230  SCIP_CALL( SCIPallocBufferArray(scip, &pathdist, nnodes) );
231  SCIP_CALL( SCIPallocBufferArray(scip, &vbase, nnodes) );
232  SCIP_CALL( SCIPallocBufferArray(scip, &pathedge, nnodes) );
233  SCIP_CALL( SCIPallocBufferArray(scip, &vnoi, nnodes) );
234 
235  for( e = 0; e < nedges; ++e )
236  {
237  assert(SCIPvarIsBinary(vars[e]));
238 
239  /* variable is already fixed, we must not trust the reduced cost */
240  if( SCIPvarGetLbLocal(vars[e]) + 0.5 > SCIPvarGetUbLocal(vars[e]) )
241  {
242  if( SCIPvarGetLbLocal(vars[e]) > 0.5 )
243  cost[e] = 0.0;
244  else
245  {
246  assert(SCIPvarGetUbLocal(vars[e]) < 0.5);
247  cost[e] = FARAWAY;
248  }
249  }
250  else
251  {
252  if( SCIPisFeasZero(scip, SCIPgetSolVal(scip, NULL, vars[e])) )
253  {
254  assert(!SCIPisDualfeasNegative(scip, SCIPgetVarRedcost(scip, vars[e])));
255  cost[e] = SCIPgetVarRedcost(scip, vars[e]);
256  }
257  else
258  {
259  assert(!SCIPisDualfeasPositive(scip, SCIPgetVarRedcost(scip, vars[e])));
260  assert(SCIPisFeasEQ(scip, SCIPgetSolVal(scip, NULL, vars[e]), 1.0) || SCIPisDualfeasZero(scip, SCIPgetVarRedcost(scip, vars[e])));
261  cost[e] = 0.0;
262  }
263  }
264  if( e % 2 == 0 )
265  costrev[e + 1] = cost[e];
266  else
267  costrev[e - 1] = cost[e];
268  }
269 
270  for( k = 0; k < nnodes; k++ )
271  graph->mark[k] = (graph->grad[k] > 0);
272 
273  /* distance from root to all nodes */
274  graph_path_execX(scip, graph, graph->source[0], cost, pathdist, pathedge);
275 
276  /* no paths should go back to the root */
277  for( e = graph->outbeg[graph->source[0]]; e != EAT_LAST; e = graph->oeat[e] )
278  costrev[e] = FARAWAY;
279 
280  /* build voronoi diagram */
281  voronoi_terms(scip, graph, costrev, vnoi, vbase, graph->path_heap, graph->path_state);
282 
283  for( k = 0; k < nnodes; k++ )
284  {
286  if( Is_term(graph->term[k]) )
287  continue;
288 
289  if( !Is_term(graph->term[k]) && SCIPisGT(scip, pathdist[k] + vnoi[k].dist, minpathcost) )
290  {
291  for( e = graph->outbeg[k]; e != EAT_LAST; e = graph->oeat[e] )
292  {
293  /* try to fix edge */
294  SCIP_CALL( fixedgevar(scip, vars[e], &nfixed) );
295 
296  /* try to fix reversed edge */
297  SCIP_CALL( fixedgevar(scip, vars[flipedge(e)], &nfixed) );
298  }
299  }
300  else
301  {
302  for( e = graph->outbeg[k]; e != EAT_LAST; e = graph->oeat[e] )
303  {
304  if( SCIPisGT(scip, pathdist[k] + cost[e] + vnoi[graph->head[e]].dist, minpathcost) )
305  {
306  edgevar = vars[e];
307  /* try to fix edge */
308  SCIP_CALL( fixedgevar(scip, edgevar, &nfixed) );
309  }
310  }
311  }
312  }
313  SCIPdebugMessage("fixed by STP propagator: %d \n", nfixed );
314 
315  if( nfixed > 0 )
316  {
317  propdata->nfails = 0;
318  *result = SCIP_REDUCEDDOM;
319  }
320  else
321  {
322  propdata->nfails++;
323  }
324 
325  SCIPfreeBufferArray(scip, &vnoi);
326  SCIPfreeBufferArray(scip, &pathedge);
327  SCIPfreeBufferArray(scip, &vbase);
328  SCIPfreeBufferArray(scip, &pathdist);
329  SCIPfreeBufferArray(scip, &costrev);
330  SCIPfreeBufferArray(scip, &cost);
331  return SCIP_OKAY;
332 }
333 
334 /**@} */
335 
336 /**@name Interface methods
337  *
338  * @{
339  */
340 
341 /** creates the stp propagator and includes it in SCIP */
342 SCIP_RETCODE SCIPincludePropStp(
343  SCIP* scip /**< SCIP data structure */
344  )
345 {
346  SCIP_PROP* prop;
347  SCIP_PROPDATA* propdata;
348 
349  /* create redcost propagator data */
350  SCIP_CALL( SCIPallocMemory(scip, &propdata) );
351 
352  /* include propagator */
353  SCIP_CALL( SCIPincludePropBasic(scip, &prop, PROP_NAME, PROP_DESC, PROP_PRIORITY, PROP_FREQ, PROP_DELAY, PROP_TIMING,
354  propExecStp, propdata) );
355 
356  assert(prop != NULL);
357 
358  /* set optional callbacks via setter functions */
359  SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyStp) );
360  SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeStp) );
361  propdata->nfails = 0;
362  propdata->ncalls = 0;
363  propdata->nlastcall = 0;
364 
365  return SCIP_OKAY;
366 }
367 
368 /**@} */
#define Is_term(a)
Definition: grph.h:158
Definition: grph.h:55
SCIP_RETCODE fixedgevar(SCIP *scip, SCIP_VAR *edgevar, int *nfixed)
Definition: prop_stp.c:76
int * path_heap
Definition: grph.h:114
static SCIP_DECL_PROPCOPY(propCopyStp)
Definition: prop_stp.c:100
SCIP_VAR ** SCIPprobdataGetVars(SCIP *scip)
#define EAT_LAST
Definition: grph.h:31
int * path_state
Definition: grph.h:115
int * oeat
Definition: grph.h:100
GRAPH * SCIPprobdataGetGraph(SCIP_PROBDATA *probdata)
int * head
Definition: grph.h:94
int * mark
Definition: grph.h:71
void graph_path_execX(SCIP *, const GRAPH *, int, SCIP_Real *, SCIP_Real *, int *)
Definition: grphpath.c:639
#define PROP_NAME
Definition: prop_stp.c:37
int stp_type
Definition: grph.h:123
int * outbeg
Definition: grph.h:77
SCIP_Longint nfails
Definition: prop_stp.c:65
int * term
Definition: grph.h:69
int knots
Definition: grph.h:61
#define STP_MAX_NODE_WEIGHT
Definition: grph.h:47
void voronoi_terms(SCIP *, const GRAPH *, SCIP_Real *, PATH *, int *, int *, int *)
Definition: grphpath.c:1679
#define FARAWAY
Definition: grph.h:149
SCIP_RETCODE SCIPincludePropStp(SCIP *scip)
Definition: prop_stp.c:342
propagator for Steiner tree problems, using the LP reduced costs
SCIP_Longint nlastcall
Definition: prop_stp.c:67
#define PROP_DELAY
Definition: prop_stp.c:42
static SCIP_DECL_PROPFREE(propFreeStp)
Definition: prop_stp.c:115
#define PROP_PRIORITY
Definition: prop_stp.c:40
#define PROP_FREQ
Definition: prop_stp.c:41
#define STP_PRIZE_COLLECTING
Definition: grph.h:40
int * grad
Definition: grph.h:74
#define STP_ROOTED_PRIZE_COLLECTING
Definition: grph.h:41
#define DEFAULT_MAXNWAITINGROUNDS
Definition: prop_stp.c:51
int * source
Definition: grph.h:67
#define PROP_DESC
Definition: prop_stp.c:38
int edges
Definition: grph.h:89
#define flipedge(edge)
Definition: grph.h:143
static SCIP_DECL_PROPEXEC(propExecStp)
Definition: prop_stp.c:133
SCIP_Longint ncalls
Definition: prop_stp.c:66
double dist
Definition: grph.h:139
#define PROP_TIMING
Definition: prop_stp.c:39