Scippy

SCIP

Solving Constraint Integer Programs

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-2025 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
36#include <assert.h>
37#include <string.h>
38
40#include "scip/scip_expr.h"
41#include "scip/scip_nlpi.h"
42#include "scip/expr_varidx.h"
43#include "scip/expr_pow.h"
44#include "scip/expr_sum.h"
45#include "scip/pub_message.h"
46#include "scip/pub_misc.h"
47#include "scip/pub_nlp.h"
48#include "scip/pub_sepa.h"
49#include "scip/pub_var.h"
50#include "scip/scip_cut.h"
51#include "scip/scip_general.h"
52#include "scip/scip_lp.h"
53#include "scip/scip_mem.h"
54#include "scip/scip_message.h"
55#include "scip/scip_nlp.h"
56#include "scip/scip_numerics.h"
57#include "scip/scip_param.h"
58#include "scip/scip_prob.h"
59#include "scip/scip_sepa.h"
60#include "scip/scip_sol.h"
62#include "scip/scip_timing.h"
63#include "scip/scip_tree.h"
65#include <string.h>
66
67
68#define SEPA_NAME "convexproj"
69#define SEPA_DESC "separate at projection of point onto convex region"
70#define SEPA_PRIORITY 0
71#define SEPA_FREQ -1
72#define SEPA_MAXBOUNDDIST 1.0
73#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
74#define SEPA_DELAY TRUE /**< should separation method be delayed, if other separators found cuts? */
75
76#define DEFAULT_MAXDEPTH -1 /**< maximum depth at which the separator is applied; -1 means no limit */
77#define DEFAULT_NLPITERLIM 250 /**< default NLP iteration limit */
78
79#define VIOLATIONFAC 100 /**< points regarded violated if max violation > VIOLATIONFAC*SCIPfeastol() */
80
81/*
82 * Data structures
83 */
84
85/** side that makes an nlrow convex */
87{
88 LHS = 0, /**< left hand side */
89 RHS = 1 /**< right hand side */
90};
92
93/** separator data
94 * it keeps the nlpi which represents the projection problem (see sepa_convexproj.h); it also keeps the convex nlrows
95 * and the side which actually makes them convex; when separating, we use the nlpi to compute the projection and then
96 * the convex nlrows to compute the actual gradient cuts */
97struct SCIP_SepaData
98{
99 SCIP_NLPI* nlpi; /**< nlpi used to create the nlpi problem */
100 SCIP_NLPIPROBLEM* nlpiprob; /**< nlpi problem representing the convex NLP relaxation */
101 SCIP_VAR** nlpivars; /**< array containing all variables of the nlpi */
102 SCIP_HASHMAP* var2nlpiidx; /**< mapping between variables and nlpi indices */
103 int nlpinvars; /**< total number of nlpi variables */
104
105 SCIP_Bool skipsepa; /**< should separator be skipped? */
106
107 SCIP_NLROW** nlrows; /**< convex nlrows */
108 CONVEXSIDE* convexsides; /**< which sides make the nlrows convex */
109 SCIP_Real* constraintviolation;/**< array storing the violation of constraint by current solution; 0.0 if it is not violated */
110 int nnlrows; /**< total number of nlrows */
111 int nlrowssize; /**< memory allocated for nlrows, convexsides and nlrowsidx */
112
113 /* parameter */
114 int nlpiterlimit; /**< iteration limit of NLP solver; 0 for no limit */
115 int maxdepth; /**< maximal depth at which the separator is applied */
116
117 int ncuts; /**< number of cuts generated */
118};
119
120
121/*
122 * Local methods
123 */
124
125/** clears the sepadata data */
126static
128 SCIP* scip, /**< SCIP data structure */
129 SCIP_SEPADATA* sepadata /**< separator data */
130 )
131{
132 assert(sepadata != NULL);
133
134 /* nlrowssize gets allocated first and then its decided whether to create the nlpiprob */
135 if( sepadata->nlrowssize > 0 )
136 {
137 SCIPfreeBlockMemoryArray(scip, &sepadata->constraintviolation, sepadata->nlrowssize);
138 SCIPfreeBlockMemoryArray(scip, &sepadata->convexsides, sepadata->nlrowssize);
139 SCIPfreeBlockMemoryArray(scip, &sepadata->nlrows, sepadata->nlrowssize);
140 sepadata->nlrowssize = 0;
141 }
142
143 if( sepadata->nlpiprob != NULL )
144 {
145 assert(sepadata->nlpi != NULL);
146
147 SCIPfreeBlockMemoryArray(scip, &sepadata->nlpivars, sepadata->nlpinvars);
148
149 SCIPhashmapFree(&sepadata->var2nlpiidx);
150 SCIP_CALL( SCIPfreeNlpiProblem(scip, sepadata->nlpi, &sepadata->nlpiprob) );
151
152 sepadata->nlpinvars = 0;
153 sepadata->nnlrows = 0;
154 }
155 assert(sepadata->nlpinvars == 0);
156 assert(sepadata->nnlrows == 0);
157 assert(sepadata->nlrowssize == 0);
158
159 sepadata->skipsepa = FALSE;
160
161 return SCIP_OKAY;
162}
163
164/** computes gradient cut (linearization) of nlrow at projection */
165static
167 SCIP* scip, /**< SCIP data structure */
168 SCIP_SEPA* sepa, /**< the cut separator itself */
169 SCIP_SOL* projection, /**< point where we compute gradient cut */
170 SCIP_NLROW* nlrow, /**< constraint for which we generate gradient cut */
171 CONVEXSIDE convexside, /**< which side makes the nlrow convex */
172 SCIP_Real activity, /**< activity of constraint at projection */
173 SCIP_EXPRITER* exprit, /**< expression iterator that can be used */
174 SCIP_ROW** row /**< storage for cut */
175 )
176{
177 char rowname[SCIP_MAXSTRLEN];
178 SCIP_SEPADATA* sepadata;
179 SCIP_Real gradx0; /* <grad f(x_0), x_0> */
180 SCIP_EXPR* expr;
181 int i;
182
183 assert(scip != NULL);
184 assert(sepa != NULL);
185 assert(nlrow != NULL);
186 assert(row != NULL);
187
188 sepadata = SCIPsepaGetData(sepa);
189
190 assert(sepadata != NULL);
191
192 gradx0 = 0.0;
193
194 /* an nlrow has a linear part and expression; ideally one would just build the gradient but we
195 * do not know if the different parts share variables or not, so we can't just build the gradient; for this reason
196 * we create the row right away and compute the gradients of each part independently and add them to the row; the
197 * row takes care to add coeffs corresponding to the same variable when they appear in different parts of the nlrow
198 * NOTE: a gradient cut is globally valid whenever the constraint from which it is deduced is globally valid; since
199 * we build the convex relaxation using only globally valid constraints, the cuts are globally valid
200 */
201 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "proj_cut_%s_%u", SCIPnlrowGetName(nlrow), ++(sepadata->ncuts));
203 TRUE) );
204
206
207 /* linear part */
208 for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
209 {
210 gradx0 += SCIPgetSolVal(scip, projection, SCIPnlrowGetLinearVars(nlrow)[i]) * SCIPnlrowGetLinearCoefs(nlrow)[i];
212 }
213
214 expr = SCIPnlrowGetExpr(nlrow);
215 assert(expr != NULL);
216
217 SCIP_CALL( SCIPevalExprGradient(scip, expr, projection, 0L) );
218
220 for( ; !SCIPexpriterIsEnd(exprit); expr = SCIPexpriterGetNext(exprit) ) /*lint !e441*/ /*lint !e440*/
221 {
222 SCIP_Real grad;
223 SCIP_VAR* var;
224
225 if( !SCIPisExprVar(scip, expr) )
226 continue;
227
228 grad = SCIPexprGetDerivative(expr);
229 var = SCIPgetVarExprVar(expr);
230 assert(var != NULL);
231
232 gradx0 += grad * SCIPgetSolVal(scip, projection, var);
233 SCIP_CALL( SCIPaddVarToRow(scip, *row, var, grad) );
234 }
235
237
238 SCIPdebugPrintf("gradient: ");
240 SCIPdebugPrintf("gradient dot x_0: %g\n", gradx0);
241
242 /* gradient cut is f(x_0) - <grad f(x_0), x_0> + <grad f(x_0), x> <= rhs or >= lhs */
243 if( convexside == RHS )
244 {
245 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
246 SCIP_CALL( SCIPchgRowRhs(scip, *row, SCIPnlrowGetRhs(nlrow) - activity + gradx0) );
247 }
248 else
249 {
250 assert(convexside == LHS);
251 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
252 SCIP_CALL( SCIPchgRowLhs(scip, *row, SCIPnlrowGetLhs(nlrow) - activity + gradx0) );
253 }
254
255 SCIPdebugPrintf("gradient cut: ");
257
258 return SCIP_OKAY;
259}
260
261/** set quadratic part of objective function: \f$ \sum_i x_i^2 \f$
262 *
263 * the objective function is \f$ ||x - x_0||^2 \f$,
264 * 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$
265 * which is linear and is set every time we want to separate a point, see separateCuts()
266 */
267static
269 SCIP* scip, /**< SCIP data structure */
270 SCIP_SEPADATA* sepadata /**< the cut separator data */
271 )
272{
273 SCIP_EXPR* exprsum;
274 SCIP_EXPR** exprspow;
275 int i;
276
277 assert(scip != NULL);
278 assert(sepadata != NULL);
279 assert(sepadata->nlpi != NULL);
280 assert(sepadata->nlpiprob != NULL);
281 assert(sepadata->var2nlpiidx != NULL);
282 assert(sepadata->nlpinvars > 0);
283
284 SCIP_CALL( SCIPallocBufferArray(scip, &exprspow, sepadata->nlpinvars) );
285 for( i = 0; i < sepadata->nlpinvars; i++ )
286 {
287 SCIP_VAR* var;
288 SCIP_EXPR* varexpr;
289
290 var = sepadata->nlpivars[i];
291 assert(SCIPhashmapExists(sepadata->var2nlpiidx, (void*)var) );
292
293 SCIP_CALL( SCIPcreateExprVaridx(scip, &varexpr, SCIPhashmapGetImageInt(sepadata->var2nlpiidx, (void*)var), NULL, NULL) );
294 SCIP_CALL( SCIPcreateExprPow(scip, &exprspow[i], varexpr, 2.0, NULL, NULL) );
295 SCIP_CALL( SCIPreleaseExpr(scip, &varexpr) );
296 }
297
298 SCIP_CALL( SCIPcreateExprSum(scip, &exprsum, sepadata->nlpinvars, exprspow, NULL, 0.0, NULL, NULL) );
299
300 /* set quadratic part of objective function */
301 SCIP_CALL( SCIPsetNlpiObjective(scip, sepadata->nlpi, sepadata->nlpiprob, 0, NULL, NULL, exprsum, 0.0) );
302
303 /* free memory */
304 SCIP_CALL( SCIPreleaseExpr(scip, &exprsum) );
305 for( i = sepadata->nlpinvars-1; i >= 0; --i )
306 {
307 SCIP_CALL( SCIPreleaseExpr(scip, &exprspow[i]) );
308 }
309 SCIPfreeBufferArray(scip, &exprspow);
310
311 return SCIP_OKAY;
312}
313
314/** projects sol onto convex relaxation (stored in sepadata) and tries to generate gradient cuts at the projection
315 *
316 * it generates cuts only for the constraints that were violated by the LP solution and are now active or still
317 * violated (in case we don't solve to optimality).
318 * @todo: store a feasible solution if one is found to use as warmstart
319 */
320static
322 SCIP* scip, /**< SCIP data structure */
323 SCIP_SEPA* sepa, /**< the cut separator itself */
324 SCIP_SOL* sol, /**< solution that should be separated */
325 SCIP_RESULT* result /**< pointer to store the result of the separation call */
326 )
327{
328 SCIP_SEPADATA* sepadata;
329 SCIP_SOL* projection;
330 SCIP_Real* linvals;
331 SCIP_Real* nlpisol;
332 int nlpinvars;
333 int i;
334 int* lininds;
335 SCIP_Bool nlpunstable;
336 SCIP_EXPRITER* exprit;
337
338 nlpunstable = FALSE;
339
340 assert(sepa != NULL);
341
342 sepadata = SCIPsepaGetData(sepa);
343
344 assert(result != NULL);
345 assert(sepadata != NULL);
346 assert(sepadata->nnlrows > 0);
347 assert(sepadata->nlpi != NULL);
348 assert(sepadata->nlpinvars > 0);
349 assert(sepadata->nlrows != NULL);
350 assert(sepadata->nlpiprob != NULL);
351 assert(sepadata->var2nlpiidx != NULL);
352 assert(sepadata->convexsides != NULL);
353 assert(sepadata->constraintviolation != NULL);
354
355 nlpinvars = sepadata->nlpinvars;
356 /* set linear part of objective function: \norm(x - x^0)^2 = \norm(x)^2 - \sum 2 * x_i * x^0_i + const
357 * we ignore the constant; x0 is `sol`
358 */
359 SCIP_CALL( SCIPallocBufferArray(scip, &linvals, nlpinvars) );
360 SCIP_CALL( SCIPallocBufferArray(scip, &lininds, nlpinvars) );
361 for( i = 0; i < nlpinvars; i++ )
362 {
363 SCIP_VAR* var;
364
365 var = sepadata->nlpivars[i];
366 assert(SCIPhashmapExists(sepadata->var2nlpiidx, (void*)var) );
367
368 lininds[i] = SCIPhashmapGetImageInt(sepadata->var2nlpiidx, (void*)var);
369 linvals[i] = - 2.0 * SCIPgetSolVal(scip, sol, var);
370
371 /* if coefficient is too large, don't separate */
372 if( SCIPisHugeValue(scip, REALABS(linvals[i])) )
373 {
374 SCIPdebugMsg(scip, "Don't separate points too close to infinity\n");
375 goto CLEANUP;
376 }
377 }
378
379 /* set linear part of objective function */
380 SCIP_CALL( SCIPchgNlpiLinearCoefs(scip, sepadata->nlpi, sepadata->nlpiprob, -1, nlpinvars, lininds, linvals) );
381
382 /* compute the projection onto the convex NLP relaxation */
383 SCIP_CALL( SCIPsolveNlpi(scip, sepadata->nlpi, sepadata->nlpiprob,
384 .iterlimit = sepadata->nlpiterlimit > 0 ? sepadata->nlpiterlimit : INT_MAX,
385 .feastol = SCIPfeastol(scip) / 10.0, /* use tighter tolerances for the NLP solver */
386 .opttol = MAX(SCIPfeastol(scip), SCIPdualfeastol(scip))) ); /*lint !e666*/
387 SCIPdebugMsg(scip, "NLP solstat = %d\n", SCIPgetNlpiSolstat(scip, sepadata->nlpi, sepadata->nlpiprob));
388
389 /* if solution is feasible, add cuts */
390 switch( SCIPgetNlpiSolstat(scip, sepadata->nlpi, sepadata->nlpiprob) )
391 {
394 /* @todo: if solution is optimal, we might as well add the cut <x - P(x_0), x_0 - P(x_0)> <= 0
395 * even though this cut is implied by all the gradient cuts of the rows active at the projection,
396 * we do not add them all (only the gradient cuts of constraints that violated the LP solution */
398 /* generate cuts for violated constraints (at sol) that are active or still violated at the projection, since
399 * a suboptimal solution or numerical issues could give a solution of the projection problem where constraints
400 * are not active; if the solution of the projection problem is in the interior of the region, we do nothing
401 */
402
403 /* get solution: build SCIP_SOL out of nlpi sol */
404 SCIP_CALL( SCIPgetNlpiSolution(scip, sepadata->nlpi, sepadata->nlpiprob, &nlpisol, NULL, NULL, NULL, NULL) );
405 assert(nlpisol != NULL);
406
407 SCIP_CALL( SCIPcreateSol(scip, &projection, NULL) );
408 for( i = 0; i < nlpinvars; i++ )
409 {
410 SCIP_VAR* var;
411
412 var = sepadata->nlpivars[i];
413 assert(SCIPhashmapExists(sepadata->var2nlpiidx, (void*)var) );
414
415 SCIP_CALL( SCIPsetSolVal(scip, projection, var,
416 nlpisol[SCIPhashmapGetImageInt(sepadata->var2nlpiidx, (void *)var)]) );
417 }
418 SCIPdebug( SCIPprintSol(scip, projection, NULL, TRUE) );
419
420 /** @todo this could just be created inside generateCut and the extra argument removed */
421 SCIP_CALL( SCIPcreateExpriter(scip, &exprit) );
422
423 /* check for active or violated constraints */
424 for( i = 0; i < sepadata->nnlrows; ++i )
425 {
426 SCIP_NLROW* nlrow;
427 CONVEXSIDE convexside;
428 SCIP_Real activity;
429
430 /* ignore constraints that are not violated by `sol` */
431 if( SCIPisFeasZero(scip, sepadata->constraintviolation[i]) )
432 continue;
433
434 convexside = sepadata->convexsides[i];
435 nlrow = sepadata->nlrows[i];
436 assert(nlrow != NULL);
437
438 /* check for currently active constraints at projected point */
439 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, projection, &activity) );
440
441 /* if row cannot be evaluated, then skip it */
442 if( activity == SCIP_INVALID ) /*lint !e777*/
443 continue;
444
445 SCIPdebugMsg(scip, "NlRow activity at nlpi solution: %g <= %g <= %g\n", SCIPnlrowGetLhs(nlrow), activity,
446 SCIPnlrowGetRhs(nlrow) );
447
448 /* if nlrow is active or violates the projection, build gradient cut at projection */
449 if( (convexside == RHS && SCIPisFeasGE(scip, activity, SCIPnlrowGetRhs(nlrow)))
450 || (convexside == LHS && SCIPisFeasLE(scip, activity, SCIPnlrowGetLhs(nlrow))) )
451 {
452 SCIP_ROW* row;
453
454 SCIP_CALL( generateCut(scip, sepa, projection, nlrow, convexside, activity, exprit,
455 &row) );
456
457 SCIPdebugMsg(scip, "active or violated nlrow: (sols vio: %e)\n", sepadata->constraintviolation[i]);
459 SCIPdebugMsg(scip, "cut with efficacy %g generated\n", SCIPgetCutEfficacy(scip, sol, row));
461
462 /* add cut if it is efficacious for the point we want to separate (sol) */
463 if( SCIPisCutEfficacious(scip, sol, row) )
464 {
465 SCIP_Bool infeasible;
466
467 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
468
469 if( infeasible )
470 {
471 *result = SCIP_CUTOFF;
472 SCIP_CALL( SCIPreleaseRow(scip, &row) );
473 break;
474 }
475 else
476 {
477 *result = SCIP_SEPARATED;
478 }
479 }
480
481 /* release the row */
482 SCIP_CALL( SCIPreleaseRow(scip, &row) );
483 }
484 }
485
486 SCIPfreeExpriter(&exprit);
487
488#ifdef SCIP_DEBUG
489 {
490 SCIP_Real distance;
491
492 /* compute distance between LP sol and its projection (only makes sense when it is optimal) */
493 distance = 0.0;
494 for( i = 0; i < SCIPgetNNLPVars(scip); ++i )
495 {
496 SCIP_VAR* var;
497
498 var = SCIPgetNLPVars(scip)[i];
499 assert(var != NULL);
500
501 /* assert NLP solution is within the bounds of the variable (only make sense when sol is optimal) */
506
507 /*SCIPdebugMsg(scip, "NLP sol (LP sol): %s = %f (%g)\n", SCIPvarGetName(var),
508 * SCIPvarGetNLPSol(var), SCIPgetSolVal(scip, sol, var));
509 */
510
511 distance += SQR( SCIPvarGetNLPSol(var) - SCIPgetSolVal(scip, sol, var) );
512 }
513
514 SCIPdebugMsg(scip, "NLP objval: %e, distance: %e\n", SCIPgetNLPObjval(scip), distance);
515 }
516#endif
517
518 /* free solution */
519 SCIP_CALL( SCIPfreeSol(scip, &projection) );
520 break;
521
524 /* fallthrough;
525 * @todo: write what it means to be locinfeasible and why it can't be used to cutoff the node */
527 /* unknown... assume numerical issues */
528 nlpunstable = TRUE;
529 break;
530
532 default:
533 SCIPerrorMessage("Projection NLP is not unbounded by construction, should not get here!\n");
534 SCIPABORT();
535 nlpunstable = TRUE;
536 }
537
538 /* if nlp is detected to be unstable, don't try to separate again */
539 if( nlpunstable )
540 {
541 /* @todo: maybe change objective function to \sum [(x_i - x_i^*)/max(|x_i^*|, 1)]^2
542 * or some other scaling when unstable and try again.
543 * maybe free it here */
544 sepadata->skipsepa = TRUE;
545 }
546
547 /* reset objective */
548 BMSclearMemoryArray(linvals, nlpinvars);
549 SCIP_CALL( SCIPchgNlpiLinearCoefs(scip, sepadata->nlpi, sepadata->nlpiprob, -1, nlpinvars, lininds, linvals) );
550
551CLEANUP:
552 /* free memory */
553 SCIPfreeBufferArray(scip, &lininds);
554 SCIPfreeBufferArray(scip, &linvals);
555
556 return SCIP_OKAY;
557}
558
559/** computes the violation and maximum violation of the convex nlrows stored in sepadata wrt sol */
560static
562 SCIP* scip, /**< SCIP data structure */
563 SCIP_SEPADATA* sepadata, /**< separator data */
564 SCIP_SOL* sol, /**< solution that should be separated */
565 SCIP_Real* maxviolation /**< buffer to store maximum violation */
566 )
567{
568 SCIP_NLROW* nlrow;
569 int i;
570
571 assert(sepadata != NULL);
572 assert(sepadata->nnlrows > 0);
573 assert(sepadata->nlrows != NULL);
574 assert(sepadata->convexsides != NULL);
575 assert(sepadata->constraintviolation != NULL);
576
577 *maxviolation = 0.0;
578 for( i = 0; i < sepadata->nnlrows; i++ )
579 {
580 SCIP_Real activity;
581 SCIP_Real violation;
582
583 nlrow = sepadata->nlrows[i];
584
585 /* get activity of nlrow */
586 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
587
588 if( activity == SCIP_INVALID ) /*lint !e777*/
589 {
590 *maxviolation = SCIP_INVALID;
591 break;
592 }
593
594 /* violation = max{activity - rhs, 0.0} when convex and max{lhs - activity, 0.0} when concave */
595 if( sepadata->convexsides[i] == RHS )
596 {
598 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
599
600 violation = activity - SCIPnlrowGetRhs(nlrow);
601 sepadata->constraintviolation[i] = MAX(violation, 0.0);
602 }
603 if( sepadata->convexsides[i] == LHS )
604 {
606 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
607
608 violation = SCIPnlrowGetLhs(nlrow) - activity;
609 sepadata->constraintviolation[i] = MAX(violation, 0.0);
610 }
611
612 /* compute maximum */
613 if( *maxviolation < sepadata->constraintviolation[i] )
614 *maxviolation = sepadata->constraintviolation[i];
615 }
616
617 SCIPdebugMsg(scip, "Maximum violation %g\n", *maxviolation);
618
619 return SCIP_OKAY;
620}
621
622
623/** stores, from the constraints represented by nlrows, the nonlinear convex ones in sepadata */
624static
626 SCIP* scip, /**< SCIP data structure */
627 SCIP_SEPADATA* sepadata, /**< separator data */
628 SCIP_NLROW** nlrows, /**< nlrows from which to store convex ones */
629 int nnlrows /**< number of nlrows */
630 )
631{
632 int i;
633
634 assert(scip != NULL);
635 assert(sepadata != NULL);
636
637 SCIPdebugMsg(scip, "storing convex nlrows\n");
638
639 sepadata->nlrowssize = nnlrows;
640 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->nlrows), nnlrows) );
641 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->convexsides), nnlrows) );
642 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->constraintviolation), nnlrows) );
643
644 /* count the number of nonlinear convex rows and store them */
645 sepadata->nnlrows = 0;
646 for( i = 0; i < nnlrows; ++i )
647 {
648 SCIP_NLROW* nlrow;
649
650 nlrow = nlrows[i];
651 assert(nlrow != NULL);
652
653 /* linear case */
655 continue;
656
657 /* nonlinear case */
659 {
660 sepadata->convexsides[sepadata->nnlrows] = RHS;
661 sepadata->nlrows[sepadata->nnlrows] = nlrow;
662 ++(sepadata->nnlrows);
663 }
665 {
666 sepadata->convexsides[sepadata->nnlrows] = LHS;
667 sepadata->nlrows[sepadata->nnlrows] = nlrow;
668 ++(sepadata->nnlrows);
669 }
670 }
671
672 return SCIP_OKAY;
673}
674
675/*
676 * Callback methods of separator
677 */
678
679/** copy method for separator plugins (called when SCIP copies plugins) */
680static
681SCIP_DECL_SEPACOPY(sepaCopyConvexproj)
682{ /*lint --e{715}*/
683 assert(scip != NULL);
684 assert(sepa != NULL);
685 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
686
687 /* call inclusion method of separator */
689
690 return SCIP_OKAY;
691}
692
693/** destructor of separator to free user data (called when SCIP is exiting) */
694static
695SCIP_DECL_SEPAFREE(sepaFreeConvexproj)
696{ /*lint --e{715}*/
697 SCIP_SEPADATA* sepadata;
698
699 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
700
701 /* free separator data */
702 sepadata = SCIPsepaGetData(sepa);
703 assert(sepadata != NULL);
704
705 SCIP_CALL( sepadataClear(scip, sepadata) );
706
707 SCIPfreeBlockMemory(scip, &sepadata);
708
709 SCIPsepaSetData(sepa, NULL);
710
711 return SCIP_OKAY;
712}
713
714/** solving process deinitialization method of separator (called before branch and bound process data is freed) */
715static
716SCIP_DECL_SEPAEXITSOL(sepaExitsolConvexproj)
717{ /*lint --e{715}*/
718 SCIP_SEPADATA* sepadata;
719
720 assert(sepa != NULL);
721
722 sepadata = SCIPsepaGetData(sepa);
723
724 assert(sepadata != NULL);
725
726 SCIP_CALL( sepadataClear(scip, sepadata) );
727
728 return SCIP_OKAY;
729}
730
731
732/** LP solution separation method of separator */
733static
734SCIP_DECL_SEPAEXECLP(sepaExeclpConvexproj)
735{ /*lint --e{715}*/
736 SCIP_Real maxviolation;
737 SCIP_SOL* lpsol;
738 SCIP_SEPADATA* sepadata;
739
740 *result = SCIP_DIDNOTRUN;
741
742 sepadata = SCIPsepaGetData(sepa);
743 assert(sepadata != NULL);
744
745 /* do not run if there is no interesting convex relaxation (with at least one nonlinear convex constraint),
746 * or if we have found it to be numerically unstable
747 * @todo: should it be with at least 2 nonlinear convex constraints?
748 */
749 if( sepadata->skipsepa )
750 {
751 SCIPdebugMsg(scip, "not running because convex relaxation is uninteresting or numerically unstable\n");
752 return SCIP_OKAY;
753 }
754
755 /* the separator needs an NLP solver */
756 if( SCIPgetNNlpis(scip) == 0 )
757 return SCIP_OKAY;
758
759 /* only call separator up to a maximum depth */
760 if( sepadata->maxdepth >= 0 && depth > sepadata->maxdepth )
761 return SCIP_OKAY;
762
763 /* only call separator, if we are not close to terminating */
764 if( SCIPisStopped(scip) )
765 return SCIP_OKAY;
766
767 /* do not run if SCIP does not have constructed an NLP */
769 {
770 SCIPdebugMsg(scip, "NLP not constructed, skipping convex projection separator\n");
771 return SCIP_OKAY;
772 }
773
774 /* recompute convex NLP relaxation if the variable set changed and we are still at the root node */
775 if( sepadata->nlpiprob != NULL && SCIPgetNVars(scip) != sepadata->nlpinvars && SCIPgetDepth(scip) == 0 )
776 {
777 SCIP_CALL( sepadataClear(scip, sepadata) );
778 assert(sepadata->nlpiprob == NULL);
779 }
780
781 /* create or update convex NLP relaxation */
782 if( sepadata->nlpiprob == NULL )
783 {
784 /* store convex nonlinear constraints */
786
787 /* check that convex NLP relaxation is interesting (more than one nonlinear constraint) */
788 if( sepadata->nnlrows < 1 )
789 {
790 SCIPdebugMsg(scip, "convex relaxation uninteresting, don't run\n");
791 sepadata->skipsepa = TRUE;
792 return SCIP_OKAY;
793 }
794
795 sepadata->nlpinvars = SCIPgetNVars(scip);
796 sepadata->nlpi = SCIPgetNlpis(scip)[0];
797 assert(sepadata->nlpi != NULL);
798
799 SCIP_CALL( SCIPhashmapCreate(&sepadata->var2nlpiidx, SCIPblkmem(scip), sepadata->nlpinvars) );
800 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &sepadata->nlpivars, SCIPgetVars(scip), sepadata->nlpinvars) ); /*lint !e666*/
801
802 SCIP_CALL( SCIPcreateNlpiProblemFromNlRows(scip, sepadata->nlpi, &sepadata->nlpiprob, "convexproj-nlp", SCIPgetNLPNlRows(scip), SCIPgetNNLPNlRows(scip),
803 sepadata->var2nlpiidx, NULL, NULL, SCIPgetCutoffbound(scip), FALSE, TRUE) );
804
805 /* add rows of the LP
806 * we do not sue the depth argument of the callback because we want to build a globally valid initia lrelaxation
807 */
808 if( SCIPgetDepth(scip) == 0 )
809 {
810 SCIP_CALL( SCIPaddNlpiProblemRows(scip, sepadata->nlpi, sepadata->nlpiprob, sepadata->var2nlpiidx,
812 }
813
814 /* set quadratic part of objective function */
815 SCIP_CALL( setQuadraticObj(scip, sepadata) );
816 }
817 else
818 {
819 SCIP_CALL( SCIPupdateNlpiProblem(scip, sepadata->nlpi, sepadata->nlpiprob, sepadata->var2nlpiidx,
820 sepadata->nlpivars, sepadata->nlpinvars, SCIPgetCutoffbound(scip)) );
821 }
822
823 /* assert that the lp solution satisfies the cutoff bound; if this fails then we shouldn't have a cutoff bound in the
824 * nlpi, since then the projection could be in the interior of the actual convex relaxation */
827
828 /* get current sol: LP or pseudo solution if LP sol is not available */
830
831 /* do not run if current solution cannot be evaluated or the violation is small */
832 SCIP_CALL( computeMaxViolation(scip, sepadata, lpsol, &maxviolation) );
833 if( maxviolation == SCIP_INVALID ) /*lint !e777*/
834 {
835 SCIPdebugMsg(scip, "constraints cannot be evaluated at solution, do not separate\n");
836 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
837 return SCIP_OKAY;
838 }
839 if( maxviolation < VIOLATIONFAC * SCIPfeastol(scip) )
840 {
841 SCIPdebugMsg(scip, "solution doesn't violate constraints enough, do not separate\n");
842 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
843 return SCIP_OKAY;
844 }
845
846 /* run the separator */
847 *result = SCIP_DIDNOTFIND;
848
849 /* separateCuts computes the projection and then gradient cuts on each constraint that was originally violated */
850 SCIP_CALL( separateCuts(scip, sepa, lpsol, result) );
851
852 /* free memory */
853 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
854
855 return SCIP_OKAY;
856}
857
858
859/*
860 * separator specific interface methods
861 */
862
863/** creates the convexproj separator and includes it in SCIP */
865 SCIP* scip /**< SCIP data structure */
866 )
867{
868 SCIP_SEPADATA* sepadata;
869 SCIP_SEPA* sepa;
870
871 /* create convexproj separator data */
872 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
873
874 /* this sets all data in sepadata to 0 */
875 BMSclearMemory(sepadata);
876
877 /* include separator */
880 sepaExeclpConvexproj, NULL,
881 sepadata) );
882 assert(sepa != NULL);
883
884 /* set non fundamental callbacks via setter functions */
885 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyConvexproj) );
886 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeConvexproj) );
887 SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolConvexproj) );
888
889 /* add convexproj separator parameters */
890 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxdepth",
891 "maximal depth at which the separator is applied (-1: unlimited)",
892 &sepadata->maxdepth, FALSE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL) );
893
894 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/nlpiterlimit",
895 "iteration limit of NLP solver; 0 for no limit",
896 &sepadata->nlpiterlimit, TRUE, DEFAULT_NLPITERLIM, 0, INT_MAX, NULL, NULL) );
897
898 return SCIP_OKAY;
899}
#define NULL
Definition: def.h:262
#define SCIP_MAXSTRLEN
Definition: def.h:283
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:172
#define SQR(x)
Definition: def.h:213
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:234
#define SCIPABORT()
Definition: def.h:341
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:369
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)
Definition: expr_varidx.c:220
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:1114
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:3193
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:734
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3110
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3283
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3076
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3425
#define SCIPdebugMsg
Definition: scip_message.h:78
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:250
SCIP_RETCODE SCIPevalExprGradient(SCIP *scip, SCIP_EXPR *expr, SCIP_SOL *sol, SCIP_Longint soltag)
Definition: scip_expr.c:1673
SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
Definition: expriter.c:969
SCIP_Real SCIPexprGetDerivative(SCIP_EXPR *expr)
Definition: expr.c:3971
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition: scip_expr.c:1424
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1438
SCIP_RETCODE SCIPcreateExpriter(SCIP *scip, SCIP_EXPRITER **iterator)
Definition: scip_expr.c:2343
SCIP_EXPR * SCIPexpriterGetNext(SCIP_EXPRITER *iterator)
Definition: expriter.c:858
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
void SCIPfreeExpriter(SCIP_EXPRITER **iterator)
Definition: scip_expr.c:2357
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:606
int SCIPgetNLPRows(SCIP *scip)
Definition: scip_lp.c:627
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:169
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip_lp.c:248
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#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:1945
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:1926
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:1916
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition: nlp.c:1936
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:1876
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:1886
SCIP_EXPR * SCIPnlrowGetExpr(SCIP_NLROW *nlrow)
Definition: nlp.c:1906
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition: nlp.c:1896
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:1639
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1587
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1662
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1705
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2216
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1566
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:1457
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1611
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
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition: sepa.c:743
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
Definition: scip_sepa.c:173
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol)))
Definition: scip_sepa.c:237
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition: sepa.c:633
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition: sepa.c:643
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
Definition: scip_sepa.c:157
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:180
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:837
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip_sol.c:1627
SCIP_RETCODE SCIPcreateCurrentSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:335
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip_sol.c:1073
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
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:18162
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18152
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18483
SCIP_RETCODE SCIPincludeSepaConvexproj(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10878
memory allocation routines
#define BMSclearMemory(ptr)
Definition: memory.h:129
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
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
static SCIP_RETCODE sepadataClear(SCIP *scip, SCIP_SEPADATA *sepadata)
ConvexSide
@ LHS
@ RHS
#define SEPA_DESC
static SCIP_DECL_SEPACOPY(sepaCopyConvexproj)
#define SEPA_USESSUBSCIP
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)
#define DEFAULT_MAXDEPTH
static SCIP_DECL_SEPAEXECLP(sepaExeclpConvexproj)
static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
enum ConvexSide CONVEXSIDE
#define SEPA_MAXBOUNDDIST
#define SEPA_FREQ
#define DEFAULT_NLPITERLIM
static SCIP_RETCODE setQuadraticObj(SCIP *scip, SCIP_SEPADATA *sepadata)
#define SEPA_NAME
#define VIOLATIONFAC
static SCIP_DECL_SEPAEXITSOL(sepaExitsolConvexproj)
static SCIP_RETCODE computeMaxViolation(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_SOL *sol, SCIP_Real *maxviolation)
static SCIP_DECL_SEPAFREE(sepaFreeConvexproj)
static SCIP_RETCODE storeNonlinearConvexNlrows(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_NLROW **nlrows, int nnlrows)
convexproj separator
@ 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:716
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:43
@ 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_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
struct SCIP_SepaData SCIP_SEPADATA
Definition: type_sepa.h:52