cons_rowcuts.cpp
Go to the documentation of this file.
1 /* $Id: cons_rowcuts.cpp 1223 2017-04-20 10:41:34Z stefan $
2  *
3  * @file cons_rowcuts.c
4  * @ingroup CONSHDLRS
5  * @brief constraint handler for rowcuts constraints
6  * enables separation of convexification cuts during SCIP solution procedure
7  * @author Pietro Belotti
8  * @author Timo Berthold
9  * @license This file is licensed under the Eclipse Public License (EPL)
10  *
11  * This file is licensed under the Eclipse Public License (EPL)
12  */
13 
14 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
15 
16 #include <assert.h>
17 
18 #include "CouenneConfig.h"
19 #ifdef COIN_HAS_SCIP
20 
21 #include "cons_rowcuts.h"
22 #include "scip/cons_linear.h"
23 #include "scip/scip.h"
24 
25 #include "CouenneProblem.hpp"
26 
27 /* constraint handler properties */
28 #define CONSHDLR_NAME "rowcuts"
29 #define CONSHDLR_DESC "adds row cuts generated by Couenne in a Branch-and-Check fashion"
30 #define CONSHDLR_SEPAPRIORITY 0
31 #define CONSHDLR_ENFOPRIORITY -9999999
32 #define CONSHDLR_CHECKPRIORITY -9999999
33 #define CONSHDLR_SEPAFREQ -1
34 #define CONSHDLR_PROPFREQ -1
35 #define CONSHDLR_EAGERFREQ 100
37 #define CONSHDLR_MAXPREROUNDS 0
38 #define CONSHDLR_DELAYSEPA FALSE
39 #define CONSHDLR_DELAYPROP FALSE
40 #define CONSHDLR_DELAYPRESOL FALSE
41 #define CONSHDLR_NEEDSCONS FALSE
43 #define DEFAULT_MAXCUTTINGROUNDS 5
45 using namespace Couenne;
46 
47 /*
48  * Data structures
49  */
50 
52 struct SCIP_ConshdlrData
53 {
54  CouenneCutGenerator* cutgenerator; /* CouenneCutGenerator for linearization cuts */
55  OsiSolverInterface* milp; /* Couenne's MILP relaxation of Couenne's MINLP */
56  int maxcuttingrounds; /* how many rounds of cuts should be applied at most */
57  int ncuttingrounds; /* how many rounds of cuts have been applied already */
58 };
59 
60 
61 /*
62  * Local methods
63  */
64 
65 /* tries to find violated linearization cuts and adds them to SCIP */
66 static
67 SCIP_RETCODE checkRowcuts(
68  SCIP* scip,
69  SCIP_CONSHDLR* conshdlr,
70  SCIP_RESULT* result,
71  SCIP_Bool addcons
72  )
73 {
74  SCIP_CONSHDLRDATA* conshdlrdata;
75  CouenneProblem* problem;
76  OsiCuts cs;
77  SCIP_Real* sol;
78  SCIP_VAR** vars;
79  int nvars;
80  int i;
81 
82  assert(scip != NULL);
83  assert(conshdlr != NULL);
84  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
85  assert(result != NULL);
86 
87  /* get constraint handler data */
88  conshdlrdata = SCIPconshdlrGetData(conshdlr);
89  assert(conshdlrdata != NULL);
90 
91  /* get Couenne problem data */
92  problem = conshdlrdata->cutgenerator-> Problem ();
93 
94  /* get variable data, create sol */
95  nvars = SCIPgetNVars(scip);
96  vars = SCIPgetVars(scip);
97  sol = new SCIP_Real [nvars];
98  SCIP_CALL( SCIPgetSolVals(scip, NULL, nvars, vars, sol) );
99 
100  /* store solution into MILP data structure */
101  conshdlrdata -> milp -> setColSolution(sol);
102 
103  /* let Couenne generate linearization cuts */
104  problem -> domain () -> push (problem -> nVars (), sol,
105  problem -> domain () -> current () -> lb (),
106  problem -> domain () -> current () -> ub ());
107  conshdlrdata -> cutgenerator -> genRowCuts (*(conshdlrdata->milp), cs, 0, NULL);
108  problem -> domain () -> pop ();
109 
110  if( !addcons )
111  {
112  *result = (cs.sizeRowCuts() == 0) ? SCIP_FEASIBLE : SCIP_INFEASIBLE;
113  return SCIP_OKAY;
114  }
115 
116  for( i = 0; i < cs.sizeRowCuts(); i++ )
117  {
118  CoinPackedVector row;
119 
120  SCIP_CONS* cons;
121  SCIP_VAR** vars;
122 
123  char consname[SCIP_MAXSTRLEN];
124  SCIP_Real* vals;
125  int* idxs;
126 
127  SCIP_Real lhs;
128  SCIP_Real rhs;
129 
130  int nvals;
131  int j;
132 
133  /* get the row corresponding to the cut */
134  lhs = cs.rowCut(i).lb();
135  rhs = cs.rowCut(i).ub();
136  row = cs.rowCut(i).row();
137 
138  /* get row data */
139  nvals = row.getNumElements();
140  idxs = row.getIndices();
141  vals = row.getElements();
142 
143  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "rowcut", i);
144 
145  /* create an empty linear constraint */
146  SCIP_CALL_ABORT( SCIPcreateConsLinear(scip, &cons, consname, 0, NULL, NULL, lhs, rhs,
147  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
148 
149  /* get SCIP variable array */
150  vars = SCIPgetVars(scip);
151 
152  /* add variables to constraint */
153  for( j = 0; j < nvals; j++ )
154  {
155  SCIP_CALL( SCIPaddCoefLinear(scip, cons, vars[idxs[j]], vals[j]) );
156  }
157 
158  /* add constraint to SCIP */
159  SCIP_CALL( SCIPaddCons(scip, cons) );
160 #if 0
161  SCIP_CALL( SCIPprintCons(scip,cons,NULL) );
162 #endif
163  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
164 
165  *result = SCIP_CONSADDED;
166  }
167 
168  /* store cuts to MILP data structure */
169  if (cs.sizeRowCuts ()) {
170  conshdlrdata -> milp -> applyCuts (cs);
171  }
172 
173  return SCIP_OKAY;
174 }
175 
176 /*
177  * Callback methods of constraint handler
178  */
179 
181 #define conshdlrCopyRowcuts NULL
182 
184 static
185 SCIP_DECL_CONSFREE(consFreeRowcuts)
186 { /*lint --e{715}*/
187  SCIP_CONSHDLRDATA* conshdlrdata;
188 
189  assert(conshdlr != NULL);
190  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
191  assert(scip != NULL);
192 
193  /* get constraint handler data */
194  conshdlrdata = SCIPconshdlrGetData(conshdlr);
195  assert(conshdlrdata != NULL);
196 
197  /* free constraint handler data */
198  SCIPfreeMemory(scip, &conshdlrdata);
199  SCIPconshdlrSetData(conshdlr, NULL);
200 
201  return SCIP_OKAY;
202 }
203 
205 #define consInitRowcuts NULL
206 
208 #define consExitRowcuts NULL
209 
211 #define consInitpreRowcuts NULL
212 
214 #define consExitpreRowcuts NULL
215 
217 #define consInitsolRowcuts NULL
218 
220 #define consExitsolRowcuts NULL
221 
223 #define consDeleteRowcuts NULL
224 
226 #define consTransRowcuts NULL
227 
229 #define consInitlpRowcuts NULL
230 
232 #define consSepalpRowcuts NULL
233 
235 #define consSepasolRowcuts NULL
236 
238 static
239 SCIP_DECL_CONSENFOLP(consEnfolpRowcuts)
240 { /*lint --e{715}*/
241  SCIP_CONSHDLRDATA* conshdlrdata;
242 
243  assert(scip != NULL);
244  assert(conshdlr != NULL);
245  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
246  assert(nconss == 0 && conss == NULL); /* there should be no constraints */
247  assert(result != NULL);
248 
249 
250  conshdlrdata = SCIPconshdlrGetData(conshdlr);
251  assert(conshdlrdata != NULL);
252  if( conshdlrdata->ncuttingrounds < conshdlrdata->maxcuttingrounds )
253  {
254  SCIP_CALL( checkRowcuts(scip, conshdlr, result, TRUE) );
255  conshdlrdata->ncuttingrounds++;
256  }
257 
258  /* we want to accept all solutions, even if we added a constraint that cuts them off */
259  *result = SCIP_FEASIBLE;
260 
261  return SCIP_OKAY;
262 }
263 
265 static
266 SCIP_DECL_CONSENFOPS(consEnfopsRowcuts)
267 { /*lint --e{715}*/
268  SCIP_CONSHDLRDATA* conshdlrdata;
269 
270  assert(scip != NULL);
271  assert(conshdlr != NULL);
272  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
273  assert(nconss == 0 && conss == NULL); /* there should be no constraints */
274  assert(result != NULL);
275 
276 
277  conshdlrdata = SCIPconshdlrGetData(conshdlr);
278  assert(conshdlrdata != NULL);
279 
280  if( conshdlrdata->ncuttingrounds < conshdlrdata->maxcuttingrounds )
281  {
282  SCIP_CALL( checkRowcuts(scip, conshdlr, result, TRUE) );
283  conshdlrdata->ncuttingrounds++;
284  }
285 
286  /* we want to accept all solutions, even if we added a constraint that cuts them off */
287  *result = SCIP_FEASIBLE;
288 
289  return SCIP_OKAY;
290 }
291 
293 static
294 SCIP_DECL_CONSCHECK(consCheckRowcuts)
295 { /*lint --e{715}*/
296  SCIP_CONSHDLRDATA* conshdlrdata;
297 
298  assert(scip != NULL);
299  assert(conshdlr != NULL);
300  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
301  assert(nconss == 0 && conss == NULL); /* there should be no constraints */
302  assert(result != NULL);
303 
304 
305  conshdlrdata = SCIPconshdlrGetData(conshdlr);
306  assert(conshdlrdata != NULL);
307  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && conshdlrdata->ncuttingrounds < conshdlrdata->maxcuttingrounds )
308  {
309  SCIP_CALL( checkRowcuts(scip, conshdlr, result, TRUE) );
310  conshdlrdata->ncuttingrounds++;
311  }
312 
313  *result = SCIP_FEASIBLE;
314 
315  return SCIP_OKAY;
316 }
317 
319 #define consPropRowcuts NULL
320 
322 #define consPresolRowcuts NULL
323 
325 #define consRespropRowcuts NULL
326 
328 static
329 SCIP_DECL_CONSLOCK(consLockRowcuts)
330 { /*lint --e{715}*/
331  assert(cons == NULL);
332 
333  return SCIP_OKAY;
334 }
335 
337 #define consActiveRowcuts NULL
338 
340 #define consDeactiveRowcuts NULL
341 
343 #define consEnableRowcuts NULL
344 
346 #define consDisableRowcuts NULL
347 
349 #define consPrintRowcuts NULL
350 
352 #define consCopyRowcuts NULL
353 
355 #define consParseRowcuts NULL
356 
357 /*
358  * constraint specific interface methods
359  */
360 
362 SCIP_RETCODE SCIPincludeConshdlrRowcuts(
363  SCIP* scip,
364  CouenneCutGenerator* cutgenerator,
365  OsiSolverInterface* milp
366  )
367 {
368  SCIP_CONSHDLRDATA* conshdlrdata;
369 
370  /* create rowcuts constraint handler data */
371  SCIP_CALL( SCIPallocMemory(scip, &conshdlrdata) );
372  conshdlrdata->cutgenerator = cutgenerator;
373  conshdlrdata->milp = milp;
374  conshdlrdata->ncuttingrounds = 0;
375 
376 #if SCIP_VERSION >= 400
377  /* include constraint handler */
378  SCIP_CALL( SCIPincludeConshdlr(scip, CONSHDLR_NAME, CONSHDLR_DESC,
379  CONSHDLR_SEPAPRIORITY, CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY,
380  CONSHDLR_SEPAFREQ, CONSHDLR_PROPFREQ, CONSHDLR_EAGERFREQ, CONSHDLR_MAXPREROUNDS,
381  CONSHDLR_DELAYSEPA, CONSHDLR_DELAYPROP, CONSHDLR_NEEDSCONS,
382  SCIP_PROPTIMING_BEFORELP, SCIP_PRESOLTIMING_NONE,
383  conshdlrCopyRowcuts,
384  consFreeRowcuts, consInitRowcuts, consExitRowcuts,
385  consInitpreRowcuts, consExitpreRowcuts, consInitsolRowcuts, consExitsolRowcuts,
386  consDeleteRowcuts, consTransRowcuts, consInitlpRowcuts,
387  consSepalpRowcuts, consSepasolRowcuts, consEnfolpRowcuts, NULL, consEnfopsRowcuts, consCheckRowcuts,
388  consPropRowcuts, consPresolRowcuts, consRespropRowcuts, consLockRowcuts,
389  consActiveRowcuts, consDeactiveRowcuts,
390  consEnableRowcuts, consDisableRowcuts, NULL,
391  consPrintRowcuts, consCopyRowcuts, consParseRowcuts, NULL, NULL, NULL,
392  conshdlrdata) );
393 #elif SCIP_VERSION >= 320
394  /* include constraint handler */
395  SCIP_CALL( SCIPincludeConshdlr(scip, CONSHDLR_NAME, CONSHDLR_DESC,
396  CONSHDLR_SEPAPRIORITY, CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY,
397  CONSHDLR_SEPAFREQ, CONSHDLR_PROPFREQ, CONSHDLR_EAGERFREQ, CONSHDLR_MAXPREROUNDS,
398  CONSHDLR_DELAYSEPA, CONSHDLR_DELAYPROP, CONSHDLR_NEEDSCONS,
399  SCIP_PROPTIMING_BEFORELP, SCIP_PRESOLTIMING_NONE,
400  conshdlrCopyRowcuts,
401  consFreeRowcuts, consInitRowcuts, consExitRowcuts,
402  consInitpreRowcuts, consExitpreRowcuts, consInitsolRowcuts, consExitsolRowcuts,
403  consDeleteRowcuts, consTransRowcuts, consInitlpRowcuts,
404  consSepalpRowcuts, consSepasolRowcuts, consEnfolpRowcuts, consEnfopsRowcuts, consCheckRowcuts,
405  consPropRowcuts, consPresolRowcuts, consRespropRowcuts, consLockRowcuts,
406  consActiveRowcuts, consDeactiveRowcuts,
407  consEnableRowcuts, consDisableRowcuts, NULL,
408  consPrintRowcuts, consCopyRowcuts, consParseRowcuts, NULL, NULL, NULL,
409  conshdlrdata) );
410 #elif SCIP_VERSION >= 300
411  /* include constraint handler */
412  SCIP_CALL( SCIPincludeConshdlr(scip, CONSHDLR_NAME, CONSHDLR_DESC,
413  CONSHDLR_SEPAPRIORITY, CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY,
414  CONSHDLR_SEPAFREQ, CONSHDLR_PROPFREQ, CONSHDLR_EAGERFREQ, CONSHDLR_MAXPREROUNDS,
415  CONSHDLR_DELAYSEPA, CONSHDLR_DELAYPROP, CONSHDLR_DELAYPRESOL, CONSHDLR_NEEDSCONS,
416  SCIP_PROPTIMING_BEFORELP,
417  conshdlrCopyRowcuts,
418  consFreeRowcuts, consInitRowcuts, consExitRowcuts,
419  consInitpreRowcuts, consExitpreRowcuts, consInitsolRowcuts, consExitsolRowcuts,
420  consDeleteRowcuts, consTransRowcuts, consInitlpRowcuts,
421  consSepalpRowcuts, consSepasolRowcuts, consEnfolpRowcuts, consEnfopsRowcuts, consCheckRowcuts,
422  consPropRowcuts, consPresolRowcuts, consRespropRowcuts, consLockRowcuts,
423  consActiveRowcuts, consDeactiveRowcuts,
424  consEnableRowcuts, consDisableRowcuts, NULL,
425  consPrintRowcuts, consCopyRowcuts, consParseRowcuts, NULL, NULL,
426  conshdlrdata) );
427 #elif SCIP_VERSION >= 210
428  /* include constraint handler */
429  SCIP_CALL( SCIPincludeConshdlr(scip, CONSHDLR_NAME, CONSHDLR_DESC,
430  CONSHDLR_SEPAPRIORITY, CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY,
431  CONSHDLR_SEPAFREQ, CONSHDLR_PROPFREQ, CONSHDLR_EAGERFREQ, CONSHDLR_MAXPREROUNDS,
432  CONSHDLR_DELAYSEPA, CONSHDLR_DELAYPROP, CONSHDLR_DELAYPRESOL, CONSHDLR_NEEDSCONS,
433  SCIP_PROPTIMING_BEFORELP,
434  conshdlrCopyRowcuts,
435  consFreeRowcuts, consInitRowcuts, consExitRowcuts,
436  consInitpreRowcuts, consExitpreRowcuts, consInitsolRowcuts, consExitsolRowcuts,
437  consDeleteRowcuts, consTransRowcuts, consInitlpRowcuts,
438  consSepalpRowcuts, consSepasolRowcuts, consEnfolpRowcuts, consEnfopsRowcuts, consCheckRowcuts,
439  consPropRowcuts, consPresolRowcuts, consRespropRowcuts, consLockRowcuts,
440  consActiveRowcuts, consDeactiveRowcuts,
441  consEnableRowcuts, consDisableRowcuts, NULL,
442  consPrintRowcuts, consCopyRowcuts, consParseRowcuts,
443  conshdlrdata) );
444 #else
445  /* include constraint handler */
446  SCIP_CALL( SCIPincludeConshdlr(scip, CONSHDLR_NAME, CONSHDLR_DESC,
447  CONSHDLR_SEPAPRIORITY, CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY,
448  CONSHDLR_SEPAFREQ, CONSHDLR_PROPFREQ, CONSHDLR_EAGERFREQ, CONSHDLR_MAXPREROUNDS,
449  CONSHDLR_DELAYSEPA, CONSHDLR_DELAYPROP, CONSHDLR_DELAYPRESOL, CONSHDLR_NEEDSCONS,
450  conshdlrCopyRowcuts,
451  consFreeRowcuts, consInitRowcuts, consExitRowcuts,
452  consInitpreRowcuts, consExitpreRowcuts, consInitsolRowcuts, consExitsolRowcuts,
453  consDeleteRowcuts, consTransRowcuts, consInitlpRowcuts,
454  consSepalpRowcuts, consSepasolRowcuts, consEnfolpRowcuts, consEnfopsRowcuts, consCheckRowcuts,
455  consPropRowcuts, consPresolRowcuts, consRespropRowcuts, consLockRowcuts,
456  consActiveRowcuts, consDeactiveRowcuts,
457  consEnableRowcuts, consDisableRowcuts,
458  consPrintRowcuts, consCopyRowcuts, consParseRowcuts,
459  conshdlrdata) );
460 #endif
461 
462  /* add rowcuts constraint handler parameters */
463  SCIP_CALL( SCIPaddIntParam(scip,
464  "constraints/" CONSHDLR_NAME "/maxcuttingrounds",
465  "how many rounds of cuts should be applied at most?",
466  &conshdlrdata->maxcuttingrounds, FALSE, DEFAULT_MAXCUTTINGROUNDS, -1, INT_MAX, NULL, NULL) );
467 
468  return SCIP_OKAY;
469 }
470 
471 #endif
static char * j
Definition: OSdtoa.cpp:3622
constraint handler for rowcuts constraints enables separation of convexification cuts during SCIP sol...
static void
Definition: OSdtoa.cpp:1741