Scippy

SCIP

Solving Constraint Integer Programs

cons_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 cons_stp.c
17  * @brief Constraint handler for Steiner problems
18  * @author Gerald Gamrath
19  * @author Daniel Rehfeldt
20  * @author Michael Winkler
21  *
22  * This file checks solutions for feasibility and separates violated model constraints. For more details see \ref CONS page.
23  *
24  * @page CONS Separating violated constraints
25  *
26  * In this file a constraint handler checking solutions for feasibility and separating violated model constraints is implemented, as
27  * described in: "Solving the Steiner tree problem in graphs to optimality" by T. Koch and A. Martin.
28  * The separation problem for the cut inequalities described in \ref PROBLEM can be solved by a max-flow algorithm in
29  * polynomial time. Regarding the variable values of a given LP solution as capacities on the edges, one can check for each
30  * \f$ t \in T \setminus \{r\} \f$, with \f$ r \f$ being the root, whether the minimal \f$ (r, t) \f$-cut is less than one. In this case,
31  * a violated cut inequality has been found, otherwise none exists. In order to calculate such a minimal cut Hao
32  * and Orlin's preflow-push algorithm is used. Furthermore, the file implements a dual ascent heuristic, based on a concept described
33  * in "A dual ascent approach for Steiner tree problems on a directed graph." by R. Wong.
34  *
35  */
36 
37 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
38 
39 #include <assert.h>
40 #include <string.h>
41 
42 #include "cons_stp.h"
43 #include "probdata_stp.h"
44 #include "grph.h"
45 #include "portab.h"
46 
47 #include "scip/scip.h"
48 #include "scip/misc.h"
49 #include "scip/cons_linear.h"
50 
51 
52 /**@name Constraint handler properties
53  *
54  * @{
55  */
56 
57 #define CONSHDLR_NAME "stp"
58 #define CONSHDLR_DESC "steiner tree constraint handler"
59 #define CONSHDLR_SEPAPRIORITY 0 /**< priority of the constraint handler for separation */
60 #define CONSHDLR_ENFOPRIORITY 0 /**< priority of the constraint handler for constraint enforcing */
61 #define CONSHDLR_CHECKPRIORITY 9999999 /**< priority of the constraint handler for checking feasibility */
62 #define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
63 #define CONSHDLR_PROPFREQ 0 /**< frequency for propagating domains; zero means only preprocessing propagation */
64 #define CONSHDLR_EAGERFREQ 1 /**< frequency for using all instead of only the useful constraints in separation,
65  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
66 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
67 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
68 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
69 
70 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
71 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
72 #define DEFAULT_MAXSEPACUTS INT_MAX /**< maximal number of cuts separated per separation round */
73 #define DEFAULT_MAXSEPACUTSROOT INT_MAX /**< maximal number of cuts separated per separation round in the root node */
74 
75 
76 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
77 
78 #define DEFAULT_BACKCUT FALSE /**< Try Back-Cuts FALSE*/
79 #define DEFAULT_CREEPFLOW TRUE /**< Use Creep-Flow */
80 #define DEFAULT_DISJUNCTCUT FALSE /**< Only disjunct Cuts FALSE */
81 #define DEFAULT_NESTEDCUT FALSE /**< Try Nested-Cuts FALSE*/
82 #define DEFAULT_FLOWSEP TRUE /**< Try Flow-Cuts */
83 
84 #define DEFAULT_DAMAXDEVIATION 0.25 /**< max deviation for dual ascent */
85 
86 #define FLOW_FACTOR 100000
87 #define CREEP_VALUE 1
88 /**@} */
89 
90 /*
91  * Data structures
92  */
93 
94 /** @brief Constraint data for \ref cons_stp.c "Stp" constraints */
95 struct SCIP_ConsData
96 {
97  GRAPH* graph; /**< graph data structure */
98 };
99 
100 /** @brief Constraint handler data for \ref cons_stp.c "Stp" constraint handler */
101 struct SCIP_ConshdlrData
102 {
103  SCIP_Bool backcut; /**< should backcuts be applied? */
104  SCIP_Bool creepflow; /**< should creepflow cuts be applied? */
105  SCIP_Bool disjunctcut; /**< should disjunktion cuts be applied? */
106  SCIP_Bool nestedcut; /**< should nested cuts be applied? */
107  SCIP_Bool flowsep; /**< should flow separation be applied? */
108  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
109  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
110  int maxsepacuts; /**< maximal number of cuts separated per separation round */
111  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in the root node */
112 };
113 
114 
115 /**@name Local methods
116  *
117  * @{
118  */
119 
120 
121 /** add a cut */
122 static
123 SCIP_RETCODE cut_add(
124  SCIP* scip, /**< SCIP data structure */
125  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
126  const GRAPH* g, /**< graph data structure */
127  const int layer, /**< current layer, set to zero usually */
128  const SCIP_Real* xval, /**< edge values */
129  int* capa, /**< edges capacities (scaled) */
130  const int updatecapa, /**< update capacities? */
131  int* ncuts, /**< pointer to store number of cuts */
132  SCIP_Bool* success /**< pointer to store whether add cut be added */
133  )
134 {
135  SCIP_ROW* row;
136  SCIP_VAR** vars = SCIPprobdataGetVars(scip);
137  SCIP_Real sum = 0.0;
138  SCIP_Bool inccapa = FALSE;
139  int i;
140  int ind;
141  (*success) = FALSE;
142 
143  assert(scip != NULL);
144  assert(g != NULL);
145  assert((layer >= 0) && (layer < g->layers));
146 
147  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, "2cut", 1.0, SCIPinfinity(scip), FALSE, FALSE, TRUE) );
148 
149  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
150 
151  for( i = 0; i < g->edges; i++ )
152  {
153  if( (g->mark[g->source[layer]] == g->mark[g->tail[i]])
154  && (g->mark[g->tail[i]] != g->mark[g->head[i]]) )
155  {
156  ind = layer * g->edges + i;
157 
158  if( updatecapa )
159  {
160  if( capa[i] < FLOW_FACTOR )
161  inccapa = TRUE;
162 
163  SCIPdebugMessage("set capa[%d] from %6d to %6d\n", i, capa[i], FLOW_FACTOR);
164  capa[i] = FLOW_FACTOR;
165 
166  if( !inccapa )
167  {
168  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
169  SCIP_CALL( SCIPreleaseRow(scip, &row) );
170  return SCIP_OKAY;
171  }
172  }
173 
174  if( xval != NULL )
175  {
176  sum += xval[ind];
177 
178  if( SCIPisFeasGE(scip, sum, 1.0) )
179  {
180  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
181  SCIP_CALL( SCIPreleaseRow(scip, &row) );
182  return SCIP_OKAY;
183  }
184  }
185  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[ind], 1.0) );
186  }
187  }
188  assert(sum < 1.0);
189 
190  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
191 
192  /* checks whether cut is sufficiently violated */
193  if( SCIPisCutEfficacious(scip, NULL, row) )
194  {
195  SCIP_Bool infeasible;
196 
197  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
198 
199  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
200  (*ncuts)++;
201  (*success) = TRUE;
202  }
203 
204  SCIP_CALL( SCIPreleaseRow(scip, &row) );
205 
206  return SCIP_OKAY;
207 }
208 
209 static
210 int graph_next_term(
211  int terms,
212  int* term,
213  const int* w
214  )
215 {
216  int wmax = 0;
217  int i;
218  int k = -1;
219  int t;
220 
221  assert(term != NULL);
222 
223  for( i = 0; (i < terms); i++ )
224  {
225  if( w[term[i]] == 0 )
226  {
227  k = i;
228  break;
229  }
230  if( w[term[i]] > wmax )
231  {
232  k = i;
233  wmax = w[term[i]];
234  }
235  }
236 
237  assert(k >= 0);
238  assert(k < terms);
239 
240  t = term[k];
241  term[k] = term[terms - 1];
242 
243  return t;
244 }
245 
246 static
247 void set_capacity(
248  const GRAPH* g, /**< graph data structure */
249  const int layer, /**< current layer, usually set to zero */
250  const SCIP_Bool creep_flow, /**< creep flow? */
251  const int flip, /**< reverse the flow? */
252  int* capa, /**< edges capacities (scaled) */
253  const SCIP_Real* xval /**< edge values */
254  )
255 {
256  int k;
257 
258  assert(g != NULL);
259  assert(xval != NULL);
260 
261  for( k = 0; k < g->edges; k += 2 )
262  {
263  if( !flip )
264  {
265  capa[k] = (int)(xval[layer * g->edges + k ]
266  * FLOW_FACTOR + 0.5);
267  capa[k + 1] = (int)(xval[layer * g->edges + k + 1]
268  * FLOW_FACTOR + 0.5);
269  }
270  else
271  {
272  capa[k] = (int)(xval[layer * g->edges + k + 1]
273  * FLOW_FACTOR + 0.5);
274  capa[k + 1] = (int)(xval[layer * g->edges + k ]
275  * FLOW_FACTOR + 0.5);
276  }
277 
278  if( creep_flow && (capa[k] == 0) && (capa[k + 1] == 0) )
279  {
280  capa[k] = CREEP_VALUE;
281  capa[k + 1] = CREEP_VALUE;
282  }
283  }
284 }
285 
286 /** separate */
287 static
288 SCIP_RETCODE sep_flow(
289  SCIP* scip, /**< SCIP data structure */
290  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
291  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
292  SCIP_CONSDATA* consdata, /**< constraint data */
293  int maxcuts, /**< maximal number of cuts */
294  int* ncuts /**< pointer to store number of cuts */
295  )
296 {
297  GRAPH* g;
298  SCIP_VAR** vars;
299  SCIP_ROW* row = NULL;
300  SCIP_Real* xval;
301  SCIP_Real sum;
302  int i;
303  int k;
304  int j;
305  int ind;
306  int layer;
307  int count = 0;
308  unsigned int flowsep;
309 
310  assert(scip != NULL);
311  assert(conshdlr != NULL);
312  assert(conshdlrdata != NULL);
313 
314  vars = SCIPprobdataGetVars(scip);
315  flowsep = conshdlrdata->flowsep;
316 
317  /* get the graph */
318  g = consdata->graph;
319  assert(g != NULL);
320 
321  xval = SCIPprobdataGetXval(scip, NULL);
322  assert(xval != NULL);
323 
324  for(i = 0; i < g->knots; i++)
325  {
326  for(layer = 0; layer < g->layers; layer++)
327  {
328  /* continue at root */
329  if( i == g->source[layer] )
330  continue;
331 
332  /* at terminal: input sum == 1
333  * basically a cut (starcut))
334  */
335  if( g->term[i] == layer )
336  {
337  sum = 0.0;
338 
339  for( k = g->inpbeg[i]; k != EAT_LAST; k = g->ieat[k] )
340  {
341  ind = layer * g->edges + k;
342  sum += (xval != NULL) ? xval[ind] : 0.0;
343  }
344 
345  if( !SCIPisFeasEQ(scip, sum, 1.0) )
346  {
347  SCIP_Bool infeasible;
348 
349  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, "term", 1.0,
350  1.0, FALSE, FALSE, TRUE) );
351 
352  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
353 
354  for(k = g->inpbeg[i]; k != EAT_LAST; k = g->ieat[k])
355  {
356  ind = layer * g->edges + k;
357 
358  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[ind], 1.0) );
359  }
360 
361  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
362 
363  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
364  count++;
365 
366  SCIP_CALL( SCIPreleaseRow(scip, &row) );
367 
368  if( *ncuts + count >= maxcuts )
369  goto TERMINATE;
370  }
371  }
372 
373  /* flow cuts disabled? */
374  if( !flowsep )
375  continue;
376 
377  /* the value of each outgoing edge needs to be smaller than the sum of the ingoing edges */
378  for( j = g->outbeg[i]; j != EAT_LAST; j = g->oeat[j] )
379  {
380  ind = layer * g->edges + j;
381  sum = (xval != NULL) ? -xval[ind] : -1.0;
382 
383  for( k = g->inpbeg[i]; k != EAT_LAST; k = g->ieat[k] )
384  {
385  ind = layer * g->edges + k;
386  sum += (xval != NULL) ? xval[ind] : 0.0;
387  }
388  if( SCIPisFeasNegative(scip, sum) )
389  {
390  SCIP_Bool infeasible;
391 
392  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, "flow", 0.0, SCIPinfinity(scip),
393  FALSE, FALSE, TRUE) );
394 
395  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
396 
397  ind = layer * g->edges + j;
398 
399  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[ind], -1.0) );
400 
401  for( k = g->inpbeg[i]; k != EAT_LAST; k = g->ieat[k] )
402  {
403  ind = layer * g->edges + k;
404 
405  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[ind], 1.0) );
406  }
407 
408  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
409 
410  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
411  count++;
412 
413  SCIP_CALL( SCIPreleaseRow(scip, &row) );
414 
415  if( *ncuts + count >= maxcuts )
416  goto TERMINATE;
417  }
418  }
419 
420  /* consider only non terminals */
421  if( g->term[i] == layer )
422  continue;
423 
424  /* input of a vertex has to be <= 1.0 */
425  sum = 0.0;
426 
427  for( k = g->inpbeg[i]; k != EAT_LAST; k = g->ieat[k] )
428  {
429  ind = layer * g->edges + k;
430  sum += (xval != NULL) ? xval[ind] : 1.0;
431  }
432  if( SCIPisFeasGT(scip, sum, 1.0) )
433  {
434  SCIP_Bool infeasible;
435 
436  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, "infl", -SCIPinfinity(scip),
437  1.0, FALSE, FALSE, TRUE) );
438 
439  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
440 
441  for( k = g->inpbeg[i]; k != EAT_LAST; k = g->ieat[k] )
442  {
443  ind = layer * g->edges + k;
444 
445  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[ind], 1.0) );
446  }
447 
448  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
449 
450  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
451  count++;
452 
453  SCIP_CALL( SCIPreleaseRow(scip, &row) );
454 
455  if( *ncuts + count >= maxcuts )
456  goto TERMINATE;
457  }
458 #if 1
459  /* incoming flow <= outgoing flow */
460  sum = 0.0;
461 
462  for( k = g->inpbeg[i]; k != EAT_LAST; k = g->ieat[k] )
463  {
464  ind = layer * g->edges + k;
465  sum -= (xval != NULL) ? xval[ind] : 1.0;
466  }
467  for( k = g->outbeg[i]; k != EAT_LAST; k = g->oeat[k] )
468  {
469  ind = layer * g->edges + k;
470  sum += (xval != NULL) ? xval[ind] : 0.0;
471  }
472  if( SCIPisFeasNegative(scip, sum) )
473  {
474  SCIP_Bool infeasible;
475 
476  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, "bala", 0.0,
477  (g->locals[layer] == 2) ? 0.0 : SCIPinfinity(scip), FALSE, FALSE, TRUE) );
478 
479  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
480 
481  for( k = g->inpbeg[i]; k != EAT_LAST; k = g->ieat[k] )
482  {
483  ind = layer * g->edges + k;
484 
485  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[ind], -1.0) );
486  }
487  for( k = g->outbeg[i]; k != EAT_LAST; k = g->oeat[k] )
488  {
489  ind = layer * g->edges + k;
490 
491  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[ind], 1.0) );
492  }
493 
494  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
495 
496  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
497  count++;
498 
499  SCIP_CALL( SCIPreleaseRow(scip, &row) );
500 
501  if( *ncuts + count >= maxcuts )
502  goto TERMINATE;
503  }
504 #endif
505  }
506  }
507 
508  TERMINATE:
509  SCIPdebugMessage("In/Out Separator: %d Inequalities added\n", count);
510 
511  *ncuts += count;
512 
513  return SCIP_OKAY;
514 }
515 
516 /** separate 2-cuts */
517 static
518 SCIP_RETCODE sep_2cut(
519  SCIP* scip, /**< SCIP data structure */
520  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
521  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
522  SCIP_CONSDATA* consdata, /**< constraint data */
523  int maxcuts, /**< maximal number of cuts */
524  int* ncuts /**< pointer to store number of cuts */
525  )
526 {
527  const SCIP_Bool nested_cut = conshdlrdata->nestedcut;
528  const SCIP_Bool back_cut = conshdlrdata->backcut;
529  const SCIP_Bool creep_flow = conshdlrdata->creepflow;
530  SCIP_Bool disjunct_cut;
531  const SCIP_Bool flowsep = conshdlrdata->flowsep;
532 
533  GRAPH* g;
534  SCIP_Real* xval;
535  SCIP_Real* cost;
536  PATH* path;
537  int* w;
538  int* capa;
539  int* term;
540  int terms = 0;
541  int tsave;
542  int i;
543  int k;
544  int layer;
545  int count = 0;
546  int rerun = FALSE;
547  int nedges;
548  int nnodes;
549  SCIP_Bool addedcut;
550 
551  assert(scip != NULL);
552  assert(conshdlr != NULL);
553  assert(conshdlrdata != NULL);
554 
555  g = consdata->graph;
556  assert(g != NULL);
557 
558  if( g->stp_type != STP_MAX_NODE_WEIGHT )
559  disjunct_cut = conshdlrdata->disjunctcut;
560  else
561  disjunct_cut = TRUE;
562 
563  nedges = g->edges;
564  nnodes = g->knots;
565  addedcut = FALSE;
566 
567  xval = SCIPprobdataGetXval(scip, NULL);
568  assert(xval != NULL);
569 
570  SCIP_CALL( SCIPallocBufferArray(scip, &capa, nedges) );
571  SCIP_CALL( SCIPallocBufferArray(scip, &cost, nedges) );
572  SCIP_CALL( SCIPallocBufferArray(scip, &w, nnodes) );
573  SCIP_CALL( SCIPallocBufferArray(scip, &term, g->terms) );
574  SCIP_CALL( SCIPallocBufferArray(scip, &path, nnodes) );
575 
576  for( layer = 0; layer < g->layers; layer++ )
577  {
578  /* For 2-terminal nets no cuts are necessary if flows are given */
579  if( flowsep && (g->locals[layer] == 2) )
580  continue;
581 
582  for( i = 0; i < nedges; i++ )
583  cost[i] = SCIPisFeasLT(scip, xval[layer * nedges + i], 1.0) ? 1.0 : 0.0;
584 
585  for( i = 0; i < nnodes; i++ )
586  {
587  w[i] = 0;
588  g->mark[i] = TRUE;
589  }
590 
591  graph_path_exec(scip, g, FSP_MODE, g->source[layer], cost, path);
592 
593  /* search all terminals not connected to the root by the LP solution */
594  for( i = 0, count = 0; i < nnodes; i++ )
595  {
596  if( (g->term[i] == layer) && (i != g->source[layer]) )
597  {
598  if( SCIPisPositive(scip, path[i].dist) )
599  term[terms++] = i;
600  else
601  count++;
602  }
603  }
604  SCIPdebugMessage("Cut Pretest: %d eliminations\n", count);
605 
606  count = 0;
607  tsave = terms;
608 
609  /* from source to terminal */
610  if( !nested_cut || disjunct_cut )
611  set_capacity(g, layer, creep_flow, 0, capa, xval);
612 
613  while( terms > 0 )
614  {
615  if( SCIPisStopped(scip) && terms % 100 == 0 )
616  break;
617 
618  /* look for reachable terminal */
619  i = graph_next_term(terms, term, w);
620 
621  terms--;
622 
623  assert(g->term[i] == layer);
624  assert(g->source[layer] != i);
625 
626  if( nested_cut && !disjunct_cut )
627  set_capacity(g, layer, creep_flow, 0, capa, xval);
628 
629  do
630  {
631  graph_mincut_exec(g, g->source[layer], i, capa, w, rerun);
632 
633  rerun = TRUE;
634 
635  /* cut */
636  for( k = 0; k < nnodes; k++ )
637  g->mark[k] = (w[k] != 0);
638 
639  SCIP_CALL( cut_add(scip, conshdlr, g, layer, xval, capa, nested_cut || disjunct_cut, ncuts, &addedcut) );
640  if( addedcut )
641  {
642  count++;
643 
644  if( *ncuts >= maxcuts )
645  goto TERMINATE;
646  }
647  else
648  break;
649  }
650  while( nested_cut ); /* Nested Cut is CONSTANT ! */
651  }
652 
653  /* back cuts enabled? */
654  if( back_cut )
655  {
656  if( !nested_cut || disjunct_cut )
657  set_capacity(g, layer, creep_flow, 1, capa, xval);
658 
659  terms = tsave;
660 
661  while( terms > 0 )
662  {
663  /* look for reachable terminal */
664  i = graph_next_term(terms, term, w);
665 
666  terms--;
667 
668  assert(g->term[i] == layer);
669  assert(g->source[layer] != i);
670 
671  if( nested_cut && !disjunct_cut )
672  set_capacity(g, layer, creep_flow, 1, capa, xval);
673 
674  rerun = FALSE;
675 
676  do
677  {
678  graph_mincut_exec(g, i, g->source[layer], capa, w, rerun);
679 
680  rerun = TRUE;
681 
682  for( k = 0; k < nnodes; k++ )
683  g->mark[k] = (w[k] != 0) ? 1 : 0;
684 
685  SCIP_CALL( cut_add(scip, conshdlr, g, layer, xval, capa, nested_cut || disjunct_cut, ncuts, &addedcut) );
686  if( addedcut )
687  {
688  count++;
689 
690  if( *ncuts >= maxcuts )
691  goto TERMINATE;
692  }
693  else
694  break;
695 #if 0
696  if (nested_cut || disjunct_cut)
697  for(k = p->beg[p->rcnt - 1]; k < p->nzcnt; k++)
698  capa[p->ind[k] % nedges
699  + (((p->ind[k] % nedges) % 2)
700  ? -1 : 1)] = FLOW_FACTOR;
701 #endif
702  }
703  while( nested_cut ); /* Nested Cut is CONSTANT ! */
704 
705  rerun = FALSE;
706  }
707  }
708  }
709 
710  TERMINATE:
711  SCIPfreeBufferArray(scip, &path);
712  SCIPfreeBufferArray(scip, &term);
713  SCIPfreeBufferArray(scip, &w);
714  SCIPfreeBufferArray(scip, &cost);
715  SCIPfreeBufferArray(scip, &capa);
716 
717  SCIPdebugMessage("2-cut Separator: %d Inequalities added\n", count);
718 
719  return SCIP_OKAY;
720 }
721 
722 
723 
724 /**@} */
725 
726 
727 /**@name Callback methods
728  *
729  * @{
730  */
731 
732 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
733 static
734 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyStp)
735 { /*lint --e{715}*/
736  assert(scip != NULL);
737  assert(conshdlr != NULL);
738  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
739 
740  /* call inclusion method of constraint handler */
741  SCIP_CALL( SCIPincludeConshdlrStp(scip) );
742 
743  *valid = TRUE;
744 
745  return SCIP_OKAY;
746 }
747 
748 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
749 static
750 SCIP_DECL_CONSFREE(consFreeStp)
751 { /*lint --e{715}*/
752  SCIP_CONSHDLRDATA* conshdlrdata;
753 
754  assert(scip != NULL);
755  assert(conshdlr != NULL);
756  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
757 
758  /* free constraint handler data */
759  conshdlrdata = SCIPconshdlrGetData(conshdlr);
760  assert(conshdlrdata != NULL);
761 
762  SCIPfreeMemory(scip, &conshdlrdata);
763 
764  SCIPconshdlrSetData(conshdlr, NULL);
765 
766  return SCIP_OKAY;
767 }
768 
769 /** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
770 static
771 SCIP_DECL_CONSINITSOL(consInitsolStp)
772 { /*lint --e{715}*/
773 #if 0
774  SCIP_PROBDATA* probdata;
775  GRAPH* graph;
776  printf("init \n\n");
777  probdata = SCIPgetProbData(scip);
778  assert(probdata != NULL);
779 
780  graph = SCIPprobdataGetGraph(probdata);
781  assert(graph != NULL);
782 
783  SCIP_CALL( SCIPdualAscentStp(scip, graph, 10) );
784 #endif
785  return SCIP_OKAY;
786 }
787 
788 /** frees specific constraint data */
789 static
790 SCIP_DECL_CONSDELETE(consDeleteStp)
791 { /*lint --e{715}*/
792  assert(conshdlr != NULL);
793  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
794  assert(consdata != NULL);
795  assert(*consdata != NULL);
796 
797  SCIPfreeBlockMemory(scip, consdata);
798 
799  return SCIP_OKAY;
800 }
801 
802 /** transforms constraint data into data belonging to the transformed problem */
803 static
804 SCIP_DECL_CONSTRANS(consTransStp)
805 { /*lint --e{715}*/
806  SCIP_CONSDATA* sourcedata;
807  SCIP_CONSDATA* targetdata;
808 
809  assert(conshdlr != NULL);
810  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
811  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
812  assert(sourcecons != NULL);
813  assert(targetcons != NULL);
814 
815  sourcedata = SCIPconsGetData(sourcecons);
816  assert(sourcedata != NULL);
817 
818  /* create constraint data for target constraint */
819  SCIP_CALL( SCIPallocBlockMemory(scip, &targetdata) );
820 
821  targetdata->graph = sourcedata->graph;
822 
823  /* create target constraint */
824  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
825  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
826  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
827  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
828  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
829 
830  return SCIP_OKAY;
831 }
832 
833 #if 1
834 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
835 static
836 SCIP_DECL_CONSINITLP(consInitlpStp)
837 { /*lint --e{715}*/
838 #if 0
839  SCIP_PROBDATA* probdata;
840  GRAPH* graph;
841 
842  SCIP_Real lpobjval;
843 
844  printf("init \n\n");
845  probdata = SCIPgetProbData(scip);
846  assert(probdata != NULL);
847 
848  graph = SCIPprobdataGetGraph(probdata);
849  assert(graph != NULL);
850 
851  SCIP_CALL( SCIPdualAscentPcStp(scip, graph, NULL, &lpobjval, TRUE, 1) );
852 #endif
853 
854  return SCIP_OKAY;
855 }
856 #endif
857 /** separation method of constraint handler for LP solutions */
858 static
859 SCIP_DECL_CONSSEPALP(consSepalpStp)
860 { /*lint --e{715}*/
861  SCIP_CONSHDLRDATA* conshdlrdata;
862  int maxcuts;
863  int ncuts = 0;
864  int i;
865 
866  *result = SCIP_DIDNOTRUN;
867 
868  conshdlrdata = SCIPconshdlrGetData(conshdlr);
869  assert(conshdlrdata != NULL);
870 
871  maxcuts = SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) == 0 ?
872  conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts;
873 
874  for( i = 0; i < nconss; ++i )
875  {
876  SCIP_CONSDATA* consdata;
877 
878  consdata = SCIPconsGetData(conss[i]);
879 
880  SCIP_CALL( sep_flow(scip, conshdlr, conshdlrdata, consdata, maxcuts, &ncuts) );
881 
882  SCIP_CALL( sep_2cut(scip, conshdlr, conshdlrdata, consdata, maxcuts, &ncuts) );
883  }
884 
885  if( ncuts > 0 )
886  *result = SCIP_SEPARATED;
887 
888  return SCIP_OKAY;
889 }
890 
891 
892 /** constraint enforcing method of constraint handler for LP solutions */
893 static
894 SCIP_DECL_CONSENFOLP(consEnfolpStp)
895 { /*lint --e{715}*/
896  SCIP_Bool feasible;
897  SCIP_CONSDATA* consdata;
898  int i;
899 
900  for( i = 0; i < nconss; i++ )
901  {
902  consdata = SCIPconsGetData(conss[i]);
903 
904  SCIP_CALL( SCIPvalidateStpSol(scip, consdata->graph, SCIPprobdataGetXval(scip, NULL), &feasible) );
905 
906  if( !feasible )
907  {
908  *result = SCIP_INFEASIBLE;
909  return SCIP_OKAY;
910  }
911  }
912  *result = SCIP_FEASIBLE;
913 
914  return SCIP_OKAY;
915 }
916 
917 /** constraint enforcing method of constraint handler for pseudo solutions */
918 static
919 SCIP_DECL_CONSENFOPS(consEnfopsStp)
920 { /*lint --e{715}*/
921  SCIP_Bool feasible;
922  SCIP_CONSDATA* consdata;
923  int i;
924 
925  for( i = 0; i < nconss; i++ )
926  {
927  consdata = SCIPconsGetData(conss[i]);
928 
929  SCIP_CALL( SCIPvalidateStpSol(scip, consdata->graph, SCIPprobdataGetXval(scip, NULL), &feasible) );
930 
931  if( !feasible )
932  {
933  *result = SCIP_INFEASIBLE;
934  return SCIP_OKAY;
935  }
936  }
937  *result = SCIP_FEASIBLE;
938 
939  return SCIP_OKAY;
940 }
941 
942 /** feasibility check method of constraint handler for integral solutions */
943 static
944 SCIP_DECL_CONSCHECK(consCheckStp)
945 { /*lint --e{715}*/
946  SCIP_Bool feasible;
947  SCIP_CONSDATA* consdata;
948  int i;
949 
950  for( i = 0; i < nconss; i++ )
951  {
952  consdata = SCIPconsGetData(conss[i]);
953 
954  SCIP_CALL( SCIPvalidateStpSol(scip, consdata->graph, SCIPprobdataGetXval(scip, sol), &feasible) );
955 
956  if( !feasible )
957  {
958  *result = SCIP_INFEASIBLE;
959  return SCIP_OKAY;
960  }
961  }
962  *result = SCIP_FEASIBLE;
963 
964  return SCIP_OKAY;
965 }
966 
967 /** domain propagation method of constraint handler */
968 static
969 SCIP_DECL_CONSPROP(consPropStp)
970 { /*lint --e{715}*/
971  SCIP_PROBDATA* probdata;
972  GRAPH* graph;
973 
974  probdata = SCIPgetProbData(scip);
975  assert(probdata != NULL);
976 
977  graph = SCIPprobdataGetGraph(probdata);
978  assert(graph != NULL);
979 
980  /* for degree constrained model, check whether problem is infeasible */
981  if( graph->stp_type == STP_DEG_CONS )
982  {
983  int k;
984  int nnodes;
985  int degsum;
986  int* maxdegs;
987 
988  nnodes = graph->knots;
989  maxdegs = graph->maxdeg;
990 
991  assert(maxdegs != NULL);
992 
993  degsum = 0;
994  for( k = 0; k < nnodes; k++ )
995  {
996  if( Is_term(graph->term[k]) )
997  {
998  assert(maxdegs[k] > 0);
999  degsum += maxdegs[k] - 1;
1000  }
1001  else
1002  {
1003  assert(maxdegs[k] >= 0);
1004  degsum += MAX(maxdegs[k] - 2, 0);
1005  }
1006  }
1007 
1008  if( degsum < graph->terms - 2 )
1009  *result = SCIP_CUTOFF;
1010  else
1011  *result = SCIP_DIDNOTFIND;
1012  }
1013  return SCIP_OKAY;
1014 }
1015 
1016 /** variable rounding lock method of constraint handler */
1017 static
1018 SCIP_DECL_CONSLOCK(consLockStp)
1019 { /*lint --e{715}*/
1020  SCIP_VAR** vars;
1021  int nvars;
1022  int v;
1023 
1024  assert(scip != NULL);
1025  assert(cons != NULL);
1026 
1027  vars = SCIPprobdataGetVars(scip);
1028  nvars = SCIPprobdataGetNVars(scip);
1029 
1030  for( v = 0; v < nvars; ++v )
1031  SCIP_CALL( SCIPaddVarLocks(scip, vars[v], 1, 1) );
1032 
1033  return SCIP_OKAY;
1034 }
1035 
1036 /** constraint copying method of constraint handler */
1037 static
1038 SCIP_DECL_CONSCOPY(consCopyStp)
1039 { /*lint --e{715}*/
1040  const char* consname;
1041  SCIP_PROBDATA* probdata;
1042  GRAPH* graph;
1043 
1044  probdata = SCIPgetProbData(scip);
1045  assert(probdata != NULL);
1046 
1047  graph = SCIPprobdataGetGraph(probdata);
1048  assert(graph != NULL);
1049 
1050  consname = SCIPconsGetName(sourcecons);
1051 
1052  /* creates and captures a and constraint */
1053  SCIP_CALL( SCIPcreateConsStp(scip, cons, consname, graph) );
1054 
1055  *valid = TRUE;
1056 
1057  return SCIP_OKAY;
1058 }
1059 
1060 
1061 /**@} */
1062 
1063 /**@name Interface methods
1064  *
1065  * @{
1066  */
1067 
1068 /** creates the handler for stp constraints and includes it in SCIP */
1069 SCIP_RETCODE SCIPincludeConshdlrStp(
1070  SCIP* scip /**< SCIP data structure */
1071  )
1072 {
1073  SCIP_CONSHDLRDATA* conshdlrdata;
1074  SCIP_CONSHDLR* conshdlr;
1075 
1076  /* create stp constraint handler data */
1077  SCIP_CALL( SCIPallocMemory(scip, &conshdlrdata) );
1078 
1079  conshdlr = NULL;
1080  /* include constraint handler */
1081  SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC,
1083  consEnfolpStp, consEnfopsStp, consCheckStp, consLockStp,
1084  conshdlrdata) );
1085  assert(conshdlr != NULL);
1086 
1087  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyStp, consCopyStp) );
1088  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteStp) );
1089  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransStp) );
1090  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolStp) );
1091  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpStp) );
1092  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropStp, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
1094  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpStp, NULL, CONSHDLR_SEPAFREQ,
1096  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeStp) );
1097 
1098  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/stp/backcut", "Try Back-Cuts",
1099  &conshdlrdata->backcut, TRUE, DEFAULT_BACKCUT, NULL, NULL) );
1100  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/stp/creepflow", "Use Creep-Flow",
1101  &conshdlrdata->creepflow, TRUE, DEFAULT_CREEPFLOW, NULL, NULL) );
1102  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/stp/disjunctcut", "Only disjunct Cuts",
1103  &conshdlrdata->disjunctcut, TRUE, DEFAULT_DISJUNCTCUT, NULL, NULL) );
1104  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/stp/nestedcut", "Try Nested-Cuts",
1105  &conshdlrdata->nestedcut, TRUE, DEFAULT_NESTEDCUT, NULL, NULL) );
1106  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/stp/flowsep", "Try Flow-Cuts",
1107  &conshdlrdata->flowsep, TRUE, DEFAULT_FLOWSEP, NULL, NULL) );
1108  SCIP_CALL( SCIPaddIntParam(scip,
1109  "constraints/"CONSHDLR_NAME"/maxrounds",
1110  "maximal number of separation rounds per node (-1: unlimited)",
1111  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
1112  SCIP_CALL( SCIPaddIntParam(scip,
1113  "constraints/"CONSHDLR_NAME"/maxroundsroot",
1114  "maximal number of separation rounds per node in the root node (-1: unlimited)",
1115  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
1116  SCIP_CALL( SCIPaddIntParam(scip,
1117  "constraints/"CONSHDLR_NAME"/maxsepacuts",
1118  "maximal number of cuts separated per separation round",
1119  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
1120  SCIP_CALL( SCIPaddIntParam(scip,
1121  "constraints/"CONSHDLR_NAME"/maxsepacutsroot",
1122  "maximal number of cuts separated per separation round in the root node",
1123  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
1124 
1125 
1126  return SCIP_OKAY;
1127 }
1128 
1129 /** creates and captures a stp constraint */
1130 SCIP_RETCODE SCIPcreateConsStp(
1131  SCIP* scip, /**< SCIP data structure */
1132  SCIP_CONS** cons, /**< pointer to hold the created constraint */
1133  const char* name, /**< name of constraint */
1134  GRAPH* graph /**< graph data structure */
1135  )
1136 {
1137  SCIP_CONSHDLR* conshdlr;
1138  SCIP_CONSDATA* consdata;
1139 
1140  /* find the stp constraint handler */
1141  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
1142  if( conshdlr == NULL )
1143  {
1144  SCIPerrorMessage("stp constraint handler not found\n");
1145  return SCIP_PLUGINNOTFOUND;
1146  }
1147 
1148  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
1149 
1150  consdata->graph = graph;
1151 
1152  /* create constraint */
1153  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, FALSE, TRUE, TRUE, TRUE, TRUE,
1154  FALSE, FALSE, FALSE, FALSE, FALSE) );
1155 
1156  return SCIP_OKAY;
1157 }
1158 
1159 /** dual ascent heuristic for the STP */
1160 SCIP_RETCODE SCIPdualAscentStp(
1161  SCIP* scip, /**< SCIP data structure */
1162  GRAPH* g, /**< graph data structure */
1163  SCIP_Real* redcost, /**< array to store reduced costs or NULL */
1164  SCIP_Real* objval, /**< pointer to store objective value */
1165  SCIP_Bool addcuts, /**< should dual ascent add Steiner cuts? */
1166  GNODE** gnodearrterms, /**< gnode terminals array for internal computations or NULL */
1167  int* edgearrint, /**< int edges array for internal computations or NULL */
1168  int* nodearrint, /**< int vertices array for internal computations or NULL */
1169  int root, /**< the root */
1170  int nruns, /**< number of dual ascent runs */
1171  char* edgearrchar, /**< char edges array for internal computations or NULL */
1172  char* nodearrchar /**< char vertices array for internal computations or NULL */
1173  )
1174 {
1175 #if 0
1176  SCIP_CONSHDLR* conshdlr;
1177 #endif
1178  SCIP_QUEUE* queue;
1179  SCIP_PQUEUE* pqueue;
1180  SCIP_VAR** vars;
1181  SCIP_Real min;
1182  SCIP_Real prio1;
1183  SCIP_Real score;
1184  SCIP_Real dualobj;
1185  SCIP_Real currscore;
1186  SCIP_Real maxdeviation;
1187  SCIP_Real* rescap;
1188 #if 0
1189  SCIP_Bool infeasible;
1190 #endif
1191  GNODE* gnodeact;
1192  GNODE** gnodearr;
1193  int i;
1194  int k;
1195  int v;
1196  int a;
1197  int s;
1198  int tail;
1199  int shift;
1200  int nnodes;
1201  int nterms;
1202  int nedges;
1203  int ncutverts;
1204  int nunsatarcs;
1205  int norgcutverts;
1206  int* pnode;
1207  int* cutverts;
1208  int* unsatarcs;
1209  char firstrun;
1210  char* sat;
1211  char* active;
1212 
1213  assert(g != NULL);
1214  assert(scip != NULL);
1215  assert(nruns >= 0);
1216  assert(objval != NULL);
1217  assert(Is_term(g->term[root]));
1218 
1219  if( g->knots == 1 )
1220  return SCIP_OKAY;
1221 
1222  if( addcuts )
1223  {
1224  vars = SCIPprobdataGetVars(scip);
1225  assert(vars != NULL);
1226  }
1227  else
1228  {
1229  vars = NULL;
1230  }
1231 
1232  score = 0.0;
1233  nnodes = g->knots;
1234  nedges = g->edges;
1235  nterms = g->terms;
1236  dualobj = 0.0;
1237 #if 0
1238  conshdlr = SCIPfindConshdlr(scip, "stp");
1239 #endif
1240  ncutverts = 0;
1241  nunsatarcs = 0;
1242  norgcutverts = 0;
1243  maxdeviation = DEFAULT_DAMAXDEVIATION;
1244 
1245  /* if specified root is not a terminal, take default root */
1246  if( !Is_term(g->term[root]) )
1247  root = g->source[0];
1248 
1249  /* allocate memory if not available */
1250 
1251  if( redcost == NULL )
1252  {
1253  SCIP_CALL( SCIPallocBufferArray(scip, &rescap, nedges) );
1254  }
1255  else
1256  {
1257  rescap = redcost;
1258  }
1259 
1260  if( edgearrchar == NULL )
1261  {
1262  SCIP_CALL( SCIPallocBufferArray(scip, &sat, nedges) );
1263  }
1264  else
1265  {
1266  sat = edgearrchar;
1267  }
1268 
1269  if( nodearrchar == NULL )
1270  {
1271  SCIP_CALL( SCIPallocBufferArray(scip, &active, nnodes) );
1272  }
1273  else
1274  {
1275  active = nodearrchar;
1276  }
1277 
1278  if( nodearrint == NULL )
1279  {
1280  SCIP_CALL( SCIPallocBufferArray(scip, &cutverts, nnodes) );
1281  }
1282  else
1283  {
1284  cutverts = nodearrint;
1285  }
1286 
1287  if( edgearrint == NULL )
1288  {
1289  SCIP_CALL( SCIPallocBufferArray(scip, &unsatarcs, nedges) );
1290  }
1291  else
1292  {
1293  unsatarcs = edgearrint;
1294  }
1295 
1296 
1297  if( gnodearrterms == NULL )
1298  {
1299  SCIP_CALL( SCIPallocBufferArray(scip, &gnodearr, nterms - 1) );
1300  for( i = 0; i < nterms - 1; i++ )
1301  {
1302  SCIP_CALL( SCIPallocBuffer(scip, &gnodearr[i]) ); /*lint !e866*/
1303  }
1304  }
1305  else
1306  {
1307  gnodearr = gnodearrterms;
1308  }
1309 
1310  SCIP_CALL( SCIPqueueCreate(&queue, nnodes - nterms + 1, 2.0) );
1311  SCIP_CALL( SCIPpqueueCreate(&pqueue, nterms, 2.0, GNODECmpByDist) );
1312 
1313  k = 0;
1314 
1315  /* mark terminals as active, add all except root to pqueue */
1316  for( i = 0; i < nnodes; i++ )
1317  {
1318  if( Is_term(g->term[i]) )
1319  {
1320  active[i] = TRUE;
1321  assert(g->grad[i] > 0);
1322  if( i != root )
1323  {
1324  gnodearr[k]->number = i;
1325  gnodearr[k]->dist = g->grad[i];
1326  if( g->grad[i] == 2 )
1327  {
1328  for( a = g->inpbeg[i]; a != EAT_LAST; a = g->ieat[a] )
1329  if( SCIPisEQ(scip, g->cost[a], 0.0) )
1330  break;
1331 
1332  if( a != EAT_LAST )
1333  gnodearr[k]->dist += g->grad[g->tail[a]] - 1;
1334 #if 0
1335  printf("%d grad: %d grad2 %d, score %f\n", i, g->grad[i], g->grad[g->tail[a]], gnodearr[k]->dist);
1336 #endif
1337  assert(gnodearr[k]->dist > 0);
1338  }
1339 
1340  SCIP_CALL( SCIPpqueueInsert(pqueue, gnodearr[k++]) );
1341  }
1342  }
1343  else
1344  {
1345  active[i] = FALSE;
1346  }
1347  g->mark[i] = FALSE;
1348  }
1349 
1350  /* set residual capacities and mark whether an arc is satisfied (has capacity 0) */
1351  for( i = 0; i < nedges; i++ )
1352  {
1353  rescap[i] = g->cost[i];
1354 
1355  if( SCIPisZero(scip, rescap[i]) )
1356  sat[i] = TRUE;
1357  else
1358  sat[i] = FALSE;
1359  }
1360 
1361  /* (main) dual ascent loop */
1362  while( SCIPpqueueNElems(pqueue) > 0 && !SCIPisStopped(scip) )
1363  {
1364  /* get active vertex of minimum score */
1365  gnodeact = (GNODE*) SCIPpqueueRemove(pqueue);
1366 
1367  v = gnodeact->number;
1368  prio1 = gnodeact->dist;
1369  currscore = prio1;
1370  firstrun = TRUE;
1371 
1372  /* perform augmentation as long as priority of root component does not exceed max deviation */
1373  while( !SCIPisStopped(scip) )
1374  {
1375  assert(SCIPqueueIsEmpty(queue));
1376  /* 1. step: BFS from v (or connected component) on saturated, incoming arcs */
1377 
1378  if( firstrun )
1379  {
1380  score = g->grad[v];
1381  ncutverts = 0;
1382  firstrun = FALSE;
1383  nunsatarcs = 0;
1384  g->mark[v] = TRUE;
1385  cutverts[ncutverts++] = v;
1386  SCIP_CALL( SCIPqueueInsert(queue, &(g->tail[g->outbeg[v]])) );
1387  }
1388  /* not in first processing of root component: */
1389  else
1390  {
1391  for( i = norgcutverts; i < ncutverts; i++ )
1392  {
1393  s = cutverts[i];
1394  assert(g->mark[s]);
1395  if( active[s] )
1396  {
1397  active[v] = FALSE;
1398  SCIPqueueClear(queue);
1399  goto ENDOFLOOP;
1400  }
1401 
1402  SCIP_CALL( SCIPqueueInsert(queue, &(g->tail[g->outbeg[s]])) );
1403  }
1404  }
1405 
1406  while( !SCIPqueueIsEmpty(queue) )
1407  {
1408  pnode = (SCIPqueueRemove(queue));
1409 
1410  /* traverse incoming arcs */
1411  for( a = g->inpbeg[*pnode]; a != EAT_LAST; a = g->ieat[a] )
1412  {
1413  tail = g->tail[a];
1414  if( sat[a] )
1415  {
1416  if( !g->mark[tail] )
1417  {
1418  /* if an active vertex has been hit, break */
1419  if( active[tail] )
1420  {
1421  active[v] = FALSE;
1422  SCIPqueueClear(queue);
1423  goto ENDOFLOOP;
1424  }
1425  score += g->grad[tail];
1426  g->mark[tail] = TRUE;
1427  cutverts[ncutverts++] = tail;
1428  SCIP_CALL( SCIPqueueInsert(queue, &(g->tail[a])) );
1429  }
1430  }
1431  else if( !g->mark[tail] )
1432  {
1433  unsatarcs[nunsatarcs++] = a;
1434  }
1435  }
1436  }
1437 
1438  /* 2. step: get minimum residual capacity among cut-arcs */
1439 
1440  /* adjust array of unsatisfied arcs */
1441  min = FARAWAY;
1442  shift = 0;
1443 
1444  for( i = 0; i < nunsatarcs; i++ )
1445  {
1446  a = unsatarcs[i];
1447  if( g->mark[g->tail[a]] )
1448  {
1449  shift++;
1450  }
1451  else
1452  {
1453 
1454  assert(!sat[a]);
1455  if( SCIPisLT(scip, rescap[a], min) )
1456  min = rescap[a];
1457  if( shift != 0 )
1458  unsatarcs[i - shift] = a;
1459  }
1460  }
1461 
1462  assert(SCIPisLT(scip, min, FARAWAY));
1463  nunsatarcs -= shift;
1464 #if 0
1465  printf("\n aft: ");
1466  for( i = 0; i < nunsatarcs; i++ )
1467  printf("[%d]: %d ", i, unsatarcs[i]);
1468  printf("\n");
1469 #endif
1470  if( nunsatarcs > 0)
1471  assert(!g->mark[g->tail[unsatarcs[nunsatarcs-1]]]);
1472 
1473 
1474 
1475  currscore = score - (ncutverts - 1);
1476  assert(SCIPisGE(scip, currscore, prio1));
1477  norgcutverts = ncutverts;
1478 
1479  /* augmentation criteria met? */
1480  if( SCIPisLT(scip, (currscore - prio1) / prio1, maxdeviation) )
1481  {
1482 #if 0
1483  SCIP_ROW* row;
1484 #endif
1485  SCIP_CONS* cons = NULL;
1486 
1487  /* 3. step: perform augmentation */
1488 #if 0
1489  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, "dualascentcut", 1.0, SCIPinfinity(scip), FALSE, FALSE, TRUE) );
1490  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
1491 #endif
1492 
1493  /* create constraints? */
1494  if( addcuts )
1495  {
1496  SCIP_CALL( SCIPcreateConsLinear ( scip, &cons, "da", 0, NULL, NULL,
1497  1.0, SCIPinfinity(scip), TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1498 
1499  SCIP_CALL( SCIPaddCons(scip, cons) );
1500  }
1501 
1502  dualobj += min;
1503  for( i = 0; i < nunsatarcs; i++ )
1504  {
1505  a = unsatarcs[i];
1506 #if 0
1507  if( a == -1 )
1508  continue;
1509 #endif
1510 #if 0
1511  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[a], 1.0) );
1512 #endif
1513  if( addcuts )
1514  {
1515  assert(cons != NULL);
1516  assert(vars != NULL);
1517  SCIP_CALL( SCIPaddCoefLinear(scip, cons, vars[a], 1.0) );
1518  }
1519  rescap[a] -= min;
1520 
1521  assert(SCIPisGE(scip, rescap[a], 0.0));
1522 
1523  if( SCIPisEQ(scip, rescap[a], 0.0) )
1524  {
1525  sat[a] = TRUE;
1526  if( !(g->mark[g->tail[a]]) )
1527  {
1528  tail = g->tail[a];
1529  score += g->grad[tail];
1530  g->mark[tail] = TRUE;
1531  cutverts[ncutverts++] = tail;
1532  }
1533  }
1534  }
1535 #if 0
1536  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
1537  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
1538  SCIP_CALL( SCIPreleaseRow(scip, &row) );
1539 #endif
1540  if( addcuts )
1541  {
1542  assert(cons != NULL);
1543  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1544  }
1545 
1546  currscore = score - (ncutverts - 1);
1547  continue;
1548  }
1549  else
1550  {
1551  /* reinsert active vertex */
1552  gnodeact->dist = currscore;
1553  SCIP_CALL( SCIPpqueueInsert(pqueue, gnodeact) );
1554  }
1555 
1556  ENDOFLOOP:
1557 
1558  for( i = 0; i < ncutverts; i++ )
1559  g->mark[cutverts[i]] = FALSE;
1560 
1561  break;
1562  } /* augmentation loop */
1563 
1564  } /* dual ascent loop */
1565 
1566  SCIPdebugMessage("DA: dualglobal: %f \n", dualobj);
1567  *objval = dualobj;
1568 
1569  /* free memory */
1570 
1571  SCIPpqueueFree(&pqueue);
1572  SCIPqueueFree(&queue);
1573 
1574  if( gnodearrterms == NULL )
1575  {
1576  for( i = nterms - 2; i >= 0; i-- )
1577  SCIPfreeBuffer(scip, &gnodearr[i]);
1578  SCIPfreeBufferArray(scip, &gnodearr);
1579  }
1580 
1581  if( edgearrint == NULL )
1582  SCIPfreeBufferArray(scip, &unsatarcs);
1583 
1584  if( nodearrint == NULL )
1585  SCIPfreeBufferArray(scip, &cutverts);
1586 
1587  if( nodearrchar == NULL )
1588  SCIPfreeBufferArray(scip, &active);
1589 
1590  if( edgearrchar == NULL )
1591  SCIPfreeBufferArray(scip, &sat);
1592 
1593  if( redcost == NULL )
1594  SCIPfreeBufferArray(scip, &rescap);
1595 
1596  return SCIP_OKAY;
1597 }
1598 
1599 
1600 /** dual ascent heuristic */
1601 SCIP_RETCODE SCIPdualAscentPcStp(
1602  SCIP* scip, /**< SCIP data structure */
1603  GRAPH* g, /**< graph data structure */
1604  SCIP_Real* redcost, /**< array to store reduced costs or NULL */
1605  SCIP_Real* objval, /**< pointer to store objective value */
1606  SCIP_Bool addcuts, /**< should dual ascent add Steiner cuts? */
1607  int nruns /**< number of dual ascent runs */
1608  )
1609 {
1610 #if 0
1611  SCIP_CONSHDLR* conshdlr;
1612 #endif
1613  SCIP_QUEUE* queue;
1614  SCIP_PQUEUE* pqueue;
1615  SCIP_VAR** vars;
1616  GRAPH* transgraph;
1617  SCIP_Real min;
1618  SCIP_Real prio1;
1619  SCIP_Real score;
1620  SCIP_Real offset;
1621  SCIP_Real dualobj;
1622  SCIP_Real currscore;
1623  SCIP_Real maxdeviation;
1624  SCIP_Real* rescap;
1625  GNODE* gnodeact;
1626  GNODE** gnodearr;
1627  int s;
1628  int i;
1629  int k;
1630  int v;
1631  int a;
1632  int tail;
1633  int shift;
1634  int root;
1635  int nnodes;
1636  int nterms;
1637  int nedges;
1638  int ncutverts;
1639  int pseudoroot;
1640  int nunsatarcs;
1641  int norgcutverts;
1642  int* pnode;
1643  int* cutverts;
1644  char* origedge;
1645  int* unsatarcs;
1646  char firstrun;
1647  char* sat;
1648  char* active;
1649 
1650  assert(g != NULL);
1651  assert(scip != NULL);
1652  assert(nruns >= 0);
1653  assert(objval != NULL);
1654 
1655  if( g->knots == 1 )
1656  return SCIP_OKAY;
1657 
1658  if( addcuts )
1659  {
1660  vars = SCIPprobdataGetVars(scip);
1661  assert(vars != NULL);
1662  }
1663  else
1664  {
1665  vars = NULL;
1666  }
1667 
1668  root = g->source[0];
1669  score = 0.0;
1670  offset = 0.0;
1671  dualobj = 0.0;
1672 #if 0
1673  conshdlr = SCIPfindConshdlr(scip, "stp");
1674 #endif
1675  ncutverts = 0;
1676  nunsatarcs = 0;
1677  norgcutverts = 0;
1678  maxdeviation = DEFAULT_DAMAXDEVIATION;
1679 
1680  SCIP_CALL( graph_PcSapCopy(scip, g, &transgraph, &offset) );
1681 
1682  nnodes = transgraph->knots;
1683  nedges = transgraph->edges;
1684  nterms = transgraph->terms;
1685  pseudoroot = nnodes - 1;
1686 
1687  if( redcost == NULL )
1688  {
1689  SCIP_CALL( SCIPallocBufferArray(scip, &rescap, nedges) );
1690  }
1691  else
1692  {
1693  rescap = redcost;
1694  }
1695 
1696  SCIP_CALL( SCIPallocBufferArray(scip, &sat, nedges) );
1697  SCIP_CALL( SCIPallocBufferArray(scip, &active, nnodes) );
1698  SCIP_CALL( SCIPallocBufferArray(scip, &cutverts, nnodes) );
1699  SCIP_CALL( SCIPallocBufferArray(scip, &gnodearr, nterms - 1) );
1700  SCIP_CALL( SCIPallocBufferArray(scip, &unsatarcs, nedges) );
1701  SCIP_CALL( SCIPallocBufferArray(scip, &origedge, nedges) );
1702 
1703  /* @todo add FARAWAY arcs? */
1704  for( i = 0; i < nedges; i++ )
1705  if( !Is_term(transgraph->term[transgraph->tail[i]]) && transgraph->head[i] == pseudoroot )
1706  origedge[i] = FALSE;
1707  else if( transgraph->tail[i] == pseudoroot && !Is_term(transgraph->term[transgraph->head[i]]) )
1708  origedge[i] = FALSE;
1709  else
1710  origedge[i] = TRUE;
1711 
1712  for( i = 0; i < nterms - 1; i++ )
1713  {
1714  SCIP_CALL( SCIPallocBuffer(scip, &gnodearr[i]) ); /*lint !e866*/
1715  }
1716 
1717  SCIP_CALL( SCIPqueueCreate(&queue, nnodes, 2.0) );
1718  SCIP_CALL( SCIPpqueueCreate( &pqueue, nnodes, 2.0, GNODECmpByDist) );
1719 
1720  k = 0;
1721  /* mark terminals as active, add all except root to pqueue */
1722  for( i = 0; i < nnodes; i++ )
1723  {
1724  if( Is_term(transgraph->term[i]) )
1725  {
1726  active[i] = TRUE;
1727  assert(transgraph->grad[i] > 0);
1728  if( i != root )
1729  {
1730  gnodearr[k]->number = i;
1731  gnodearr[k]->dist = transgraph->grad[i];
1732 
1733  for( a = transgraph->inpbeg[i]; a != EAT_LAST; a = transgraph->ieat[a] )
1734  if( SCIPisEQ(scip, transgraph->cost[a], 0.0) )
1735  break;
1736 
1737  if( a != EAT_LAST )
1738  gnodearr[k]->dist += transgraph->grad[transgraph->tail[a]] - 1;
1739 
1740  assert(gnodearr[k]->dist > 0);
1741 
1742  SCIP_CALL( SCIPpqueueInsert(pqueue, gnodearr[k++]) );
1743  }
1744  }
1745  else
1746  {
1747  active[i] = FALSE;
1748  }
1749  transgraph->mark[i] = FALSE;
1750  }
1751 
1752  for( i = 0; i < nedges; i++ )
1753  {
1754  rescap[i] = transgraph->cost[i];
1755  if( SCIPisZero(scip, rescap[i]) )
1756  sat[i] = TRUE;
1757  else
1758  sat[i] = FALSE;
1759  }
1760 
1761  /* dual ascent loop */
1762  while( SCIPpqueueNElems(pqueue) > 0 && !SCIPisStopped(scip) )
1763  {
1764  /* get active vertex of minimum score */
1765  gnodeact = (GNODE*) SCIPpqueueRemove(pqueue);
1766 
1767  v = gnodeact->number;
1768  prio1 = gnodeact->dist;
1769 
1770  firstrun = TRUE;
1771  nunsatarcs = 0;
1772 
1773  /* perform augmentation as long as ... */
1774  while( !SCIPisStopped(scip) )
1775  {
1776  assert(SCIPqueueIsEmpty(queue));
1777  /* 1. step: BFS from v (or connected component) on saturated, incoming arcs */
1778 
1779  if( firstrun )
1780  {
1781  score = transgraph->grad[v];
1782  ncutverts = 0;
1783  firstrun = FALSE;
1784  nunsatarcs = 0;
1785  transgraph->mark[v] = TRUE;
1786  cutverts[ncutverts++] = v;
1787  SCIP_CALL( SCIPqueueInsert(queue, &(transgraph->tail[transgraph->outbeg[v]])) );
1788  }
1789  /* not in first processing of root component: */
1790  else
1791  {
1792  for( i = norgcutverts; i < ncutverts; i++ )
1793  {
1794  s = cutverts[i];
1795  assert(transgraph->mark[s]);
1796  if( active[s] )
1797  {
1798  active[v] = FALSE;
1799  SCIPqueueClear(queue);
1800  goto ENDOFLOOP;
1801  }
1802 
1803  SCIP_CALL( SCIPqueueInsert(queue, &(transgraph->tail[transgraph->outbeg[s]])) );
1804  }
1805  }
1806 
1807  while( !SCIPqueueIsEmpty(queue) )
1808  {
1809  pnode = (SCIPqueueRemove(queue));
1810 
1811  /* traverse incoming arcs */
1812  for( a = transgraph->inpbeg[*pnode]; a != EAT_LAST; a = transgraph->ieat[a] )
1813  {
1814  tail = transgraph->tail[a];
1815  if( sat[a] )
1816  {
1817  if( !transgraph->mark[tail] )
1818  {
1819  /* if an active vertex has been hit, break */
1820  if( active[tail] )
1821  {
1822  active[v] = FALSE;
1823  SCIPqueueClear(queue);
1824  goto ENDOFLOOP;
1825  }
1826 
1827  score += transgraph->grad[tail];
1828  transgraph->mark[tail] = TRUE;
1829  cutverts[ncutverts++] = tail;
1830  SCIP_CALL( SCIPqueueInsert(queue, &(transgraph->tail[a])) );
1831  }
1832  }
1833  else if( !transgraph->mark[tail] )
1834  {
1835  unsatarcs[nunsatarcs++] = a;
1836  }
1837  }
1838  }
1839 
1840  /* 2. pass: get minimum residual capacity among cut-arcs */
1841 
1842  /* adjust array of unsatisfied arcs */
1843  min = FARAWAY;
1844  shift = 0;
1845 
1846  for( i = 0; i < nunsatarcs; i++ )
1847  {
1848  a = unsatarcs[i];
1849  if( transgraph->mark[transgraph->tail[a]] )
1850  {
1851  shift++;
1852  }
1853  else
1854  {
1855 
1856  assert(!sat[a]);
1857  if( SCIPisLT(scip, rescap[a], min) )
1858  min = rescap[a];
1859  if( shift != 0 )
1860  unsatarcs[i - shift] = a;
1861  }
1862  }
1863 
1864  assert(SCIPisLT(scip, min, FARAWAY));
1865  nunsatarcs -= shift;
1866 
1867  if( nunsatarcs > 0)
1868  assert(!transgraph->mark[transgraph->tail[unsatarcs[nunsatarcs-1]]]);
1869 
1870  currscore = score - (ncutverts - 1);
1871  norgcutverts = ncutverts;
1872 
1873  assert(SCIPisGE(scip, currscore, prio1));
1874 
1875 
1876  /* augmentation criteria met? */
1877  if( SCIPisLE(scip, (currscore - prio1) / prio1, maxdeviation) )
1878  {
1879  int in = FALSE;
1880 #if 0
1881  SCIP_ROW* row;
1882 #endif
1883  SCIP_CONS* cons = NULL;
1884 
1885  /* 3. pass: perform augmentation */
1886 
1887 
1888  /* create constraint */
1889 
1890  if( addcuts )
1891  {
1892 #if 1
1893  SCIP_CALL( SCIPcreateConsLinear ( scip, &cons, "da", 0, NULL, NULL,
1894  1.0, SCIPinfinity(scip), TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1895 
1896  SCIP_CALL( SCIPaddCons(scip, cons) );
1897 #else
1898  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, "dualascentcut", 1.0, SCIPinfinity(scip), FALSE, FALSE, TRUE) );
1899  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
1900  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
1901  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
1902 #endif
1903 
1904  }
1905 
1906  dualobj += min;
1907  for( i = 0; i < nunsatarcs; i++ )
1908  {
1909  a = unsatarcs[i];
1910  if( a == -1 )
1911  continue;
1912 
1913  if( addcuts && origedge[a] )
1914  {
1915  assert(vars != NULL);
1916  assert(cons != NULL);
1917 
1918  if( g->tail[a] == root && g->head[a ] == v )
1919  in = TRUE;
1920 #if 1
1921  SCIP_CALL( SCIPaddCoefLinear(scip, cons, vars[a], 1.0) );
1922 #else
1923  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[a], 1.0) );
1924 #endif
1925  }
1926  rescap[a] -= min;
1927 
1928  assert(SCIPisGE(scip, rescap[a], 0.0));
1929 
1930  if( SCIPisEQ(scip, rescap[a], 0.0) )
1931  {
1932  sat[a] = TRUE;
1933  if( !(transgraph->mark[transgraph->tail[a]]) )
1934  {
1935  tail = transgraph->tail[a];
1936  score += transgraph->grad[tail];
1937  transgraph->mark[tail] = TRUE;
1938  cutverts[ncutverts++] = tail;
1939  }
1940  }
1941  }
1942 
1943  if( addcuts )
1944  {
1945  if( !in )
1946  {
1947  assert(vars != NULL);
1948  for( i = g->outbeg[root]; i != EAT_LAST; i = g->oeat[i] )
1949  {
1950  if( g->head[i] == v )
1951  {
1952  SCIP_CALL( SCIPaddCoefLinear(scip, cons, vars[i], 1.0) );
1953  }
1954  }
1955  }
1956 #if 1
1957  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1958 #else
1959  SCIP_CALL( SCIPreleaseRow(scip, &row) );
1960 #endif
1961 
1962  }
1963  currscore = score - (ncutverts - 1);
1964  continue;
1965  }
1966  else
1967  {
1968  /* reinsert active vertex */
1969  gnodeact->dist = currscore;
1970  SCIP_CALL( SCIPpqueueInsert(pqueue, gnodeact) );
1971  }
1972 
1973  ENDOFLOOP:
1974 
1975  for( i = 0; i < ncutverts; i++ )
1976  transgraph->mark[cutverts[i]] = FALSE;
1977 
1978  break;
1979  } /* augmentation loop */
1980 
1981  } /* dual ascent loop */
1982 
1983 
1984  *objval = dualobj + offset;
1985  SCIPdebugMessage("DA: dualglobal: %f \n", *objval + SCIPprobdataGetOffset(scip));
1986 
1987  /* free memory */
1988  SCIPpqueueFree(&pqueue);
1989  SCIPqueueFree(&queue);
1990 
1991  for( i = nterms - 2; i >= 0; i-- )
1992  SCIPfreeBuffer(scip, &gnodearr[i]);
1993 
1994  SCIPfreeBufferArray(scip, &origedge);
1995  SCIPfreeBufferArray(scip, &unsatarcs);
1996  SCIPfreeBufferArray(scip, &cutverts);
1997  SCIPfreeBufferArray(scip, &gnodearr);
1998  SCIPfreeBufferArray(scip, &active);
1999  SCIPfreeBufferArray(scip, &sat);
2000 
2001  if( redcost == NULL )
2002  SCIPfreeBufferArray(scip, &rescap);
2003 
2004  graph_free(scip, transgraph, TRUE);
2005 
2006  return SCIP_OKAY;
2007 
2008 }
2009 
2010 /** dual ascent heuristic */
2011 SCIP_RETCODE SCIPdualAscentAddCutsStp(
2012  SCIP* scip, /**< SCIP data structure */
2013  GRAPH* g, /**< graph data structure */
2014  int nruns /**< number of dual ascent runs */
2015  )
2016 {
2017  GNODE** gnodearr;
2018  SCIP_Real max;
2019  SCIP_Real objval;
2020  SCIP_Real* redcost;
2021  int i;
2022  int r;
2023  int k;
2024  int nterms;
2025  int nedges;
2026  int nnodes;
2027  int maxroot;
2028  int* root;
2029  int* degs;
2030  int* nodearrint;
2031  int* edgearrint;
2032  char* edgearrchar;
2033  char* nodearrchar;
2034 
2035  assert(scip != NULL);
2036  assert(g != NULL);
2037  assert(nruns > 0);
2038 
2039  k = 0;
2040  max = -1.0;
2041  nnodes = g->knots;
2042  nedges = g->edges;
2043  nterms = g->terms;
2044  maxroot = -1;
2045 
2046  if( nterms <= 1 )
2047  return SCIP_OKAY;
2048 
2049  SCIP_CALL( SCIPallocBufferArray(scip, &gnodearr, nterms - 1) );
2050  for( i = 0; i < nterms - 1; i++ )
2051  {
2052  SCIP_CALL( SCIPallocBuffer(scip, &gnodearr[i]) ); /*lint !e866*/
2053  }
2054 
2055  SCIP_CALL( SCIPallocBufferArray(scip, &root, nterms) );
2056  SCIP_CALL( SCIPallocBufferArray(scip, &degs, nterms) );
2057  SCIP_CALL( SCIPallocBufferArray(scip, &redcost, nedges) );
2058  SCIP_CALL( SCIPallocBufferArray(scip, &edgearrint, nedges) );
2059  SCIP_CALL( SCIPallocBufferArray(scip, &nodearrint, nnodes) );
2060  SCIP_CALL( SCIPallocBufferArray(scip, &edgearrchar, nedges) );
2061  SCIP_CALL( SCIPallocBufferArray(scip, &nodearrchar, nnodes) );
2062 
2063  for( i = 0; i < nnodes; i++ )
2064  {
2065  if( Is_term(g->term[i]) && (g->grad[i] > 0) )
2066  {
2067  degs[k] = g->grad[i];
2068  root[k++] = i;
2069  }
2070  }
2071  nruns = MIN(nruns, k);
2072  SCIPsortIntInt(degs, root, nterms);
2073 
2074  for( i = 0; i < nruns; i++ )
2075  {
2076  r = root[k - i - 1];
2077 
2078  SCIP_CALL( SCIPdualAscentStp(scip, g, redcost, &objval, FALSE, gnodearr, edgearrint, nodearrint, r, 1, edgearrchar, nodearrchar) );
2079 
2080  if( SCIPisGT(scip, objval, max ) )
2081  {
2082  max = objval;
2083  maxroot = r;
2084  }
2085  }
2086 
2087  g->source[0] = maxroot;
2088  SCIP_CALL( SCIPdualAscentStp(scip, g, redcost, &objval, TRUE, gnodearr, edgearrint, nodearrint, maxroot, 1, edgearrchar, nodearrchar) );
2089 
2090  SCIPfreeBufferArray(scip, &nodearrchar);
2091  SCIPfreeBufferArray(scip, &edgearrchar);
2092  SCIPfreeBufferArray(scip, &nodearrint);
2093  SCIPfreeBufferArray(scip, &edgearrint);
2094  SCIPfreeBufferArray(scip, &redcost);
2095  SCIPfreeBufferArray(scip, &degs);
2096  SCIPfreeBufferArray(scip, &root);
2097 
2098  for( i = nterms - 2; i >= 0; i-- )
2099  SCIPfreeBuffer(scip, &gnodearr[i]);
2100  SCIPfreeBufferArray(scip, &gnodearr);
2101  return SCIP_OKAY;
2102 }
2103 
2104 /**@} */
#define Is_term(a)
Definition: grph.h:158
#define CONSHDLR_PROPFREQ
Definition: cons_stp.c:63
#define DEFAULT_CREEPFLOW
Definition: cons_stp.c:80
static SCIP_DECL_CONSINITSOL(consInitsolStp)
Definition: cons_stp.c:772
#define DEFAULT_NESTEDCUT
Definition: cons_stp.c:82
SCIP_RETCODE SCIPdualAscentStp(SCIP *scip, GRAPH *g, SCIP_Real *redcost, SCIP_Real *objval, SCIP_Bool addcuts, GNODE **gnodearrterms, int *edgearrint, int *nodearrint, int root, int nruns, char *edgearrchar, char *nodearrchar)
Definition: cons_stp.c:1161
Definition: grph.h:55
static void set_capacity(const GRAPH *g, const int layer, const SCIP_Bool creep_flow, const int flip, int *capa, const SCIP_Real *xval)
Definition: cons_stp.c:248
#define TRUE
Definition: portab.h:34
static SCIP_DECL_CONSENFOLP(consEnfolpStp)
Definition: cons_stp.c:895
static SCIP_DECL_CONSSEPALP(consSepalpStp)
Definition: cons_stp.c:860
Constraint handler for Steiner problems.
#define DEFAULT_BACKCUT
Definition: cons_stp.c:79
SCIP_RETCODE SCIPdualAscentAddCutsStp(SCIP *scip, GRAPH *g, int nruns)
Definition: cons_stp.c:2012
int terms
Definition: grph.h:63
SCIP_RETCODE SCIPvalidateStpSol(SCIP *, const GRAPH *, const double *, SCIP_Bool *)
Definition: validate.c:206
SCIP_VAR ** SCIPprobdataGetVars(SCIP *scip)
SCIP_RETCODE graph_PcSapCopy(SCIP *, GRAPH *, GRAPH **, SCIP_Real *)
Definition: grphbase.c:792
#define EAT_LAST
Definition: grph.h:31
static SCIP_RETCODE sep_flow(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONSDATA *consdata, int maxcuts, int *ncuts)
Definition: cons_stp.c:289
#define FLOW_FACTOR
Definition: cons_stp.c:87
Problem data for stp problem.
int SCIPprobdataGetNVars(SCIP *scip)
int * oeat
Definition: grph.h:100
void graph_free(SCIP *, GRAPH *, SCIP_Bool)
Definition: grphbase.c:1137
#define DEFAULT_MAXROUNDS
Definition: cons_stp.c:71
int number
Definition: misc_stp.h:37
static SCIP_DECL_CONSFREE(consFreeStp)
Definition: cons_stp.c:751
#define DEFAULT_DISJUNCTCUT
Definition: cons_stp.c:81
static SCIP_RETCODE sep_2cut(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONSDATA *consdata, int maxcuts, int *ncuts)
Definition: cons_stp.c:519
#define CONSHDLR_CHECKPRIORITY
Definition: cons_stp.c:61
static SCIP_DECL_CONSLOCK(consLockStp)
Definition: cons_stp.c:1019
GRAPH * SCIPprobdataGetGraph(SCIP_PROBDATA *probdata)
int * head
Definition: grph.h:94
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyStp)
Definition: cons_stp.c:735
#define FALSE
Definition: portab.h:37
int * mark
Definition: grph.h:71
static int graph_next_term(int terms, int *term, const int *w)
Definition: cons_stp.c:211
#define CONSHDLR_DESC
Definition: cons_stp.c:58
int stp_type
Definition: grph.h:123
int * outbeg
Definition: grph.h:77
SCIP_Real SCIPprobdataGetOffset(SCIP *scip)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_stp.c:59
int * locals
Definition: grph.h:65
SCIP_Real dist
Definition: misc_stp.h:38
SCIP_RETCODE SCIPincludeConshdlrStp(SCIP *scip)
Definition: cons_stp.c:1070
#define DEFAULT_MAXROUNDSROOT
Definition: cons_stp.c:72
int * maxdeg
Definition: grph.h:79
int * tail
Definition: grph.h:93
#define FSP_MODE
Definition: grph.h:153
int * term
Definition: grph.h:69
int knots
Definition: grph.h:61
#define STP_MAX_NODE_WEIGHT
Definition: grph.h:47
#define CONSHDLR_DELAYPROP
Definition: cons_stp.c:68
#define STP_DEG_CONS
Definition: grph.h:43
int * inpbeg
Definition: grph.h:75
#define FARAWAY
Definition: grph.h:149
#define CONSHDLR_NAME
Definition: cons_stp.c:57
int GNODECmpByDist(void *first_arg, void *second_arg)
static SCIP_DECL_CONSENFOPS(consEnfopsStp)
Definition: cons_stp.c:920
#define DEFAULT_MAXSEPACUTS
Definition: cons_stp.c:73
static SCIP_DECL_CONSCOPY(consCopyStp)
Definition: cons_stp.c:1039
static SCIP_DECL_CONSTRANS(consTransStp)
Definition: cons_stp.c:805
#define DEFAULT_DAMAXDEVIATION
Definition: cons_stp.c:85
static SCIP_DECL_CONSDELETE(consDeleteStp)
Definition: cons_stp.c:791
Constraint data for Stp constraints.
Definition: cons_stp.c:96
#define CONSHDLR_EAGERFREQ
Definition: cons_stp.c:64
#define CREEP_VALUE
Definition: cons_stp.c:88
SCIP_RETCODE SCIPdualAscentPcStp(SCIP *scip, GRAPH *g, SCIP_Real *redcost, SCIP_Real *objval, SCIP_Bool addcuts, int nruns)
Definition: cons_stp.c:1602
#define DEFAULT_FLOWSEP
Definition: cons_stp.c:83
SCIP_RETCODE SCIPcreateConsStp(SCIP *scip, SCIP_CONS **cons, const char *name, GRAPH *graph)
Definition: cons_stp.c:1131
includes various files containing graph methods used for Steiner problems
Portable defintions.
int layers
Definition: grph.h:64
GRAPH * graph
Definition: cons_stp.c:98
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_stp.c:74
int * grad
Definition: grph.h:74
static SCIP_DECL_CONSINITLP(consInitlpStp)
Definition: cons_stp.c:837
#define CONSHDLR_DELAYSEPA
Definition: cons_stp.c:67
SCIP_Real * cost
Definition: grph.h:91
#define CONSHDLR_SEPAFREQ
Definition: cons_stp.c:62
Constraint handler data for Stp constraint handler.
Definition: cons_stp.c:102
int * source
Definition: grph.h:67
#define CONSHDLR_PROP_TIMING
Definition: cons_stp.c:77
SCIP_Real * SCIPprobdataGetXval(SCIP *scip, SCIP_SOL *sol)
#define CONSHDLR_ENFOPRIORITY
Definition: cons_stp.c:60
int edges
Definition: grph.h:89
int * ieat
Definition: grph.h:99
#define CONSHDLR_NEEDSCONS
Definition: cons_stp.c:69
static SCIP_DECL_CONSCHECK(consCheckStp)
Definition: cons_stp.c:945
static SCIP_DECL_CONSPROP(consPropStp)
Definition: cons_stp.c:970
void graph_path_exec(SCIP *, const GRAPH *, int, int, SCIP_Real *, PATH *)
Definition: grphpath.c:453
static SCIP_RETCODE cut_add(SCIP *scip, SCIP_CONSHDLR *conshdlr, const GRAPH *g, const int layer, const SCIP_Real *xval, int *capa, const int updatecapa, int *ncuts, SCIP_Bool *success)
Definition: cons_stp.c:124
void graph_mincut_exec(GRAPH *, int, int, const int *, int *, int)
Definition: grphmcut.c:568