SCIP Doxygen Documentation
Loading...
Searching...
No Matches
sepa_convexproj.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file sepa_convexproj.c
26 * @ingroup DEFPLUGINS_SEPA
27 * @brief convexproj separator
28 * @author Felipe Serrano
29 *
30 * @todo should separator only be run when SCIPallColsInLP is true?
31 * @todo check if it makes sense to implement the copy callback
32 * @todo add SCIPisStopped(scip) to the condition of time consuming loops
33 */
34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35
37#include "scip/scip_expr.h"
38#include "scip/scip_nlpi.h"
39#include "scip/expr_varidx.h"
40#include "scip/expr_pow.h"
41#include "scip/expr_sum.h"
42#include "scip/pub_message.h"
43#include "scip/pub_misc.h"
44#include "scip/pub_nlp.h"
45#include "scip/pub_sepa.h"
46#include "scip/pub_var.h"
47#include "scip/scip_cut.h"
48#include "scip/scip_general.h"
49#include "scip/scip_lp.h"
50#include "scip/scip_mem.h"
51#include "scip/scip_message.h"
52#include "scip/scip_nlp.h"
53#include "scip/scip_numerics.h"
54#include "scip/scip_param.h"
55#include "scip/scip_prob.h"
56#include "scip/scip_sepa.h"
57#include "scip/scip_sol.h"
59#include "scip/scip_timing.h"
60#include "scip/scip_tree.h"
62
63
64#define SEPA_NAME "convexproj"
65#define SEPA_DESC "separate at projection of point onto convex region"
66#define SEPA_PRIORITY 0
67#define SEPA_FREQ -1
68#define SEPA_MAXBOUNDDIST 1.0
69#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
70#define SEPA_DELAY TRUE /**< should separation method be delayed, if other separators found cuts? */
71
72#define DEFAULT_MAXDEPTH -1 /**< maximum depth at which the separator is applied; -1 means no limit */
73#define DEFAULT_NLPITERLIM 250 /**< default NLP iteration limit */
74
75#define VIOLATIONFAC 100 /**< points regarded violated if max violation > VIOLATIONFAC*SCIPfeastol() */
76
77/*
78 * Data structures
79 */
80
81/** side that makes an nlrow convex */
83{
84 LHS = 0, /**< left hand side */
85 RHS = 1 /**< right hand side */
86};
88
89/** separator data
90 * it keeps the nlpi which represents the projection problem (see sepa_convexproj.h); it also keeps the convex nlrows
91 * and the side which actually makes them convex; when separating, we use the nlpi to compute the projection and then
92 * the convex nlrows to compute the actual gradient cuts */
93struct SCIP_SepaData
94{
95 SCIP_NLPI* nlpi; /**< nlpi used to create the nlpi problem */
96 SCIP_NLPIPROBLEM* nlpiprob; /**< nlpi problem representing the convex NLP relaxation */
97 SCIP_VAR** nlpivars; /**< array containing all variables of the nlpi */
98 SCIP_HASHMAP* var2nlpiidx; /**< mapping between variables and nlpi indices */
99 int nlpinvars; /**< total number of nlpi variables */
100
101 SCIP_Bool skipsepa; /**< should separator be skipped? */
102
103 SCIP_NLROW** nlrows; /**< convex nlrows */
104 CONVEXSIDE* convexsides; /**< which sides make the nlrows convex */
105 SCIP_Real* constraintviolation;/**< array storing the violation of constraint by current solution; 0.0 if it is not violated */
106 int nnlrows; /**< total number of nlrows */
107 int nlrowssize; /**< memory allocated for nlrows, convexsides and nlrowsidx */
108
109 /* parameter */
110 int nlpiterlimit; /**< iteration limit of NLP solver; 0 for no limit */
111 int maxdepth; /**< maximal depth at which the separator is applied */
112
113 int ncuts; /**< number of cuts generated */
114};
115
116
117/*
118 * Local methods
119 */
120
121/** clears the sepadata data */
122static
124 SCIP* scip, /**< SCIP data structure */
125 SCIP_SEPADATA* sepadata /**< separator data */
126 )
127{
128 assert(sepadata != NULL);
129
130 /* nlrowssize gets allocated first and then its decided whether to create the nlpiprob */
131 if( sepadata->nlrowssize > 0 )
132 {
133 SCIPfreeBlockMemoryArray(scip, &sepadata->constraintviolation, sepadata->nlrowssize);
134 SCIPfreeBlockMemoryArray(scip, &sepadata->convexsides, sepadata->nlrowssize);
135 SCIPfreeBlockMemoryArray(scip, &sepadata->nlrows, sepadata->nlrowssize);
136 sepadata->nlrowssize = 0;
137 }
138
139 if( sepadata->nlpiprob != NULL )
140 {
141 assert(sepadata->nlpi != NULL);
142
143 SCIPfreeBlockMemoryArray(scip, &sepadata->nlpivars, sepadata->nlpinvars);
144
145 SCIPhashmapFree(&sepadata->var2nlpiidx);
146 SCIP_CALL( SCIPfreeNlpiProblem(scip, sepadata->nlpi, &sepadata->nlpiprob) );
147
148 sepadata->nlpinvars = 0;
149 sepadata->nnlrows = 0;
150 }
151 assert(sepadata->nlpinvars == 0);
152 assert(sepadata->nnlrows == 0);
153 assert(sepadata->nlrowssize == 0);
154
155 sepadata->skipsepa = FALSE;
156
157 return SCIP_OKAY;
158}
159
160/** computes gradient cut (linearization) of nlrow at projection */
161static
163 SCIP* scip, /**< SCIP data structure */
164 SCIP_SEPA* sepa, /**< the cut separator itself */
165 SCIP_SOL* projection, /**< point where we compute gradient cut */
166 SCIP_NLROW* nlrow, /**< constraint for which we generate gradient cut */
167 CONVEXSIDE convexside, /**< which side makes the nlrow convex */
168 SCIP_Real activity, /**< activity of constraint at projection */
169 SCIP_EXPRITER* exprit, /**< expression iterator that can be used */
170 SCIP_ROW** row /**< storage for cut */
171 )
172{
173 char rowname[SCIP_MAXSTRLEN];
175 SCIP_Real gradx0; /* <grad f(x_0), x_0> */
176 SCIP_EXPR* expr;
177 int i;
178
179 assert(scip != NULL);
180 assert(sepa != NULL);
181 assert(nlrow != NULL);
182 assert(row != NULL);
183
185
186 assert(sepadata != NULL);
187
188 gradx0 = 0.0;
189
190 /* an nlrow has a linear part and expression; ideally one would just build the gradient but we
191 * do not know if the different parts share variables or not, so we can't just build the gradient; for this reason
192 * we create the row right away and compute the gradients of each part independently and add them to the row; the
193 * row takes care to add coeffs corresponding to the same variable when they appear in different parts of the nlrow
194 * NOTE: a gradient cut is globally valid whenever the constraint from which it is deduced is globally valid; since
195 * we build the convex relaxation using only globally valid constraints, the cuts are globally valid
196 */
197 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "proj_cut_%s_%u", SCIPnlrowGetName(nlrow), ++(sepadata->ncuts));
199 TRUE) );
200
202
203 /* linear part */
204 for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
205 {
206 gradx0 += SCIPgetSolVal(scip, projection, SCIPnlrowGetLinearVars(nlrow)[i]) * SCIPnlrowGetLinearCoefs(nlrow)[i];
208 }
209
210 expr = SCIPnlrowGetExpr(nlrow);
211 assert(expr != NULL);
212
213 SCIP_CALL( SCIPevalExprGradient(scip, expr, projection, 0L) );
214
216 for( ; !SCIPexpriterIsEnd(exprit); expr = SCIPexpriterGetNext(exprit) ) /*lint !e441*/ /*lint !e440*/
217 {
218 SCIP_Real grad;
219 SCIP_VAR* var;
220
221 if( !SCIPisExprVar(scip, expr) )
222 continue;
223
224 grad = SCIPexprGetDerivative(expr);
225 var = SCIPgetVarExprVar(expr);
226 assert(var != NULL);
227
228 gradx0 += grad * SCIPgetSolVal(scip, projection, var);
229 SCIP_CALL( SCIPaddVarToRow(scip, *row, var, grad) );
230 }
231
233
234 SCIPdebugPrintf("gradient: ");
236 SCIPdebugPrintf("gradient dot x_0: %g\n", gradx0);
237
238 /* gradient cut is f(x_0) - <grad f(x_0), x_0> + <grad f(x_0), x> <= rhs or >= lhs */
239 if( convexside == RHS )
240 {
242 SCIP_CALL( SCIPchgRowRhs(scip, *row, SCIPnlrowGetRhs(nlrow) - activity + gradx0) );
243 }
244 else
245 {
246 assert(convexside == LHS);
248 SCIP_CALL( SCIPchgRowLhs(scip, *row, SCIPnlrowGetLhs(nlrow) - activity + gradx0) );
249 }
250
251 SCIPdebugPrintf("gradient cut: ");
253
254 return SCIP_OKAY;
255}
256
257/** set quadratic part of objective function: \f$ \sum_i x_i^2 \f$
258 *
259 * the objective function is \f$ ||x - x_0||^2 \f$,
260 * where \f$ x_0 \f$ is the point to separate; the only part that changes is the term \f$ -2 \langle x_0, x \rangle \f$
261 * which is linear and is set every time we want to separate a point, see separateCuts()
262 */
263static
265 SCIP* scip, /**< SCIP data structure */
266 SCIP_SEPADATA* sepadata /**< the cut separator data */
267 )
268{
269 SCIP_EXPR* exprsum;
270 SCIP_EXPR** exprspow;
271 int i;
272
273 assert(scip != NULL);
274 assert(sepadata != NULL);
275 assert(sepadata->nlpi != NULL);
276 assert(sepadata->nlpiprob != NULL);
277 assert(sepadata->var2nlpiidx != NULL);
278 assert(sepadata->nlpinvars > 0);
279
280 SCIP_CALL( SCIPallocBufferArray(scip, &exprspow, sepadata->nlpinvars) );
281 for( i = 0; i < sepadata->nlpinvars; i++ )
282 {
283 SCIP_VAR* var;
284 SCIP_EXPR* varexpr;
285
286 var = sepadata->nlpivars[i];
287 assert(SCIPhashmapExists(sepadata->var2nlpiidx, (void*)var) );
288
289 SCIP_CALL( SCIPcreateExprVaridx(scip, &varexpr, SCIPhashmapGetImageInt(sepadata->var2nlpiidx, (void*)var), NULL, NULL) );
290 SCIP_CALL( SCIPcreateExprPow(scip, &exprspow[i], varexpr, 2.0, NULL, NULL) );
291 SCIP_CALL( SCIPreleaseExpr(scip, &varexpr) );
292 }
293
294 SCIP_CALL( SCIPcreateExprSum(scip, &exprsum, sepadata->nlpinvars, exprspow, NULL, 0.0, NULL, NULL) );
295
296 /* set quadratic part of objective function */
297 SCIP_CALL( SCIPsetNlpiObjective(scip, sepadata->nlpi, sepadata->nlpiprob, 0, NULL, NULL, exprsum, 0.0) );
298
299 /* free memory */
300 SCIP_CALL( SCIPreleaseExpr(scip, &exprsum) );
301 for( i = sepadata->nlpinvars-1; i >= 0; --i )
302 {
303 SCIP_CALL( SCIPreleaseExpr(scip, &exprspow[i]) );
304 }
305 SCIPfreeBufferArray(scip, &exprspow);
306
307 return SCIP_OKAY;
308}
309
310/** projects sol onto convex relaxation (stored in sepadata) and tries to generate gradient cuts at the projection
311 *
312 * it generates cuts only for the constraints that were violated by the LP solution and are now active or still
313 * violated (in case we don't solve to optimality).
314 * @todo: store a feasible solution if one is found to use as warmstart
315 */
316static
318 SCIP* scip, /**< SCIP data structure */
319 SCIP_SEPA* sepa, /**< the cut separator itself */
320 SCIP_SOL* sol, /**< solution that should be separated */
321 SCIP_RESULT* result /**< pointer to store the result of the separation call */
322 )
323{
325 SCIP_SOL* projection;
326 SCIP_Real* linvals;
327 SCIP_Real* nlpisol;
328 int nlpinvars;
329 int i;
330 int* lininds;
331 SCIP_Bool nlpunstable;
332 SCIP_EXPRITER* exprit;
333
334 nlpunstable = FALSE;
335
336 assert(sepa != NULL);
337
339
340 assert(result != NULL);
341 assert(sepadata != NULL);
342 assert(sepadata->nnlrows > 0);
343 assert(sepadata->nlpi != NULL);
344 assert(sepadata->nlpinvars > 0);
345 assert(sepadata->nlrows != NULL);
346 assert(sepadata->nlpiprob != NULL);
347 assert(sepadata->var2nlpiidx != NULL);
348 assert(sepadata->convexsides != NULL);
349 assert(sepadata->constraintviolation != NULL);
350
351 nlpinvars = sepadata->nlpinvars;
352 /* set linear part of objective function: \norm(x - x^0)^2 = \norm(x)^2 - \sum 2 * x_i * x^0_i + const
353 * we ignore the constant; x0 is `sol`
354 */
355 SCIP_CALL( SCIPallocBufferArray(scip, &linvals, nlpinvars) );
356 SCIP_CALL( SCIPallocBufferArray(scip, &lininds, nlpinvars) );
357 for( i = 0; i < nlpinvars; i++ )
358 {
359 SCIP_VAR* var;
360
361 var = sepadata->nlpivars[i];
362 assert(SCIPhashmapExists(sepadata->var2nlpiidx, (void*)var) );
363
364 lininds[i] = SCIPhashmapGetImageInt(sepadata->var2nlpiidx, (void*)var);
365 linvals[i] = - 2.0 * SCIPgetSolVal(scip, sol, var);
366
367 /* if coefficient is too large, don't separate */
368 if( SCIPisHugeValue(scip, REALABS(linvals[i])) )
369 {
370 SCIPdebugMsg(scip, "Don't separate points too close to infinity\n");
371 goto CLEANUP;
372 }
373 }
374
375 /* set linear part of objective function */
376 SCIP_CALL( SCIPchgNlpiLinearCoefs(scip, sepadata->nlpi, sepadata->nlpiprob, -1, nlpinvars, lininds, linvals) );
377
378 /* compute the projection onto the convex NLP relaxation */
379 SCIP_CALL( SCIPsolveNlpi(scip, sepadata->nlpi, sepadata->nlpiprob,
380 .iterlimit = sepadata->nlpiterlimit > 0 ? sepadata->nlpiterlimit : INT_MAX,
381 .feastol = SCIPfeastol(scip) / 10.0, /* use tighter tolerances for the NLP solver */
382 .opttol = MAX(SCIPfeastol(scip), SCIPdualfeastol(scip))) ); /*lint !e666*/
383 SCIPdebugMsg(scip, "NLP solstat = %d\n", SCIPgetNlpiSolstat(scip, sepadata->nlpi, sepadata->nlpiprob));
384
385 /* if solution is feasible, add cuts */
386 switch( SCIPgetNlpiSolstat(scip, sepadata->nlpi, sepadata->nlpiprob) )
387 {
390 /* @todo: if solution is optimal, we might as well add the cut <x - P(x_0), x_0 - P(x_0)> <= 0
391 * even though this cut is implied by all the gradient cuts of the rows active at the projection,
392 * we do not add them all (only the gradient cuts of constraints that violated the LP solution */
394 /* generate cuts for violated constraints (at sol) that are active or still violated at the projection, since
395 * a suboptimal solution or numerical issues could give a solution of the projection problem where constraints
396 * are not active; if the solution of the projection problem is in the interior of the region, we do nothing
397 */
398
399 /* get solution: build SCIP_SOL out of nlpi sol */
400 SCIP_CALL( SCIPgetNlpiSolution(scip, sepadata->nlpi, sepadata->nlpiprob, &nlpisol, NULL, NULL, NULL, NULL) );
401 assert(nlpisol != NULL);
402
403 SCIP_CALL( SCIPcreateSol(scip, &projection, NULL) );
404 for( i = 0; i < nlpinvars; i++ )
405 {
406 SCIP_VAR* var;
407
408 var = sepadata->nlpivars[i];
409 assert(SCIPhashmapExists(sepadata->var2nlpiidx, (void*)var) );
410
411 SCIP_CALL( SCIPsetSolVal(scip, projection, var,
412 nlpisol[SCIPhashmapGetImageInt(sepadata->var2nlpiidx, (void *)var)]) );
413 }
414 SCIPdebug( SCIPprintSol(scip, projection, NULL, TRUE) );
415
416 /** @todo this could just be created inside generateCut and the extra argument removed */
417 SCIP_CALL( SCIPcreateExpriter(scip, &exprit) );
418
419 /* check for active or violated constraints */
420 for( i = 0; i < sepadata->nnlrows; ++i )
421 {
422 SCIP_NLROW* nlrow;
423 CONVEXSIDE convexside;
424 SCIP_Real activity;
425
426 /* ignore constraints that are not violated by `sol` */
427 if( SCIPisFeasZero(scip, sepadata->constraintviolation[i]) )
428 continue;
429
430 convexside = sepadata->convexsides[i];
431 nlrow = sepadata->nlrows[i];
432 assert(nlrow != NULL);
433
434 /* check for currently active constraints at projected point */
435 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, projection, &activity) );
436
437 /* if row cannot be evaluated, then skip it */
438 if( activity == SCIP_INVALID ) /*lint !e777*/
439 continue;
440
441 SCIPdebugMsg(scip, "NlRow activity at nlpi solution: %g <= %g <= %g\n", SCIPnlrowGetLhs(nlrow), activity,
442 SCIPnlrowGetRhs(nlrow) );
443
444 /* if nlrow is active or violates the projection, build gradient cut at projection */
445 if( (convexside == RHS && SCIPisFeasGE(scip, activity, SCIPnlrowGetRhs(nlrow)))
446 || (convexside == LHS && SCIPisFeasLE(scip, activity, SCIPnlrowGetLhs(nlrow))) )
447 {
448 SCIP_ROW* row;
449
450 SCIP_CALL( generateCut(scip, sepa, projection, nlrow, convexside, activity, exprit,
451 &row) );
452
453 SCIPdebugMsg(scip, "active or violated nlrow: (sols vio: %e)\n", sepadata->constraintviolation[i]);
455 SCIPdebugMsg(scip, "cut with efficacy %g generated\n", SCIPgetCutEfficacy(scip, sol, row));
457
458 /* add cut if it is efficacious for the point we want to separate (sol) */
459 if( SCIPisCutEfficacious(scip, sol, row) )
460 {
461 SCIP_Bool infeasible;
462
463 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
464
465 if( infeasible )
466 {
468 SCIP_CALL( SCIPreleaseRow(scip, &row) );
469 break;
470 }
471 else
472 {
474 }
475 }
476
477 /* release the row */
478 SCIP_CALL( SCIPreleaseRow(scip, &row) );
479 }
480 }
481
482 SCIPfreeExpriter(&exprit);
483
484#ifdef SCIP_DEBUG
485 {
486 SCIP_Real distance;
487
488 /* compute distance between LP sol and its projection (only makes sense when it is optimal) */
489 distance = 0.0;
490 for( i = 0; i < SCIPgetNNLPVars(scip); ++i )
491 {
492 SCIP_VAR* var;
493
495 assert(var != NULL);
496
497 /* assert NLP solution is within the bounds of the variable (only make sense when sol is optimal) */
502
503 /*SCIPdebugMsg(scip, "NLP sol (LP sol): %s = %f (%g)\n", SCIPvarGetName(var),
504 * SCIPvarGetNLPSol(var), SCIPgetSolVal(scip, sol, var));
505 */
506
507 distance += SQR( SCIPvarGetNLPSol(var) - SCIPgetSolVal(scip, sol, var) );
508 }
509
510 SCIPdebugMsg(scip, "NLP objval: %e, distance: %e\n", SCIPgetNLPObjval(scip), distance);
511 }
512#endif
513
514 /* free solution */
515 SCIP_CALL( SCIPfreeSol(scip, &projection) );
516 break;
517
520 /* fallthrough;
521 * @todo: write what it means to be locinfeasible and why it can't be used to cutoff the node */
523 /* unknown... assume numerical issues */
524 nlpunstable = TRUE;
525 break;
526
528 default:
529 SCIPerrorMessage("Projection NLP is not unbounded by construction, should not get here!\n");
530 SCIPABORT();
531 nlpunstable = TRUE;
532 }
533
534 /* if nlp is detected to be unstable, don't try to separate again */
535 if( nlpunstable )
536 {
537 /* @todo: maybe change objective function to \sum [(x_i - x_i^*)/max(|x_i^*|, 1)]^2
538 * or some other scaling when unstable and try again.
539 * maybe free it here */
540 sepadata->skipsepa = TRUE;
541 }
542
543 /* reset objective */
544 BMSclearMemoryArray(linvals, nlpinvars);
545 SCIP_CALL( SCIPchgNlpiLinearCoefs(scip, sepadata->nlpi, sepadata->nlpiprob, -1, nlpinvars, lininds, linvals) );
546
547CLEANUP:
548 /* free memory */
549 SCIPfreeBufferArray(scip, &lininds);
550 SCIPfreeBufferArray(scip, &linvals);
551
552 return SCIP_OKAY;
553}
554
555/** computes the violation and maximum violation of the convex nlrows stored in sepadata wrt sol */
556static
558 SCIP* scip, /**< SCIP data structure */
559 SCIP_SEPADATA* sepadata, /**< separator data */
560 SCIP_SOL* sol, /**< solution that should be separated */
561 SCIP_Real* maxviolation /**< buffer to store maximum violation */
562 )
563{
564 SCIP_NLROW* nlrow;
565 int i;
566
567 assert(sepadata != NULL);
568 assert(sepadata->nnlrows > 0);
569 assert(sepadata->nlrows != NULL);
570 assert(sepadata->convexsides != NULL);
571 assert(sepadata->constraintviolation != NULL);
572
573 *maxviolation = 0.0;
574 for( i = 0; i < sepadata->nnlrows; i++ )
575 {
576 SCIP_Real activity;
577 SCIP_Real violation;
578
579 nlrow = sepadata->nlrows[i];
580
581 /* get activity of nlrow */
582 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
583
584 if( activity == SCIP_INVALID ) /*lint !e777*/
585 {
586 *maxviolation = SCIP_INVALID;
587 break;
588 }
589
590 /* violation = max{activity - rhs, 0.0} when convex and max{lhs - activity, 0.0} when concave */
591 if( sepadata->convexsides[i] == RHS )
592 {
595
596 violation = activity - SCIPnlrowGetRhs(nlrow);
597 sepadata->constraintviolation[i] = MAX(violation, 0.0);
598 }
599 if( sepadata->convexsides[i] == LHS )
600 {
603
604 violation = SCIPnlrowGetLhs(nlrow) - activity;
605 sepadata->constraintviolation[i] = MAX(violation, 0.0);
606 }
607
608 /* compute maximum */
609 if( *maxviolation < sepadata->constraintviolation[i] )
610 *maxviolation = sepadata->constraintviolation[i];
611 }
612
613 SCIPdebugMsg(scip, "Maximum violation %g\n", *maxviolation);
614
615 return SCIP_OKAY;
616}
617
618
619/** stores, from the constraints represented by nlrows, the nonlinear convex ones in sepadata */
620static
622 SCIP* scip, /**< SCIP data structure */
623 SCIP_SEPADATA* sepadata, /**< separator data */
624 SCIP_NLROW** nlrows, /**< nlrows from which to store convex ones */
625 int nnlrows /**< number of nlrows */
626 )
627{
628 int i;
629
630 assert(scip != NULL);
631 assert(sepadata != NULL);
632
633 SCIPdebugMsg(scip, "storing convex nlrows\n");
634
635 sepadata->nlrowssize = nnlrows;
636 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->nlrows), nnlrows) );
637 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->convexsides), nnlrows) );
638 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->constraintviolation), nnlrows) );
639
640 /* count the number of nonlinear convex rows and store them */
641 sepadata->nnlrows = 0;
642 for( i = 0; i < nnlrows; ++i )
643 {
644 SCIP_NLROW* nlrow;
645
646 nlrow = nlrows[i];
647 assert(nlrow != NULL);
648
649 /* linear case */
651 continue;
652
653 /* nonlinear case */
655 {
656 sepadata->convexsides[sepadata->nnlrows] = RHS;
657 sepadata->nlrows[sepadata->nnlrows] = nlrow;
658 ++(sepadata->nnlrows);
659 }
661 {
662 sepadata->convexsides[sepadata->nnlrows] = LHS;
663 sepadata->nlrows[sepadata->nnlrows] = nlrow;
664 ++(sepadata->nnlrows);
665 }
666 }
667
668 return SCIP_OKAY;
669}
670
671/*
672 * Callback methods of separator
673 */
674
675/** copy method for separator plugins (called when SCIP copies plugins) */
676static
677SCIP_DECL_SEPACOPY(sepaCopyConvexproj)
678{ /*lint --e{715}*/
679 assert(scip != NULL);
680 assert(sepa != NULL);
681
683
684 /* call inclusion method of separator */
686
687 return SCIP_OKAY;
688}
689
690/** destructor of separator to free user data (called when SCIP is exiting) */
691static
692SCIP_DECL_SEPAFREE(sepaFreeConvexproj)
693{ /*lint --e{715}*/
695
697
698 /* free separator data */
700 assert(sepadata != NULL);
701
703
705
706 SCIPsepaSetData(sepa, NULL);
707
708 return SCIP_OKAY;
709}
710
711/** solving process deinitialization method of separator (called before branch and bound process data is freed) */
712static
713SCIP_DECL_SEPAEXITSOL(sepaExitsolConvexproj)
714{ /*lint --e{715}*/
716
717 assert(sepa != NULL);
718
720
721 assert(sepadata != NULL);
722
724
725 return SCIP_OKAY;
726}
727
728
729/** LP solution separation method of separator */
730static
731SCIP_DECL_SEPAEXECLP(sepaExeclpConvexproj)
732{ /*lint --e{715}*/
733 SCIP_Real maxviolation;
734 SCIP_SOL* lpsol;
736
738
740 assert(sepadata != NULL);
741
742 /* do not run if there is no interesting convex relaxation (with at least one nonlinear convex constraint),
743 * or if we have found it to be numerically unstable
744 * @todo: should it be with at least 2 nonlinear convex constraints?
745 */
746 if( sepadata->skipsepa )
747 {
748 SCIPdebugMsg(scip, "not running because convex relaxation is uninteresting or numerically unstable\n");
749 return SCIP_OKAY;
750 }
751
752 /* the separator needs an NLP solver */
753 if( SCIPgetNNlpis(scip) == 0 )
754 return SCIP_OKAY;
755
756 /* only call separator up to a maximum depth */
757 if( sepadata->maxdepth >= 0 && depth > sepadata->maxdepth )
758 return SCIP_OKAY;
759
760 /* only call separator, if we are not close to terminating */
761 if( SCIPisStopped(scip) )
762 return SCIP_OKAY;
763
764 /* do not run if SCIP does not have constructed an NLP */
766 {
767 SCIPdebugMsg(scip, "NLP not constructed, skipping convex projection separator\n");
768 return SCIP_OKAY;
769 }
770
771 /* recompute convex NLP relaxation if the variable set changed and we are still at the root node */
772 if( sepadata->nlpiprob != NULL && SCIPgetNVars(scip) != sepadata->nlpinvars && SCIPgetDepth(scip) == 0 )
773 {
775 assert(sepadata->nlpiprob == NULL);
776 }
777
778 /* create or update convex NLP relaxation */
779 if( sepadata->nlpiprob == NULL )
780 {
781 /* store convex nonlinear constraints */
783
784 /* check that convex NLP relaxation is interesting (more than one nonlinear constraint) */
785 if( sepadata->nnlrows < 1 )
786 {
787 SCIPdebugMsg(scip, "convex relaxation uninteresting, don't run\n");
788 sepadata->skipsepa = TRUE;
789 return SCIP_OKAY;
790 }
791
792 sepadata->nlpinvars = SCIPgetNVars(scip);
793 sepadata->nlpi = SCIPgetNlpis(scip)[0];
794 assert(sepadata->nlpi != NULL);
795
796 SCIP_CALL( SCIPhashmapCreate(&sepadata->var2nlpiidx, SCIPblkmem(scip), sepadata->nlpinvars) );
797 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &sepadata->nlpivars, SCIPgetVars(scip), sepadata->nlpinvars) ); /*lint !e666*/
798
800 sepadata->var2nlpiidx, NULL, NULL, SCIPgetCutoffbound(scip), FALSE, TRUE) );
801
802 /* add rows of the LP
803 * we do not sue the depth argument of the callback because we want to build a globally valid initia lrelaxation
804 */
805 if( SCIPgetDepth(scip) == 0 )
806 {
807 SCIP_CALL( SCIPaddNlpiProblemRows(scip, sepadata->nlpi, sepadata->nlpiprob, sepadata->var2nlpiidx,
809 }
810
811 /* set quadratic part of objective function */
813 }
814 else
815 {
816 SCIP_CALL( SCIPupdateNlpiProblem(scip, sepadata->nlpi, sepadata->nlpiprob, sepadata->var2nlpiidx,
817 sepadata->nlpivars, sepadata->nlpinvars, SCIPgetCutoffbound(scip)) );
818 }
819
820 /* assert that the lp solution satisfies the cutoff bound; if this fails then we shouldn't have a cutoff bound in the
821 * nlpi, since then the projection could be in the interior of the actual convex relaxation */
824
825 /* get current sol: LP or pseudo solution if LP sol is not available */
827
828 /* do not run if current solution cannot be evaluated or the violation is small */
829 SCIP_CALL( computeMaxViolation(scip, sepadata, lpsol, &maxviolation) );
830 if( maxviolation == SCIP_INVALID ) /*lint !e777*/
831 {
832 SCIPdebugMsg(scip, "constraints cannot be evaluated at solution, do not separate\n");
833 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
834 return SCIP_OKAY;
835 }
836 if( maxviolation < VIOLATIONFAC * SCIPfeastol(scip) )
837 {
838 SCIPdebugMsg(scip, "solution doesn't violate constraints enough, do not separate\n");
839 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
840 return SCIP_OKAY;
841 }
842
843 /* run the separator */
845
846 /* separateCuts computes the projection and then gradient cuts on each constraint that was originally violated */
847 SCIP_CALL( separateCuts(scip, sepa, lpsol, result) );
848
849 /* free memory */
850 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
851
852 return SCIP_OKAY;
853}
854
855
856/*
857 * separator specific interface methods
858 */
859
860/** creates the convexproj separator and includes it in SCIP */
862 SCIP* scip /**< SCIP data structure */
863 )
864{
866 SCIP_SEPA* sepa;
867
868 /* create convexproj separator data */
870
871 /* this sets all data in sepadata to 0 */
873
874 /* include separator */
877 sepaExeclpConvexproj, NULL,
878 sepadata) );
879 assert(sepa != NULL);
880
881 /* set non fundamental callbacks via setter functions */
882 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyConvexproj) );
883 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeConvexproj) );
884 SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolConvexproj) );
885
886 /* add convexproj separator parameters */
887 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxdepth",
888 "maximal depth at which the separator is applied (-1: unlimited)",
889 &sepadata->maxdepth, FALSE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL) );
890
891 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/nlpiterlimit",
892 "iteration limit of NLP solver; 0 for no limit",
893 &sepadata->nlpiterlimit, TRUE, DEFAULT_NLPITERLIM, 0, INT_MAX, NULL, NULL) );
894
895 return SCIP_OKAY;
896}
#define DEFAULT_MAXDEPTH
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define SQR(x)
Definition def.h:208
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIPABORT()
Definition def.h:336
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
power and signed power expression handlers
sum expression handler
handler for variable index expressions
SCIP_RETCODE SCIPcreateExprVaridx(SCIP *scip, SCIP_EXPR **expr, int varidx, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_sum.c:1117
SCIP_RETCODE SCIPcreateExprPow(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_pow.c:3186
SCIP_Bool SCIPisStopped(SCIP *scip)
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition scip_prob.c:2201
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition misc.c:3095
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3304
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
#define SCIPdebugMsg
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:83
SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition scip_cut.c:94
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition scip_cut.c:117
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
SCIP_RETCODE SCIPevalExprGradient(SCIP *scip, SCIP_EXPR *expr, SCIP_SOL *sol, SCIP_Longint soltag)
Definition scip_expr.c:1692
SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
Definition expriter.c:969
SCIP_Real SCIPexprGetDerivative(SCIP_EXPR *expr)
Definition expr.c:3972
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition scip_expr.c:1443
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1457
SCIP_RETCODE SCIPcreateExpriter(SCIP *scip, SCIP_EXPRITER **iterator)
Definition scip_expr.c:2362
SCIP_EXPR * SCIPexpriterGetNext(SCIP_EXPRITER *iterator)
Definition expriter.c:858
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition expr_var.c:423
void SCIPfreeExpriter(SCIP_EXPRITER **iterator)
Definition scip_expr.c:2376
SCIP_RETCODE SCIPexpriterInit(SCIP_EXPRITER *iterator, SCIP_EXPR *expr, SCIP_EXPRITER_TYPE type, SCIP_Bool allowrevisit)
Definition expriter.c:501
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
Definition scip_lp.c:611
int SCIPgetNLPRows(SCIP *scip)
Definition scip_lp.c:632
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition scip_lp.c:174
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition scip_lp.c:253
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:105
SCIP_RETCODE SCIPaddNlpiProblemRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2idx, SCIP_ROW **rows, int nrows)
Definition scip_nlpi.c:787
SCIP_RETCODE SCIPupdateNlpiProblem(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2nlpiidx, SCIP_VAR **nlpivars, int nlpinvars, SCIP_Real cutoffbound)
Definition scip_nlpi.c:735
#define SCIPsolveNlpi(scip, nlpi,...)
Definition scip_nlpi.h:208
SCIP_RETCODE SCIPcreateNlpiProblemFromNlRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM **nlpiprob, const char *name, SCIP_NLROW **nlrows, int nnlrows, SCIP_HASHMAP *var2idx, SCIP_HASHMAP *nlrow2idx, SCIP_Real *nlscore, SCIP_Real cutoffbound, SCIP_Bool setobj, SCIP_Bool onlyconvex)
Definition scip_nlpi.c:449
int SCIPgetNNlpis(SCIP *scip)
Definition scip_nlpi.c:205
SCIP_NLPI ** SCIPgetNlpis(SCIP *scip)
Definition scip_nlpi.c:192
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition scip_nlp.c:110
SCIP_Real SCIPgetNLPObjval(SCIP *scip)
Definition scip_nlp.c:645
int SCIPgetNNLPVars(SCIP *scip)
Definition scip_nlp.c:201
int SCIPgetNNLPNlRows(SCIP *scip)
Definition scip_nlp.c:341
SCIP_VAR ** SCIPgetNLPVars(SCIP *scip)
Definition scip_nlp.c:179
SCIP_NLROW ** SCIPgetNLPNlRows(SCIP *scip)
Definition scip_nlp.c:319
const char * SCIPnlrowGetName(SCIP_NLROW *nlrow)
Definition nlp.c:1933
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition nlp.c:1914
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition nlp.c:1904
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition nlp.c:1924
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition nlp.c:1864
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition nlp.c:1874
SCIP_EXPR * SCIPnlrowGetExpr(SCIP_NLROW *nlrow)
Definition nlp.c:1894
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition nlp.c:1884
SCIP_RETCODE SCIPprintNlRow(SCIP *scip, SCIP_NLROW *nlrow, FILE *file)
Definition scip_nlp.c:1617
SCIP_RETCODE SCIPgetNlRowSolActivity(SCIP *scip, SCIP_NLROW *nlrow, SCIP_SOL *sol, SCIP_Real *activity)
Definition scip_nlp.c:1522
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1581
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition scip_lp.c:1529
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1604
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition scip_lp.c:1429
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition scip_lp.c:1553
SCIP_RETCODE SCIPincludeSepaBasic(SCIP *scip, SCIP_SEPA **sepa, const char *name, const char *desc, int priority, int freq, SCIP_Real maxbounddist, SCIP_Bool usessubscip, SCIP_Bool delay, SCIP_DECL_SEPAEXECLP((*sepaexeclp)), SCIP_DECL_SEPAEXECSOL((*sepaexecsol)), SCIP_SEPADATA *sepadata)
Definition scip_sepa.c:115
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:173
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition sepa.c:746
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:237
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition sepa.c:636
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition sepa.c:646
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:157
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition scip_sol.c:2351
SCIP_RETCODE SCIPcreateCurrentSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition scip_sol.c:747
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition scip_sol.c:1569
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPdualfeastol(SCIP *scip)
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition var.c:24723
SCIP_RETCODE SCIPincludeSepaConvexproj(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
SCIPfreeSol(scip, &heurdata->sol))
SCIPcreateSol(scip, &heurdata->sol, heur))
int maxdepth
int depth
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
SCIP_VAR * var
memory allocation routines
#define BMSclearMemory(ptr)
Definition memory.h:129
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPdebug(x)
Definition pub_message.h:93
#define SCIPdebugPrintf
Definition pub_message.h:99
public data structures and miscellaneous methods
public methods for NLP management
public methods for separators
public methods for problem variables
public methods for cuts and aggregation rows
public functions to work with algebraic expressions
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for NLPI solver interfaces
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for separator plugins
public methods for solutions
public methods for querying solving statistics
public methods for timing
public methods for the branch-and-bound tree
#define SEPA_PRIORITY
#define SEPA_DELAY
#define SEPA_DESC
#define SEPA_USESSUBSCIP
#define SEPA_MAXBOUNDDIST
#define SEPA_FREQ
#define SEPA_NAME
static SCIP_RETCODE sepadataClear(SCIP *scip, SCIP_SEPADATA *sepadata)
ConvexSide
@ LHS
@ RHS
static SCIP_RETCODE generateCut(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *projection, SCIP_NLROW *nlrow, CONVEXSIDE convexside, SCIP_Real activity, SCIP_EXPRITER *exprit, SCIP_ROW **row)
static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
enum ConvexSide CONVEXSIDE
#define DEFAULT_NLPITERLIM
static SCIP_RETCODE setQuadraticObj(SCIP *scip, SCIP_SEPADATA *sepadata)
#define VIOLATIONFAC
static SCIP_RETCODE computeMaxViolation(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_SOL *sol, SCIP_Real *maxviolation)
static SCIP_RETCODE storeNonlinearConvexNlrows(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_NLROW **nlrows, int nnlrows)
convexproj separator
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
struct SCIP_ExprIter SCIP_EXPRITER
Definition type_expr.h:722
@ SCIP_EXPRCURV_CONVEX
Definition type_expr.h:63
@ SCIP_EXPRCURV_LINEAR
Definition type_expr.h:65
@ SCIP_EXPRCURV_CONCAVE
Definition type_expr.h:64
@ SCIP_EXPRITER_DFS
Definition type_expr.h:718
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_LPSOLSTAT_OPTIMAL
Definition type_lp.h:44
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
struct SCIP_NlRow SCIP_NLROW
Definition type_nlp.h:41
struct SCIP_NlpiProblem SCIP_NLPIPROBLEM
Definition type_nlpi.h:53
struct SCIP_Nlpi SCIP_NLPI
Definition type_nlpi.h:51
@ SCIP_NLPSOLSTAT_UNBOUNDED
Definition type_nlpi.h:165
@ SCIP_NLPSOLSTAT_GLOBINFEASIBLE
Definition type_nlpi.h:164
@ SCIP_NLPSOLSTAT_LOCINFEASIBLE
Definition type_nlpi.h:163
@ SCIP_NLPSOLSTAT_FEASIBLE
Definition type_nlpi.h:162
@ SCIP_NLPSOLSTAT_LOCOPT
Definition type_nlpi.h:161
@ SCIP_NLPSOLSTAT_GLOBOPT
Definition type_nlpi.h:160
@ SCIP_NLPSOLSTAT_UNKNOWN
Definition type_nlpi.h:166
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_SEPARATED
Definition type_result.h:49
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_SepaData SCIP_SEPADATA
Definition type_sepa.h:52
#define SCIP_DECL_SEPAEXECLP(x)
Definition type_sepa.h:136
#define SCIP_DECL_SEPAFREE(x)
Definition type_sepa.h:69
#define SCIP_DECL_SEPAEXITSOL(x)
Definition type_sepa.h:107
struct SCIP_Sepa SCIP_SEPA
Definition type_sepa.h:51
#define SCIP_DECL_SEPACOPY(x)
Definition type_sepa.h:61
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Var SCIP_VAR
Definition type_var.h:166