Scippy

GCG

Branch-and-Price & Column Generation for Everyone

sepa_basis.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file sepa_basis.c
29  * @brief basis separator
30  * @author Jonas Witt
31  */
32 
33 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34 
35 /*#define SCIP_DEBUG*/
36 
37 #include <assert.h>
38 #include <stdio.h>
39 #include <string.h>
40 
41 #include "scip/scip.h"
42 #include "scip/scipdefplugins.h"
43 #include "sepa_basis.h"
44 #include "sepa_master.h"
45 #include "gcg.h"
46 #include "relax_gcg.h"
47 #include "pricer_gcg.h"
48 #include "pub_gcgvar.h"
49 
50 
51 #ifdef WITH_GSL
52 #include <gsl/gsl_matrix.h>
53 #include <gsl/gsl_permutation.h>
54 #include <gsl/gsl_linalg.h>
55 #endif
56 
57 #define SEPA_NAME "basis"
58 #define SEPA_DESC "separator calculates a basis of the orig problem to generate cuts, which cut off the master lp sol"
59 #define SEPA_PRIORITY 100
60 #define SEPA_FREQ 0
61 #define SEPA_MAXBOUNDDIST 1.0
62 #define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
63 #define SEPA_DELAY TRUE /**< should separation method be delayed, if other separators found cuts? */
64 
65 #define STARTMAXCUTS 50 /**< maximal cuts used at the beginning */
66 
67 
68 /*
69  * Data structures
70  */
71 
72 /** separator data */
74 {
75  SCIP_ROW** mastercuts; /**< cuts in the master problem */
76  SCIP_ROW** origcuts; /**< cuts in the original problem */
77  int norigcuts; /**< number of cuts in the original problem */
78  int nmastercuts; /**< number of cuts in the master problem */
79  int maxcuts; /**< maximal number of allowed cuts */
80  SCIP_ROW** newcuts; /**< new cuts to tighten original problem */
81  int nnewcuts; /**< number of new cuts */
82  int maxnewcuts; /**< maximal number of allowed new cuts */
83  int round; /**< number of separation round in probing LP of current node */
84  int currentnodenr; /**< number of current node */
85  SCIP_ROW* objrow; /**< row with obj coefficients */
86  SCIP_Bool enable; /**< parameter returns if basis separator is enabled */
87  SCIP_Bool enableobj; /**< parameter returns if objective constraint is enabled */
88  SCIP_Bool enableobjround; /**< parameter returns if rhs/lhs of objective constraint is rounded, when obj is int */
89  SCIP_Bool enableppcuts; /**< parameter returns if cuts generated during pricing are added to newconss array */
90  SCIP_Bool enableppobjconss; /**< parameter returns if objective constraint for each redcost of pp is enabled */
91  SCIP_Bool enableppobjcg; /**< parameter returns if objective constraint for each redcost of pp is enabled during pricing */
92  int separationsetting; /**< parameter returns which parameter setting is used for separation */
93  SCIP_Bool chgobj; /**< parameter returns if basis is searched with different objective */
94  SCIP_Bool chgobjallways; /**< parameter returns if obj is not only changed in first iteration */
95  SCIP_Bool genobjconvex; /**< parameter returns if objconvex is generated dynamically */
96  SCIP_Bool enableposslack; /**< parameter returns if positive slack should influence the probing objective function */
97  SCIP_Bool forcecuts; /**< parameter returns if cuts are forced to enter the LP */
98  int posslackexp; /**< parameter returns exponent of usage of positive slack */
99  SCIP_Bool posslackexpgen; /**< parameter returns if exponent should be automatically generated */
100  SCIP_Real posslackexpgenfactor; /**< parameter returns factor for automatically generated exponent */
101  int maxrounds; /**< parameter returns maximum number of separation rounds in probing LP (-1 if unlimited) */
102  int maxroundsroot; /**< parameter returns maximum number of separation rounds in probing LP in root node (-1 if unlimited) */
103  int mincuts; /**< parameter returns number of minimum cuts needed to return *result = SCIP_Separated */
104  SCIP_Real objconvex; /**< parameter return convex combination factor */
105 };
106 
107 /*
108  * Local methods
109  */
110 
111 /** allocates enough memory to hold more cuts */
112 static
113 SCIP_RETCODE ensureSizeCuts(
114  SCIP* scip, /**< SCIP data structure */
115  SCIP_SEPADATA* sepadata, /**< separator data data structure */
116  int size /**< new size of cut arrays */
117  )
118 {
119  assert(scip != NULL);
120  assert(sepadata != NULL);
121  assert(sepadata->mastercuts != NULL);
122  assert(sepadata->origcuts != NULL);
123  assert(sepadata->norigcuts <= sepadata->maxcuts);
124  assert(sepadata->norigcuts >= 0);
125  assert(sepadata->nmastercuts <= sepadata->maxcuts);
126  assert(sepadata->nmastercuts >= 0);
127 
128  if( sepadata->maxcuts < size )
129  {
130  int newmaxcuts = SCIPcalcMemGrowSize(scip, size);
131  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(sepadata->mastercuts), sepadata->maxcuts, newmaxcuts) );
132  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(sepadata->origcuts), sepadata->maxcuts, newmaxcuts) );
133  sepadata->maxcuts = newmaxcuts;
134  }
135  assert(sepadata->maxcuts >= size);
136 
137  return SCIP_OKAY;
138 }
139 
140 /** allocates enough memory to hold more new cuts */
141 static
142 SCIP_RETCODE ensureSizeNewCuts(
143  SCIP* scip, /**< SCIP data structure */
144  SCIP_SEPADATA* sepadata, /**< separator data data structure */
145  int size /**< new size of cut arrays */
146  )
147 {
148  assert(scip != NULL);
149  assert(sepadata != NULL);
150  assert(sepadata->newcuts != NULL);
151  assert(sepadata->nnewcuts <= sepadata->maxnewcuts);
152  assert(sepadata->nnewcuts >= 0);
153 
154  if( sepadata->maxnewcuts < size )
155  {
156  int newmaxnewcuts = SCIPcalcMemGrowSize(scip, size);
157  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(sepadata->newcuts), sepadata->maxnewcuts, newmaxnewcuts) );
158  sepadata->maxnewcuts = newmaxnewcuts;
159  }
160  assert(sepadata->maxnewcuts >= size);
161 
162  return SCIP_OKAY;
163 }
164 
165 /** returns the result of the exponentiation for given exponent and basis (basis^exponent) */
166 static
167 SCIP_Real exponentiate(
168  SCIP_Real basis, /**< basis for exponentiation */
169  int exponent /**< exponent for exponentiation */
170  )
171 {
172  SCIP_Real result;
173  int i;
174 
175  assert(exponent >= 0);
176 
177  result = 1.0;
178  for( i = 0; i < exponent; ++i )
179  {
180  result *= basis;
181  }
182 
183  return result;
184 }
185 
186 /**< Initialize probing objective coefficient for each variable with original objective. */
187 static
188 SCIP_RETCODE initProbingObjWithOrigObj(
189  SCIP* origscip, /**< orig scip problem */
190  SCIP_Bool enableobj, /**< returns if objective row was added to the lp */
191  SCIP_Real objfactor /**< factor, the objective is multiplied with */
192 )
193 {
194  SCIP_VAR** origvars;
195  int norigvars;
196  SCIP_VAR* origvar;
197 
198  SCIP_Real newobj;
199  int i;
200 
201  assert(SCIPinProbing(origscip));
202 
203  origvars = SCIPgetVars(origscip);
204  norigvars = SCIPgetNVars(origscip);
205 
206  /* loop over original variables */
207  for( i = 0; i < norigvars; ++i )
208  {
209  /* get variable information */
210  origvar = origvars[i];
211  newobj = 0.0;
212 
213  /* if objective row is enabled consider also the original objective value */
214  if( enableobj )
215  newobj = objfactor * SCIPvarGetObj(origvar);
216 
217  SCIP_CALL( SCIPchgVarObjProbing(origscip, origvar, newobj) );
218  }
219  return SCIP_OKAY;
220 }
221 
222 /**< Change probing objective coefficient for each variable by adding original objective
223  * to the probing objective.
224  */
225 static
226 SCIP_RETCODE chgProbingObjAddingOrigObj(
227  SCIP* origscip, /**< orig scip problem */
228  SCIP_Real objfactor, /**< factor the additional part of the objective is multiplied with */
229  SCIP_Real objdivisor /**< factor the additional part of the objective is divided with */
230 )
231 {
232  SCIP_VAR** origvars;
233  int norigvars;
234  SCIP_VAR* origvar;
235 
236  SCIP_Real newobj;
237  int i;
238 
239  assert(SCIPinProbing(origscip));
240 
241  origvars = SCIPgetVars(origscip);
242  norigvars = SCIPgetNVars(origscip);
243 
244  /* loop over original variables */
245  for( i = 0; i < norigvars; ++i )
246  {
247  /* get variable information */
248  origvar = origvars[i];
249 
250  newobj = SCIPgetVarObjProbing(origscip, origvar) + (objfactor * SCIPvarGetObj(origvar))/ objdivisor ;
251 
252  SCIP_CALL( SCIPchgVarObjProbing(origscip, origvar, newobj) );
253  }
254  return SCIP_OKAY;
255 }
256 
257 /**< Initialize probing objective coefficient for each variable depending on the current origsol.
258  *
259  * If variable is at upper bound set objective to -1, if variable is at lower bound set obj to 1,
260  * else set obj to 0.
261  * Additionally, add original objective to the probing objective if this is enabled.
262  */
263 static
264 SCIP_RETCODE initProbingObjUsingVarBounds(
265  SCIP* origscip, /**< orig scip problem */
266  SCIP_SEPADATA* sepadata, /**< separator specific data */
267  SCIP_SOL* origsol, /**< orig solution */
268  SCIP_Bool enableobj, /**< returns if objective row was added to the lp */
269  SCIP_Real objfactor /**< factor the objective is multiplied with */
270 )
271 {
272  SCIP_Bool enableposslack;
273  int posslackexp;
274 
275  SCIP_VAR** origvars;
276  int norigvars;
277  SCIP_VAR* origvar;
278 
279  SCIP_Real lb;
280  SCIP_Real ub;
281  SCIP_Real solval;
282  SCIP_Real newobj;
283  SCIP_Real distance;
284 
285  int i;
286 
287  origvars = SCIPgetVars(origscip);
288  norigvars = SCIPgetNVars(origscip);
289 
290  enableposslack = sepadata->enableposslack;
291  posslackexp = sepadata->posslackexp;
292 
293  /* loop over original variables */
294  for( i = 0; i < norigvars; ++i )
295  {
296  /* get variable information */
297  origvar = origvars[i];
298  lb = SCIPvarGetLbLocal(origvar);
299  ub = SCIPvarGetUbLocal(origvar);
300  solval = SCIPgetSolVal(origscip, origsol, origvar);
301 
302  assert(SCIPisFeasLE(origscip, solval, ub));
303  assert(SCIPisFeasGE(origscip, solval, lb));
304 
305  /* if solution value of variable is at ub or lb initialize objective value of the variable
306  * such that the difference to this bound is minimized
307  */
308  if( SCIPisFeasEQ(origscip, lb, ub) )
309  {
310  newobj = 0.0;
311  }
312  else if( SCIPisLT(origscip, ub, SCIPinfinity(origscip)) && SCIPisFeasLE(origscip, ub, solval) )
313  {
314  newobj = -1.0;
315  }
316  else if( SCIPisGT(origscip, lb, -SCIPinfinity(origscip)) && SCIPisFeasGE(origscip, lb, solval) )
317  {
318  newobj = 1.0;
319  }
320  else if( enableposslack )
321  {
322  /* compute distance from solution to variable bound */
323  distance = MIN(solval - lb, ub - solval);
324 
325  assert(SCIPisFeasPositive(origscip, distance));
326 
327  /* check if distance is lower than 1 and compute factor */
328  if( SCIPisLT(origscip, distance, 1.0) )
329  {
330  newobj = exponentiate(MAX(0.0, 1.0 - distance), posslackexp);
331 
332  /* check if algebraic sign has to be changed */
333  if( SCIPisLT(origscip, distance, solval - lb) )
334  newobj = -newobj;
335  }
336  else
337  {
338  newobj = 0.0;
339  }
340  }
341  else
342  {
343  newobj = 0.0;
344  }
345 
346  /* if objective row is enabled consider also the original objective value */
347  if( enableobj )
348  newobj = newobj + SCIPvarGetObj(origvar);
349 
350  SCIP_CALL( SCIPchgVarObjProbing(origscip, origvar, objfactor*newobj) );
351  }
352 
353  return SCIP_OKAY;
354 }
355 
356 /**< Change probing objective depending on the current origsol.
357  *
358  * Loop over all constraints lhs <= sum a_i*x_i <= rhs. If lhs == sum a_i*x_i^* add a_i to objective
359  * of variable i and if rhs == sum a_i*x_i^* add -a_i to objective of variable i.
360  */
361 static
363  SCIP* origscip, /**< orig scip problem */
364  SCIP_SEPADATA* sepadata, /**< separator data */
365  SCIP_SOL* origsol, /**< orig solution */
366  SCIP_Real objfactor, /**< factor the objective is multiplied with */
367  SCIP_Real objdivisor /**< factor the objective is divided with */
368 )
369 {
370  SCIP_Bool enableposslack;
371  int posslackexp;
372 
373  SCIP_ROW** rows;
374  int nrows;
375  SCIP_ROW* row;
376  SCIP_Real* vals;
377  SCIP_VAR** vars;
378  SCIP_COL** cols;
379  int nvars;
380 
381  SCIP_Real lhs;
382  SCIP_Real rhs;
383  SCIP_Real* solvals;
384  SCIP_Real activity;
385  SCIP_Real factor;
386  SCIP_Real objadd;
387  SCIP_Real obj;
388  SCIP_Real norm;
389  SCIP_Real distance;
390 
391  int i;
392  int j;
393 
394  rows = SCIPgetLPRows(origscip);
395  nrows = SCIPgetNLPRows(origscip);
396 
397  enableposslack = sepadata->enableposslack;
398  posslackexp = sepadata->posslackexp;
399 
400  assert(SCIPinProbing(origscip));
401 
402  SCIP_CALL( SCIPallocBufferArray(origscip, &solvals, SCIPgetNVars(origscip)) );
403  SCIP_CALL( SCIPallocBufferArray(origscip, &vars, SCIPgetNVars(origscip)) );
404 
405  /* loop over constraint and check activity */
406  for( i = 0; i < nrows; ++i )
407  {
408  row = rows[i];
409  lhs = SCIProwGetLhs(row);
410  rhs = SCIProwGetRhs(row);
411 
412  nvars = SCIProwGetNNonz(row);
413  if( nvars == 0 || (sepadata->objrow != NULL && strcmp(SCIProwGetName(row),SCIProwGetName(sepadata->objrow)) == 0 ) )
414  continue;
415 
416  /* get values, variables and solution values */
417  vals = SCIProwGetVals(row);
418  cols = SCIProwGetCols(row);
419  for( j = 0; j < nvars; ++j )
420  {
421  vars[j] = SCIPcolGetVar(cols[j]);
422  }
423 
424  activity = SCIPgetRowSolActivity(origscip, row, origsol);
425 
426  if( SCIPisFeasEQ(origscip, rhs, lhs) )
427  {
428  continue;
429  }
430  if( SCIPisLT(origscip, rhs, SCIPinfinity(origscip)) && SCIPisFeasLE(origscip, rhs, activity) )
431  {
432  factor = -1.0;
433  }
434  else if( SCIPisGT(origscip, lhs, -SCIPinfinity(origscip)) && SCIPisFeasGE(origscip, lhs, activity) )
435  {
436  factor = 1.0;
437  }
438  else if( enableposslack )
439  {
440  assert(!(SCIPisInfinity(origscip, rhs) && SCIPisInfinity(origscip, lhs)));
441  assert(!(SCIPisInfinity(origscip, activity) && SCIPisInfinity(origscip, -activity)));
442 
443  /* compute distance from solution to row */
444  if( SCIPisInfinity(origscip, rhs) && SCIPisGT(origscip, lhs, -SCIPinfinity(origscip)) )
445  distance = activity - lhs;
446  else if( SCIPisInfinity(origscip, lhs) && SCIPisLT(origscip, rhs, SCIPinfinity(origscip)) )
447  distance = rhs - activity;
448  else
449  distance = MIN(activity - lhs, rhs - activity);
450 
451  assert(SCIPisFeasPositive(origscip, distance) || !SCIPisCutEfficacious(origscip, origsol, row));
452 
453  /* check if distance is lower than 1 and compute factor */
454  if( SCIPisLT(origscip, distance, 1.0) )
455  {
456  factor = exponentiate(MAX(0.0, 1.0 - distance), posslackexp);
457 
458  /* check if algebraic sign has to be changed */
459  if( SCIPisLT(origscip, distance, activity - lhs) )
460  factor = -1.0*factor;
461  }
462  else
463  {
464  continue;
465  }
466  }
467  else
468  {
469  continue;
470  }
471 
472  norm = SCIProwGetNorm(row);
473 
474  /* loop over variables of the constraint and change objective */
475  for( j = 0; j < nvars; ++j )
476  {
477  obj = SCIPgetVarObjProbing(origscip, vars[j]);
478  objadd = (factor * vals[j]) / norm;
479 
480  SCIP_CALL( SCIPchgVarObjProbing(origscip, vars[j], obj + (objfactor * objadd) / objdivisor) );
481  }
482  }
483 
484  SCIPfreeBufferArray(origscip, &solvals);
485  SCIPfreeBufferArray(origscip, &vars);
486 
487  return SCIP_OKAY;
488 }
489 
490 #ifdef WITH_GSL
491 /** Get matrix (including nrows and ncols) of rows that are satisfied with equality by sol */
492 static
493 SCIP_RETCODE getEqualityMatrixGsl(
494  SCIP* scip, /**< SCIP data structure */
495  SCIP_SOL* sol, /**< solution */
496  gsl_matrix** matrix, /**< pointer to store equality matrix */
497  int* nrows, /**< pointer to store number of rows */
498  int* ncols, /**< pointer to store number of columns */
499  int* prerank /**< pointer to store preprocessed rank */
500 )
501 {
502  int* var2col;
503  int* delvars;
504 
505  int nvar2col;
506  int ndelvars;
507 
508  SCIP_ROW** lprows;
509  int nlprows;
510 
511  SCIP_COL** lpcols;
512  int nlpcols;
513 
514  int i;
515  int j;
516 
517  *ncols = SCIPgetNLPCols(scip);
518  nlprows = SCIPgetNLPRows(scip);
519  lprows = SCIPgetLPRows(scip);
520  nlpcols = SCIPgetNLPCols(scip);
521  lpcols = SCIPgetLPCols(scip);
522 
523  *nrows = 0;
524 
525  ndelvars = 0;
526  nvar2col = 0;
527 
528  SCIP_CALL( SCIPallocBufferArray(scip, &var2col, nlpcols) );
529  SCIP_CALL( SCIPallocBufferArray(scip, &delvars, nlpcols) );
530 
531  /* loop over lp cols and check if it is at one of its bounds */
532  for( i = 0; i < nlpcols; ++i )
533  {
534  SCIP_COL* lpcol;
535  SCIP_VAR* lpvar;
536 
537  lpcol = lpcols[i];
538 
539  lpvar = SCIPcolGetVar(lpcol);
540 
541  if( SCIPisEQ(scip, SCIPgetSolVal(scip, sol, lpvar), SCIPcolGetUb(lpcol) )
542  || SCIPisEQ(scip, SCIPgetSolVal(scip, sol, lpvar), SCIPcolGetLb(lpcol)) )
543  {
544  int ind;
545 
546  ind = SCIPcolGetIndex(lpcol);
547 
548  delvars[ndelvars] = ind;
549 
550  ++ndelvars;
551 
552  var2col[ind] = -1;
553  }
554  else
555  {
556  int ind;
557 
558  ind = SCIPcolGetIndex(lpcol);
559 
560  var2col[ind] = nvar2col;
561 
562  ++nvar2col;
563  }
564  }
565 
566  SCIPsortInt(delvars, ndelvars);
567 
568  *matrix = gsl_matrix_calloc(nlprows, nvar2col);
569 
570  *ncols = nvar2col;
571 
572  /* loop over lp rows and check if solution feasibility is equal to zero */
573  for( i = 0; i < nlprows; ++i )
574  {
575  SCIP_ROW* lprow;
576 
577  lprow = lprows[i];
578 
579  /* if solution feasiblity is equal to zero, add row to matrix */
580  if( SCIPisEQ(scip, SCIPgetRowSolFeasibility(scip, lprow, sol), 0.0) )
581  {
582  SCIP_COL** cols;
583  SCIP_Real* vals;
584  int nnonz;
585 
586  cols = SCIProwGetCols(lprow);
587  vals = SCIProwGetVals(lprow);
588  nnonz = SCIProwGetNNonz(lprow);
589 
590  /* get nonzero coefficients of row */
591  for( j = 0; j < nnonz; ++j )
592  {
593  int ind;
594  int pos;
595 
596  ind = SCIPcolGetIndex(cols[j]);
597  assert(ind >= 0 && ind < nlpcols);
598 
599  if( !SCIPsortedvecFindInt(delvars, ind, ndelvars, &pos) )
600  {
601  gsl_matrix_set(*matrix, *nrows, var2col[ind], vals[j]);
602  }
603  }
604  ++(*nrows);
605  }
606  }
607  *nrows = nlprows;
608  *prerank = ndelvars;
609 
610  SCIPfreeBufferArray(scip, &delvars);
611  SCIPfreeBufferArray(scip, &var2col);
612 
613  return SCIP_OKAY;
614 }
615 
616 /** get the rank of a given matrix */
617 static
618 SCIP_RETCODE getRank(
619  SCIP* scip,
620  gsl_matrix* matrix,
621  int nrows,
622  int ncols,
623  int* rank
624 )
625 {
626  gsl_matrix* matrixq;
627  gsl_matrix* matrixr;
628 
629  gsl_vector* tau;
630  gsl_vector* norm;
631  gsl_permutation* permutation;
632 
633  int ranktmp;
634  int signum;
635 
636  int i;
637 
638  matrixq = gsl_matrix_alloc(nrows, nrows);
639  matrixr = gsl_matrix_alloc(nrows, ncols);
640 
641  norm = gsl_vector_alloc(ncols);
642  tau = gsl_vector_alloc(MIN(nrows, ncols));
643 
644  permutation = gsl_permutation_alloc(ncols);
645 
646  gsl_linalg_QRPT_decomp(matrix, tau, permutation, &signum, norm);
647 
648  gsl_linalg_QR_unpack(matrix, tau, matrixq, matrixr);
649 
650  ranktmp = 0;
651 
652  for( i = 0; i < MIN(nrows, ncols); ++i )
653  {
654  SCIP_Real val;
655 
656  val = gsl_matrix_get(matrixr, i, i);
657 
658  if( SCIPisZero(scip, val) )
659  {
660  break;
661  }
662  ++(ranktmp);
663  }
664 
665  *rank = ranktmp;
666 
667  gsl_matrix_free(matrixq);
668  gsl_matrix_free(matrixr);
669 
670  gsl_vector_free(tau);
671  gsl_vector_free(norm);
672 
673  gsl_permutation_free(permutation);
674 
675  return SCIP_OKAY;
676 }
677 
678 /** Get rank (number of linear independent rows) of rows that are satisfied
679  * with equality by solution sol */
680 static
681 SCIP_RETCODE getEqualityRankGsl(
682  SCIP* scip, /**< SCIP data structure */
683  SCIP_SOL* sol, /**< solution */
684  int* equalityrank /**< pointer to store rank of rows with equality */
685  )
686 {
687  gsl_matrix* matrix;
688  int nrows;
689  int ncols;
690 
691  int prerank;
692  int rowrank;
693 
694  SCIP_CALL( getEqualityMatrixGsl(scip, sol, &matrix, &nrows, &ncols, &prerank) );
695 
696  SCIP_CALL( getRank(scip, matrix, nrows, ncols, &rowrank) );
697 
698  gsl_matrix_free(matrix);
699 
700  *equalityrank = rowrank + prerank;
701 
702  return SCIP_OKAY;
703 }
704 #endif
705 
706 /** add cuts based on the last objective function of the pricing problems, which did not yield any new columns
707  * (stating that the reduced cost are non-negative) */
708 static
709 SCIP_RETCODE addPPObjConss(
710  SCIP* scip, /**< SCIP data structure */
711  SCIP_SEPA* sepa, /**< separator basis */
712  int ppnumber, /**< number of pricing problem */
713  SCIP_Real dualsolconv, /**< dual solution corresponding to convexity constraint */
714  SCIP_Bool newcuts, /**< add cut to newcuts in sepadata? (otherwise add it just to the cutpool) */
715  SCIP_Bool probing /**< add cut to probing LP? */
716 )
717 {
718  SCIP_SEPADATA* sepadata;
719 
720  SCIP* pricingscip;
721 
722  SCIP_VAR** pricingvars;
723  SCIP_VAR* var;
724 
725  int npricingvars;
726  int nvars;
727 
728  char name[SCIP_MAXSTRLEN];
729 
730  int j;
731  int k;
732 
733  SCIP_Real lhs;
734  SCIP_Real rhs;
735 
736  sepadata = SCIPsepaGetData(sepa);
737 
738  nvars = 0;
739  pricingscip = GCGgetPricingprob(scip, ppnumber);
740  pricingvars = SCIPgetOrigVars(pricingscip);
741  npricingvars = SCIPgetNOrigVars(pricingscip);
742 
743  if( !GCGisPricingprobRelevant(scip, ppnumber) || pricingscip == NULL )
744  return SCIP_OKAY;
745 
746  lhs = dualsolconv;
747  rhs = SCIPinfinity(scip);
748 
749  for( k = 0; k < GCGgetNIdenticalBlocks(scip, ppnumber); ++k )
750  {
751  SCIP_ROW* origcut;
752 
753  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "newconstraint_%d_%d_%d", SCIPsepaGetNCalls(sepa), ppnumber, k);
754 
755  SCIP_CALL( SCIPcreateEmptyRowUnspec(scip, &origcut, name, lhs, rhs, FALSE, FALSE, TRUE) );
756 
757  nvars = 0;
758 
759  for( j = 0; j < npricingvars ; ++j )
760  {
761  assert(GCGvarIsPricing(pricingvars[j]));
762 
763  if( !SCIPisEQ(scip, SCIPvarGetObj(pricingvars[j]), 0.0) )
764  {
765  var = GCGpricingVarGetOrigvars(pricingvars[j])[k];
766  assert(var != NULL);
767  SCIP_CALL( SCIPaddVarToRow(scip, origcut, var, SCIPvarGetObj(pricingvars[j])) );
768  ++nvars;
769  }
770  }
771 
772  if( nvars > 0 )
773  {
774  if( newcuts )
775  {
776  SCIP_CALL( ensureSizeNewCuts(scip, sepadata, sepadata->nnewcuts + 1) );
777 
778  sepadata->newcuts[sepadata->nnewcuts] = origcut;
779  SCIP_CALL( SCIPcaptureRow(scip, sepadata->newcuts[sepadata->nnewcuts]) );
780  ++(sepadata->nnewcuts);
781 
782  SCIPdebugMessage("cut added to new cuts in relaxdata\n");
783  }
784  else
785  {
786  SCIP_CALL( SCIPaddPoolCut(scip, origcut) );
787  SCIPdebugMessage("cut added to orig cut pool\n");
788  }
789 
790  if( probing )
791  {
792  SCIP_CALL( SCIPaddRowProbing(scip, origcut) );
793  SCIPdebugMessage("cut added to probing\n");
794  }
795 
796 
797  }
798  SCIP_CALL( SCIPreleaseRow(scip, &origcut) );
799  }
800 
801  return SCIP_OKAY;
802 }
803 /*
804  * Callback methods of separator
805  */
806 
807 /** copy method for separator plugins (called when SCIP copies plugins) */
808 #define sepaCopyBasis NULL
809 
810 /** destructor of separator to free user data (called when SCIP is exiting) */
811 static
812 SCIP_DECL_SEPAFREE(sepaFreeBasis)
813 { /*lint --e{715}*/
814  SCIP_SEPADATA* sepadata;
815 
816  sepadata = SCIPsepaGetData(sepa);
817  assert(sepadata != NULL);
818 
819  SCIPfreeBlockMemory(scip, &sepadata);
820 
821  return SCIP_OKAY;
822 }
823 
824 /** initialization method of separator (called after problem was transformed) */
825 static
826 SCIP_DECL_SEPAINIT(sepaInitBasis)
827 { /*lint --e{715}*/
828  SCIP* origscip;
829  SCIP_SEPADATA* sepadata;
830 
831  SCIP_VAR** origvars;
832  int norigvars;
833 
834  char name[SCIP_MAXSTRLEN];
835 
836  SCIP_Real obj;
837  int i;
838 
839  SCIP_Bool enable;
840  SCIP_Bool enableobj;
841 
842  assert(scip != NULL);
843 
844  origscip = GCGmasterGetOrigprob(scip);
845  assert(origscip != NULL);
846 
847  sepadata = SCIPsepaGetData(sepa);
848  assert(sepadata != NULL);
849 
850  origvars = SCIPgetVars(origscip);
851  norigvars = SCIPgetNVars(origscip);
852 
853  SCIPdebugMessage("sepaInitBasis\n");
854 
855  enable = sepadata->enable;
856  enableobj = sepadata->enableobj;
857 
858  sepadata->maxcuts = SCIPcalcMemGrowSize(scip, STARTMAXCUTS);
859  sepadata->norigcuts = 0;
860  sepadata->nmastercuts = 0;
861  sepadata->maxnewcuts = SCIPcalcMemGrowSize(scip, STARTMAXCUTS);
862  sepadata->nnewcuts = 0;
863  sepadata->objrow = NULL;
864  /* if separator is disabled do nothing */
865  if( !enable )
866  {
867  return SCIP_OKAY;
868  }
869 
870  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->origcuts), sepadata->maxcuts) ); /*lint !e506*/
871  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->mastercuts), sepadata->maxcuts) ); /*lint !e506*/
872  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->newcuts), sepadata->maxnewcuts) ); /*lint !e506*/
873 
874  /* if objective row is enabled create row with objective coefficients */
875  if( enableobj )
876  {
877  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "objrow");
878  SCIP_CALL( SCIPcreateEmptyRowUnspec(origscip, &(sepadata->objrow), name, -SCIPinfinity(origscip), SCIPinfinity(origscip), TRUE, FALSE, TRUE) );
879 
880  for( i = 0; i < norigvars; ++i )
881  {
882  obj = SCIPvarGetObj(origvars[i]);
883  SCIP_CALL( SCIPaddVarToRow(origscip, sepadata->objrow, origvars[i], obj) );
884  }
885  }
886 
887  return SCIP_OKAY;
888 }
889 
890 
891 /** deinitialization method of separator (called before transformed problem is freed) */
892 static
893 SCIP_DECL_SEPAEXIT(sepaExitBasis)
894 { /*lint --e{715}*/
895  SCIP* origscip;
896  SCIP_SEPADATA* sepadata;
897  SCIP_Bool enableobj;
898 
899  int i;
900 
901  sepadata = SCIPsepaGetData(sepa);
902  assert(sepadata != NULL);
903  enableobj = sepadata->enableobj;
904  assert(sepadata->nmastercuts == sepadata->norigcuts);
905 
906  origscip = GCGmasterGetOrigprob(scip);
907  assert(origscip != NULL);
908 
909  for( i = 0; i < sepadata->norigcuts; i++ )
910  {
911  SCIP_CALL( SCIPreleaseRow(origscip, &(sepadata->origcuts[i])) );
912  }
913 
914  for( i = 0; i < sepadata->nnewcuts; ++i )
915  {
916  if( sepadata->newcuts[i] != NULL )
917  SCIP_CALL( SCIPreleaseRow(origscip, &(sepadata->newcuts[i])) );
918  }
919 
920  if( enableobj )
921  SCIP_CALL( SCIPreleaseRow(origscip, &(sepadata->objrow)) );
922 
923  SCIPfreeBlockMemoryArrayNull(scip, &(sepadata->origcuts), sepadata->maxcuts);
924  SCIPfreeBlockMemoryArrayNull(scip, &(sepadata->mastercuts), sepadata->maxcuts);
925  SCIPfreeBlockMemoryArrayNull(scip, &(sepadata->newcuts), sepadata->maxnewcuts);
926 
927  return SCIP_OKAY;
928 }
929 
930 /** solving process initialization method of separator (called when branch and bound process is about to begin) */
931 static
932 SCIP_DECL_SEPAINITSOL(sepaInitsolBasis)
933 { /*lint --e{715}*/
934  SCIP_SEPADATA* sepadata;
935 
936  sepadata = SCIPsepaGetData(sepa);
937  assert(sepadata != NULL);
938 
939  sepadata->nmastercuts = 0;
940 
941  return SCIP_OKAY;
942 }
943 
944 
945 /** solving process deinitialization method of separator (called before branch and bound process data is freed) */
946 static
947 SCIP_DECL_SEPAEXITSOL(sepaExitsolBasis)
948 { /*lint --e{715}*/
949  SCIP_SEPADATA* sepadata;
950  int i;
951 
952  sepadata = SCIPsepaGetData(sepa);
953  assert(sepadata != NULL);
954  assert(sepadata->nmastercuts == sepadata->norigcuts);
955 
956  assert(GCGmasterGetOrigprob(scip) != NULL);
957 
958  for( i = 0; i < sepadata->nmastercuts; i++ )
959  {
960  SCIP_CALL( SCIPreleaseRow(scip, &(sepadata->mastercuts[i])) );
961  }
962 
963  return SCIP_OKAY;
964 }
965 
966 
967 /** Initialize generic convex combination coefficient */
968 static
969 SCIP_RETCODE initGenconv(
970  SCIP* origscip, /**< original SCIP data structure */
971  SCIP_SEPADATA* sepadata, /**< separator data structure */
972  SCIP_SOL* origsol, /**< current original solution */
973  int nbasis, /**< rank of constraint matrix */
974  SCIP_Real* convex /**< pointer to store convex combination coefficient */
975 )
976 { /*lint --e{715}*/
977 #ifdef WITH_GSL
978  int rank;
979 
980 
981  SCIP_CALL( getEqualityRankGsl(origscip, origsol, &rank) );
982 
983  *convex = 1.0* rank/nbasis;
984 
985  SCIPdebugMessage("use generic coefficient %d/%d = %f\n", rank, nbasis, *convex);
986 
987 #else
988  SCIPwarningMessage(origscip, "Gnu Scientific Library is not enabled! \n"
989  "either set sepa/basis/genobjconvex = FALSE sepa/basis/posslackexpgen = FALSE \n"
990  "or compile with GSL=true and include Gnu Scientific Library\n");
991  *convex = sepadata->objconvex;
992 #endif
993 
994  return SCIP_OKAY;
995 }
996 
997 
998 /** Initialize objective as convex combination of so-called face objective function and original objective function */
999 static
1000 SCIP_RETCODE initConvObj(
1001  SCIP* origscip, /**< original SCIP data structure */
1002  SCIP_SEPADATA* sepadata, /**< separator data structure */
1003  SCIP_SOL* origsol, /**< current original solution */
1004  SCIP_Real convex, /**< convex coefficient to initialize objective */
1005  SCIP_Bool genericconv /**< was convex coefficient calculated generically? */
1006 )
1007 {
1008  SCIP_Real objnormnull;
1009  SCIP_Real objnormcurrent;
1010 
1011  objnormnull = 1.0;
1012  objnormcurrent = 1.0;
1013 
1014  /* if coefficient is zero, only use original objective function */
1015  if( SCIPisEQ(origscip, convex, 0.0) )
1016  {
1017  SCIP_CALL( initProbingObjWithOrigObj(origscip, TRUE, 1.0) );
1018  }
1019  /* if coefficient is between zero and one, calculate convex combination */
1020  else if( SCIPisLT(origscip, convex, 1.0) )
1021  {
1022  SCIP_CALL( initProbingObjWithOrigObj(origscip, TRUE, 1.0) );
1023  objnormnull = SCIPgetObjNorm(origscip);
1024 
1025  SCIP_CALL( initProbingObjUsingVarBounds(origscip, sepadata, origsol, FALSE, convex) );
1026  SCIP_CALL( chgProbingObjUsingRows(origscip, sepadata, origsol, convex, 1.0) );
1027 
1028  objnormcurrent = SCIPgetObjNorm(origscip)/(convex);
1029 
1030  if( SCIPisEQ(origscip, objnormcurrent, 0.0) )
1031  SCIP_CALL( initProbingObjWithOrigObj(origscip, TRUE, 1.0) );
1032  else if( SCIPisGT(origscip, objnormnull, 0.0) )
1033  SCIP_CALL( chgProbingObjAddingOrigObj(origscip, (1.0 - convex) * objnormcurrent, objnormnull) );
1034  }
1035  /* if coefficient is one, only use so-called face objective function (based on activity of rows and variables) */
1036  else if( SCIPisEQ(origscip, convex, 1.0) )
1037  {
1038  SCIP_CALL( initProbingObjUsingVarBounds(origscip, sepadata, origsol, !genericconv && sepadata->enableobj, 1.0) );
1039  SCIP_CALL( chgProbingObjUsingRows(origscip, sepadata, origsol, 1.0, 1.0) );
1040  }
1041 
1042  return SCIP_OKAY;
1043 }
1044 
1045 /** LP solution separation method of separator */
1046 static
1047 SCIP_DECL_SEPAEXECLP(sepaExeclpBasis)
1048 { /*lint --e{715}*/
1049 
1050  SCIP* origscip;
1051  SCIP_SEPADATA* sepadata;
1052 
1053  SCIP_ROW** cuts;
1054  SCIP_ROW* mastercut;
1055  SCIP_ROW* origcut;
1056  SCIP_COL** cols;
1057  SCIP_VAR** roworigvars;
1058  SCIP_VAR** mastervars;
1059  SCIP_Real* mastervals;
1060  int ncols;
1061  int ncuts;
1062  SCIP_Real* vals;
1063  int nmastervars;
1064 
1065  SCIP_SOL* origsol;
1066  SCIP_Bool lperror;
1067  SCIP_Bool delayed;
1068  SCIP_Bool cutoff;
1069  SCIP_Bool infeasible;
1070  SCIP_Real obj;
1071 
1072  SCIP_Bool enable;
1073  SCIP_Bool enableobj;
1074  SCIP_Bool enableobjround;
1075  SCIP_Bool enableppobjconss;
1076 
1077  char name[SCIP_MAXSTRLEN];
1078 
1079  int i;
1080  int j;
1081  int iteration;
1082  int nbasis;
1083  int nlprowsstart;
1084  int nlprows;
1085  int maxrounds;
1086  SCIP_ROW** lprows;
1087  int nviolatedcuts;
1088 
1089  SCIP_Bool isroot;
1090 
1091  SCIP_RESULT resultdummy;
1092 
1093  SCIP_Bool enoughcuts;
1094  int maxcuts;
1095 
1096  int maxnsepastallrounds;
1097 
1098  SCIP_Real objreldiff;
1099  int nfracs;
1100  SCIP_Real stalllpobjval;
1101  SCIP_Real lpobjval;
1102  SCIP_Bool stalling;
1103  int nsepastallrounds;
1104  int stallnfracs;
1105  SCIP_LPSOLSTAT stalllpsolstat;
1106 
1107 
1108  assert(scip != NULL);
1109  assert(result != NULL);
1110 
1111  origscip = GCGmasterGetOrigprob(scip);
1112  assert(origscip != NULL);
1113 
1114  sepadata = SCIPsepaGetData(sepa);
1115  assert(sepadata != NULL);
1116 
1117  SCIPdebugMessage("calling sepaExeclpBasis\n");
1118 
1119  *result = SCIP_DIDNOTFIND;
1120 
1121  enable = sepadata->enable;
1122  enableobj = sepadata->enableobj;
1123  enableobjround = sepadata->enableobjround;
1124  enableppobjconss = sepadata->enableppobjconss;
1125 
1126  /* if separator is disabled do nothing */
1127  if( !enable )
1128  {
1129  SCIPdebugMessage("separator is not enabled\n");
1130  *result = SCIP_DIDNOTRUN;
1131  return SCIP_OKAY;
1132  }
1133 
1134  /* ensure master LP is solved to optimality */
1135  if( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
1136  {
1137  SCIPdebugMessage("master LP not solved to optimality, do no separation!\n");
1138  *result = SCIP_DIDNOTRUN;
1139  return SCIP_OKAY;
1140  }
1141 
1142  /* ensure pricing problems were not aggregated */
1143  if( GCGgetNRelPricingprobs(origscip) < GCGgetNPricingprobs(origscip) )
1144  {
1145  SCIPdebugMessage("aggregated pricing problems, do no separation!\n");
1146  *result = SCIP_DIDNOTRUN;
1147  return SCIP_OKAY;
1148  }
1149 
1150  /* ensure to separate current sol */
1151  SCIP_CALL( GCGrelaxUpdateCurrentSol(origscip) );
1152 
1153  /* do not separate if current solution is feasible */
1154  if( GCGrelaxIsOrigSolFeasible(origscip) )
1155  {
1156  SCIPdebugMessage("Current solution is feasible, no separation necessary!\n");
1157  *result = SCIP_DIDNOTRUN;
1158  return SCIP_OKAY;
1159  }
1160 
1161  /* reset information on separation rounds in probing LP at current node */
1162  if( sepadata->currentnodenr != SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) )
1163  {
1164  sepadata->currentnodenr = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
1165  sepadata->round = 0;
1166  }
1167 
1168  isroot = SCIPgetCurrentNode(scip) == SCIPgetRootNode(scip);
1169 
1170  /* set maximum number of rounds at current node */
1171  maxrounds = (isroot ? sepadata->maxroundsroot : sepadata->maxrounds);
1172 
1173  /* if no limit on number of rounds, set maxrounds to INT_MAX */
1174  if( maxrounds == -1 )
1175  maxrounds = INT_MAX;
1176 
1177  /* get current original solution */
1178  origsol = GCGrelaxGetCurrentOrigSol(origscip);
1179 
1180  /* get trans objective value */
1181  obj = SCIPgetSolTransObj(origscip, origsol);
1182 
1183  /* get number of linearly independent rows needed for basis */
1184  nbasis = SCIPgetNLPCols(origscip);
1185 
1186  *result = SCIP_DIDNOTFIND;
1187 
1188  /* init iteration count of current sepa call */
1189  iteration = 0;
1190 
1191  /* set parameter setting for separation */
1192  SCIP_CALL( SCIPsetSeparating(origscip, (SCIP_PARAMSETTING) sepadata->separationsetting, TRUE) );
1193 
1194  /* disable rapid learning because it does not generate cuts */
1195  SCIP_CALL( SCIPsetIntParam(origscip, "separating/rapidlearning/freq", -1) );
1196 
1197  /* start probing */
1198  SCIP_CALL( SCIPstartProbing(origscip) );
1199  SCIP_CALL( SCIPnewProbingNode(origscip) );
1200  SCIP_CALL( SCIPconstructLP(origscip, &cutoff) );
1201 
1202  /* add origcuts to probing lp */
1203  for( i = 0; i < GCGsepaGetNCuts(scip); ++i )
1204  {
1205  if( SCIProwGetLPPos(GCGsepaGetOrigcuts(scip)[i]) == -1 )
1206  SCIP_CALL( SCIPaddRowProbing(origscip, GCGsepaGetOrigcuts(scip)[i]) );
1207  }
1208 
1209  /* add new cuts which did not cut off master sol to probing lp */
1210  for( i = 0; i < sepadata->nnewcuts; ++i )
1211  {
1212  if( SCIProwGetLPPos(sepadata->newcuts[i]) == -1 )
1213  SCIP_CALL( SCIPaddRowProbing(origscip, sepadata->newcuts[i]) );
1214  }
1215 
1216  /* store number of lp rows in the beginning */
1217  nlprowsstart = SCIPgetNLPRows(origscip);
1218 
1219  nsepastallrounds = 0;
1220  stalllpobjval = SCIP_REAL_MIN;
1221  stallnfracs = INT_MAX;
1222  stalling = FALSE;
1223 
1224  maxcuts = 0;
1225  if( isroot )
1226  SCIP_CALL( SCIPgetIntParam(origscip, "separating/maxcutsroot", &maxcuts) );
1227  else
1228  SCIP_CALL( SCIPgetIntParam(origscip, "separating/maxcuts", &maxcuts) );
1229 
1230  maxnsepastallrounds = 0;
1231  if( isroot )
1232  SCIP_CALL( SCIPgetIntParam(origscip, "separating/maxstallroundsroot", &maxnsepastallrounds) );
1233  else
1234  SCIP_CALL( SCIPgetIntParam(origscip, "separating/maxstallrounds", &maxnsepastallrounds) );
1235 
1236  if( maxnsepastallrounds == -1 )
1237  maxnsepastallrounds = INT_MAX;
1238 
1239  stalllpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
1240 
1241 
1242  /* while the counter is smaller than the number of allowed rounds,
1243  * try to separate origsol via probing lp sol */
1244  while( sepadata->round < maxrounds && nsepastallrounds < maxnsepastallrounds )
1245  {
1246  SCIPdebugMessage("round %d of at most %d rounds\n", sepadata->round + 1, maxrounds);
1247 
1248  SCIP_CALL( SCIPapplyCutsProbing(origscip, &cutoff) );
1249 
1250  /* add new constraints if this is enabled */
1251  if( enableppobjconss && iteration == 0 )
1252  {
1253  SCIP_Real* dualsolconv;
1254 
1255  SCIPdebugMessage("add reduced cost cut for relevant pricing problems\n");
1256 
1257  SCIP_CALL( SCIPallocBufferArray(scip, &dualsolconv, GCGgetNPricingprobs(origscip)) );
1258  SCIP_CALL( GCGsetPricingObjs(scip, dualsolconv) );
1259 
1260  for( i = 0; i < GCGgetNPricingprobs(origscip); ++i )
1261  {
1262  SCIP_CALL( addPPObjConss(origscip, sepa, i, dualsolconv[i], FALSE, TRUE) );
1263  }
1264 
1265  SCIPfreeBufferArray(scip, &dualsolconv);
1266  }
1267 
1268  /* initialize objective of probing LP */
1269  if( sepadata->chgobj && (iteration == 0 || sepadata->chgobjallways) )
1270  {
1271  SCIPdebugMessage("initialize objective function\n");
1272  if( sepadata->genobjconvex )
1273  {
1274  SCIP_Real genconvex;
1275 
1276  SCIP_CALL( initGenconv(origscip, sepadata, origsol, nbasis, &genconvex) );
1277 
1278  SCIP_CALL( initConvObj(origscip, sepadata, origsol, genconvex, TRUE) );
1279  }
1280  else
1281  {
1282  SCIPdebugMessage("use given coefficient %g\n", sepadata->objconvex);
1283 
1284  if( sepadata->enableposslack && sepadata->posslackexpgen )
1285  {
1286  SCIP_Real genconvex;
1287  SCIP_Real factor;
1288 
1289  factor = sepadata->posslackexpgenfactor;
1290 
1291  SCIP_CALL( initGenconv(origscip, sepadata, origsol, nbasis, &genconvex) );
1292 
1293  sepadata->posslackexp = (int) (SCIPceil(origscip, factor/(1.0 - genconvex)) + 0.5);
1294 
1295  SCIPdebugMessage("exponent = %d\n", sepadata->posslackexp);
1296 
1297  }
1298  SCIP_CALL( initConvObj(origscip, sepadata, origsol, sepadata->objconvex, FALSE) );
1299  }
1300  }
1301 
1302  /* update rhs/lhs of objective constraint and add it to probing LP, if it exists (only in first iteration) */
1303  if( enableobj && iteration == 0 )
1304  {
1305  SCIPdebugMessage("initialize original objective cut\n");
1306 
1307  /* round rhs/lhs of objective constraint, if it exists, obj is integral and this is enabled */
1308  if( SCIPisObjIntegral(origscip) && enableobjround )
1309  {
1310  SCIPdebugMessage("round lhs up\n");
1311  obj = SCIPceil(origscip, obj);
1312  }
1313 
1314  SCIP_CALL( SCIPchgRowLhs(origscip, sepadata->objrow, obj) );
1315  SCIP_CALL( SCIPchgRowRhs(origscip, sepadata->objrow, SCIPinfinity(origscip)) );
1316 
1317  SCIPdebugMessage("add original objective cut to probing LP\n");
1318 
1319  /* add row to probing lp */
1320  SCIP_CALL( SCIPaddRowProbing(origscip, sepadata->objrow) );
1321  }
1322 
1323  SCIPdebugMessage("solve probing LP\n");
1324 
1325  /* solve probing lp */
1326  SCIP_CALL( SCIPsolveProbingLP(origscip, -1, &lperror, &cutoff) );
1327 
1328  assert(!lperror);
1329 
1330  /* check if we are stalling
1331  * We are stalling if
1332  * the LP value did not improve and
1333  * the number of fractional variables did not decrease.
1334  */
1335  if( SCIPgetLPSolstat(origscip) == SCIP_LPSOLSTAT_OPTIMAL )
1336  {
1337  SCIP_CALL( SCIPgetLPBranchCands(origscip, NULL, NULL, NULL, &nfracs, NULL, NULL) );
1338  lpobjval = SCIPgetLPObjval(origscip);
1339 
1340  objreldiff = SCIPrelDiff(lpobjval, stalllpobjval);
1341  SCIPdebugMessage(" -> LP bound moved from %g to %g (reldiff: %g)\n",
1342  stalllpobjval, lpobjval, objreldiff);
1343 
1344  stalling = (objreldiff <= 1e-04 &&
1345  nfracs >= (0.9 - 0.1 * nsepastallrounds) * stallnfracs);
1346 
1347  stalllpobjval = lpobjval;
1348  stallnfracs = nfracs;
1349  }
1350  else
1351  {
1352  stalling = (stalllpsolstat == SCIPgetLPSolstat(origscip));
1353  }
1354 
1355  if( !stalling )
1356  {
1357  nsepastallrounds = 0;
1358  }
1359  else
1360  {
1361  nsepastallrounds++;
1362  }
1363  stalllpsolstat = SCIPgetLPSolstat(origscip);
1364 
1365  /* separate cuts in cutpool */
1366  SCIPdebugMessage("separate current LP sol in cutpool\n");
1367  SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetGlobalCutpool(origscip), NULL, isroot, &resultdummy) );
1368 
1369  enoughcuts = (SCIPgetNCuts(origscip) >= 2 * (SCIP_Longint)maxcuts) || (resultdummy == SCIP_NEWROUND);
1370 
1371  if( !enoughcuts )
1372  {
1373  /* separate current probing lp sol of origscip */
1374  SCIPdebugMessage("separate current LP solution\n");
1375  SCIP_CALL( SCIPseparateSol(origscip, NULL, isroot, isroot, FALSE, &delayed, &cutoff) );
1376 
1377  enoughcuts = enoughcuts || (SCIPgetNCuts(origscip) >= 2 * (SCIP_Longint)maxcuts) || (resultdummy == SCIP_NEWROUND);
1378 
1379  /* if we are close to the stall round limit, also call the delayed separators */
1380  if( !enoughcuts && delayed && !cutoff && nsepastallrounds >= maxnsepastallrounds-1)
1381  {
1382  SCIPdebugMessage("call delayed separators\n");
1383  SCIP_CALL( SCIPseparateSol(origscip, NULL, isroot, isroot, TRUE, &delayed, &cutoff) );
1384  }
1385  }
1386 
1387  if( !enoughcuts && !cutoff )
1388  {
1389  /* separate cuts in cutpool */
1390  SCIPdebugMessage("separate current LP sol in cutpool\n");
1391  SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetGlobalCutpool(origscip), NULL, isroot, &resultdummy) );
1392 
1393  enoughcuts = enoughcuts || (SCIPgetNCuts(origscip) >= 2 * (SCIP_Longint)maxcuts) || (resultdummy == SCIP_NEWROUND);
1394  }
1395 
1396  if( SCIPgetNCuts(origscip) == 0 && !cutoff )
1397  {
1398  /* separate cuts in delayed cutpool */
1399  SCIPdebugMessage("separate current LP sol in delayed cutpool\n");
1400  SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetDelayedGlobalCutpool(origscip), NULL, isroot, &resultdummy) );
1401 
1402  enoughcuts = enoughcuts || (SCIPgetNCuts(origscip) >= 2 * (SCIP_Longint)maxcuts) || (resultdummy == SCIP_NEWROUND);
1403  }
1404 
1405  /* if cut off is detected set result pointer and return SCIP_OKAY */
1406  if( cutoff )
1407  {
1408  *result = SCIP_CUTOFF;
1409  SCIP_CALL( SCIPendProbing(origscip) );
1410 
1411  /* disable separating again */
1412  SCIP_CALL( SCIPsetSeparating(origscip, SCIP_PARAMSETTING_OFF, TRUE) );
1413 
1414  return SCIP_OKAY;
1415  }
1416 
1417  /* separate cuts in cutpool */
1418  SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetGlobalCutpool(origscip), origsol, isroot, &resultdummy) );
1419  SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetDelayedGlobalCutpool(origscip), origsol, isroot, &resultdummy) );
1420 
1421  assert(sepadata->norigcuts == sepadata->nmastercuts);
1422 
1423  SCIPdebugMessage("%d cuts are in the original sepastore!\n", SCIPgetNCuts(origscip));
1424 
1425  /* get separated cuts */
1426  cuts = SCIPgetCuts(origscip);
1427  ncuts = SCIPgetNCuts(origscip);
1428 
1429  SCIP_CALL( ensureSizeCuts(scip, sepadata, sepadata->norigcuts + ncuts) );
1430 
1431  mastervars = SCIPgetVars(scip);
1432  nmastervars = SCIPgetNVars(scip);
1433  SCIP_CALL( SCIPallocBufferArray(scip, &mastervals, nmastervars) );
1434 
1435  /* using nviolated cuts is a workaround for a SCIP issue:
1436  * it might happen that non-violated cuts are added to the sepastore,
1437  * which could lead to an infinite loop
1438  */
1439  /* initialize nviolated counting the number of cuts in the sepastore
1440  * that are violated by the current LP solution */
1441  nviolatedcuts = 0;
1442 
1443  /* loop over cuts and transform cut to master problem (and safe cuts) if it seperates origsol */
1444  for( i = 0; i < ncuts; i++ )
1445  {
1446  SCIP_Bool colvarused;
1447  SCIP_Real shift;
1448 
1449  colvarused = FALSE;
1450  origcut = cuts[i];
1451 
1452  /* if cut is violated by LP solution, increase nviolatedcuts */
1453  if( SCIPisCutEfficacious(origscip, NULL, origcut) )
1454  {
1455  ++nviolatedcuts;
1456  }
1457 
1458  /* get columns and vals of the cut */
1459  ncols = SCIProwGetNNonz(origcut);
1460  cols = SCIProwGetCols(origcut);
1461  vals = SCIProwGetVals(origcut);
1462 
1463  /* get the variables corresponding to the columns in the cut */
1464  SCIP_CALL( SCIPallocBufferArray(scip, &roworigvars, ncols) );
1465  for( j = 0; j < ncols; j++ )
1466  {
1467  roworigvars[j] = SCIPcolGetVar(cols[j]);
1468  assert(roworigvars[j] != NULL);
1469  if( !GCGvarIsOriginal(roworigvars[j]) )
1470  {
1471  colvarused = TRUE;
1472  break;
1473  }
1474  }
1475 
1476  if( colvarused )
1477  {
1478  SCIPwarningMessage(origscip, "colvar used in original cut %s\n", SCIProwGetName(origcut));
1479  SCIPfreeBufferArray(scip, &roworigvars);
1480  continue;
1481  }
1482 
1483  if( !SCIPisCutEfficacious(origscip, origsol, origcut) )
1484  {
1485  if( !SCIProwIsLocal(origcut) )
1486  SCIP_CALL( SCIPaddPoolCut(origscip, origcut) );
1487 
1488  SCIPfreeBufferArray(scip, &roworigvars);
1489 
1490  continue;
1491  }
1492 
1493  /* add the cut to the original cut storage */
1494  sepadata->origcuts[sepadata->norigcuts] = origcut;
1495  SCIP_CALL( SCIPcaptureRow(origscip, sepadata->origcuts[sepadata->norigcuts]) );
1496  sepadata->norigcuts++;
1497 
1498  /* transform the original variables to master variables */
1499  shift = GCGtransformOrigvalsToMastervals(origscip, roworigvars, vals, ncols, mastervars, mastervals, nmastervars);
1500 
1501  /* create new cut in the master problem */
1502  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "mc_basis_%s", SCIProwGetName(origcut));
1503  SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &mastercut, sepa, name,
1504  ( SCIPisInfinity(scip, -SCIProwGetLhs(origcut)) ?
1505  SCIProwGetLhs(origcut) : SCIProwGetLhs(origcut) - SCIProwGetConstant(origcut) - shift),
1506  ( SCIPisInfinity(scip, SCIProwGetRhs(origcut)) ?
1507  SCIProwGetRhs(origcut) : SCIProwGetRhs(origcut) - SCIProwGetConstant(origcut) - shift),
1508  SCIProwIsLocal(origcut), TRUE, FALSE) );
1509 
1510  /* add master variables to the cut */
1511  SCIP_CALL( SCIPaddVarsToRow(scip, mastercut, nmastervars, mastervars, mastervals) );
1512 
1513  /* add the cut to the master problem and to the master cut storage */
1514  SCIP_CALL( SCIPaddRow(scip, mastercut, sepadata->forcecuts, &infeasible) );
1515  sepadata->mastercuts[sepadata->nmastercuts] = mastercut;
1516  SCIP_CALL( SCIPcaptureRow(scip, sepadata->mastercuts[sepadata->nmastercuts]) );
1517  sepadata->nmastercuts++;
1518  SCIP_CALL( GCGsepaAddMastercuts(scip, origcut, mastercut) );
1519 
1520  SCIP_CALL( SCIPreleaseRow(scip, &mastercut) );
1521  SCIPfreeBufferArray(scip, &roworigvars);
1522  }
1523 
1524  SCIPdebugMessage("%d cuts are in the master sepastore!\n", SCIPgetNCuts(scip));
1525 
1526  ++sepadata->round;
1527  ++iteration;
1528 
1529  if( SCIPgetNCuts(scip) >= sepadata->mincuts )
1530  {
1531  *result = SCIP_SEPARATED;
1532 
1533  SCIPfreeBufferArray(scip, &mastervals);
1534  break;
1535  }
1536  /* use nviolated cuts instead of number of cuts in sepastore,
1537  * because non-violated might be added to the sepastore */
1538  else if( nviolatedcuts == 0 )
1539  {
1540  SCIPfreeBufferArray(scip, &mastervals);
1541  break;
1542  }
1543 
1544  SCIPfreeBufferArray(scip, &mastervals);
1545 
1546  assert(sepadata->norigcuts == sepadata->nmastercuts );
1547  }
1548 
1549  SCIP_CALL( SCIPclearCuts(origscip) );
1550 
1551  lprows = SCIPgetLPRows(origscip);
1552  nlprows = SCIPgetNLPRows(origscip);
1553 
1554  assert(nlprowsstart <= nlprows);
1555 
1556  SCIP_CALL( ensureSizeNewCuts(scip, sepadata, sepadata->nnewcuts + nlprows - nlprowsstart) );
1557 
1558  for( i = nlprowsstart; i < nlprows; ++i )
1559  {
1560  if( SCIProwGetOrigintype(lprows[i]) == SCIP_ROWORIGINTYPE_SEPA )
1561  {
1562  sepadata->newcuts[sepadata->nnewcuts] = lprows[i];
1563  SCIP_CALL( SCIPcaptureRow(origscip, sepadata->newcuts[sepadata->nnewcuts]) );
1564  ++(sepadata->nnewcuts);
1565  }
1566  }
1567 
1568  /* end probing */
1569  SCIP_CALL( SCIPendProbing(origscip) );
1570 
1571  if( SCIPgetNCuts(scip) > 0 )
1572  {
1573  *result = SCIP_SEPARATED;
1574  }
1575 
1576  /* disable separating again */
1577  SCIP_CALL( SCIPsetSeparating(origscip, SCIP_PARAMSETTING_OFF, TRUE) );
1578 
1579  SCIPdebugMessage("exiting sepaExeclpBasis\n");
1580 
1581  return SCIP_OKAY;
1582 }
1583 
1584 /** arbitrary primal solution separation method of separator */
1585 #define sepaExecsolBasis NULL
1586 
1587 /*
1588  * separator specific interface methods
1589  */
1590 
1591 /** creates the basis separator and includes it in SCIP */
1593  SCIP* scip /**< SCIP data structure */
1594  )
1595 {
1596  SCIP_SEPADATA* sepadata;
1597 
1598  /* create master separator data */
1599  SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
1600 
1601  sepadata->mastercuts = NULL;
1602  sepadata->origcuts = NULL;
1603  sepadata->norigcuts = 0;
1604  sepadata->nmastercuts = 0;
1605  sepadata->maxcuts = 0;
1606  sepadata->newcuts = NULL;
1607  sepadata->nnewcuts = 0;
1608  sepadata->maxnewcuts = 0;
1609  sepadata->objrow = NULL;
1610  sepadata->round = 0;
1611  sepadata->currentnodenr = -1;
1612 
1613  /* include separator */
1614  SCIP_CALL( SCIPincludeSepa(scip, SEPA_NAME, SEPA_DESC, SEPA_PRIORITY, SEPA_FREQ, SEPA_MAXBOUNDDIST,
1616  sepaCopyBasis, sepaFreeBasis, sepaInitBasis, sepaExitBasis, sepaInitsolBasis, sepaExitsolBasis, sepaExeclpBasis, sepaExecsolBasis,
1617  sepadata) );
1618 
1619  /* add basis separator parameters */
1620  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/enable", "is basis separator enabled?",
1621  &(sepadata->enable), FALSE, TRUE, NULL, NULL) );
1622 
1623  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/enableobj", "is objective constraint of separator enabled?",
1624  &(sepadata->enableobj), FALSE, FALSE, NULL, NULL) );
1625 
1626  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/enableobjround", "round obj rhs/lhs of obj constraint if obj is int?",
1627  &(sepadata->enableobjround), FALSE, FALSE, NULL, NULL) );
1628 
1629  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/enableppcuts", "add cuts generated during pricing to newconss array?",
1630  &(sepadata->enableppcuts), FALSE, FALSE, NULL, NULL) );
1631 
1632  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/enableppobjconss", "is objective constraint for redcost of each pp of "
1633  "separator enabled?", &(sepadata->enableppobjconss), FALSE, FALSE, NULL, NULL) );
1634 
1635  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/enableppobjcg", "is objective constraint for redcost of each pp during "
1636  "pricing of separator enabled?", &(sepadata->enableppobjcg), FALSE, FALSE, NULL, NULL) );
1637 
1638  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/genobjconvex", "generated obj convex dynamically",
1639  &(sepadata->genobjconvex), FALSE, FALSE, NULL, NULL) );
1640 
1641  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/enableposslack", "should positive slack influence the probing objective "
1642  "function?", &(sepadata->enableposslack), FALSE, FALSE, NULL, NULL) );
1643 
1644  SCIP_CALL( SCIPaddIntParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/posslackexp", "exponent of positive slack usage",
1645  &(sepadata->posslackexp), FALSE, 1, 1, INT_MAX, NULL, NULL) );
1646 
1647  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/posslackexpgen", "automatically generated exponent?",
1648  &(sepadata->posslackexpgen), FALSE, FALSE, NULL, NULL) );
1649 
1650  SCIP_CALL( SCIPaddRealParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/posslackexpgenfactor", "factor for automatically generated exponent",
1651  &(sepadata->posslackexpgenfactor), FALSE, 0.1, SCIPepsilon(GCGmasterGetOrigprob(scip)),
1652  SCIPinfinity(GCGmasterGetOrigprob(scip)), NULL, NULL) );
1653 
1654  SCIP_CALL( SCIPaddRealParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/objconvex", "convex combination factor (= 0.0, use original objective; = 1.0, use face objective)",
1655  &(sepadata->objconvex), FALSE, 0.0, 0.0, 1.0, NULL, NULL) );
1656 
1657  SCIP_CALL( SCIPaddIntParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/paramsetting", "parameter returns which parameter setting is used for "
1658  "separation (default = 0, aggressive = 1, fast = 2", &(sepadata->separationsetting), FALSE, 0, 0, 2, NULL, NULL) );
1659 
1660  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/chgobj", "parameter returns if basis is searched with different objective",
1661  &(sepadata->chgobj), FALSE, TRUE, NULL, NULL) );
1662 
1663  SCIP_CALL( SCIPaddIntParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/maxrounds", "parameter returns maximum number of separation rounds in probing LP (-1 if unlimited)",
1664  &(sepadata->maxrounds), FALSE, -1, -1, INT_MAX , NULL, NULL) );
1665 
1666  SCIP_CALL( SCIPaddIntParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/maxroundsroot", "parameter returns maximum number of separation rounds in probing LP in root node (-1 if unlimited)",
1667  &(sepadata->maxroundsroot), FALSE, -1, -1, INT_MAX , NULL, NULL) );
1668 
1669  SCIP_CALL( SCIPaddIntParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/mincuts", "parameter returns number of minimum cuts needed to "
1670  "return *result = SCIP_Separated", &(sepadata->mincuts), FALSE, 50, 1, INT_MAX, NULL, NULL) );
1671 
1672  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/chgobjallways", "parameter returns if obj is changed not only in the "
1673  "first round", &(sepadata->chgobjallways), FALSE, FALSE, NULL, NULL) );
1674 
1675  SCIP_CALL( SCIPaddBoolParam(GCGmasterGetOrigprob(scip), "sepa/" SEPA_NAME "/forcecuts", "parameter returns if cuts are forced to enter the LP ",
1676  &(sepadata->forcecuts), FALSE, FALSE, NULL, NULL) );
1677 
1678  return SCIP_OKAY;
1679 }
1680 
1681 
1682 /** returns the array of original cuts saved in the separator data */
1684  SCIP* scip /**< SCIP data structure */
1685  )
1686 {
1687  SCIP_SEPA* sepa;
1688  SCIP_SEPADATA* sepadata;
1689 
1690  assert(scip != NULL);
1691 
1692  sepa = SCIPfindSepa(scip, SEPA_NAME);
1693  assert(sepa != NULL);
1694 
1695  sepadata = SCIPsepaGetData(sepa);
1696  assert(sepadata != NULL);
1697 
1698  return sepadata->origcuts;
1699 }
1700 
1701 /** returns the number of original cuts saved in the separator data */
1703  SCIP* scip /**< SCIP data structure */
1704  )
1705 {
1706  SCIP_SEPA* sepa;
1707  SCIP_SEPADATA* sepadata;
1708 
1709  assert(scip != NULL);
1710 
1711  sepa = SCIPfindSepa(scip, SEPA_NAME);
1712  assert(sepa != NULL);
1713 
1714  sepadata = SCIPsepaGetData(sepa);
1715  assert(sepadata != NULL);
1716 
1717  return sepadata->norigcuts;
1718 }
1719 
1720 /** returns the array of master cuts saved in the separator data */
1722  SCIP* scip /**< SCIP data structure */
1723  )
1724 {
1725  SCIP_SEPA* sepa;
1726  SCIP_SEPADATA* sepadata;
1727 
1728  assert(scip != NULL);
1729 
1730  sepa = SCIPfindSepa(scip, SEPA_NAME);
1731  assert(sepa != NULL);
1732 
1733  sepadata = SCIPsepaGetData(sepa);
1734  assert(sepadata != NULL);
1735 
1736  return sepadata->mastercuts;
1737 }
1738 
1739 /** returns the number of master cuts saved in the separator data */
1741  SCIP* scip /**< SCIP data structure */
1742  )
1743 {
1744  SCIP_SEPA* sepa;
1745  SCIP_SEPADATA* sepadata;
1746 
1747  assert(scip != NULL);
1748 
1749  sepa = SCIPfindSepa(scip, SEPA_NAME);
1750  assert(sepa != NULL);
1751 
1752  sepadata = SCIPsepaGetData(sepa);
1753  assert(sepadata != NULL);
1754 
1755  return sepadata->nmastercuts;
1756 }
1757 
1758 /** transforms cut in pricing variables to cut in original variables and adds it to newcuts array */
1760  SCIP* scip,
1761  int ppnumber,
1762  SCIP_ROW* cut
1763  )
1764 {
1765  SCIP* origscip;
1766  SCIP_SEPA* sepa;
1767  SCIP_SEPADATA* sepadata;
1768 
1769  SCIP* pricingprob;
1770  SCIP_Real* vals;
1771  SCIP_COL** cols;
1772  SCIP_VAR** pricingvars;
1773  int nvars;
1774 
1775  int i;
1776  int j;
1777  int k;
1778 
1779  char name[SCIP_MAXSTRLEN];
1780 
1781  assert(GCGisMaster(scip));
1782 
1783  sepa = SCIPfindSepa(scip, SEPA_NAME);
1784 
1785  if( sepa == NULL )
1786  {
1787  SCIPerrorMessage("sepa basis not found\n");
1788  return SCIP_OKAY;
1789  }
1790 
1791  sepadata = SCIPsepaGetData(sepa);
1792  origscip = GCGmasterGetOrigprob(scip);
1793  pricingprob = GCGgetPricingprob(origscip, ppnumber);
1794 
1795  if( !sepadata->enableppcuts )
1796  {
1797  return SCIP_OKAY;
1798  }
1799 
1800  assert(!SCIProwIsLocal(cut));
1801 
1802  nvars = SCIProwGetNNonz(cut);
1803  cols = SCIProwGetCols(cut);
1804  vals = SCIProwGetVals(cut);
1805 
1806  if( nvars == 0 )
1807  {
1808  return SCIP_OKAY;
1809  }
1810 
1811  SCIP_CALL( SCIPallocBufferArray(scip, &pricingvars, nvars) );
1812 
1813  for( i = 0; i < nvars; ++i )
1814  {
1815  pricingvars[i] = SCIPcolGetVar(cols[i]);
1816  assert(pricingvars[i] != NULL);
1817  }
1818 
1819  for( k = 0; k < GCGgetNIdenticalBlocks(origscip, ppnumber); ++k )
1820  {
1821  SCIP_ROW* origcut;
1822 
1823  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "ppcut_%d_%d_%d", SCIPsepaGetNCalls(sepa), ppnumber, k);
1824 
1825  SCIP_CALL( SCIPcreateEmptyRowUnspec(origscip, &origcut, name,
1826  ( SCIPisInfinity(pricingprob, -SCIProwGetLhs(cut)) ?
1827  -SCIPinfinity(origscip) : SCIProwGetLhs(cut) - SCIProwGetConstant(cut)),
1828  ( SCIPisInfinity(pricingprob, SCIProwGetRhs(cut)) ?
1829  SCIPinfinity(origscip) : SCIProwGetRhs(cut) - SCIProwGetConstant(cut)),
1830  FALSE, FALSE, TRUE) );
1831 
1832  for( j = 0; j < nvars ; ++j )
1833  {
1834  SCIP_VAR* var;
1835 
1836  if( !GCGvarIsPricing(pricingvars[j]) )
1837  {
1838  nvars = 0;
1839  break;
1840  }
1841  assert(GCGvarIsPricing(pricingvars[j]));
1842 
1843  var = GCGpricingVarGetOrigvars(pricingvars[j])[k];
1844  assert(var != NULL);
1845 
1846  SCIP_CALL( SCIPaddVarToRow(origscip, origcut, var, vals[j]) );
1847  }
1848 
1849  if( nvars > 0 )
1850  {
1851  SCIP_CALL( ensureSizeNewCuts(scip, sepadata, sepadata->nnewcuts + 1) );
1852 
1853  sepadata->newcuts[sepadata->nnewcuts] = origcut;
1854  SCIP_CALL( SCIPcaptureRow(scip, sepadata->newcuts[sepadata->nnewcuts]) );
1855  ++(sepadata->nnewcuts);
1856 
1857  SCIPdebugMessage("cut added to orig cut pool\n");
1858  }
1859  SCIP_CALL( SCIPreleaseRow(origscip, &origcut) );
1860  }
1861 
1862  SCIPfreeBufferArray(scip, &pricingvars);
1863 
1864  return SCIP_OKAY;
1865 }
1866 
1867 /** add cuts which are due to the latest objective function of the pricing problems
1868  * (reduced cost non-negative) */
1870  SCIP* scip, /**< SCIP data structure */
1871  int ppnumber, /**< number of pricing problem */
1872  SCIP_Real dualsolconv, /**< dual solution corresponding to convexity constraint */
1873  SCIP_Bool newcuts /**< add cut to newcuts in sepadata? (otherwise add it just to the cutpool) */
1874 )
1875 {
1876  SCIP_SEPA* sepa;
1877 
1878  assert(GCGisMaster(scip));
1879 
1880  sepa = SCIPfindSepa(scip, SEPA_NAME);
1881 
1882  if( sepa == NULL )
1883  {
1884  SCIPerrorMessage("sepa basis not found\n");
1885  return SCIP_OKAY;
1886  }
1887 
1888  SCIP_CALL( addPPObjConss(GCGmasterGetOrigprob(scip), sepa, ppnumber, dualsolconv, newcuts, FALSE) );
1889 
1890  return SCIP_OKAY;
1891 }
#define SEPA_MAXBOUNDDIST
Definition: sepa_basis.c:61
static SCIP_DECL_SEPAEXIT(sepaExitBasis)
Definition: sepa_basis.c:893
SCIP_Bool enableppobjcg
Definition: sepa_basis.c:91
GCG interface methods.
SCIP_Bool GCGrelaxIsOrigSolFeasible(SCIP *scip)
Definition: relax_gcg.c:4202
SCIP_Bool forcecuts
Definition: sepa_basis.c:97
static SCIP_RETCODE chgProbingObjUsingRows(SCIP *origscip, SCIP_SEPADATA *sepadata, SCIP_SOL *origsol, SCIP_Real objfactor, SCIP_Real objdivisor)
Definition: sepa_basis.c:362
#define STARTMAXCUTS
Definition: sepa_basis.c:65
SCIP_ROW ** mastercuts
Definition: sepa_basis.c:75
#define sepaExecsolBasis
Definition: sepa_basis.c:1585
#define SEPA_NAME
Definition: sepa_basis.c:57
static SCIP_DECL_SEPAEXITSOL(sepaExitsolBasis)
Definition: sepa_basis.c:947
int currentnodenr
Definition: sepa_basis.c:84
SCIP_Bool enableposslack
Definition: sepa_basis.c:96
#define SEPA_PRIORITY
Definition: sepa_basis.c:59
#define SEPA_DESC
Definition: sepa_basis.c:58
SCIP_Bool GCGvarIsPricing(SCIP_VAR *var)
Definition: gcgvar.c:134
SCIP_ROW ** origcuts
Definition: sepa_basis.c:76
SCIP * GCGgetPricingprob(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:3939
SCIP_Bool enableppcuts
Definition: sepa_basis.c:89
int GCGsepaBasisGetNMastercuts(SCIP *scip)
Definition: sepa_basis.c:1740
SCIP_Bool enable
Definition: sepa_basis.c:86
int GCGgetNPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3979
SCIP_Bool chgobj
Definition: sepa_basis.c:93
SCIP_Bool GCGvarIsOriginal(SCIP_VAR *var)
Definition: gcgvar.c:166
GCG variable pricer.
SCIP_ROW ** GCGsepaBasisGetOrigcuts(SCIP *scip)
Definition: sepa_basis.c:1683
SCIP_RETCODE GCGrelaxUpdateCurrentSol(SCIP *scip)
Definition: relax_gcg.c:4796
int GCGsepaGetNCuts(SCIP *scip)
Definition: sepa_master.c:419
SCIP_Bool genobjconvex
Definition: sepa_basis.c:95
SCIP_Real posslackexpgenfactor
Definition: sepa_basis.c:100
SCIP_ROW ** GCGsepaGetOrigcuts(SCIP *scip)
Definition: sepa_master.c:400
static SCIP_RETCODE ensureSizeCuts(SCIP *scip, SCIP_SEPADATA *sepadata, int size)
Definition: sepa_basis.c:113
static SCIP_RETCODE addPPObjConss(SCIP *scip, SCIP_SEPA *sepa, int ppnumber, SCIP_Real dualsolconv, SCIP_Bool newcuts, SCIP_Bool probing)
Definition: sepa_basis.c:709
SCIP_Bool enableobjround
Definition: sepa_basis.c:88
SCIP_Bool GCGisMaster(SCIP *scip)
Definition: misc.c:675
#define SEPA_USESSUBSCIP
Definition: sepa_basis.c:62
master separator
int separationsetting
Definition: sepa_basis.c:92
basis separator
int GCGgetNIdenticalBlocks(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4053
SCIP_RETCODE SCIPincludeSepaBasis(SCIP *scip)
Definition: sepa_basis.c:1592
int GCGgetNRelPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3959
SCIP_ROW ** GCGsepaBasisGetMastercuts(SCIP *scip)
Definition: sepa_basis.c:1721
SCIP * GCGmasterGetOrigprob(SCIP *scip)
static SCIP_RETCODE initConvObj(SCIP *origscip, SCIP_SEPADATA *sepadata, SCIP_SOL *origsol, SCIP_Real convex, SCIP_Bool genericconv)
Definition: sepa_basis.c:1000
SCIP_SOL * GCGrelaxGetCurrentOrigSol(SCIP *scip)
Definition: relax_gcg.c:4183
static SCIP_RETCODE ensureSizeNewCuts(SCIP *scip, SCIP_SEPADATA *sepadata, int size)
Definition: sepa_basis.c:142
#define sepaCopyBasis
Definition: sepa_basis.c:808
SCIP_Bool chgobjallways
Definition: sepa_basis.c:94
GCG relaxator.
SCIP_Real GCGtransformOrigvalsToMastervals(SCIP *scip, SCIP_VAR **origvars, SCIP_Real *origvals, int norigvars, SCIP_VAR **mastervars, SCIP_Real *mastervals, int nmastervars)
Definition: misc.c:545
SCIP_VAR ** GCGpricingVarGetOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:1015
static SCIP_DECL_SEPAEXECLP(sepaExeclpBasis)
Definition: sepa_basis.c:1047
int GCGsepaBasisGetNOrigcuts(SCIP *scip)
Definition: sepa_basis.c:1702
SCIP_Bool posslackexpgen
Definition: sepa_basis.c:99
#define SEPA_FREQ
Definition: sepa_basis.c:60
SCIP_RETCODE GCGsepaBasisAddPricingCut(SCIP *scip, int ppnumber, SCIP_ROW *cut)
Definition: sepa_basis.c:1759
SCIP_Bool enableobj
Definition: sepa_basis.c:87
static SCIP_RETCODE initGenconv(SCIP *origscip, SCIP_SEPADATA *sepadata, SCIP_SOL *origsol, int nbasis, SCIP_Real *convex)
Definition: sepa_basis.c:969
SCIP_RETCODE GCGsepaAddMastercuts(SCIP *scip, SCIP_ROW *origcut, SCIP_ROW *mastercut)
Definition: sepa_master.c:457
SCIP_Bool enableppobjconss
Definition: sepa_basis.c:90
#define SEPA_DELAY
Definition: sepa_basis.c:63
public methods for GCG variables
SCIP_ROW * objrow
Definition: sepa_basis.c:85
SCIP_Bool GCGisPricingprobRelevant(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4000
static SCIP_DECL_SEPAINITSOL(sepaInitsolBasis)
Definition: sepa_basis.c:932
static SCIP_DECL_SEPAINIT(sepaInitBasis)
Definition: sepa_basis.c:826
SCIP_RETCODE GCGsetPricingObjs(SCIP *scip, SCIP_Real *dualsolconv)
SCIP_Real objconvex
Definition: sepa_basis.c:104
static SCIP_DECL_SEPAFREE(sepaFreeBasis)
Definition: sepa_basis.c:812
SCIP_RETCODE SCIPsepaBasisAddPPObjConss(SCIP *scip, int ppnumber, SCIP_Real dualsolconv, SCIP_Bool newcuts)
Definition: sepa_basis.c:1869
SCIP_ROW ** newcuts
Definition: sepa_basis.c:80