SCIP Doxygen Documentation
Loading...
Searching...
No Matches
heur_shiftandpropagate.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 heur_shiftandpropagate.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief shiftandpropagate primal heuristic
28 * @author Timo Berthold
29 * @author Gregor Hendel
30 */
31
32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33
36#include "scip/pub_event.h"
37#include "scip/pub_heur.h"
38#include "scip/pub_lp.h"
39#include "scip/pub_message.h"
40#include "scip/pub_misc.h"
41#include "scip/pub_misc_sort.h"
42#include "scip/pub_sol.h"
43#include "scip/pub_var.h"
45#include "scip/scip_event.h"
46#include "scip/scip_exact.h"
47#include "scip/scip_general.h"
48#include "scip/scip_heur.h"
49#include "scip/scip_lp.h"
50#include "scip/scip_mem.h"
51#include "scip/scip_message.h"
52#include "scip/scip_numerics.h"
53#include "scip/scip_param.h"
54#include "scip/scip_prob.h"
55#include "scip/scip_probing.h"
57#include "scip/scip_sol.h"
59#include "scip/scip_tree.h"
60#include "scip/scip_var.h"
61
62
63#define HEUR_NAME "shiftandpropagate"
64#define HEUR_DESC "Pre-root heuristic to expand an auxiliary branch-and-bound tree and apply propagation techniques"
65#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_PROP
66#define HEUR_PRIORITY 1000
67#define HEUR_FREQ 0
68#define HEUR_FREQOFS 0
69#define HEUR_MAXDEPTH -1
70#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
71#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
72
73#define DEFAULT_WEIGHT_INEQUALITY 1 /**< the heuristic row weight for inequalities */
74#define DEFAULT_WEIGHT_EQUALITY 3 /**< the heuristic row weight for equations */
75#define DEFAULT_RELAX TRUE /**< Should continuous variables be relaxed from the problem? */
76#define DEFAULT_PROBING TRUE /**< Is propagation of solution values enabled? */
77#define DEFAULT_ONLYWITHOUTSOL TRUE /**< Should heuristic only be executed if no primal solution was found, yet? */
78#define DEFAULT_NPROPROUNDS 10 /**< The default number of propagation rounds for each propagation used */
79#define DEFAULT_PROPBREAKER 65000 /**< fixed maximum number of propagations */
80#define DEFAULT_CUTOFFBREAKER 15 /**< fixed maximum number of allowed cutoffs before the heuristic stops */
81#define DEFAULT_RANDSEED 29 /**< the default random seed for random number generation */
82#define DEFAULT_SORTKEY 'v' /**< the default key for variable sorting */
83#define DEFAULT_SORTVARS TRUE /**< should variables be processed in sorted order? */
84#define DEFAULT_COLLECTSTATS TRUE /**< should variable statistics be collected during probing? */
85#define DEFAULT_STOPAFTERFEASIBLE TRUE /**< Should the heuristic stop calculating optimal shift values when no more rows are violated? */
86#define DEFAULT_PREFERBINARIES TRUE /**< Should binary variables be shifted first? */
87#define DEFAULT_SELECTBEST FALSE /**< should the heuristic choose the best candidate in every round? (set to FALSE for static order)? */
88#define DEFAULT_MAXCUTOFFQUOT 0.0 /**< maximum percentage of allowed cutoffs before stopping the heuristic */
89#define SORTKEYS "nrtuv"/**< options sorting key: (n)orms down, norms (u)p, (v)iolated rows decreasing,
90 * viola(t)ed rows increasing, or (r)andom */
91#define DEFAULT_NOZEROFIXING FALSE /**< should variables with a zero shifting value be delayed instead of being fixed? */
92#define DEFAULT_FIXBINLOCKS TRUE /**< should binary variables with no locks in one direction be fixed to that direction? */
93#define DEFAULT_BINLOCKSFIRST FALSE /**< should binary variables with no locks be preferred in the ordering? */
94#define DEFAULT_NORMALIZE TRUE /**< should coefficients and left/right hand sides be normalized by max row coeff? */
95#define DEFAULT_UPDATEWEIGHTS FALSE /**< should row weight be increased every time the row is violated? */
96#define DEFAULT_IMPLISCONTINUOUS TRUE /**< should implicit integer variables be treated as continuous variables? */
97#define DEFAULT_MINFIXINGRATELP 0.0 /**< minimum fixing rate over all variables (including continuous) to solve LP */
98
99#define EVENTHDLR_NAME "eventhdlrshiftandpropagate"
100#define EVENTHDLR_DESC "event handler to catch bound changes"
101#define EVENTTYPE_SHIFTANDPROPAGATE (SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_GBDCHANGED)
102
103
104/*
105 * Data structures
106 */
107
108/** primal heuristic data */
109struct SCIP_HeurData
110{
111 SCIP_COL** lpcols; /**< stores lp columns with discrete variables before cont. variables */
112 SCIP_RANDNUMGEN* randnumgen; /**< random number generation */
113 int* rowweights; /**< row weight storage */
114 SCIP_Bool relax; /**< should continuous variables be relaxed from the problem */
115 SCIP_Bool probing; /**< should probing be executed? */
116 SCIP_Bool onlywithoutsol; /**< Should heuristic only be executed if no primal solution was found, yet? */
117 int nlpcols; /**< the number of lp columns */
118 int nproprounds; /**< The default number of propagation rounds for each propagation used */
119 int cutoffbreaker; /**< the number of cutoffs before heuristic execution is stopped, or -1 for no
120 * limit */
121 SCIP_EVENTHDLR* eventhdlr; /**< event handler to register and process variable bound changes */
122
123 SCIP_Real maxcutoffquot; /**< maximum percentage of allowed cutoffs before stopping the heuristic */
124 SCIP_Real minfixingratelp; /**< minimum fixing rate over all variables (including continuous) to solve LP */
125 char sortkey; /**< the key by which variables are sorted */
126 SCIP_Bool sortvars; /**< should variables be processed in sorted order? */
127 SCIP_Bool collectstats; /**< should variable statistics be collected during probing? */
128 SCIP_Bool stopafterfeasible; /**< Should the heuristic stop calculating optimal shift values when no
129 * more rows are violated? */
130 SCIP_Bool preferbinaries; /**< Should binary variables be shifted first? */
131 SCIP_Bool nozerofixing; /**< should variables with a zero shifting value be delayed instead of being fixed? */
132 SCIP_Bool fixbinlocks; /**< should binary variables with no locks in one direction be fixed to that direction? */
133 SCIP_Bool binlocksfirst; /**< should binary variables with no locks be preferred in the ordering? */
134 SCIP_Bool normalize; /**< should coefficients be normalized by max row coeff for col norm? */
135 SCIP_Bool updateweights; /**< should row weight be increased every time the row is violated? */
136 SCIP_Bool impliscontinuous; /**< should implicit integer variables be treated as continuous variables? */
137 SCIP_Bool selectbest; /**< should the heuristic choose the best candidate in every round? (set to FALSE for static order)? */
139 SCIP_LPSOLSTAT lpsolstat; /**< the probing status after probing */
140 SCIP_Longint ntotaldomredsfound; /**< the total number of domain reductions during heuristic */
141 SCIP_Longint nlpiters; /**< number of LP iterations which the heuristic needed */
142 int nremainingviols; /**< the number of remaining violations */
143 int nprobings; /**< how many probings has the heuristic executed? */
144 int ncutoffs; /**< has the probing node been cutoff? */
145 )
146};
147
148/** status of a variable in heuristic transformation */
150{
151 TRANSFORMSTATUS_NONE = 0, /**< variable has not been transformed yet */
152 TRANSFORMSTATUS_LB = 1, /**< variable has been shifted by using lower bound (x-lb) */
153 TRANSFORMSTATUS_NEG = 2, /**< variable has been negated by using upper bound (ub-x) */
154 TRANSFORMSTATUS_FREE = 3 /**< variable does not have to be shifted */
155};
157
158/** information about the matrix after its heuristic transformation */
159struct ConstraintMatrix
160{
161 SCIP_Real* rowmatvals; /**< matrix coefficients row by row */
162 int* rowmatind; /**< the indices of the corresponding variables */
163 int* rowmatbegin; /**< the starting indices of each row */
164 SCIP_Real* colmatvals; /**< matrix coefficients column by column */
165 int* colmatind; /**< the indices of the corresponding rows for each coefficient */
166 int* colmatbegin; /**< the starting indices of each column */
167 int* violrows; /**< the number of violated rows for every variable */
168 TRANSFORMSTATUS* transformstatus; /**< information about transform status of every discrete variable */
169 SCIP_Real* lhs; /**< left hand side vector after normalization */
170 SCIP_Real* rhs; /**< right hand side vector after normalization */
171 SCIP_Real* colnorms; /**< vector norms of all discrete problem variables after normalization */
172 SCIP_Real* upperbounds; /**< the upper bounds of every non-continuous variable after transformation*/
173 SCIP_Real* transformshiftvals; /**< values by which original discrete variable bounds were shifted */
174 int nnonzs; /**< number of nonzero column entries */
175 int nrows; /**< number of rows of matrix */
176 int ncols; /**< the number of columns in matrix (including continuous vars) */
177 int ndiscvars; /**< number of discrete problem variables */
178 SCIP_Bool normalized; /**< indicates if the matrix data has already been normalized */
179};
180typedef struct ConstraintMatrix CONSTRAINTMATRIX;
181
182struct SCIP_EventhdlrData
183{
184 CONSTRAINTMATRIX* matrix; /**< the constraint matrix of the heuristic */
185 SCIP_HEURDATA* heurdata; /**< heuristic data */
186 int* violatedrows; /**< all currently violated LP rows */
187 int* violatedrowpos; /**< position in violatedrows array for every row */
188 int* nviolatedrows; /**< pointer to the total number of currently violated rows */
189};
190
191struct SCIP_EventData
192{
193 int colpos; /**< column position of the event-related variable */
194};
195/*
196 * Local methods
197 */
198
199/** returns whether a given variable is counted as discrete, depending on the parameter impliscontinuous */
200static
202 SCIP_VAR* var, /**< variable to check for discreteness */
203 SCIP_Bool impliscontinuous /**< should implicit integer variables be counted as continuous? */
204 )
205{
206 return SCIPvarIsIntegral(var) && ( !impliscontinuous || !SCIPvarIsImpliedIntegral(var) );
207}
208
209/** returns whether a given column is counted as discrete, depending on the parameter impliscontinuous */
210static
212 SCIP_COL* col, /**< column to check for discreteness */
213 SCIP_Bool impliscontinuous /**< should implicit integer variables be counted as continuous? */
214 )
215{
216 return SCIPcolIsIntegral(col) && (!impliscontinuous || !SCIPcolIsImpliedIntegral(col));
217}
218
219/** returns nonzero values and corresponding columns of given row */
220static
222 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
223 int rowindex, /**< index of the desired row */
224 SCIP_Real** valpointer, /**< pointer to store the nonzero coefficients of the row */
225 SCIP_Real* lhs, /**< lhs of the row */
226 SCIP_Real* rhs, /**< rhs of the row */
227 int** indexpointer, /**< pointer to store column indices which belong to the nonzeros */
228 int* nrowvals /**< pointer to store number of nonzeros in the desired row (or NULL) */
229 )
230{
231 int arrayposition;
232
233 assert(matrix != NULL);
234 assert(0 <= rowindex && rowindex < matrix->nrows);
235
236 arrayposition = matrix->rowmatbegin[rowindex];
237
238 if ( nrowvals != NULL )
239 {
240 if( rowindex == matrix->nrows - 1 )
241 *nrowvals = matrix->nnonzs - arrayposition;
242 else
243 *nrowvals = matrix->rowmatbegin[rowindex + 1] - arrayposition; /*lint !e679*/
244 }
245
246 if( valpointer != NULL )
247 *valpointer = &(matrix->rowmatvals[arrayposition]);
248 if( indexpointer != NULL )
249 *indexpointer = &(matrix->rowmatind[arrayposition]);
250
251 if( lhs != NULL )
252 *lhs = matrix->lhs[rowindex];
253
254 if( rhs != NULL )
255 *rhs = matrix->rhs[rowindex];
256}
257
258/** returns nonzero values and corresponding rows of given column */
259static
261 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
262 int colindex, /**< the index of the desired column */
263 SCIP_Real** valpointer, /**< pointer to store the nonzero coefficients of the column */
264 int** indexpointer, /**< pointer to store row indices which belong to the nonzeros */
265 int* ncolvals /**< pointer to store number of nonzeros in the desired column */
266 )
267{
268 int arrayposition;
269
270 assert(matrix != NULL);
271 assert(0 <= colindex && colindex < matrix->ncols);
272
273 arrayposition = matrix->colmatbegin[colindex];
274
275 if( ncolvals != NULL )
276 {
277 if( colindex == matrix->ncols - 1 )
278 *ncolvals = matrix->nnonzs - arrayposition;
279 else
280 *ncolvals = matrix->colmatbegin[colindex + 1] - arrayposition; /*lint !e679*/
281 }
282 if( valpointer != NULL )
283 *valpointer = &(matrix->colmatvals[arrayposition]);
284
285 if( indexpointer != NULL )
286 *indexpointer = &(matrix->colmatind[arrayposition]);
287}
288
289/** relaxes a continuous variable from all its rows, which has influence
290 * on both the left and right hand side of the constraint.
291 */
292static
294 SCIP* scip, /**< current scip instance */
295 SCIP_VAR* var, /**< variable which is relaxed from the problem */
296 CONSTRAINTMATRIX* matrix /**< constraint matrix object */
297 )
298{
299 SCIP_ROW** colrows;
300 SCIP_COL* varcol;
301 SCIP_Real* colvals;
302 SCIP_Real ub;
303 SCIP_Real lb;
304 int ncolvals;
305 int r;
306
307 assert(var != NULL);
309
310 varcol = SCIPvarGetCol(var);
311 assert(varcol != NULL);
312
313 /* get nonzero values and corresponding rows of variable */
314 colvals = SCIPcolGetVals(varcol);
315 ncolvals = SCIPcolGetNLPNonz(varcol);
316 colrows = SCIPcolGetRows(varcol);
317
320
321 assert(colvals != NULL || ncolvals == 0);
322
323 SCIPdebugMsg(scip, "Relaxing variable <%s> with lb <%g> and ub <%g>\n",
324 SCIPvarGetName(var), lb, ub);
325
326 assert(matrix->normalized);
327 /* relax variable from all its constraints */
328 for( r = 0; r < ncolvals; ++r )
329 {
330 SCIP_ROW* colrow;
331 SCIP_Real lhs;
332 SCIP_Real rhs;
333 SCIP_Real lhsvarbound;
334 SCIP_Real rhsvarbound;
335 SCIP_Real colval;
336 int rowindex;
337
338 colrow = colrows[r];
339 rowindex = SCIProwGetLPPos(colrow);
340
341 if( rowindex == -1 )
342 break;
343
344 assert(colvals != NULL); /* to please flexelint */
345 colval = colvals[r];
346
347 assert(0 <= rowindex && rowindex < matrix->nrows);
348 getRowData(matrix, rowindex, NULL, &lhs, &rhs, NULL, NULL);
349 /* variables bound influence the lhs and rhs of current row depending on the sign
350 * of the variables coefficient.
351 */
352 if( SCIPisFeasPositive(scip, colval) )
353 {
354 lhsvarbound = ub;
355 rhsvarbound = lb;
356 }
357 else if( SCIPisFeasNegative(scip, colval) )
358 {
359 lhsvarbound = lb;
360 rhsvarbound = ub;
361 }
362 else
363 continue;
364
365 /* relax variable from the current row */
366 if( !SCIPisInfinity(scip, -matrix->lhs[rowindex]) && !SCIPisInfinity(scip, ABS(lhsvarbound)) )
367 matrix->lhs[rowindex] -= colval * lhsvarbound;
368 else
369 matrix->lhs[rowindex] = -SCIPinfinity(scip);
370
371 if( !SCIPisInfinity(scip, matrix->rhs[rowindex]) && !SCIPisInfinity(scip, ABS(rhsvarbound)) )
372 matrix->rhs[rowindex] -= colval * rhsvarbound;
373 else
374 matrix->rhs[rowindex] = SCIPinfinity(scip);
375
376 SCIPdebugMsg(scip, "Row <%s> changed:Coefficient <%g>, LHS <%g> --> <%g>, RHS <%g> --> <%g>\n",
377 SCIProwGetName(colrow), colval, lhs, matrix->lhs[rowindex], rhs, matrix->rhs[rowindex]);
378 } /*lint !e438*/
379}
380
381/** transforms bounds of a given variable s.t. its lower bound equals zero afterwards.
382 * If the variable already has lower bound zero, the variable is not transformed,
383 * if not, the variable's bounds are changed w.r.t. the smaller absolute value of its
384 * bounds in order to avoid numerical inaccuracies. If both lower and upper bound
385 * of the variable differ from infinity, there are two cases. If |lb| <= |ub|,
386 * the bounds are shifted by -lb, else a new variable ub - x replaces x.
387 * The transformation is memorized by the transform status of the variable s.t.
388 * retransformation is possible.
389 */
390static
392 SCIP* scip, /**< current scip instance */
393 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
394 SCIP_HEURDATA* heurdata, /**< heuristic data */
395 int colpos /**< position of variable column in matrix */
396 )
397{
398 SCIP_COL* col;
399 SCIP_VAR* var;
400 SCIP_Real lb;
401 SCIP_Real ub;
402
403 SCIP_Bool negatecoeffs; /* do the row coefficients need to be negated? */
404 SCIP_Real deltashift; /* difference from previous transformation */
405
406 assert(matrix != NULL);
407 assert(0 <= colpos && colpos < heurdata->nlpcols);
408 col = heurdata->lpcols[colpos];
409 assert(col != NULL);
410 assert(SCIPcolIsInLP(col));
411
412 var = SCIPcolGetVar(col);
413 assert(var != NULL);
417
418 negatecoeffs = FALSE;
419 /* if both lower and upper bound are -infinity and infinity, resp., this is reflected by a free transform status.
420 * If the lower bound is already zero, this is reflected by identity transform status. In both cases, none of the
421 * corresponding rows needs to be modified.
422 */
423 if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
424 {
425 if( matrix->transformstatus[colpos] == TRANSFORMSTATUS_NEG )
426 negatecoeffs = TRUE;
427
428 deltashift = matrix->transformshiftvals[colpos];
429 matrix->transformshiftvals[colpos] = 0.0;
430 matrix->transformstatus[colpos] = TRANSFORMSTATUS_FREE;
431 }
432 else if( SCIPisLE(scip, REALABS(lb), REALABS(ub)) )
433 {
435
436 matrix->transformstatus[colpos] = TRANSFORMSTATUS_LB;
437 deltashift = lb;
438 matrix->transformshiftvals[colpos] = lb;
439 }
440 else
441 {
443 if( matrix->transformstatus[colpos] != TRANSFORMSTATUS_NEG )
444 negatecoeffs = TRUE;
445 matrix->transformstatus[colpos] = TRANSFORMSTATUS_NEG;
446 deltashift = ub;
447 matrix->transformshiftvals[colpos] = ub;
448 }
449
450 /* determine the upper bound for this variable in heuristic transformation (lower bound is implicit; always 0) */
451 if( !SCIPisInfinity(scip, ub) && !SCIPisInfinity(scip, lb) )
452 matrix->upperbounds[colpos] = MIN(ub - lb, SCIPinfinity(scip)); /*lint !e666*/
453 else
454 matrix->upperbounds[colpos] = SCIPinfinity(scip);
455
456 /* a real transformation is necessary. The variable x is either shifted by -lb or
457 * replaced by ub - x, depending on the smaller absolute of lb and ub.
458 */
459 if( !SCIPisFeasZero(scip, deltashift) || negatecoeffs )
460 {
461 SCIP_Real* vals;
462 int* rows;
463 int nrows;
464 int i;
465
466 assert(!SCIPisInfinity(scip, deltashift));
467
468 /* get nonzero values and corresponding rows of column */
469 getColumnData(matrix, colpos, &vals, &rows, &nrows);
470 assert(nrows == 0 ||(vals != NULL && rows != NULL));
471
472 /* go through rows and modify its lhs, rhs and the variable coefficient, if necessary */
473 for( i = 0; i < nrows; ++i )
474 {
475 int rowpos = rows[i];
476 assert(rowpos >= 0);
477 assert(rowpos < matrix->nrows);
478
479 if( !SCIPisInfinity(scip, -(matrix->lhs[rowpos])) )
480 matrix->lhs[rowpos] -= (vals[i]) * deltashift;
481
482 if( !SCIPisInfinity(scip, matrix->rhs[rowpos]) )
483 matrix->rhs[rowpos] -= (vals[i]) * deltashift;
484
485 if( negatecoeffs )
486 (vals[i]) = -(vals[i]);
487
488 assert(SCIPisFeasLE(scip, matrix->lhs[rowpos], matrix->rhs[rowpos]));
489 }
490 }
491 SCIPdebugMsg(scip, "Variable <%s> at colpos %d transformed. Status %d LB <%g> --> <%g>, UB <%g> --> <%g>\n",
492 SCIPvarGetName(var), colpos, matrix->transformstatus[colpos], lb, 0.0, ub, matrix->upperbounds[colpos]);
493}
494
495/** initializes copy of the original coefficient matrix and applies heuristic specific adjustments: normalizing row
496 * vectors, transforming variable domains such that lower bound is zero, and relaxing continuous variables.
497 */
498static
500 SCIP* scip, /**< current scip instance */
501 CONSTRAINTMATRIX* matrix, /**< constraint matrix object to be initialized */
502 SCIP_HEURDATA* heurdata, /**< heuristic data */
503 int* colposs, /**< position of columns according to variable type sorting */
504 int* nmaxrows, /**< maximum number of rows a variable appears in */
505 SCIP_Bool relax, /**< should continuous variables be relaxed from the problem? */
506 SCIP_Bool* initialized, /**< was the initialization successful? */
507 SCIP_Bool* infeasible /**< is the problem infeasible? */
508 )
509{
511 SCIP_COL** lpcols;
512 SCIP_Bool impliscontinuous;
513 int i;
514 int j;
515 int currentpointer;
516
517 int nrows;
518 int ncols;
519
520 assert(scip != NULL);
521 assert(matrix != NULL);
522 assert(initialized!= NULL);
523 assert(infeasible != NULL);
524 assert(nmaxrows != NULL);
525
526 SCIPdebugMsg(scip, "entering Matrix Initialization method of SHIFTANDPROPAGATE heuristic!\n");
527
528 /* get LP row data; column data is already initialized in heurdata */
530 lpcols = heurdata->lpcols;
531 ncols = heurdata->nlpcols;
532
533 matrix->nrows = nrows;
534 matrix->nnonzs = 0;
535 matrix->normalized = FALSE;
536 matrix->ndiscvars = 0;
537 *nmaxrows = 0;
538 impliscontinuous = heurdata->impliscontinuous;
539
540 /* count the number of nonzeros of the LP constraint matrix */
541 for( j = 0; j < ncols; ++j )
542 {
543 assert(lpcols[j] != NULL);
544 assert(SCIPcolGetLPPos(lpcols[j]) >= 0);
545
546 if( colIsDiscrete(lpcols[j], impliscontinuous) )
547 {
548 matrix->nnonzs += SCIPcolGetNLPNonz(lpcols[j]);
549 ++matrix->ndiscvars;
550 }
551 }
552
553 matrix->ncols = matrix->ndiscvars;
554
555 if( matrix->nnonzs == 0 )
556 {
557 SCIPdebugMsg(scip, "No matrix entries - Terminating initialization of matrix.\n");
558
559 *initialized = FALSE;
560
561 return SCIP_OKAY;
562 }
563
564 /* allocate memory for the members of heuristic matrix */
565 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->rowmatvals, matrix->nnonzs) );
566 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->rowmatind, matrix->nnonzs) );
567 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->colmatvals, matrix->nnonzs) );
568 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->colmatind, matrix->nnonzs) );
569 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->rowmatbegin, matrix->nrows) );
570 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->colmatbegin, matrix->ncols) );
571 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->lhs, matrix->nrows) );
572 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->rhs, matrix->nrows) );
573 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->colnorms, matrix->ncols) );
574 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->violrows, matrix->ncols) );
575 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->transformstatus, matrix->ndiscvars) );
576 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->upperbounds, matrix->ndiscvars) );
577 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->transformshiftvals, matrix->ndiscvars) );
578
579 /* set transform status of variables */
580 for( j = 0; j < matrix->ndiscvars; ++j )
581 matrix->transformstatus[j] = TRANSFORMSTATUS_NONE;
582
583 currentpointer = 0;
584 *infeasible = FALSE;
585
586 /* initialize the rows vector of the heuristic matrix together with its corresponding
587 * lhs, rhs.
588 */
589 for( i = 0; i < nrows; ++i )
590 {
591 SCIP_COL** cols;
592 SCIP_ROW* row;
593 SCIP_Real* rowvals;
594 SCIP_Real constant;
595 int nrowlpnonz;
596
597 /* get LP row information */
598 row = lprows[i];
599 rowvals = SCIProwGetVals(row);
600 nrowlpnonz = SCIProwGetNLPNonz(row);
601 cols = SCIProwGetCols(row);
602 constant = SCIProwGetConstant(row);
603
605 assert(!SCIPisInfinity(scip, constant));
606
607 matrix->rowmatbegin[i] = currentpointer;
608
609 /* modify the lhs and rhs w.r.t to the rows constant */
610 if( !SCIPisInfinity(scip, -SCIProwGetLhs(row)) )
611 matrix->lhs[i] = SCIProwGetLhs(row) - constant;
612 else
613 matrix->lhs[i] = -SCIPinfinity(scip);
614
615 if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) )
616 matrix->rhs[i] = SCIProwGetRhs(row) - constant;
617 else
618 matrix->rhs[i] = SCIPinfinity(scip);
619
620 /* in case of empty rows with a 0 < lhs <= 0.0 or 0.0 <= rhs < 0 we deduce the infeasibility of the problem */
621 if( nrowlpnonz == 0 && (SCIPisFeasPositive(scip, matrix->lhs[i]) || SCIPisFeasNegative(scip, matrix->rhs[i])) )
622 {
623 *infeasible = TRUE;
624 SCIPdebugMsg(scip, " Matrix initialization stopped because of row infeasibility! \n");
625 break;
626 }
627
628 /* row coefficients are normalized and copied to heuristic matrix */
629 for( j = 0; j < nrowlpnonz; ++j )
630 {
631 if( !colIsDiscrete(cols[j], impliscontinuous) )
632 continue;
633 assert(SCIPcolGetLPPos(cols[j]) >= 0);
634 assert(currentpointer < matrix->nnonzs);
635
636 matrix->rowmatvals[currentpointer] = rowvals[j];
637 matrix->rowmatind[currentpointer] = colposs[SCIPcolGetLPPos(cols[j])];
638
639 ++currentpointer;
640 }
641 }
642
643 matrix->normalized = TRUE;
644
645 if( *infeasible )
646 return SCIP_OKAY;
647
648 assert(currentpointer == matrix->nnonzs);
649
650 currentpointer = 0;
651
652 /* copy the nonzero coefficient data column by column to heuristic matrix */
653 for( j = 0; j < matrix->ncols; ++j )
654 {
655 SCIP_COL* currentcol;
656 SCIP_ROW** rows;
657 SCIP_Real* colvals;
658 int ncolnonz;
659
660 assert(SCIPcolGetLPPos(lpcols[j]) >= 0);
661
662 currentcol = lpcols[j];
663 assert(colIsDiscrete(currentcol, impliscontinuous));
664
665 colvals = SCIPcolGetVals(currentcol);
666 rows = SCIPcolGetRows(currentcol);
667 ncolnonz = SCIPcolGetNLPNonz(currentcol);
668 matrix->colnorms[j] = ncolnonz;
669
670 *nmaxrows = MAX(*nmaxrows, ncolnonz);
671
672 /* loop over all rows with nonzero coefficients in the column, transform them and add them to the heuristic matrix */
673 matrix->colmatbegin[j] = currentpointer;
674
675 for( i = 0; i < ncolnonz; ++i )
676 {
677 SCIP_Real normval = colvals[i];
678
679 assert(rows[i] != NULL);
680 assert(0 <= SCIProwGetLPPos(rows[i]));
681 assert(SCIProwGetLPPos(rows[i]) < nrows);
682 assert(currentpointer < matrix->nnonzs);
683 matrix->colmatvals[currentpointer] = colvals[i];
684 matrix->colmatind[currentpointer] = SCIProwGetLPPos(rows[i]);
685
686 if( heurdata->normalize )
687 normval /= SCIPgetRowMaxCoef(scip, rows[i]);
688
689 /* update the column norm for maximum normalized rows */
690 matrix->colnorms[j] += ABS(normval);
691 ++currentpointer;
692 }
693 }
694 assert(currentpointer == matrix->nnonzs);
695
696 /* each variable is either transformed, if it supposed to be integral, or relaxed */
697 for( j = 0; j < (relax ? ncols : matrix->ndiscvars); ++j )
698 {
699 SCIP_COL* col;
700
701 col = lpcols[j];
702 if( colIsDiscrete(col, impliscontinuous) )
703 {
704 matrix->transformshiftvals[j] = 0.0;
705 transformVariable(scip, matrix, heurdata, j);
706 }
707 else
708 {
709 SCIP_VAR* var;
710 var = SCIPcolGetVar(col);
711 assert(!varIsDiscrete(var, impliscontinuous));
712 relaxVar(scip, var, matrix);
713 }
714 }
715 *initialized = TRUE;
716
717 SCIPdebugMsg(scip, "Matrix initialized for %d discrete variables with %d cols, %d rows and %d nonzero entries\n",
718 matrix->ndiscvars, matrix->ncols, matrix->nrows, matrix->nnonzs);
719 return SCIP_OKAY;
720}
721
722/** frees all members of the heuristic matrix */
723static
725 SCIP* scip, /**< current SCIP instance */
726 CONSTRAINTMATRIX** matrix /**< constraint matrix object */
727 )
728{
729 assert(scip != NULL);
730 assert(matrix != NULL);
731
732 /* all fields are only allocated, if problem is not empty */
733 if( (*matrix)->nnonzs > 0 )
734 {
735 assert((*matrix) != NULL);
736 assert((*matrix)->rowmatbegin != NULL);
737 assert((*matrix)->rowmatvals != NULL);
738 assert((*matrix)->rowmatind != NULL);
739 assert((*matrix)->colmatbegin != NULL);
740 assert((*matrix)->colmatvals!= NULL);
741 assert((*matrix)->colmatind != NULL);
742 assert((*matrix)->lhs != NULL);
743 assert((*matrix)->rhs != NULL);
744 assert((*matrix)->transformstatus != NULL);
745 assert((*matrix)->transformshiftvals != NULL);
746
747 /* free all fields */
748 SCIPfreeBufferArray(scip, &((*matrix)->transformshiftvals));
749 SCIPfreeBufferArray(scip, &((*matrix)->upperbounds));
750 SCIPfreeBufferArray(scip, &((*matrix)->transformstatus));
751 SCIPfreeBufferArray(scip, &((*matrix)->violrows));
752 SCIPfreeBufferArray(scip, &((*matrix)->colnorms));
753 SCIPfreeBufferArray(scip, &((*matrix)->rhs));
754 SCIPfreeBufferArray(scip, &((*matrix)->lhs));
755 SCIPfreeBufferArray(scip, &((*matrix)->colmatbegin));
756 SCIPfreeBufferArray(scip, &((*matrix)->rowmatbegin));
757 SCIPfreeBufferArray(scip, &((*matrix)->colmatind));
758 SCIPfreeBufferArray(scip, &((*matrix)->colmatvals));
759 SCIPfreeBufferArray(scip, &((*matrix)->rowmatind));
760 SCIPfreeBufferArray(scip, &((*matrix)->rowmatvals));
761
762 (*matrix)->nrows = 0;
763 (*matrix)->ncols = 0;
764 }
765
766 /* free matrix */
767 SCIPfreeBuffer(scip, matrix);
768}
769
770/** updates the information about a row whenever violation status changes */
771static
773 SCIP* scip, /**< current SCIP instance */
774 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
775 int rowindex, /**< index of the row */
776 int* violatedrows, /**< contains all violated rows */
777 int* violatedrowpos, /**< positions of rows in the violatedrows array */
778 int* nviolatedrows, /**< pointer to update total number of violated rows */
779 int* rowweights, /**< row weight storage */
780 SCIP_Bool updateweights /**< should row weight be increased every time the row is violated? */
781 )
782{
783 int* cols;
784 int ncols;
785 int c;
786 int violadd;
787 assert(matrix != NULL);
788 assert(violatedrows != NULL);
789 assert(violatedrowpos != NULL);
790 assert(nviolatedrows != NULL);
791
792 getRowData(matrix, rowindex, NULL, NULL, NULL, &cols, &ncols);
793 violadd = 0;
794
795 /* row is now violated. Enqueue it in the set of violated rows. */
796 if( violatedrowpos[rowindex] == -1 && (SCIPisFeasGT(scip, matrix->lhs[rowindex], 0.0) || SCIPisFeasLT(scip, matrix->rhs[rowindex], 0.0)) )
797 {
798 assert(*nviolatedrows < matrix->nrows);
799
800 violatedrows[*nviolatedrows] = rowindex;
801 violatedrowpos[rowindex] = *nviolatedrows;
802 ++(*nviolatedrows);
803 if( updateweights )
804 ++rowweights[rowindex];
805
806 violadd = 1;
807 }
808 /* row is now feasible. Remove it from the set of violated rows. */
809 else if( violatedrowpos[rowindex] >= 0 && SCIPisFeasLE(scip, matrix->lhs[rowindex], 0.0) && SCIPisFeasGE(scip, matrix->rhs[rowindex], 0.0) )
810 {
811 /* swap the row with last violated row */
812 if( violatedrowpos[rowindex] != *nviolatedrows - 1 )
813 {
814 assert(*nviolatedrows - 1 >= 0);
815 violatedrows[violatedrowpos[rowindex]] = violatedrows[*nviolatedrows - 1];
816 violatedrowpos[violatedrows[*nviolatedrows - 1]] = violatedrowpos[rowindex];
817 }
818
819 /* unlink the row from its position in the array and decrease number of violated rows */
820 violatedrowpos[rowindex] = -1;
821 --(*nviolatedrows);
822 violadd = -1;
823 }
824
825 /* increase or decrease the column violation counter */
826 for( c = 0; c < ncols; ++c )
827 {
828 matrix->violrows[cols[c]] += violadd;
829 assert(matrix->violrows[cols[c]] >= 0);
830 }
831}
832
833/** collects the necessary information about row violations for the zero-solution. That is,
834 * all solution values in heuristic transformation are zero.
835 */
836static
838 SCIP* scip, /**< current scip instance */
839 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
840 int colidx, /**< column index for specific column, or -1 for all rows */
841 int* violatedrows, /**< violated rows */
842 int* violatedrowpos, /**< row positions of violated rows */
843 int* nviolatedrows, /**< pointer to store the number of violated rows */
844 int* rowweights, /**< weight array for every row */
845 SCIP_Bool updateweights /**< should row weight be increased every time the row is violated? */
846 )
847{
848 int nrows;
849 int* rowindices;
850 int i;
851
852 assert(matrix != NULL);
853 assert(violatedrows != NULL);
854 assert(violatedrowpos != NULL);
855 assert(nviolatedrows != NULL);
856 assert(-1 <= colidx && colidx < matrix->ncols);
857
858 /* check if we requested an update for a single variable, or if we want to (re)-initialize the whole violation info */
859 if( colidx >= 0 )
860 getColumnData(matrix, colidx, NULL, &rowindices, &nrows);
861 else
862 {
863 nrows = matrix->nrows;
864 rowindices = NULL;
865 *nviolatedrows = 0;
866
867 /* reinitialize the violated rows */
868 for( i = 0; i < nrows; ++i )
869 violatedrowpos[i] = -1;
870
871 /* clear the violated row counters for all variables */
872 BMSclearMemoryArray(matrix->violrows, matrix->ndiscvars);
873 }
874
875 assert(colidx < 0 || *nviolatedrows >= 0);
876 SCIPdebugMsg(scip, "Entering violation check for %d rows! \n", nrows);
877 /* loop over rows and check if it is violated */
878 for( i = 0; i < nrows; ++i )
879 {
880 int rowpos;
881 if( colidx >= 0 )
882 {
883 assert(rowindices != NULL);
884 rowpos = rowindices[i];
885 }
886 else
887 rowpos = i;
888 /* check, if zero solution violates this row */
889 checkRowViolation(scip, matrix, rowpos, violatedrows, violatedrowpos, nviolatedrows, rowweights, updateweights);
890
891 assert((violatedrowpos[rowpos] == -1 && SCIPisFeasGE(scip, matrix->rhs[rowpos], 0.0) && SCIPisFeasLE(scip, matrix->lhs[rowpos], 0.0))
892 || (violatedrowpos[rowpos] >= 0 &&(SCIPisFeasLT(scip, matrix->rhs[rowpos], 0.0) || SCIPisFeasGT(scip, matrix->lhs[rowpos], 0.0))));
893 }
894}
895
896/** retransforms solution values of variables according to their transformation status */
897static
899 SCIP* scip, /**< current scip instance */
900 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
901 SCIP_VAR* var, /**< variable whose solution value has to be retransformed */
902 int varindex, /**< permutation of variable indices according to sorting */
903 SCIP_Real solvalue /**< solution value of the variable */
904 )
905{
906 TRANSFORMSTATUS status;
907
908 assert(matrix != NULL);
909 assert(var != NULL);
910
911 status = matrix->transformstatus[varindex];
912 assert(status != TRANSFORMSTATUS_NONE);
913
914 /* check if original variable has different bounds and transform solution value correspondingly */
915 if( status == TRANSFORMSTATUS_LB )
916 {
918
919 return solvalue + matrix->transformshiftvals[varindex];
920 }
921 else if( status == TRANSFORMSTATUS_NEG )
922 {
924 return matrix->transformshiftvals[varindex] - solvalue;
925 }
926 return solvalue;
927}
928
929/** determines the best shifting value of a variable
930 * @todo if there is already an incumbent solution, try considering the objective cutoff as additional constraint */
931static
933 SCIP* scip, /**< current scip instance */
934 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
935 int varindex, /**< index of variable which should be shifted */
936 int direction, /**< the direction for this variable */
937 int* rowweights, /**< weighting of rows for best shift calculation */
938 SCIP_Real* steps, /**< buffer array to store the individual steps for individual rows */
939 int* violationchange, /**< buffer array to store the individual change of feasibility of row */
940 SCIP_Real* beststep, /**< pointer to store optimal shifting step */
941 int* rowviolations /**< pointer to store new weighted sum of row violations, i.e, v - f */
942 )
943{
944 SCIP_Real* vals;
945 int* rows;
946
947 SCIP_Real slacksurplus;
948 SCIP_Real upperbound;
949
950 int nrows;
951 int sum;
952 int i;
953
954 SCIP_Bool allzero;
955
956 assert(beststep != NULL);
957 assert(rowviolations != NULL);
958 assert(rowweights != NULL);
959 assert(steps != NULL);
960 assert(violationchange != NULL);
961 assert(direction == 1 || direction == -1);
962
963 upperbound = matrix->upperbounds[varindex];
964
965 /* get nonzero values and corresponding rows of variable */
966 getColumnData(matrix, varindex, &vals, &rows, &nrows);
967
968 /* loop over rows and calculate, which is the minimum shift to make this row feasible
969 * or the minimum shift to violate this row
970 */
971 allzero = TRUE;
972 slacksurplus = 0.0;
973 for( i = 0; i < nrows; ++i )
974 {
975 SCIP_Real lhs;
976 SCIP_Real rhs;
977 SCIP_Real val;
978 int rowpos;
979 SCIP_Bool rowisviolated;
980 int rowweight;
981
982 /* get the row data */
983 rowpos = rows[i];
984 assert(rowpos >= 0);
985 lhs = matrix->lhs[rowpos];
986 rhs = matrix->rhs[rowpos];
987 rowweight = rowweights[rowpos];
988 val = direction * vals[i];
989 assert(!SCIPisZero(scip, val));
990
991 /* determine if current row is violated or not */
992 rowisviolated = (SCIPisFeasLT(scip, rhs, 0.0) || SCIPisFeasLT(scip, -lhs, 0.0));
993
994 /* for a feasible row, determine the minimum integer value within the bounds of the variable by which it has to be
995 * shifted to make row infeasible.
996 */
997 if( !rowisviolated )
998 {
999 SCIP_Real maxfeasshift;
1000
1001 maxfeasshift = SCIPinfinity(scip);
1002
1003 /* feasibility can only be violated if the variable has a lock in the corresponding direction,
1004 * i.e. a positive coefficient for a "<="-constraint, a negative coefficient for a ">="-constraint.
1005 * if the variable has no lock in the current row, it can still help to increase the slack of this row;
1006 * we measure slack increase for shifting by one
1007 */
1008 if( val < 0.0 )
1009 {
1010 if( !SCIPisInfinity(scip, -lhs) )
1011 maxfeasshift = SCIPfeasFloor(scip, MIN(lhs, 0.0) / val);
1012 else
1013 slacksurplus -= val;
1014 }
1015 else
1016 {
1017 if( !SCIPisInfinity(scip, rhs) )
1018 maxfeasshift = SCIPfeasFloor(scip, MAX(rhs, 0.0) / val);
1019 else
1020 slacksurplus += val;
1021 }
1022
1023 /* check if the least violating shift lies within variable bounds and set corresponding array values */
1024 if( !SCIPisInfinity(scip, maxfeasshift) && SCIPisFeasLE(scip, maxfeasshift + 1.0, upperbound) )
1025 {
1026 steps[i] = maxfeasshift + 1.0;
1027 violationchange[i] = rowweight;
1028 allzero = FALSE;
1029 }
1030 else
1031 {
1032 steps[i] = upperbound;
1033 violationchange[i] = 0;
1034 }
1035 }
1036 /* for a violated row, determine the minimum integral value within the bounds of the variable by which it has to be
1037 * shifted to make row feasible.
1038 */
1039 else
1040 {
1041 SCIP_Real minfeasshift;
1042
1043 minfeasshift = SCIPinfinity(scip);
1044
1045 /* if coefficient has the right sign to make row feasible, determine the minimum integer to shift variable
1046 * to obtain feasibility
1047 */
1048 if( val < 0.0 )
1049 {
1050 if( SCIPisFeasLT(scip, rhs, 0.0) )
1051 minfeasshift = SCIPfeasCeil(scip, MIN(rhs, val) / val);
1052 }
1053 else
1054 {
1055 if( SCIPisFeasLT(scip, -lhs, 0.0) )
1056 minfeasshift = SCIPfeasCeil(scip, MAX(lhs, val) / val);
1057 }
1058
1059 /* check if the minimum feasibility recovery shift lies within variable bounds and set corresponding array
1060 * values
1061 */
1062 if( !SCIPisInfinity(scip, minfeasshift) && SCIPisFeasLE(scip, minfeasshift, upperbound) )
1063 {
1064 steps[i] = minfeasshift;
1065 violationchange[i] = -rowweight;
1066 allzero = FALSE;
1067 }
1068 else
1069 {
1070 steps[i] = upperbound;
1071 violationchange[i] = 0;
1072 }
1073 }
1074 }
1075
1076 /* in case that the variable cannot affect the feasibility of any row, in particular it cannot violate
1077 * a single row, but we can add slack to already feasible rows, we will do this
1078 */
1079 if( allzero )
1080 {
1081 if( ! SCIPisInfinity(scip, upperbound) && SCIPisGT(scip, slacksurplus, 0.0) )
1082 *beststep = direction * upperbound;
1083 else
1084 *beststep = 0.0;
1085
1086 return SCIP_OKAY;
1087 }
1088
1089 /* sorts rows by increasing value of steps */
1090 SCIPsortRealInt(steps, violationchange, nrows);
1091
1092 *beststep = 0.0;
1093 *rowviolations = 0;
1094 sum = 0;
1095
1096 /* best shifting step is calculated by summing up the violation changes for each relevant step and
1097 * taking the one which leads to the minimum sum. This sum measures the balance of feasibility recovering and
1098 * violating changes which will be obtained by shifting the variable by this step
1099 * note, the sums for smaller steps have to be taken into account for all bigger steps, i.e., the sums can be
1100 * computed iteratively
1101 */
1102 for( i = 0; i < nrows && !SCIPisInfinity(scip, steps[i]); ++i )
1103 {
1104 sum += violationchange[i];
1105
1106 /* if we reached the last entry for the current step value, we have finished computing its sum and
1107 * update the step defining the minimum sum
1108 */
1109 if( (i == nrows-1 || steps[i+1] > steps[i]) && sum < *rowviolations ) /*lint !e679*/
1110 {
1111 *rowviolations = sum;
1112 *beststep = direction * steps[i];
1113 }
1114 }
1115 assert(*rowviolations <= 0);
1116 assert(!SCIPisInfinity(scip, *beststep));
1117
1118 return SCIP_OKAY;
1119}
1120
1121/** updates transformation of a given variable by taking into account current local bounds. if the bounds have changed
1122 * since last update, updating the heuristic specific upper bound of the variable, its current transformed solution value
1123 * and all affected rows is necessary.
1124 */
1125static
1127 SCIP* scip, /**< current scip */
1128 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
1129 SCIP_HEURDATA* heurdata, /**< heuristic data */
1130 int varindex, /**< index of variable in matrix */
1131 SCIP_Real lb, /**< local lower bound of the variable */
1132 SCIP_Real ub, /**< local upper bound of the variable */
1133 int* violatedrows, /**< violated rows */
1134 int* violatedrowpos, /**< violated row positions */
1135 int* nviolatedrows /**< pointer to store number of violated rows */
1136 )
1137{
1138 TRANSFORMSTATUS status;
1139 SCIP_Real deltashift;
1140 SCIP_Bool checkviolations;
1141
1142 assert(scip != NULL);
1143 assert(matrix != NULL);
1144 assert(0 <= varindex && varindex < matrix->ndiscvars);
1145
1146 /* deltashift is the difference between the old and new transformation value. */
1147 deltashift = 0.0;
1148 status = matrix->transformstatus[varindex];
1149
1150 SCIPdebugMsg(scip, " Variable <%d> [%g,%g], status %d(%g), ub %g \n", varindex, lb, ub, status,
1151 matrix->transformshiftvals[varindex], matrix->upperbounds[varindex]);
1152
1153 checkviolations = FALSE;
1154 /* depending on the variable status, deltashift is calculated differently. */
1155 switch( status )
1156 {
1157 case TRANSFORMSTATUS_LB:
1158 if( SCIPisInfinity(scip, -lb) )
1159 {
1160 transformVariable(scip, matrix, heurdata, varindex);
1161 checkviolations = TRUE;
1162 }
1163 else
1164 {
1165 deltashift = lb - (matrix->transformshiftvals[varindex]);
1166 matrix->transformshiftvals[varindex] = lb;
1167 if( !SCIPisInfinity(scip, ub) )
1168 matrix->upperbounds[varindex] = ub - lb;
1169 else
1170 matrix->upperbounds[varindex] = SCIPinfinity(scip);
1171 }
1172 break;
1174 if( SCIPisInfinity(scip, ub) )
1175 {
1176 transformVariable(scip, matrix, heurdata, varindex);
1177 checkviolations = TRUE;
1178 }
1179 else
1180 {
1181 deltashift = (matrix->transformshiftvals[varindex]) - ub;
1182 matrix->transformshiftvals[varindex] = ub;
1183
1184 if( !SCIPisInfinity(scip, -lb) )
1185 matrix->upperbounds[varindex] = MIN(ub - lb, SCIPinfinity(scip)); /*lint !e666*/
1186 else
1187 matrix->upperbounds[varindex] = SCIPinfinity(scip);
1188 }
1189 break;
1191 /* in case of a free transform status, if one of the bounds has become finite, we want
1192 * to transform this variable to a variable with a lowerbound or a negated transform status */
1193 if( !SCIPisInfinity(scip, -lb) || !SCIPisInfinity(scip, ub) )
1194 {
1195 transformVariable(scip, matrix, heurdata, varindex);
1196
1197 /* violations have to be rechecked for rows in which variable appears */
1198 checkviolations = TRUE;
1199
1200 assert(matrix->transformstatus[varindex] == TRANSFORMSTATUS_LB || matrix->transformstatus[varindex] == TRANSFORMSTATUS_NEG);
1201 assert(SCIPisLE(scip, ABS(lb), ABS(ub)) || matrix->transformstatus[varindex] == TRANSFORMSTATUS_NEG);
1202 }
1203 break;
1204
1206 default:
1207 SCIPerrorMessage("Error: Invalid variable status <%d> in shift and propagagate heuristic, aborting!\n", status);
1208 SCIPABORT();
1209 return SCIP_INVALIDDATA; /*lint !e527*/
1210 }
1211 /* if the bound, by which the variable was shifted, has changed, deltashift is different from zero, which requires
1212 * an update of all affected rows
1213 */
1214 if( !SCIPisFeasZero(scip, deltashift) )
1215 {
1216 int i;
1217 int* rows;
1218 SCIP_Real* vals;
1219 int nrows;
1220
1221 /* get nonzero values and corresponding rows of variable */
1222 getColumnData(matrix, varindex, &vals, &rows, &nrows);
1223
1224 /* go through rows, update the rows w.r.t. the influence of the changed transformation of the variable */
1225 for( i = 0; i < nrows; ++i )
1226 {
1227 SCIPdebugMsg(scip, " update slacks of row<%d>: coefficient <%g>, %g <= 0 <= %g \n",
1228 rows[i], vals[i], matrix->lhs[rows[i]], matrix->rhs[rows[i]]);
1229
1230 if( !SCIPisInfinity(scip, -(matrix->lhs[rows[i]])) )
1231 matrix->lhs[rows[i]] -= (vals[i]) * deltashift;
1232
1233 if( !SCIPisInfinity(scip, matrix->rhs[rows[i]]) )
1234 matrix->rhs[rows[i]] -= (vals[i]) * deltashift;
1235 }
1236 checkviolations = TRUE;
1237 }
1238
1239 /* check and update information about violated rows, if necessary */
1240 if( checkviolations )
1241 checkViolations(scip, matrix, varindex, violatedrows, violatedrowpos, nviolatedrows, heurdata->rowweights, heurdata->updateweights);
1242
1243 SCIPdebugMsg(scip, " Variable <%d> [%g,%g], status %d(%g), ub %g \n", varindex, lb, ub, status,
1244 matrix->transformshiftvals[varindex], matrix->upperbounds[varindex]);
1245
1246 return SCIP_OKAY;
1247}
1248
1249/** comparison method for columns; binary < integer < implicit < continuous variables */
1250static
1251SCIP_DECL_SORTPTRCOMP(heurSortColsShiftandpropagate)
1252{
1253 SCIP_COL* col1;
1254 SCIP_COL* col2;
1255 SCIP_VAR* var1;
1256 SCIP_VAR* var2;
1257 SCIP_VARTYPE vartype1;
1258 SCIP_VARTYPE vartype2;
1259
1260 col1 = (SCIP_COL*)elem1;
1261 col2 = (SCIP_COL*)elem2;
1262 var1 = SCIPcolGetVar(col1);
1263 var2 = SCIPcolGetVar(col2);
1264 assert(var1 != NULL);
1265 assert(var2 != NULL);
1266
1269
1270 if( vartype1 < vartype2 )
1271 return -1;
1272 if( vartype1 > vartype2 )
1273 return +1;
1274
1275 assert(vartype1 == vartype2);
1276 return 0;
1277}
1278
1279/*
1280 * Callback methods of primal heuristic
1281 */
1282
1283/** deinitialization method of primal heuristic(called before transformed problem is freed) */
1284static
1285SCIP_DECL_HEUREXIT(heurExitShiftandpropagate)
1286{ /*lint --e{715}*/
1288
1289 heurdata = SCIPheurGetData(heur);
1290 assert(heurdata != NULL);
1291
1292 /* free random number generator */
1293 SCIPfreeRandom(scip, &heurdata->randnumgen);
1294
1295 /* if statistic mode is enabled, statistics are printed to console */
1298 " DETAILS : %d violations left, %d probing status\n",
1299 heurdata->nremainingviols,
1300 heurdata->lpsolstat
1301 );
1303 " SHIFTANDPROPAGATE PROBING : %d probings, %" SCIP_LONGINT_FORMAT " domain reductions, ncutoffs: %d , LP iterations: %" SCIP_LONGINT_FORMAT " \n ",
1304 heurdata->nprobings,
1305 heurdata->ntotaldomredsfound,
1306 heurdata->ncutoffs,
1307 heurdata->nlpiters);
1308 );
1309
1310 return SCIP_OKAY;
1311}
1312
1313/** initialization method of primal heuristic(called after problem was transformed). We only need this method for
1314 * statistic mode of heuristic.
1315 */
1316static
1317SCIP_DECL_HEURINIT(heurInitShiftandpropagate)
1318{ /*lint --e{715}*/
1320
1321 heurdata = SCIPheurGetData(heur);
1322
1323 assert(heurdata != NULL);
1324
1325 /* create random number generator */
1326 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
1328
1331 heurdata->nremainingviols = 0;
1332 heurdata->nprobings = 0;
1333 heurdata->ntotaldomredsfound = 0;
1334 heurdata->ncutoffs = 0;
1335 heurdata->nlpiters = 0;
1336 )
1337 return SCIP_OKAY;
1338}
1339
1340/** destructor of primal heuristic to free user data(called when SCIP is exiting) */
1341static
1342SCIP_DECL_HEURFREE(heurFreeShiftandpropagate)
1343{ /*lint --e{715}*/
1345 SCIP_EVENTHDLR* eventhdlr;
1346 SCIP_EVENTHDLRDATA* eventhdlrdata;
1347
1348 heurdata = SCIPheurGetData(heur);
1349 assert(heurdata != NULL);
1350 eventhdlr = heurdata->eventhdlr;
1351 assert(eventhdlr != NULL);
1352 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1353
1354 SCIPfreeBlockMemoryNull(scip, &eventhdlrdata);
1355
1356 /* free heuristic data */
1358
1359 SCIPheurSetData(heur, NULL);
1360
1361 return SCIP_OKAY;
1362}
1363
1364
1365/** copy method for primal heuristic plugins(called when SCIP copies plugins) */
1366static
1367SCIP_DECL_HEURCOPY(heurCopyShiftandpropagate)
1368{ /*lint --e{715}*/
1369 assert(scip != NULL);
1370 assert(heur != NULL);
1371
1373
1374 /* call inclusion method of primal heuristic */
1376
1377 return SCIP_OKAY;
1378}
1379
1380/** execution method of primal heuristic */
1381static
1382SCIP_DECL_HEUREXEC(heurExecShiftandpropagate)
1383{ /*lint --e{715}*/
1384 SCIP_HEURDATA* heurdata; /* heuristic data */
1385 SCIP_EVENTHDLR* eventhdlr; /* shiftandpropagate event handler */
1386 SCIP_EVENTHDLRDATA* eventhdlrdata; /* event handler data */
1387 SCIP_EVENTDATA** eventdatas; /* event data for every variable */
1388
1389 CONSTRAINTMATRIX* matrix; /* constraint matrix object */
1390 SCIP_COL** lpcols; /* lp columns */
1391 SCIP_SOL* sol; /* solution pointer */
1392 SCIP_Real* colnorms; /* contains Euclidean norms of column vectors */
1393
1394 SCIP_Real* steps; /* buffer arrays for best shift selection in main loop */
1395 int* violationchange;
1396
1397 int* violatedrows; /* the violated rows */
1398 int* violatedrowpos; /* the array position of a violated row, or -1 */
1399 int* permutation; /* reflects the position of the variables after sorting */
1400 int* violatedvarrows; /* number of violated rows for each variable */
1401 int* colposs; /* position of columns according to variable type sorting */
1402 int nlpcols; /* number of lp columns */
1403 int nviolatedrows; /* number of violated rows */
1404 int ndiscvars; /* number of non-continuous variables of the problem */
1405 int lastindexofsusp; /* last variable which has been swapped due to a cutoff */
1406 int nbinvars; /* number of binary variables */
1407#ifndef NDEBUG
1408 int nintvars = 0; /* number of integer variables */
1409#endif
1410 int i;
1411 int r;
1412 int v;
1413 int c;
1414 int ncutoffs; /* counts the number of cutoffs for this execution */
1415 int nprobings; /* counts the number of probings */
1416 int nlprows; /* the number LP rows */
1417 int nmaxrows; /* maximum number of LP rows of a variable */
1418
1419 SCIP_Bool initialized; /* has the matrix been initialized? */
1420 SCIP_Bool cutoff; /* has current probing node been cutoff? */
1421 SCIP_Bool probing; /* should probing be applied or not? */
1422 SCIP_Bool infeasible; /* FALSE as long as currently infeasible rows have variables left */
1423 SCIP_Bool impliscontinuous;
1424
1425 heurdata = SCIPheurGetData(heur);
1426 assert(heurdata != NULL);
1427
1428 eventhdlr = heurdata->eventhdlr;
1429 assert(eventhdlr != NULL);
1430
1431 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1432 assert(eventhdlrdata != NULL);
1433
1435 SCIPdebugMsg(scip, "entering execution method of shift and propagate heuristic\n");
1436
1437 /* heuristic is obsolete if there are only continuous variables */
1438 if( SCIPgetNVars(scip) - SCIPgetNContVars(scip) == 0 )
1439 return SCIP_OKAY;
1440
1441 /* stop execution method if there is already a primarily feasible solution at hand */
1442 if( SCIPgetBestSol(scip) != NULL && heurdata->onlywithoutsol )
1443 return SCIP_OKAY;
1444
1445 /* stop if there is no LP available */
1446 if ( ! SCIPhasCurrentNodeLP(scip) )
1447 return SCIP_OKAY;
1448
1450 {
1451 /* note that this call can have the side effect that variables are created */
1453
1454 /* manually cut off the node if the LP construction detected infeasibility (heuristics cannot return such a
1455 * result); the cutoff result is safe to use in exact solving mode, but we don't have enough information to
1456 * give a certificate for the cutoff
1457 */
1458 if( cutoff && !SCIPisCertified(scip) )
1459 {
1461 return SCIP_OKAY;
1462 }
1463
1465 }
1466
1468
1470
1471 SCIP_CALL( SCIPgetLPColsData(scip, &lpcols, &nlpcols) );
1472 assert(nlpcols == 0 || lpcols != NULL);
1473
1474 /* we need an LP */
1475 if( nlprows == 0 || nlpcols == 0 )
1476 return SCIP_OKAY;
1477
1479 initialized = FALSE;
1480
1481 /* allocate lp column array */
1482 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->lpcols, nlpcols) );
1483 heurdata->nlpcols = nlpcols;
1484
1485 impliscontinuous = heurdata->impliscontinuous;
1486
1487#ifndef NDEBUG
1488 BMSclearMemoryArray(heurdata->lpcols, nlpcols);
1489#endif
1490
1491 /* copy and sort the columns by their variable types (binary before integer before implicit integer before continuous) */
1492 BMScopyMemoryArray(heurdata->lpcols, lpcols, nlpcols);
1493
1494 SCIPsortPtr((void**)heurdata->lpcols, heurSortColsShiftandpropagate, nlpcols);
1495
1496 SCIP_CALL( SCIPallocBufferArray(scip, &colposs, nlpcols) );
1497
1498 /* we have to collect the number of different variable types before we start probing since during probing variable
1499 * can be created (e.g., cons_xor.c)
1500 */
1501 ndiscvars = 0;
1502 nbinvars = 0;
1503 for( c = 0; c < nlpcols; ++c )
1504 {
1505 SCIP_COL* col;
1506 SCIP_VAR* colvar;
1507
1508 col = heurdata->lpcols[c];
1509 assert(col != NULL);
1510 colvar = SCIPcolGetVar(col);
1511 assert(colvar != NULL);
1512
1513 if( varIsDiscrete(colvar, impliscontinuous) )
1514 ++ndiscvars;
1516 ++nbinvars;
1517#ifndef NDEBUG
1518 else if( SCIPvarGetType(colvar) == SCIP_VARTYPE_INTEGER && !SCIPvarIsImpliedIntegral(colvar) )
1519 ++nintvars;
1520#endif
1521
1522 /* save the position of this column in the array such that it can be accessed as the "true" column position */
1523 assert(SCIPcolGetLPPos(col) >= 0);
1524 colposs[SCIPcolGetLPPos(col)] = c;
1525 }
1526 assert(nbinvars + nintvars <= ndiscvars);
1527
1528 /* start probing mode */
1530
1531 /* enables collection of variable statistics during probing */
1532 if( heurdata->collectstats )
1534 else
1536
1537 /* this should always be fulfilled because we perform shift and propagate only at the root node */
1539
1540 /* @todo check if this node is necessary (I don't think so) */
1542 ncutoffs = 0;
1543 nprobings = 0;
1544 nmaxrows = 0;
1545 infeasible = FALSE;
1546
1547 /* initialize heuristic matrix and working solution */
1548 SCIP_CALL( SCIPallocBuffer(scip, &matrix) );
1549 SCIP_CALL( initMatrix(scip, matrix, heurdata, colposs, &nmaxrows, heurdata->relax, &initialized, &infeasible) );
1550
1551 /* could not initialize matrix */
1552 if( !initialized || infeasible )
1553 {
1554 SCIPdebugMsg(scip, " MATRIX not initialized -> Execution of heuristic stopped! \n");
1555 goto TERMINATE;
1556 }
1557
1558 /* the number of discrete LP column variables can be less than the actual number of variables, if, e.g., there
1559 * are nonlinearities in the problem. The heuristic execution can be terminated in that case.
1560 */
1561 if( matrix->ndiscvars < ndiscvars )
1562 {
1563 SCIPdebugMsg(scip, "Not all discrete variables are in the current LP. Shiftandpropagate execution terminated.\n");
1564 goto TERMINATE;
1565 }
1566
1567 assert(nmaxrows > 0);
1568
1569 eventhdlrdata->matrix = matrix;
1570 eventhdlrdata->heurdata = heurdata;
1571
1572 SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
1573 SCIPsolSetHeur(sol, heur);
1574
1575 /* allocate arrays for execution method */
1576 SCIP_CALL( SCIPallocBufferArray(scip, &permutation, ndiscvars) );
1577 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowweights, matrix->nrows) );
1578
1579 /* allocate necessary memory for best shift search */
1580 SCIP_CALL( SCIPallocBufferArray(scip, &steps, nmaxrows) );
1581 SCIP_CALL( SCIPallocBufferArray(scip, &violationchange, nmaxrows) );
1582
1583 /* allocate arrays to store information about infeasible rows */
1584 SCIP_CALL( SCIPallocBufferArray(scip, &violatedrows, matrix->nrows) );
1585 SCIP_CALL( SCIPallocBufferArray(scip, &violatedrowpos, matrix->nrows) );
1586
1587 eventhdlrdata->violatedrows = violatedrows;
1588 eventhdlrdata->violatedrowpos = violatedrowpos;
1589 eventhdlrdata->nviolatedrows = &nviolatedrows;
1590
1591 /* initialize arrays. Before sorting, permutation is the identity permutation */
1592 for( i = 0; i < ndiscvars; ++i )
1593 permutation[i] = i;
1594
1595 /* initialize row weights */
1596 for( r = 0; r < matrix->nrows; ++r )
1597 {
1598 if( !SCIPisInfinity(scip, -(matrix->lhs[r])) && !SCIPisInfinity(scip, matrix->rhs[r]) )
1599 heurdata->rowweights[r] = DEFAULT_WEIGHT_EQUALITY;
1600 else
1601 heurdata->rowweights[r] = DEFAULT_WEIGHT_INEQUALITY;
1602 }
1603 colnorms = matrix->colnorms;
1604
1605 assert(nbinvars >= 0);
1606 assert(nintvars >= 0);
1607
1608 /* check rows for infeasibility */
1609 checkViolations(scip, matrix, -1, violatedrows, violatedrowpos, &nviolatedrows, heurdata->rowweights, heurdata->updateweights);
1610
1611 /* allocate memory for violatedvarrows array only if variable ordering relies on it */
1612 if( heurdata->sortvars && (heurdata->sortkey == 't' || heurdata->sortkey == 'v') )
1613 {
1614 SCIP_CALL( SCIPallocBufferArray(scip, &violatedvarrows, ndiscvars) );
1615 BMScopyMemoryArray(violatedvarrows, matrix->violrows, ndiscvars);
1616 }
1617 else
1618 violatedvarrows = NULL;
1619
1620 /* sort variables w.r.t. the sorting key parameter. Sorting is indirect, all matrix column data
1621 * stays in place, but permutation array gives access to the sorted order of variables
1622 */
1623 if( heurdata->sortvars )
1624 {
1625 switch (heurdata->sortkey)
1626 {
1627 case 'n':
1628 /* variable ordering w.r.t. column norms nonincreasing */
1629 if( heurdata->preferbinaries )
1630 {
1631 if( nbinvars > 0 )
1632 SCIPsortDownRealInt(colnorms, permutation, nbinvars);
1633 if( nbinvars < ndiscvars )
1634 SCIPsortDownRealInt(&colnorms[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
1635 }
1636 else
1637 {
1638 SCIPsortDownRealInt(colnorms, permutation, ndiscvars);
1639 }
1640 SCIPdebugMsg(scip, "Variables sorted down w.r.t their normalized columns!\n");
1641 break;
1642 case 'u':
1643 /* variable ordering w.r.t. column norms nondecreasing */
1644 if( heurdata->preferbinaries )
1645 {
1646 if( nbinvars > 0 )
1647 SCIPsortRealInt(colnorms, permutation, nbinvars);
1648 if( nbinvars < ndiscvars )
1649 SCIPsortRealInt(&colnorms[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
1650 }
1651 else
1652 {
1653 SCIPsortRealInt(colnorms, permutation, ndiscvars);
1654 }
1655 SCIPdebugMsg(scip, "Variables sorted w.r.t their normalized columns!\n");
1656 break;
1657 case 'v':
1658 /* variable ordering w.r.t. nonincreasing number of violated rows */
1659 assert(violatedvarrows != NULL);
1660 if( heurdata->preferbinaries )
1661 {
1662 if( nbinvars > 0 )
1663 SCIPsortDownIntInt(violatedvarrows, permutation, nbinvars);
1664 if( nbinvars < ndiscvars )
1665 SCIPsortDownIntInt(&violatedvarrows[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
1666 }
1667 else
1668 {
1669 SCIPsortDownIntInt(violatedvarrows, permutation, ndiscvars);
1670 }
1671
1672 SCIPdebugMsg(scip, "Variables sorted down w.r.t their number of currently infeasible rows!\n");
1673 break;
1674 case 't':
1675 /* variable ordering w.r.t. nondecreasing number of violated rows */
1676 assert(violatedvarrows != NULL);
1677 if( heurdata->preferbinaries )
1678 {
1679 if( nbinvars > 0 )
1680 SCIPsortIntInt(violatedvarrows, permutation, nbinvars);
1681 if( nbinvars < ndiscvars )
1682 SCIPsortIntInt(&violatedvarrows[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
1683 }
1684 else
1685 {
1686 SCIPsortIntInt(violatedvarrows, permutation, ndiscvars);
1687 }
1688
1689 SCIPdebugMsg(scip, "Variables sorted (upwards) w.r.t their number of currently infeasible rows!\n");
1690 break;
1691 case 'r':
1692 /* random sorting */
1693 if( heurdata->preferbinaries )
1694 {
1695 if( nbinvars > 0 )
1696 SCIPrandomPermuteIntArray(heurdata->randnumgen, permutation, 0, nbinvars - 1);
1697 if( nbinvars < ndiscvars )
1698 SCIPrandomPermuteIntArray(heurdata->randnumgen, &permutation[nbinvars], nbinvars - 1,
1699 ndiscvars - nbinvars - 1);
1700 }
1701 else
1702 {
1703 SCIPrandomPermuteIntArray(heurdata->randnumgen, permutation, 0, ndiscvars - 1);
1704 }
1705 SCIPdebugMsg(scip, "Variables permuted randomly!\n");
1706 break;
1707 default:
1708 SCIPdebugMsg(scip, "No variable permutation applied\n");
1709 break;
1710 }
1711 }
1712
1713 /* should binary variables without locks be treated first? */
1714 if( heurdata->binlocksfirst )
1715 {
1716 SCIP_VAR* var;
1717 int nbinwithoutlocks = 0;
1718
1719 /* count number of binaries without locks */
1720 if( heurdata->preferbinaries )
1721 {
1722 for( c = 0; c < nbinvars; ++c )
1723 {
1724 var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
1727 ++nbinwithoutlocks;
1728 }
1729 }
1730 else
1731 {
1732 for( c = 0; c < ndiscvars; ++c )
1733 {
1734 var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
1735 if( SCIPvarIsBinary(var) )
1736 {
1739 ++nbinwithoutlocks;
1740 }
1741 }
1742 }
1743
1744 if( nbinwithoutlocks > 0 )
1745 {
1746 SCIP_VAR* binvar;
1747 int b = 1;
1748 int tmp;
1749 c = 0;
1750
1751 /* if c reaches nbinwithoutlocks, then all binary variables without locks were sorted to the beginning of the array */
1752 while( c < nbinwithoutlocks && b < ndiscvars )
1753 {
1754 assert(c < b);
1755 assert(c < ndiscvars);
1756 assert(b < ndiscvars);
1757 var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
1758 binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
1759
1760 /* search for next variable which is not a binary variable without locks */
1763 {
1764 ++c;
1765 if( c >= nbinwithoutlocks )
1766 break;
1767 var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
1768 }
1769 if( c >= nbinwithoutlocks )
1770 break;
1771
1772 /* search for next binary variable without locks (with position > c) */
1773 if( b <= c )
1774 {
1775 b = c + 1;
1776 binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
1777 }
1778 while( !SCIPvarIsBinary(binvar) || (SCIPvarGetNLocksUpType(binvar, SCIP_LOCKTYPE_MODEL) > 0
1780 {
1781 ++b;
1782 assert(b < ndiscvars);
1783 binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
1784 }
1785
1786 /* swap the two variables */
1787 tmp = permutation[b];
1788 permutation[b] = permutation[c];
1789 permutation[c] = tmp;
1790
1791 /* increase counters */
1792 ++c;
1793 ++b;
1794 }
1795 }
1796
1797#ifndef NDEBUG
1798 for( c = 0; c < ndiscvars; ++c )
1799 {
1800 assert((c < nbinwithoutlocks) == (SCIPvarIsBinary(SCIPcolGetVar(heurdata->lpcols[permutation[c]]))
1801 && (SCIPvarGetNLocksUpType(SCIPcolGetVar(heurdata->lpcols[permutation[c]]), SCIP_LOCKTYPE_MODEL) == 0
1802 || SCIPvarGetNLocksDownType(SCIPcolGetVar(heurdata->lpcols[permutation[c]]), SCIP_LOCKTYPE_MODEL) == 0)));
1803 }
1804#endif
1805 }
1806
1807 SCIP_CALL( SCIPallocBufferArray(scip, &eventdatas, matrix->ndiscvars) );
1808 BMSclearMemoryArray(eventdatas, matrix->ndiscvars);
1809
1810 /* initialize variable events to catch bound changes during propagation */
1811 for( c = 0; c < matrix->ndiscvars; ++c )
1812 {
1813 SCIP_VAR* var;
1814
1815 var = SCIPcolGetVar(heurdata->lpcols[c]);
1816 assert(var != NULL);
1818 assert(eventdatas[c] == NULL);
1819
1820 SCIP_CALL( SCIPallocBuffer(scip, &(eventdatas[c])) ); /*lint !e866*/
1821
1822 eventdatas[c]->colpos = c;
1823
1824 SCIP_CALL( SCIPcatchVarEvent(scip, var, EVENTTYPE_SHIFTANDPROPAGATE, eventhdlr, eventdatas[c], NULL) );
1825 }
1826
1827 cutoff = FALSE;
1828
1829 lastindexofsusp = -1;
1830 probing = heurdata->probing;
1831 infeasible = FALSE;
1832
1833 SCIPdebugMsg(scip, "SHIFT_AND_PROPAGATE heuristic starts main loop with %d violations and %d remaining variables!\n",
1834 nviolatedrows, ndiscvars);
1835
1836 assert(matrix->ndiscvars == ndiscvars);
1837
1838 /* loop over variables, shift them according to shifting criteria and try to reduce the global infeasibility */
1839 for( c = 0; c < ndiscvars; ++c )
1840 {
1841 SCIP_VAR* var;
1842 SCIP_Longint ndomredsfound;
1843 SCIP_Real optimalshiftvalue;
1844 SCIP_Real origsolval;
1845 SCIP_Real lb;
1846 SCIP_Real ub;
1847 int nviolations;
1848 int permutedvarindex;
1849 int j;
1850 SCIP_Bool marksuspicious;
1851
1852 if( heurdata->selectbest )
1853 { /* search for best candidate */
1854 j = c + 1;
1855 while( j < ndiscvars )
1856 {
1857 /* run through remaining variables and search for best candidate */
1858 if( matrix->violrows[permutation[c]] < matrix->violrows[permutation[j]] )
1859 {
1860 int tmp;
1861 tmp = permutation[c];
1862 permutation[c] = permutation[j];
1863 permutation[j] = tmp;
1864 }
1865 ++j;
1866 }
1867 }
1868 permutedvarindex = permutation[c];
1869 optimalshiftvalue = 0.0;
1870 nviolations = 0;
1871 var = SCIPcolGetVar(heurdata->lpcols[permutedvarindex]);
1872 lb = SCIPvarGetLbLocal(var);
1873 ub = SCIPvarGetUbLocal(var);
1876
1877 /* check whether we hit some limit, e.g. the time limit, in between
1878 * since the check itself consumes some time, we only do it every tenth iteration
1879 */
1880 if( c % 10 == 0 && SCIPisStopped(scip) )
1881 goto TERMINATE2;
1882
1883 /* if propagation is enabled, check if propagation has changed the variables bounds
1884 * and update the transformed upper bound correspondingly
1885 * @todo this should not be necessary
1886 */
1887 if( heurdata->probing )
1888 {
1889 SCIP_CALL( updateTransformation(scip, matrix, heurdata, permutedvarindex,lb, ub, violatedrows, violatedrowpos,
1890 &nviolatedrows) );
1891 }
1892
1893 SCIPdebugMsg(scip, "Variable %s with local bounds [%g,%g], status <%d>, matrix bound <%g>\n",
1894 SCIPvarGetName(var), lb, ub, matrix->transformstatus[permutedvarindex], matrix->upperbounds[permutedvarindex]);
1895
1896 /* ignore variable if propagation fixed it (lb and ub will be zero) */
1897 if( SCIPisFeasZero(scip, matrix->upperbounds[permutedvarindex]) )
1898 {
1899 assert(!SCIPisInfinity(scip, ub));
1900 assert(SCIPisFeasEQ(scip, lb, ub));
1901
1903
1904 continue;
1905 }
1906
1907 marksuspicious = FALSE;
1908
1909 /* check whether the variable is binary and has no locks in one direction, so that we want to fix it to the
1910 * respective bound (only enabled by parameter)
1911 */
1912 if( heurdata->fixbinlocks && SCIPvarIsBinary(var)
1915 {
1917 origsolval = SCIPvarGetUbLocal(var);
1918 else
1919 {
1921 origsolval = SCIPvarGetLbLocal(var);
1922 }
1923 }
1924 else
1925 {
1926 /* only apply the computationally expensive best shift selection, if there is a violated row left */
1927 if( !heurdata->stopafterfeasible || nviolatedrows > 0 )
1928 {
1929 /* compute optimal shift value for variable */
1930 SCIP_CALL( getOptimalShiftingValue(scip, matrix, permutedvarindex, 1, heurdata->rowweights, steps, violationchange,
1931 &optimalshiftvalue, &nviolations) );
1932 assert(SCIPisFeasGE(scip, optimalshiftvalue, 0.0));
1933
1934 /* Variables with FREE transform have to be dealt with twice */
1935 if( matrix->transformstatus[permutedvarindex] == TRANSFORMSTATUS_FREE )
1936 {
1937 SCIP_Real downshiftvalue;
1938 int ndownviolations;
1939
1940 downshiftvalue = 0.0;
1941 ndownviolations = 0;
1942 SCIP_CALL( getOptimalShiftingValue(scip, matrix, permutedvarindex, -1, heurdata->rowweights, steps, violationchange,
1943 &downshiftvalue, &ndownviolations) );
1944
1945 assert(SCIPisLE(scip, downshiftvalue, 0.0));
1946
1947 /* compare to positive direction and select the direction which makes more rows feasible */
1948 if( ndownviolations < nviolations )
1949 {
1950 optimalshiftvalue = downshiftvalue;
1951 }
1952 }
1953 }
1954 else
1955 optimalshiftvalue = 0.0;
1956
1957 /* if zero optimal shift values are forbidden by the user parameter, delay the variable by marking it suspicious */
1958 if( heurdata->nozerofixing && nviolations > 0 && SCIPisFeasZero(scip, optimalshiftvalue) )
1959 marksuspicious = TRUE;
1960
1961 /* retransform the solution value from the heuristic transformation space */
1962 assert(varIsDiscrete(var, impliscontinuous));
1963 origsolval = retransformVariable(scip, matrix, var, permutedvarindex, optimalshiftvalue);
1964 }
1965 assert(SCIPisFeasGE(scip, origsolval, lb) && SCIPisFeasLE(scip, origsolval, ub));
1966
1967 /* check if propagation should still be performed
1968 * @todo do we need the hard coded value? we could use SCIP_MAXTREEDEPTH
1969 */
1970 if( nprobings > DEFAULT_PROPBREAKER )
1971 probing = FALSE;
1972
1973 /* if propagation is enabled, fix the variable to the new solution value and propagate the fixation
1974 * (to fix other variables and to find out early whether solution is already infeasible)
1975 */
1976 if( !marksuspicious && probing )
1977 {
1978 /* this assert should be always fulfilled because we run this heuristic at the root node only and do not
1979 * perform probing if nprobings is less than DEFAULT_PROPBREAKER (currently: 65000)
1980 */
1982
1984 SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) );
1985 ndomredsfound = 0;
1986
1987 SCIPdebugMsg(scip, " Shift %g(%g originally) is optimal, propagate solution\n", optimalshiftvalue, origsolval);
1988 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
1989
1990 ++nprobings;
1991 SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
1992 SCIPdebugMsg(scip, "Propagation finished! <%" SCIP_LONGINT_FORMAT "> domain reductions %s, <%d> probing depth\n", ndomredsfound, cutoff ? "CUTOFF" : "",
1994 }
1995 assert(!cutoff || probing);
1996
1997 /* propagation led to an empty domain, hence we backtrack and postpone the variable */
1998 if( cutoff )
1999 {
2000 assert(probing);
2001
2002 ++ncutoffs;
2003
2004 /* only continue heuristic if number of cutoffs occurred so far is reasonably small */
2005 if( heurdata->cutoffbreaker >= 0 && ncutoffs >= ((heurdata->maxcutoffquot * SCIPgetProbingDepth(scip)) + heurdata->cutoffbreaker) )
2006 break;
2007
2008 cutoff = FALSE;
2009
2010 /* backtrack to the parent of the current node */
2013
2014 /* this assert should be always fulfilled because we run this heuristic at the root node only and do not
2015 * perform probing if nprobings is less than DEFAULT_PROPBREAKER (currently: 65000)
2016 */
2018
2019 /* if the variable upper and lower bound are equal to the solution value to which we tried to fix the variable,
2020 * we are trapped at an infeasible node and break; this can only happen due to an intermediate global bound change of the variable,
2021 * I guess
2022 */
2023 if( SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), origsolval) && SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), origsolval) )
2024 {
2025 cutoff = TRUE;
2026 break;
2027 }
2028 else if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), origsolval) && REALABS( origsolval ) < 1.0 / SCIPepsilon(scip) )
2029 {
2030 /* if the variable was set to one of its bounds, repropagate by tightening this bound by 1.0 into the
2031 * direction of the other bound, if possible; if the bound is too large (in abs value) do not even bother
2032 */
2033 assert(SCIPisFeasGE(scip, SCIPvarGetUbLocal(var), origsolval + 1.0));
2034
2035 ndomredsfound = 0;
2037 SCIP_CALL( SCIPchgVarLbProbing(scip, var, origsolval + 1.0) );
2038 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
2039
2040 SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
2041 }
2042 else if( SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), origsolval) && REALABS( origsolval ) < 1.0 / SCIPepsilon(scip) )
2043 {
2044 /* if the variable was set to one of its bounds, repropagate by tightening this bound by 1.0 into the
2045 * direction of the other bound, if possible; if the bound is too large (in abs value) do not even bother
2046 */
2047 assert(SCIPisFeasLE(scip, SCIPvarGetLbLocal(var), origsolval - 1.0));
2048
2049 ndomredsfound = 0;
2050
2052 SCIP_CALL( SCIPchgVarUbProbing(scip, var, origsolval - 1.0) );
2053 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
2054
2055 SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
2056 }
2057
2058 /* if the tightened bound again leads to a cutoff, both subproblems are proven infeasible and the heuristic
2059 * can be stopped */
2060 if( cutoff )
2061 {
2062 break;
2063 }
2064 else
2065 {
2066 /* since repropagation was successful, we indicate that this variable led to a cutoff in one direction */
2067 marksuspicious = TRUE;
2068 }
2069 }
2070
2071 if( marksuspicious )
2072 {
2073 /* mark the variable as suspicious */
2074 assert(permutedvarindex == permutation[c]);
2075
2076 ++lastindexofsusp;
2077 assert(lastindexofsusp >= 0 && lastindexofsusp <= c);
2078
2079 permutation[c] = permutation[lastindexofsusp];
2080 permutation[lastindexofsusp] = permutedvarindex;
2081
2082 SCIPdebugMsg(scip, " Suspicious variable! Postponed from pos <%d> to position <%d>\n", c, lastindexofsusp);
2083 }
2084 else
2085 {
2086 SCIPdebugMsg(scip, "Variable <%d><%s> successfully shifted by value <%g>!\n", permutedvarindex,
2087 SCIPvarGetName(var), optimalshiftvalue);
2088
2089 /* update solution */
2090 SCIP_CALL( SCIPsetSolVal(scip, sol, var, origsolval) );
2091
2092 /* only to ensure that some assertions can be made later on */
2093 if( !probing )
2094 {
2095 SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) );
2096 }
2097 }
2098 }
2099 SCIPdebugMsg(scip, "Heuristic finished with %d remaining violations and %d remaining variables!\n",
2100 nviolatedrows, lastindexofsusp + 1);
2101
2102 /* if constructed solution might be feasible, go through the queue of suspicious variables and set the solution
2103 * values
2104 */
2105 if( nviolatedrows == 0 && !cutoff )
2106 {
2107 SCIP_Bool stored;
2108 SCIP_Bool trysol;
2109 SCIP_Bool solvelp;
2110
2111 for( v = 0; v <= lastindexofsusp; ++v )
2112 {
2113 SCIP_VAR* var;
2114 SCIP_Real origsolval;
2115 int permutedvarindex;
2116
2117 /* get the column position of the variable */
2118 permutedvarindex = permutation[v];
2119 var = SCIPcolGetVar(heurdata->lpcols[permutedvarindex]);
2120 assert(varIsDiscrete(var, impliscontinuous));
2121
2122 /* update the transformation of the variable, since the bound might have changed after the last update. */
2123 if( heurdata->probing )
2124 SCIP_CALL( updateTransformation(scip, matrix, heurdata, permutedvarindex, SCIPvarGetLbLocal(var),
2125 SCIPvarGetUbLocal(var), violatedrows, violatedrowpos, &nviolatedrows) );
2126
2127 /* retransform the solution value from the heuristic transformed space, set the solution value accordingly */
2128 assert(varIsDiscrete(var, impliscontinuous));
2129 origsolval = retransformVariable(scip, matrix, var, permutedvarindex, 0.0);
2131 && SCIPisFeasLE(scip, origsolval, SCIPvarGetUbLocal(var)));
2132 SCIP_CALL( SCIPsetSolVal(scip, sol, var, origsolval) );
2133 SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) ); /* only to ensure that some assertions can be made later */
2134
2135 SCIPdebugMsg(scip, " Remaining variable <%s> set to <%g>; %d Violations\n", SCIPvarGetName(var), origsolval,
2136 nviolatedrows);
2137 }
2138
2139 /* Fixing of remaining variables led to infeasibility */
2140 if( nviolatedrows > 0 )
2141 goto TERMINATE2;
2142
2143 trysol = TRUE;
2144
2145 /* check if enough variables have been fixed (including continuous) to solve the remaining LP */
2146 if( nlpcols != matrix->ndiscvars )
2147 {
2148 SCIP_VAR** vars;
2149 int nvars = SCIPgetNVars(scip);
2150 int nminfixings = (int)(SCIPceil(scip, heurdata->minfixingratelp * nvars));
2151 int nfixedvars = ndiscvars;
2152
2154
2155 /* count fixed variables */
2156 for( v = ndiscvars; v < nvars && nfixedvars < nminfixings; ++v )
2157 {
2159 ++nfixedvars;
2160 }
2161
2162 solvelp = (nfixedvars >= nminfixings);
2163 trysol = solvelp;
2164 SCIPdebugMsg(scip, "Fixed %d of %d (%.1f %%) variables after probing -> %s\n",
2165 nfixedvars, nvars, (100.0 * nfixedvars / (SCIP_Real)nvars),
2166 solvelp ? "continue and solve LP for remaining variables" : "terminate without LP");
2167 }
2168 else /* no need to solve an LP */
2169 solvelp = FALSE;
2170
2171 /* if the constructed solution might still be extendable to a feasible solution, try this by
2172 * solving the remaining LP
2173 */
2174 if( solvelp )
2175 {
2176 char strbuf[SCIP_MAXSTRLEN];
2177 /* case that remaining LP has to be solved */
2179 int ncols;
2180
2181#ifndef NDEBUG
2182 {
2183 SCIP_VAR** vars;
2184
2186 assert(vars != NULL);
2187 /* ensure that all discrete variables in the remaining LP are fixed */
2188 for( v = 0; v < ndiscvars; ++v )
2189 {
2190 if( SCIPvarIsInLP(vars[v]) )
2191 {
2193 }
2194 }
2195 }
2196#endif
2197
2198 /* print message if relatively large LP is solved from scratch, since this could lead to a longer period during
2199 * which the user sees no output; more detailed probing stats only in debug mode */
2200 ncols = SCIPgetNLPCols(scip);
2201 if( !SCIPisLPSolBasic(scip) && ncols > 1000 )
2202 {
2203 int nunfixedcols = SCIPgetNUnfixedLPCols(scip);
2204
2205 if( nunfixedcols > 0.5 * ncols )
2206 {
2208 "Heuristic " HEUR_NAME " solving LP from scratch with %.1f %% unfixed columns (%d of %d) ...\n",
2209 100.0 * (nunfixedcols / (SCIP_Real)ncols), nunfixedcols, ncols);
2210 }
2211 }
2212 SCIPdebugMsg(scip, "Heuristic " HEUR_NAME " probing LP: %s\n",
2214 SCIPdebugMsg(scip, " -> old LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
2215
2216#ifdef SCIP_DEBUG
2217 SCIP_CALL( SCIPwriteLP(scip, "shiftandpropagatelp.mps") );
2218#endif
2219 /* solve LP;
2220 * errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
2221 * hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
2222 */
2223#ifdef NDEBUG
2224 {
2225 SCIP_RETCODE retstat;
2226 retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
2227 if( retstat != SCIP_OKAY )
2228 {
2229 SCIPwarningMessage(scip, "Error while solving LP in SHIFTANDPROPAGATE heuristic; LP solve terminated with code <%d>\n",
2230 retstat);
2231 }
2232 }
2233#else
2235#endif
2236
2237 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
2238 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
2239
2240 /* check if this is a feasible solution */
2242 {
2243 /* copy the current LP solution to the working solution */
2245 }
2246 else
2247 trysol = FALSE;
2248
2250 }
2251
2252 /* check solution for feasibility, and add it to solution store if possible.
2253 * None of integrality, feasibility of LP rows, variable bounds have to be checked, because they
2254 * are guaranteed by the heuristic at this stage.
2255 */
2256 if( trysol )
2257 {
2258 SCIP_Bool printreason;
2259 SCIP_Bool completely;
2260#ifdef SCIP_DEBUG
2261 printreason = TRUE;
2262#else
2263 printreason = FALSE;
2264#endif
2265#ifndef NDEBUG
2266 completely = TRUE; /*lint !e838*/
2267#else
2268 completely = FALSE;
2269#endif
2270
2271 /* we once also checked the variable bounds which should not be necessary */
2272 SCIP_CALL( SCIPtrySol(scip, sol, printreason, completely, FALSE, FALSE, FALSE, &stored) );
2273
2274 if( stored )
2275 {
2276 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
2279
2280 SCIPstatisticMessage(" Shiftandpropagate solution value: %16.9g \n", SCIPgetSolOrigObj(scip, sol));
2281 }
2282 }
2283 }
2284 else
2285 {
2286 SCIPdebugMsg(scip, "Solution constructed by heuristic is already known to be infeasible\n");
2287 }
2288
2289 SCIPstatistic( heurdata->nremainingviols = nviolatedrows; );
2290
2291 TERMINATE2:
2292 /* free allocated memory in reverse order of allocation */
2293 for( c = matrix->ndiscvars - 1; c >= 0; --c )
2294 {
2295 SCIP_VAR* var;
2296
2297 var = SCIPcolGetVar(heurdata->lpcols[c]);
2298 assert(var != NULL);
2299 assert(eventdatas[c] != NULL);
2300
2301 SCIP_CALL( SCIPdropVarEvent(scip, var, EVENTTYPE_SHIFTANDPROPAGATE, eventhdlr, eventdatas[c], -1) );
2302 SCIPfreeBuffer(scip, &(eventdatas[c]));
2303 }
2304 SCIPfreeBufferArray(scip, &eventdatas);
2305
2306 if( violatedvarrows != NULL )
2307 {
2308 assert(heurdata->sortkey == 'v' || heurdata->sortkey == 't');
2309 SCIPfreeBufferArray(scip, &violatedvarrows);
2310 }
2311 /* free all allocated memory */
2312 SCIPfreeBufferArray(scip, &violatedrowpos);
2313 SCIPfreeBufferArray(scip, &violatedrows);
2314 SCIPfreeBufferArray(scip, &violationchange);
2315 SCIPfreeBufferArray(scip, &steps);
2316 SCIPfreeBufferArray(scip, &heurdata->rowweights);
2317 SCIPfreeBufferArray(scip, &permutation);
2319
2320 eventhdlrdata->nviolatedrows = NULL;
2321 eventhdlrdata->violatedrowpos = NULL;
2322 eventhdlrdata->violatedrows = NULL;
2323
2324 TERMINATE:
2325 /* terminate probing mode and free the remaining memory */
2327 heurdata->ncutoffs += ncutoffs;
2328 heurdata->nprobings += nprobings;
2329 heurdata->nlpiters = SCIPgetNLPIterations(scip) - heurdata->nlpiters;
2330 );
2331
2333 freeMatrix(scip, &matrix);
2334 SCIPfreeBufferArray(scip, &colposs);
2336 eventhdlrdata->matrix = NULL;
2337
2338 return SCIP_OKAY;
2339}
2340
2341/** event handler execution method for the heuristic which catches all
2342 * events in which a lower or upper bound were tightened */
2343static
2344SCIP_DECL_EVENTEXEC(eventExecShiftandpropagate)
2345{ /*lint --e{715}*/
2346 SCIP_EVENTHDLRDATA* eventhdlrdata;
2347 SCIP_VAR* var;
2348 SCIP_COL* col;
2349 SCIP_Real lb;
2350 SCIP_Real ub;
2351 int colpos;
2352 CONSTRAINTMATRIX* matrix;
2354
2355 assert(scip != NULL);
2356 assert(eventhdlr != NULL);
2357
2359
2360 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2361 assert(eventhdlrdata != NULL);
2362
2363 matrix = eventhdlrdata->matrix;
2364
2365 heurdata = eventhdlrdata->heurdata;
2366 assert(heurdata != NULL && heurdata->lpcols != NULL);
2367
2368 colpos = eventdata->colpos;
2369
2370 assert(0 <= colpos && colpos < matrix->ndiscvars);
2371
2372 col = heurdata->lpcols[colpos];
2373 var = SCIPcolGetVar(col);
2374
2375 lb = SCIPvarGetLbLocal(var);
2376 ub = SCIPvarGetUbLocal(var);
2377
2378 SCIP_CALL( updateTransformation(scip, matrix, eventhdlrdata->heurdata, colpos, lb, ub, eventhdlrdata->violatedrows,
2379 eventhdlrdata->violatedrowpos, eventhdlrdata->nviolatedrows) );
2380
2381 return SCIP_OKAY;
2382}
2383
2384/*
2385 * primal heuristic specific interface methods
2386 */
2387
2388/** creates the shiftandpropagate primal heuristic and includes it in SCIP */
2390 SCIP* scip /**< SCIP data structure */
2391 )
2392{
2394 SCIP_HEUR* heur;
2395 SCIP_EVENTHDLRDATA* eventhandlerdata;
2396 SCIP_EVENTHDLR* eventhdlr;
2397
2398 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhandlerdata) );
2399 eventhandlerdata->matrix = NULL;
2400
2401 eventhdlr = NULL;
2403 eventExecShiftandpropagate, eventhandlerdata) );
2404 assert(eventhdlr != NULL);
2405
2406 /* create Shiftandpropagate primal heuristic data */
2408 heurdata->rowweights = NULL;
2409 heurdata->nlpcols = 0;
2410 heurdata->eventhdlr = eventhdlr;
2411
2412 /* include primal heuristic */
2415 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecShiftandpropagate, heurdata) );
2416
2417 assert(heur != NULL);
2418
2419 /* primal heuristic is safe to use in exact solving mode */
2420 SCIPheurMarkExact(heur);
2421
2422 /* set non-NULL pointers to callback methods */
2423 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyShiftandpropagate) );
2424 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeShiftandpropagate) );
2425 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitShiftandpropagate) );
2426 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitShiftandpropagate) );
2427
2428 /* add shiftandpropagate primal heuristic parameters */
2429 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nproprounds",
2430 "The number of propagation rounds used for each propagation",
2431 &heurdata->nproprounds, TRUE, DEFAULT_NPROPROUNDS, -1, 1000, NULL, NULL) );
2432 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/relax", "Should continuous variables be relaxed?",
2433 &heurdata->relax, TRUE, DEFAULT_RELAX, NULL, NULL) );
2434 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/probing", "Should domains be reduced by probing?",
2435 &heurdata->probing, TRUE, DEFAULT_PROBING, NULL, NULL) );
2436 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/onlywithoutsol",
2437 "Should heuristic only be executed if no primal solution was found, yet?",
2438 &heurdata->onlywithoutsol, TRUE, DEFAULT_ONLYWITHOUTSOL, NULL, NULL) );
2439 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/cutoffbreaker", "The number of cutoffs before heuristic stops",
2440 &heurdata->cutoffbreaker, TRUE, DEFAULT_CUTOFFBREAKER, -1, 1000000, NULL, NULL) );
2441 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/sortkey",
2442 "the key for variable sorting: (n)orms down, norms (u)p, (v)iolations down, viola(t)ions up, or (r)andom",
2443 &heurdata->sortkey, TRUE, DEFAULT_SORTKEY, SORTKEYS, NULL, NULL) );
2444 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/sortvars", "Should variables be sorted for the heuristic?",
2445 &heurdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL));
2446 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/collectstats", "should variable statistics be collected during probing?",
2447 &heurdata->collectstats, TRUE, DEFAULT_COLLECTSTATS, NULL, NULL) );
2448 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/stopafterfeasible",
2449 "Should the heuristic stop calculating optimal shift values when no more rows are violated?",
2450 &heurdata->stopafterfeasible, TRUE, DEFAULT_STOPAFTERFEASIBLE, NULL, NULL) );
2451 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/preferbinaries",
2452 "Should binary variables be shifted first?",
2453 &heurdata->preferbinaries, TRUE, DEFAULT_PREFERBINARIES, NULL, NULL) );
2454 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/nozerofixing",
2455 "should variables with a zero shifting value be delayed instead of being fixed?",
2456 &heurdata->nozerofixing, TRUE, DEFAULT_NOZEROFIXING, NULL, NULL) );
2457 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/fixbinlocks",
2458 "should binary variables with no locks in one direction be fixed to that direction?",
2459 &heurdata->fixbinlocks, TRUE, DEFAULT_FIXBINLOCKS, NULL, NULL) );
2460 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/binlocksfirst",
2461 "should binary variables with no locks be preferred in the ordering?",
2462 &heurdata->binlocksfirst, TRUE, DEFAULT_BINLOCKSFIRST, NULL, NULL) );
2463 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/normalize",
2464 "should coefficients be normalized by max row coeff for col norm?",
2465 &heurdata->normalize, TRUE, DEFAULT_NORMALIZE, NULL, NULL) );
2466 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/updateweights",
2467 "should row weight be increased every time the row is violated?",
2468 &heurdata->updateweights, TRUE, DEFAULT_UPDATEWEIGHTS, NULL, NULL) );
2469 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/impliscontinuous",
2470 "should implicit integer variables be treated as continuous variables?",
2471 &heurdata->impliscontinuous, TRUE, DEFAULT_IMPLISCONTINUOUS, NULL, NULL) );
2472 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/selectbest",
2473 "should the heuristic choose the best candidate in every round? (set to FALSE for static order)?",
2474 &heurdata->selectbest, TRUE, DEFAULT_SELECTBEST, NULL, NULL) );
2475 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxcutoffquot",
2476 "maximum percentage of allowed cutoffs before stopping the heuristic",
2477 &heurdata->maxcutoffquot, TRUE, DEFAULT_MAXCUTOFFQUOT, 0.0, 2.0, NULL, NULL) );
2478 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingratelp",
2479 "minimum fixing rate over all variables (including continuous) to solve LP",
2480 &heurdata->minfixingratelp, TRUE, DEFAULT_MINFIXINGRATELP, 0.0, 1.0, NULL, NULL) );
2481
2482 return SCIP_OKAY;
2483}
#define EVENTHDLR_NAME
SCIP_VAR ** b
#define EVENTHDLR_DESC
#define DEFAULT_NORMALIZE
#define DEFAULT_SORTVARS
#define DEFAULT_RANDSEED
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_MAXTREEDEPTH
Definition def.h:306
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define ABS(x)
Definition def.h:225
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_LONGINT_FORMAT
Definition def.h:157
#define SCIPABORT()
Definition def.h:336
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
SCIP_Bool SCIPisStopped(SCIP *scip)
int SCIPgetNContVars(SCIP *scip)
Definition scip_prob.c:2569
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition scip_prob.c:2201
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:167
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_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:139
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:57
void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
Definition misc.c:10264
SCIP_RETCODE SCIPincludeHeurShiftandpropagate(SCIP *scip)
SCIP_Bool SCIPisCertified(SCIP *scip)
int SCIPcolGetLPPos(SCIP_COL *col)
Definition lp.c:17487
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition lp.c:17425
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
Definition lp.c:17455
SCIP_Bool SCIPcolIsImpliedIntegral(SCIP_COL *col)
Definition lp.c:17466
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition lp.c:17555
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition lp.c:17545
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition lp.c:17534
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition lp.c:17509
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition scip_event.c:111
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:396
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:406
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition scip_event.c:413
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:183
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition heur.c:1368
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition scip_heur.c:122
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:167
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition heur.c:1457
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:215
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:199
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition heur.c:1467
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition heur.c:1378
SCIP_RETCODE SCIPflushLP(SCIP *scip)
Definition scip_lp.c:154
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition scip_lp.c:87
SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
Definition scip_lp.c:130
SCIP_Bool SCIPisLPConstructed(SCIP *scip)
Definition scip_lp.c:105
SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
Definition scip_lp.c:477
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition scip_lp.c:576
int SCIPgetNLPRows(SCIP *scip)
Definition scip_lp.c:632
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition scip_lp.c:174
int SCIPgetNUnfixedLPCols(SCIP *scip)
Definition scip_lp.c:554
int SCIPgetNLPCols(SCIP *scip)
Definition scip_lp.c:533
SCIP_RETCODE SCIPwriteLP(SCIP *scip, const char *filename)
Definition scip_lp.c:907
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition scip_lp.c:673
#define SCIPfreeBuffer(scip, ptr)
Definition scip_mem.h:134
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPallocBuffer(scip, ptr)
Definition scip_mem.h:122
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPfreeBlockMemoryNull(scip, ptr)
Definition scip_mem.h:109
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
int SCIPgetProbingDepth(SCIP *scip)
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
char * SCIPsnprintfProbingStats(SCIP *scip, char *strbuf, int len)
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
SCIP_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1886
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition lp.c:17686
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition lp.c:17632
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition lp.c:17696
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition lp.c:17621
int SCIProwGetLPPos(SCIP_ROW *row)
Definition lp.c:17895
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
const char * SCIProwGetName(SCIP_ROW *row)
Definition lp.c:17745
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition lp.c:17652
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition lp.c:17642
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2986
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition scip_sol.c:2351
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition scip_sol.c:4017
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1890
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition scip_sol.c:1569
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
Definition sol.c:4319
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
Definition scip_tree.c:436
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition scip_tree.c:91
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:23715
void SCIPdisableVarHistory(SCIP *scip)
Definition scip_var.c:11102
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
void SCIPenableVarHistory(SCIP *scip)
Definition scip_var.c:11083
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition var.c:23738
void SCIPsortDownIntInt(int *intarray1, int *intarray2, int len)
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
#define HEUR_TIMING
return SCIP_OKAY
#define HEUR_FREQOFS
#define HEUR_DESC
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
SCIPfreeSol(scip, &heurdata->sol))
#define HEUR_NAME
#define HEUR_FREQ
#define HEUR_USESSUBSCIP
SCIPcreateSol(scip, &heurdata->sol, heur))
SCIPfreeRandom(scip, &heurdata->randnumgen)
#define DEFAULT_ONLYWITHOUTSOL
Definition heur_bound.c:69
SCIP_Bool lperror
int c
static SCIP_LPSOLSTAT lpsolstat
SCIPendProbing(scip))
SCIP_Bool cutoff
SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE))
int nlprows
SCIP_ROW ** lprows
static SCIP_SOL * sol
int r
assert(minobj< SCIPgetCutoffbound(scip))
SCIP_ROW ** violrows
int nvars
SCIPlinkLPSol(scip, sol))
#define DEFAULT_MINFIXINGRATELP
Definition heur_locks.c:89
SCIP_VAR * var
static SCIP_VAR ** vars
static void relaxVar(SCIP *scip, SCIP_VAR *var, CONSTRAINTMATRIX *matrix)
#define DEFAULT_RELAX
static void transformVariable(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, int colpos)
static SCIP_RETCODE getOptimalShiftingValue(SCIP *scip, CONSTRAINTMATRIX *matrix, int varindex, int direction, int *rowweights, SCIP_Real *steps, int *violationchange, SCIP_Real *beststep, int *rowviolations)
static void getRowData(CONSTRAINTMATRIX *matrix, int rowindex, SCIP_Real **valpointer, SCIP_Real *lhs, SCIP_Real *rhs, int **indexpointer, int *nrowvals)
static void checkRowViolation(SCIP *scip, CONSTRAINTMATRIX *matrix, int rowindex, int *violatedrows, int *violatedrowpos, int *nviolatedrows, int *rowweights, SCIP_Bool updateweights)
static SCIP_Bool colIsDiscrete(SCIP_COL *col, SCIP_Bool impliscontinuous)
#define DEFAULT_PROPBREAKER
#define DEFAULT_IMPLISCONTINUOUS
#define DEFAULT_PREFERBINARIES
#define DEFAULT_NPROPROUNDS
#define DEFAULT_FIXBINLOCKS
@ TRANSFORMSTATUS_NONE
@ TRANSFORMSTATUS_FREE
@ TRANSFORMSTATUS_NEG
@ TRANSFORMSTATUS_LB
static void freeMatrix(SCIP *scip, CONSTRAINTMATRIX **matrix)
#define DEFAULT_SELECTBEST
#define DEFAULT_BINLOCKSFIRST
static SCIP_RETCODE updateTransformation(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, int varindex, SCIP_Real lb, SCIP_Real ub, int *violatedrows, int *violatedrowpos, int *nviolatedrows)
#define SORTKEYS
#define DEFAULT_MAXCUTOFFQUOT
#define DEFAULT_CUTOFFBREAKER
enum TransformStatus TRANSFORMSTATUS
#define DEFAULT_WEIGHT_INEQUALITY
#define DEFAULT_NOZEROFIXING
#define DEFAULT_SORTKEY
static void checkViolations(SCIP *scip, CONSTRAINTMATRIX *matrix, int colidx, int *violatedrows, int *violatedrowpos, int *nviolatedrows, int *rowweights, SCIP_Bool updateweights)
#define DEFAULT_UPDATEWEIGHTS
#define DEFAULT_COLLECTSTATS
static SCIP_Real retransformVariable(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_VAR *var, int varindex, SCIP_Real solvalue)
static SCIP_Bool varIsDiscrete(SCIP_VAR *var, SCIP_Bool impliscontinuous)
struct ConstraintMatrix CONSTRAINTMATRIX
#define DEFAULT_WEIGHT_EQUALITY
static void getColumnData(CONSTRAINTMATRIX *matrix, int colindex, SCIP_Real **valpointer, int **indexpointer, int *ncolvals)
#define DEFAULT_STOPAFTERFEASIBLE
#define DEFAULT_PROBING
static SCIP_RETCODE initMatrix(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, int *colposs, int *nmaxrows, SCIP_Bool relax, SCIP_Bool *initialized, SCIP_Bool *infeasible)
#define EVENTTYPE_SHIFTANDPROPAGATE
preroot heuristic that alternatingly fixes variables and propagates domains
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
public methods for managing events
public methods for primal heuristics
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPstatisticMessage
#define SCIPdebug(x)
Definition pub_message.h:93
#define SCIPstatistic(x)
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for primal CIP solutions
public methods for problem variables
public methods for certified solving
public methods for event handler plugins and event handlers
public methods for exact solving
general public methods
public methods for primal heuristic plugins and divesets
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for random numbers
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition type_event.h:160
#define SCIP_DECL_EVENTEXEC(x)
Definition type_event.h:259
#define SCIP_DECL_HEURCOPY(x)
Definition type_heur.h:97
struct SCIP_HeurData SCIP_HEURDATA
Definition type_heur.h:77
struct SCIP_Heur SCIP_HEUR
Definition type_heur.h:76
#define SCIP_DECL_HEURINIT(x)
Definition type_heur.h:113
#define SCIP_DECL_HEUREXIT(x)
Definition type_heur.h:121
#define SCIP_DECL_HEURFREE(x)
Definition type_heur.h:105
#define SCIP_DECL_HEUREXEC(x)
Definition type_heur.h:163
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition type_lp.h:52
struct SCIP_Col SCIP_COL
Definition type_lp.h:99
@ SCIP_LPSOLSTAT_NOTSOLVED
Definition type_lp.h:43
@ SCIP_LPSOLSTAT_OPTIMAL
Definition type_lp.h:44
@ SCIP_VERBLEVEL_FULL
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:189
struct SCIP_RandNumGen SCIP_RANDNUMGEN
Definition type_misc.h:127
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_FOUNDSOL
Definition type_result.h:56
@ SCIP_INVALIDDATA
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
#define SCIP_DEPRECATED_VARTYPE_IMPLINT
Definition type_var.h:79
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:65
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_VARSTATUS_COLUMN
Definition type_var.h:53
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73