00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <assert.h>
00017
00018 #include "CouenneConfig.h"
00019 #ifdef COIN_HAS_SCIP
00020
00021 #include "cons_rowcuts.h"
00022 #include "scip/cons_linear.h"
00023 #include "scip/scip.h"
00024
00025 #include "CouenneProblem.hpp"
00026
00027
00028 #define CONSHDLR_NAME "rowcuts"
00029 #define CONSHDLR_DESC "adds row cuts generated by Couenne in a Branch-and-Check fashion"
00030 #define CONSHDLR_SEPAPRIORITY 0
00031 #define CONSHDLR_ENFOPRIORITY -9999999
00032 #define CONSHDLR_CHECKPRIORITY -9999999
00033 #define CONSHDLR_SEPAFREQ -1
00034 #define CONSHDLR_PROPFREQ -1
00035 #define CONSHDLR_EAGERFREQ 100
00037 #define CONSHDLR_MAXPREROUNDS 0
00038 #define CONSHDLR_DELAYSEPA FALSE
00039 #define CONSHDLR_DELAYPROP FALSE
00040 #define CONSHDLR_DELAYPRESOL FALSE
00041 #define CONSHDLR_NEEDSCONS FALSE
00043 #define DEFAULT_MAXCUTTINGROUNDS 5
00045 using namespace Couenne;
00046
00047
00048
00049
00050
00052 struct SCIP_ConshdlrData
00053 {
00054 CouenneCutGenerator* cutgenerator;
00055 OsiSolverInterface* milp;
00056 int maxcuttingrounds;
00057 int ncuttingrounds;
00058 };
00059
00060
00061
00062
00063
00064
00065
00066 static
00067 SCIP_RETCODE checkRowcuts(
00068 SCIP* scip,
00069 SCIP_CONSHDLR* conshdlr,
00070 SCIP_RESULT* result,
00071 SCIP_Bool addcons
00072 )
00073 {
00074 SCIP_CONSHDLRDATA* conshdlrdata;
00075 CouenneProblem* problem;
00076 OsiCuts cs;
00077 SCIP_Real* sol;
00078 SCIP_VAR** vars;
00079 int nvars;
00080 int i;
00081
00082 assert(scip != NULL);
00083 assert(conshdlr != NULL);
00084 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
00085 assert(result != NULL);
00086
00087
00088 conshdlrdata = SCIPconshdlrGetData(conshdlr);
00089 assert(conshdlrdata != NULL);
00090
00091
00092 problem = conshdlrdata->cutgenerator-> Problem ();
00093
00094
00095 nvars = SCIPgetNVars(scip);
00096 vars = SCIPgetVars(scip);
00097 sol = new SCIP_Real [nvars];
00098 SCIP_CALL( SCIPgetSolVals(scip, NULL, nvars, vars, sol) );
00099
00100
00101 conshdlrdata -> milp -> setColSolution(sol);
00102
00103
00104 problem -> domain () -> push (problem -> nVars (), sol,
00105 problem -> domain () -> current () -> lb (),
00106 problem -> domain () -> current () -> ub ());
00107 conshdlrdata -> cutgenerator -> genRowCuts (*(conshdlrdata->milp), cs, 0, NULL);
00108 problem -> domain () -> pop ();
00109
00110 if( !addcons )
00111 {
00112 *result = (cs.sizeRowCuts() == 0) ? SCIP_FEASIBLE : SCIP_INFEASIBLE;
00113 return SCIP_OKAY;
00114 }
00115
00116 for( i = 0; i < cs.sizeRowCuts(); i++ )
00117 {
00118 CoinPackedVector row;
00119
00120 SCIP_CONS* cons;
00121 SCIP_VAR** vars;
00122
00123 char consname[SCIP_MAXSTRLEN];
00124 SCIP_Real* vals;
00125 int* idxs;
00126
00127 SCIP_Real lhs;
00128 SCIP_Real rhs;
00129
00130 int nvals;
00131 int j;
00132
00133
00134 lhs = cs.rowCut(i).lb();
00135 rhs = cs.rowCut(i).ub();
00136 row = cs.rowCut(i).row();
00137
00138
00139 nvals = row.getNumElements();
00140 idxs = row.getIndices();
00141 vals = row.getElements();
00142
00143 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "rowcut", i);
00144
00145
00146 SCIP_CALL_ABORT( SCIPcreateConsLinear(scip, &cons, consname, 0, NULL, NULL, lhs, rhs,
00147 TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
00148
00149
00150 vars = SCIPgetVars(scip);
00151
00152
00153 for( j = 0; j < nvals; j++ )
00154 {
00155 SCIP_CALL( SCIPaddCoefLinear(scip, cons, vars[idxs[j]], vals[j]) );
00156 }
00157
00158
00159 SCIP_CALL( SCIPaddCons(scip, cons) );
00160 #if 0
00161 SCIP_CALL( SCIPprintCons(scip,cons,NULL) );
00162 #endif
00163 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
00164
00165 *result = SCIP_CONSADDED;
00166 }
00167
00168
00169 if (cs.sizeRowCuts ()) {
00170 conshdlrdata -> milp -> applyCuts (cs);
00171 }
00172
00173 return SCIP_OKAY;
00174 }
00175
00176
00177
00178
00179
00181 #define conshdlrCopyRowcuts NULL
00182
00184 static
00185 SCIP_DECL_CONSFREE(consFreeRowcuts)
00186 {
00187 SCIP_CONSHDLRDATA* conshdlrdata;
00188
00189 assert(conshdlr != NULL);
00190 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
00191 assert(scip != NULL);
00192
00193
00194 conshdlrdata = SCIPconshdlrGetData(conshdlr);
00195 assert(conshdlrdata != NULL);
00196
00197
00198 SCIPfreeMemory(scip, &conshdlrdata);
00199 SCIPconshdlrSetData(conshdlr, NULL);
00200
00201 return SCIP_OKAY;
00202 }
00203
00205 #define consInitRowcuts NULL
00206
00208 #define consExitRowcuts NULL
00209
00211 #define consInitpreRowcuts NULL
00212
00214 #define consExitpreRowcuts NULL
00215
00217 #define consInitsolRowcuts NULL
00218
00220 #define consExitsolRowcuts NULL
00221
00223 #define consDeleteRowcuts NULL
00224
00226 #define consTransRowcuts NULL
00227
00229 #define consInitlpRowcuts NULL
00230
00232 #define consSepalpRowcuts NULL
00233
00235 #define consSepasolRowcuts NULL
00236
00238 static
00239 SCIP_DECL_CONSENFOLP(consEnfolpRowcuts)
00240 {
00241 SCIP_CONSHDLRDATA* conshdlrdata;
00242
00243 assert(scip != NULL);
00244 assert(conshdlr != NULL);
00245 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
00246 assert(nconss == 0 && conss == NULL);
00247 assert(result != NULL);
00248
00249
00250 conshdlrdata = SCIPconshdlrGetData(conshdlr);
00251 assert(conshdlrdata != NULL);
00252 if( conshdlrdata->ncuttingrounds < conshdlrdata->maxcuttingrounds )
00253 {
00254 SCIP_CALL( checkRowcuts(scip, conshdlr, result, TRUE) );
00255 conshdlrdata->ncuttingrounds++;
00256 }
00257
00258
00259 *result = SCIP_FEASIBLE;
00260
00261 return SCIP_OKAY;
00262 }
00263
00265 static
00266 SCIP_DECL_CONSENFOPS(consEnfopsRowcuts)
00267 {
00268 SCIP_CONSHDLRDATA* conshdlrdata;
00269
00270 assert(scip != NULL);
00271 assert(conshdlr != NULL);
00272 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
00273 assert(nconss == 0 && conss == NULL);
00274 assert(result != NULL);
00275
00276
00277 conshdlrdata = SCIPconshdlrGetData(conshdlr);
00278 assert(conshdlrdata != NULL);
00279
00280 if( conshdlrdata->ncuttingrounds < conshdlrdata->maxcuttingrounds )
00281 {
00282 SCIP_CALL( checkRowcuts(scip, conshdlr, result, TRUE) );
00283 conshdlrdata->ncuttingrounds++;
00284 }
00285
00286
00287 *result = SCIP_FEASIBLE;
00288
00289 return SCIP_OKAY;
00290 }
00291
00293 static
00294 SCIP_DECL_CONSCHECK(consCheckRowcuts)
00295 {
00296 SCIP_CONSHDLRDATA* conshdlrdata;
00297
00298 assert(scip != NULL);
00299 assert(conshdlr != NULL);
00300 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
00301 assert(nconss == 0 && conss == NULL);
00302 assert(result != NULL);
00303
00304
00305 conshdlrdata = SCIPconshdlrGetData(conshdlr);
00306 assert(conshdlrdata != NULL);
00307 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && conshdlrdata->ncuttingrounds < conshdlrdata->maxcuttingrounds )
00308 {
00309 SCIP_CALL( checkRowcuts(scip, conshdlr, result, TRUE) );
00310 conshdlrdata->ncuttingrounds++;
00311 }
00312
00313 *result = SCIP_FEASIBLE;
00314
00315 return SCIP_OKAY;
00316 }
00317
00319 #define consPropRowcuts NULL
00320
00322 #define consPresolRowcuts NULL
00323
00325 #define consRespropRowcuts NULL
00326
00328 static
00329 SCIP_DECL_CONSLOCK(consLockRowcuts)
00330 {
00331 assert(cons == NULL);
00332
00333 return SCIP_OKAY;
00334 }
00335
00337 #define consActiveRowcuts NULL
00338
00340 #define consDeactiveRowcuts NULL
00341
00343 #define consEnableRowcuts NULL
00344
00346 #define consDisableRowcuts NULL
00347
00349 #define consPrintRowcuts NULL
00350
00352 #define consCopyRowcuts NULL
00353
00355 #define consParseRowcuts NULL
00356
00357
00358
00359
00360
00362 SCIP_RETCODE SCIPincludeConshdlrRowcuts(
00363 SCIP* scip,
00364 CouenneCutGenerator* cutgenerator,
00365 OsiSolverInterface* milp
00366 )
00367 {
00368 SCIP_CONSHDLRDATA* conshdlrdata;
00369
00370
00371 SCIP_CALL( SCIPallocMemory(scip, &conshdlrdata) );
00372 conshdlrdata->cutgenerator = cutgenerator;
00373 conshdlrdata->milp = milp;
00374 conshdlrdata->ncuttingrounds = 0;
00375
00376 #if SCIP_VERSION >= 300
00377
00378 SCIP_CALL( SCIPincludeConshdlr(scip, CONSHDLR_NAME, CONSHDLR_DESC,
00379 CONSHDLR_SEPAPRIORITY, CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY,
00380 CONSHDLR_SEPAFREQ, CONSHDLR_PROPFREQ, CONSHDLR_EAGERFREQ, CONSHDLR_MAXPREROUNDS,
00381 CONSHDLR_DELAYSEPA, CONSHDLR_DELAYPROP, CONSHDLR_DELAYPRESOL, CONSHDLR_NEEDSCONS,
00382 SCIP_PROPTIMING_BEFORELP,
00383 conshdlrCopyRowcuts,
00384 consFreeRowcuts, consInitRowcuts, consExitRowcuts,
00385 consInitpreRowcuts, consExitpreRowcuts, consInitsolRowcuts, consExitsolRowcuts,
00386 consDeleteRowcuts, consTransRowcuts, consInitlpRowcuts,
00387 consSepalpRowcuts, consSepasolRowcuts, consEnfolpRowcuts, consEnfopsRowcuts, consCheckRowcuts,
00388 consPropRowcuts, consPresolRowcuts, consRespropRowcuts, consLockRowcuts,
00389 consActiveRowcuts, consDeactiveRowcuts,
00390 consEnableRowcuts, consDisableRowcuts, NULL,
00391 consPrintRowcuts, consCopyRowcuts, consParseRowcuts, NULL, NULL,
00392 conshdlrdata) );
00393 #elif SCIP_VERSION >= 210
00394
00395 SCIP_CALL( SCIPincludeConshdlr(scip, CONSHDLR_NAME, CONSHDLR_DESC,
00396 CONSHDLR_SEPAPRIORITY, CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY,
00397 CONSHDLR_SEPAFREQ, CONSHDLR_PROPFREQ, CONSHDLR_EAGERFREQ, CONSHDLR_MAXPREROUNDS,
00398 CONSHDLR_DELAYSEPA, CONSHDLR_DELAYPROP, CONSHDLR_DELAYPRESOL, CONSHDLR_NEEDSCONS,
00399 SCIP_PROPTIMING_BEFORELP,
00400 conshdlrCopyRowcuts,
00401 consFreeRowcuts, consInitRowcuts, consExitRowcuts,
00402 consInitpreRowcuts, consExitpreRowcuts, consInitsolRowcuts, consExitsolRowcuts,
00403 consDeleteRowcuts, consTransRowcuts, consInitlpRowcuts,
00404 consSepalpRowcuts, consSepasolRowcuts, consEnfolpRowcuts, consEnfopsRowcuts, consCheckRowcuts,
00405 consPropRowcuts, consPresolRowcuts, consRespropRowcuts, consLockRowcuts,
00406 consActiveRowcuts, consDeactiveRowcuts,
00407 consEnableRowcuts, consDisableRowcuts, NULL,
00408 consPrintRowcuts, consCopyRowcuts, consParseRowcuts,
00409 conshdlrdata) );
00410 #else
00411
00412 SCIP_CALL( SCIPincludeConshdlr(scip, CONSHDLR_NAME, CONSHDLR_DESC,
00413 CONSHDLR_SEPAPRIORITY, CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY,
00414 CONSHDLR_SEPAFREQ, CONSHDLR_PROPFREQ, CONSHDLR_EAGERFREQ, CONSHDLR_MAXPREROUNDS,
00415 CONSHDLR_DELAYSEPA, CONSHDLR_DELAYPROP, CONSHDLR_DELAYPRESOL, CONSHDLR_NEEDSCONS,
00416 conshdlrCopyRowcuts,
00417 consFreeRowcuts, consInitRowcuts, consExitRowcuts,
00418 consInitpreRowcuts, consExitpreRowcuts, consInitsolRowcuts, consExitsolRowcuts,
00419 consDeleteRowcuts, consTransRowcuts, consInitlpRowcuts,
00420 consSepalpRowcuts, consSepasolRowcuts, consEnfolpRowcuts, consEnfopsRowcuts, consCheckRowcuts,
00421 consPropRowcuts, consPresolRowcuts, consRespropRowcuts, consLockRowcuts,
00422 consActiveRowcuts, consDeactiveRowcuts,
00423 consEnableRowcuts, consDisableRowcuts,
00424 consPrintRowcuts, consCopyRowcuts, consParseRowcuts,
00425 conshdlrdata) );
00426 #endif
00427
00428
00429 SCIP_CALL( SCIPaddIntParam(scip,
00430 "constraints/"CONSHDLR_NAME"/maxcuttingrounds",
00431 "how many rounds of cuts should be applied at most?",
00432 &conshdlrdata->maxcuttingrounds, FALSE, DEFAULT_MAXCUTTINGROUNDS, -1, INT_MAX, NULL, NULL) );
00433
00434 return SCIP_OKAY;
00435 }
00436
00437 #endif