SCIP Doxygen Documentation
Loading...
Searching...
No Matches
heur_octane.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_octane.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief octane primal heuristic based on Balas, Ceria, Dawande, Margot, and Pataki
28 * @author Timo Berthold
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
34#include "scip/heur_octane.h"
35#include "scip/pub_heur.h"
36#include "scip/pub_lp.h"
37#include "scip/pub_message.h"
38#include "scip/pub_misc_sort.h"
39#include "scip/pub_var.h"
40#include "scip/scip_branch.h"
41#include "scip/scip_general.h"
42#include "scip/scip_heur.h"
43#include "scip/scip_lp.h"
44#include "scip/scip_mem.h"
45#include "scip/scip_message.h"
46#include "scip/scip_numerics.h"
47#include "scip/scip_param.h"
48#include "scip/scip_prob.h"
49#include "scip/scip_sol.h"
51
52
53#define HEUR_NAME "octane"
54#define HEUR_DESC "octane primal heuristic for pure {0;1}-problems based on Balas et al."
55#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_ROUNDING
56#define HEUR_PRIORITY -1008000
57#define HEUR_FREQ -1
58#define HEUR_FREQOFS 0
59#define HEUR_MAXDEPTH -1
60#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE
61#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
62
63#define DEFAULT_FMAX 100 /**< {0,1}-points to be checked */
64#define DEFAULT_FFIRST 10 /**< {0,1}-points to be generated at first */
65#define DEFAULT_USEFRACSPACE TRUE /**< use heuristic for the space of fractional variables or for whole space? */
66
67/** primal heuristic data */
68struct SCIP_HeurData
69{
70 SCIP_SOL* sol; /**< working solution */
71 int f_max; /**< {0,1}-points to be checked */
72 int f_first; /**< {0,1}-points to be generated at first in order to check whether restart is necessary */
73 int lastrule; /**< last ray selection rule that was performed */
74 SCIP_Bool usefracspace; /**< use heuristic for the space of fractional variables or for the whole space? */
75 SCIP_Bool useobjray; /**< should the inner normal of the objective be used as one ray direction? */
76 SCIP_Bool useavgray; /**< should the average ray of the basic cone be used as one ray direction? */
77 SCIP_Bool usediffray; /**< should difference between root sol and current LP sol be used as one ray direction? */
78 SCIP_Bool useavgwgtray; /**< should the weighted average ray of the basic cone be used as one ray direction? */
79 SCIP_Bool useavgnbray; /**< should the average ray of the nonbasic cone be used as one ray direction? */
80 int nsuccess; /**< number of runs that produced at least one feasible solution */
81};
82
83/*
84 * Local methods
85 */
86
87
88/** tries to insert the facet obtained from facet i flipped in component j into the list of the fmax nearest facets */
89static
91 SCIP* scip, /**< SCIP data structure */
92 SCIP_Bool** facets, /**< facets got so far */
93 SCIP_Real* lambda, /**< distances of the facets */
94 int i, /**< current facet */
95 int j, /**< component to flip */
96 int f_max, /**< maximal number of facets to create */
97 int nsubspacevars, /**< dimension of the fractional space */
98 SCIP_Real lam, /**< distance of the current facet */
99 int* nfacets /**< number of facets */
100 )
101{
102 SCIP_Bool* lastfacet;
103 int k;
104
105 assert(scip != NULL);
106 assert(facets != NULL);
107 assert(lambda != NULL);
108 assert(nfacets != NULL);
109
110 if( SCIPisFeasLE(scip, lam, 0.0) || SCIPisFeasGE(scip, lam, lambda[f_max-1]) )
111 return;
112
113 lastfacet = facets[f_max];
114
115 /* shifting lam through lambda, lambda keeps increasingly sorted */
116 for( k = f_max; k > 0 && SCIPisFeasGT(scip, lambda[k-1], lam); --k )
117 {
118 lambda[k] = lambda[k-1];
119 facets[k] = facets[k-1];
120 }
121 assert(i < k && k < f_max );
122
123 /* inserting new facet into list, new facet is facet at position i flipped in coordinate j, new distance lam */
124 facets[k] = lastfacet;
125 lambda[k] = lam;
126
127 /*lint --e{866}*/
128 BMScopyMemoryArray(facets[k], facets[i], nsubspacevars);
129 facets[k][j] = !facets[k][j];
130 (*nfacets)++;
131}
132
133/** constructs a solution from a given facet paying attention to the transformations made at the beginning of OCTANE */
134static
136 SCIP* scip, /**< SCIP data structure */
137 SCIP_Bool* facet, /**< current facet */
138 SCIP_SOL* sol, /**< solution to create */
139 SCIP_Bool* sign, /**< marker for retransformation */
140 SCIP_VAR** subspacevars, /**< pointer to fractional space variables */
141 int nsubspacevars /**< dimension of fractional space */
142 )
143{
144 int v;
145
146 assert(scip != NULL);
147 assert(facet != NULL);
148 assert(sol != NULL);
149 assert(sign != NULL);
150 assert(subspacevars != NULL);
151
153 for( v = nsubspacevars - 1; v >= 0; --v )
154 {
155 /* after permutation, a variable should be set to 1, iff there was no reflection in this coordinate and the hit
156 * facet has coordinate + or there was a reflection and the facet has coordinate - */
157 if( facet[v] == sign[v] )
158 {
159 SCIP_CALL( SCIPsetSolVal(scip, sol, subspacevars[v], 1.0) );
160 }
161 else
162 {
163 SCIP_CALL( SCIPsetSolVal(scip, sol, subspacevars[v], 0.0) );
164 }
165 }
166
167 return SCIP_OKAY;
168}
169
170/** generates the direction of the shooting ray as the inner normal of the objective function */
171static
173 SCIP* scip, /**< SCIP data structure */
174 SCIP_Real* raydirection, /**< shooting ray */
175 SCIP_VAR** subspacevars, /**< pointer to fractional space variables */
176 int nsubspacevars /**< dimension of fractional space */
177 )
178{
179 int v;
180
181 assert(scip != NULL);
182 assert(raydirection != NULL);
183 assert(subspacevars != NULL);
184
185 for( v = nsubspacevars - 1; v >= 0; --v )
186 raydirection[v] = SCIPvarGetObj(subspacevars[v]);
187 return SCIP_OKAY;
188}
189
190/** generates the direction of the shooting ray as the difference between the root and the current LP solution */
191static
193 SCIP* scip, /**< SCIP data structure */
194 SCIP_Real* raydirection, /**< shooting ray */
195 SCIP_VAR** subspacevars, /**< pointer to fractional space variables */
196 int nsubspacevars /**< dimension of fractional space */
197 )
198{
199 int v;
200
201 assert(scip != NULL);
202 assert(raydirection != NULL);
203 assert(subspacevars != NULL);
204
205 for( v = nsubspacevars - 1; v >= 0; --v )
206 raydirection[v] = SCIPvarGetLPSol(subspacevars[v]) - SCIPvarGetRootSol(subspacevars[v]);
207
208 return SCIP_OKAY;
209}
210
211
212/** generates the direction of the shooting ray as the average of the extreme rays of the basic cone */
213static
215 SCIP* scip, /**< SCIP data structure */
216 SCIP_Real* raydirection, /**< shooting ray */
217 SCIP_VAR** subspacevars, /**< pointer to fractional space variables */
218 int nsubspacevars, /**< dimension of fractional space */
219 SCIP_Bool weighted /**< should the rays be weighted? */
220 )
221{
222 SCIP_ROW** rows;
223 SCIP_Real** tableaurows;
224 SCIP_Real* rownorm;
225 SCIP_Real rowweight;
226 int** tableaurowinds; /* indices of non-zero entries */
227 int* ntableaurowinds; /* number of non-zero entries */
228 SCIP_Bool* usedrowids = NULL; /* visited row indices */
229 int* rowids; /* row indices */
230 int nrowids = 0; /* number of row indices */
231 int tableaurowind;
232 int nrows;
233 int i;
234 int j;
235 int sparse = -1; /* used to check that either all information is sparse or not sparse */
236
237 assert(scip != NULL);
238 assert(raydirection != NULL);
239 assert(subspacevars != NULL);
240 assert(nsubspacevars > 0);
241
242 /* get data */
243 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
244 assert(nrows > 0);
245 assert(rows != NULL);
246
247 /* allocate memory */
248 SCIP_CALL( SCIPallocBufferArray(scip, &tableaurows, nsubspacevars) );
249 SCIP_CALL( SCIPallocBufferArray(scip, &tableaurowinds, nsubspacevars) );
250 SCIP_CALL( SCIPallocBufferArray(scip, &ntableaurowinds, nsubspacevars) );
251 for( j = nsubspacevars - 1; j >= 0; --j )
252 {
253 /*lint --e{866}*/
254 SCIP_CALL( SCIPallocBufferArray(scip, &tableaurows[j], nrows) );
255 SCIP_CALL( SCIPallocBufferArray(scip, &tableaurowinds[j], nrows) );
256 }
257
258 SCIP_CALL( SCIPallocBufferArray(scip, &rownorm, nrows) );
259 BMSclearMemoryArray(rownorm, nrows);
260
261 /* clear ray */
262 BMSclearMemoryArray(raydirection, nsubspacevars);
263
264 /* get the relevant columns of the simplex tableau */
265 for( j = nsubspacevars - 1; j >= 0; --j )
266 {
267 assert(SCIPcolGetLPPos(SCIPvarGetCol(subspacevars[j])) >= 0);
268 SCIP_CALL( SCIPgetLPBInvACol(scip, SCIPcolGetLPPos(SCIPvarGetCol(subspacevars[j])), tableaurows[j], tableaurowinds[j], &ntableaurowinds[j]) );
269
270 if( ntableaurowinds[j] == -1 )
271 {
272 assert(sparse == 0 || sparse == -1);
273 sparse = 0;
274
275 for( i = nrows - 1; i >= 0; --i )
276 rownorm[i] += tableaurows[j][i] * tableaurows[j][i];
277 }
278 else
279 {
280 assert(sparse == 1 || sparse == -1);
281 sparse = 1;
282
283 /* allocate temporary memory */
284 if( usedrowids == NULL )
285 {
286 SCIP_CALL( SCIPallocBufferArray(scip, &rowids, nrows) );
287 SCIP_CALL( SCIPallocBufferArray(scip, &usedrowids, nrows) );
288 BMSclearMemoryArray(usedrowids, nrows);
289 }
290
291 for( i = ntableaurowinds[j] - 1; i >= 0; --i )
292 {
293 tableaurowind = tableaurowinds[j][i];
294 rownorm[tableaurowind] += tableaurows[j][tableaurowind] * tableaurows[j][tableaurowind];
295 assert(usedrowids != NULL); /* for lint */
296 if( !usedrowids[tableaurowind] )
297 {
298 usedrowids[tableaurowind] = TRUE;
299 rowids[nrowids] = tableaurowind; /*lint !e644*/
300 ++nrowids;
301 assert(nrowids <= nrows);
302 }
303 }
304 }
305 }
306
307 /* compute ray direction (dense) */
308 if( sparse == 0 )
309 {
310 /* take average over all rows of the tableau */
311 for( i = nrows - 1; i >= 0; --i )
312 {
313 if( SCIPisFeasZero(scip, rownorm[i]) )
314 continue;
315 else
316 rownorm[i] = sqrt(rownorm[i]);
317
318 if( weighted )
319 {
320 rowweight = SCIProwGetDualsol(rows[i]);
321 if( SCIPisFeasZero(scip, rowweight) )
322 continue;
323 }
324 else
325 rowweight = 1.0;
326
327 for( j = nsubspacevars - 1; j >= 0; --j )
328 {
329 raydirection[j] += tableaurows[j][i] / (rownorm[i] * rowweight);
330 assert( ! SCIPisInfinity(scip, REALABS(raydirection[j])) );
331 }
332 }
333 }
334 /* compute ray direction (sparse) */
335 else
336 {
337 SCIP_Real* rowweights;
338 int r;
339 int k;
340
341 assert(usedrowids != NULL);
342 assert(rowids != NULL);
343 assert(sparse == 1);
344 assert(0 <= nrowids && nrowids <= nrows);
345
346 SCIP_CALL( SCIPallocBufferArray(scip, &rowweights, nrows) );
347
348 /* compute norms of important rows and rowweights */
349 for( i = nrowids - 1; i >= 0; --i )
350 {
351 r = rowids[i];
352 assert(0 <= r && r < nrows);
353 assert(usedrowids[r]);
354
355 if( SCIPisFeasZero(scip, rownorm[r]) )
356 {
357 usedrowids[r] = FALSE;
358 --nrowids;
359 continue;
360 }
361 else
362 rownorm[r] = sqrt(rownorm[r]);
363
364 if( weighted )
365 {
366 rowweights[r] = SCIProwGetDualsol(rows[r]);
367 if( SCIPisFeasZero(scip, rowweights[r]) )
368 {
369 usedrowids[r] = FALSE;
370 --nrowids;
371 continue;
372 }
373 }
374 else
375 rowweights[r] = 1.0;
376 }
377
378 if( nrowids > 0 )
379 {
380 /* take average over all rows of the tableau */
381 for( j = nsubspacevars - 1; j >= 0; --j )
382 {
383 for( k = ntableaurowinds[j] - 1; k >= 0; --k )
384 {
385 tableaurowind = tableaurowinds[j][k];
386
387 if( usedrowids[tableaurowind] )
388 {
389 raydirection[j] += tableaurows[j][tableaurowind] / (rownorm[tableaurowind] * rowweights[tableaurowind]);
390 assert( ! SCIPisInfinity(scip, REALABS(raydirection[j])) );
391 }
392 }
393 }
394 }
395
396 SCIPfreeBufferArray(scip, &rowweights);
397 SCIPfreeBufferArray(scip, &usedrowids);
398 SCIPfreeBufferArray(scip, &rowids);
399 }
400 assert(usedrowids == NULL);
401
402 /* free memory */
403 SCIPfreeBufferArray(scip, &rownorm);
404 for( j = 0; j < nsubspacevars; ++j )
405 {
406 SCIPfreeBufferArray(scip, &tableaurowinds[j]);
407 SCIPfreeBufferArray(scip, &tableaurows[j]);
408 }
409 SCIPfreeBufferArray(scip, &ntableaurowinds);
410 SCIPfreeBufferArray(scip, &tableaurowinds);
411 SCIPfreeBufferArray(scip, &tableaurows);
412
413 return SCIP_OKAY;
414}
415
416
417/** generates the direction of the shooting ray as the average of the normalized non-basic vars and rows */
418static
420 SCIP* scip, /**< SCIP data structure */
421 SCIP_Real* raydirection, /**< shooting ray */
422 int* fracspace, /**< index set of fractional variables */
423 SCIP_VAR** subspacevars, /**< pointer to fractional space variables */
424 int nsubspacevars /**< dimension of fractional space */
425 )
426{
427 SCIP_ROW** rows;
428 SCIP_COL** cols;
429 int nrows;
430 int ncols;
431 int i;
432
433 assert(scip != NULL);
434 assert(raydirection != NULL);
435 assert(fracspace != NULL);
436 assert(subspacevars != NULL);
437
438 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
439 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
440
441 /* add up non-basic variables */
442 for( i = nsubspacevars - 1; i >= 0; --i )
443 {
444 SCIP_Real solval;
445
446 solval = SCIPvarGetLPSol(subspacevars[i]);
447
448 if( SCIPisFeasEQ(scip, solval, SCIPvarGetLbLocal(subspacevars[i])) )
449 raydirection[i] = +1.0;
450 else if( SCIPisFeasEQ(scip, solval, SCIPvarGetUbLocal(subspacevars[i])) )
451 raydirection[i] = -1.0;
452 else
453 raydirection[i] = 0.0;
454 }
455
456 /* add up non-basic rows */
457 for( i = nrows - 1; i >= 0; --i )
458 {
459 SCIP_Real dualsol;
460 SCIP_Real factor;
461 SCIP_Real* coeffs;
462 SCIP_Real rownorm;
463 int j;
464 int nnonz;
465
466 dualsol = SCIProwGetDualsol(rows[i]);
467 if( SCIPisFeasPositive(scip, dualsol) )
468 factor = 1.0;
469 else if( SCIPisFeasNegative(scip, dualsol) )
470 factor = -1.0;
471 else
472 continue;
473
474 /* get the row's data */
475 coeffs = SCIProwGetVals(rows[i]);
476 cols = SCIProwGetCols(rows[i]);
477
478 nnonz = SCIProwGetNNonz(rows[i]);
479
480 rownorm = 0.0;
481 for( j = nnonz - 1; j >= 0; --j )
482 {
483 SCIP_VAR* var;
484 var = SCIPcolGetVar(cols[j]);
485 if( fracspace[SCIPvarGetProbindex(var)] >= 0 )
486 rownorm += coeffs[j] * coeffs[j];
487 }
488
489 if( SCIPisFeasZero(scip,rownorm) )
490 continue;
491 else
492 {
493 assert(rownorm > 0);
494 rownorm = sqrt(rownorm);
495 }
496
497 for( j = nnonz - 1; j >= 0; --j )
498 {
499 SCIP_VAR* var;
500 int f;
501
502 var = SCIPcolGetVar(cols[j]);
503 f = fracspace[SCIPvarGetProbindex(var)];
504
505 if( f >= 0 )
506 {
507 raydirection[f] += factor * coeffs[j] / rownorm;
508 assert( ! SCIPisInfinity(scip, REALABS(raydirection[f])) );
509 }
510 }
511 }
512 return SCIP_OKAY;
513}
514
515/** generates the starting point for the shooting ray in original coordinates */
516static
518 SCIP* scip, /**< SCIP data structure */
519 SCIP_Real* rayorigin, /**< origin of the shooting ray */
520 SCIP_VAR** subspacevars, /**< pointer to fractional space variables */
521 int nsubspacevars /**< dimension of fractional space */
522 )
523{
524 int v;
525
526 assert(scip != NULL);
527 assert(rayorigin != NULL);
528 assert(subspacevars != NULL);
529
530 for( v = nsubspacevars - 1; v >= 0; --v )
531 rayorigin[v] = SCIPvarGetLPSol(subspacevars[v]);
532}
533
534/** translates the inner point of the LP to an inner point rayorigin of the unit hyper octahedron and
535 * transforms raydirection and rayorigin by reflections stored in sign
536 */
537static
539 SCIP_Real* rayorigin, /**< origin of the shooting ray */
540 SCIP_Real* raydirection, /**< direction of the shooting ray */
541 SCIP_Bool* sign, /**< marker for flipped coordinates */
542 int nsubspacevars /**< dimension of fractional space */
543 )
544{
545 int v;
546
547 assert(rayorigin != NULL);
548 assert(raydirection != NULL);
549 assert(sign != NULL);
550
551 for( v = nsubspacevars - 1; v >= 0; --v )
552 {
553 /* if raydirection[v] is negative, flip its sign */
554 if( raydirection[v] < 0 )
555 {
556 sign[v] = FALSE;
557 raydirection[v] *= -1.0;
558 rayorigin[v] *= -1.0; /* flip starting point in the same way like raydirection */
559 }
560 else
561 sign[v] = TRUE;
562 }
563}
564
565/** generates all facets, from which facet i could be obtained by a decreasing + to - flip
566 * or a nonincreasing - to + flip and tests whether they are among the fmax nearest ones
567 */
568static
570 SCIP* scip, /**< SCIP data structure */
571 SCIP_Bool** facets, /**< facets got so far */
572 SCIP_Real* lambda, /**< distances of the facets */
573 SCIP_Real* rayorigin, /**< origin of the shooting ray */
574 SCIP_Real* raydirection, /**< direction of the shooting ray */
575 SCIP_Real* negquotient, /**< array by which coordinates are sorted */
576 int nsubspacevars, /**< dimension of fractional space */
577 int f_max, /**< maximal number of facets to create */
578 int i, /**< current facet */
579 int* nfacets /**< number of facets */
580 )
581{
582 SCIP_Real p;
583 SCIP_Real q;
584 SCIP_Real lam;
585 int minplus;
586 int j;
587
588 assert(scip != NULL);
589 assert(facets != NULL);
590 assert(facets[i] != NULL);
591 assert(lambda != NULL);
592 assert(rayorigin != NULL);
593 assert(raydirection != NULL);
594 assert(negquotient != NULL);
595 assert(nfacets != NULL);
596 assert(0 <= i && i < f_max);
597
598 /* determine the p and q values of the next facet to fix as a closest one */
599 p = 0.5 * nsubspacevars;
600 q = 0.0;
601 for( j = nsubspacevars - 1; j >= 0; --j )
602 {
603 if( facets[i][j] )
604 {
605 p -= rayorigin[j];
606 q += raydirection[j];
607 }
608 else
609 {
610 p += rayorigin[j];
611 q -= raydirection[j];
612 }
613 }
614
615 /* get the first + entry of the facet */
616 minplus = -1;
617 for( j = 0; j < nsubspacevars; ++j )
618 {
619 if( facets[i][j] )
620 {
621 minplus = j;
622 break;
623 }
624 }
625
626 /* facet (- - ... -) cannot be hit, because raydirection >= 0 */
627 assert(minplus >= 0);
628 assert(q != 0.0);
629 assert(SCIPisFeasEQ(scip, lambda[i], p/q));
630 assert(lambda[i] >= 0.0);
631
632 /* reverse search for facets from which the actual facet can be got by a single, decreasing + to - flip */
633 /* a facet will be inserted into the queue, iff it is one of the fmax closest ones already found */
634 for( j = 0; j < nsubspacevars && !facets[i][j] && SCIPisFeasGT(scip, negquotient[j], lambda[i]); ++j )
635 {
636 if( SCIPisFeasPositive(scip, q + 2*raydirection[j]) )
637 {
638 lam = (p - 2*rayorigin[j]) / (q + 2*raydirection[j]);
639 tryToInsert(scip, facets, lambda, i, j, f_max, nsubspacevars, lam, nfacets);
640 }
641 }
642
643 /* reverse search for facets from which the actual facet can be got by a single, nonincreasing - to + flip */
644 /* a facet will be inserted into the queue, iff it is one of the fmax closest ones already found */
645 for( j = nsubspacevars - 1; j >= 0 && facets[i][j] && SCIPisFeasLE(scip, negquotient[j], lambda[i]); --j )
646 {
647 if( SCIPisFeasPositive(scip, q - 2*raydirection[j]) )
648 {
649 lam = (p + 2*rayorigin[j]) / (q - 2*raydirection[j]);
650 if( negquotient[minplus] <= lam )
651 tryToInsert(scip, facets, lambda, i, j, f_max, nsubspacevars, lam, nfacets);
652 }
653 }
654#ifndef NDEBUG
655 for( j = 1; j < f_max; j++)
656 assert(SCIPisFeasGE(scip, lambda[j], lambda[j-1]));
657#endif
658}
659
660/** tests, whether an array is completely zero */
661static
663 SCIP* scip, /**< SCIP data structure */
664 SCIP_Real* raydirection, /**< array to be checked */
665 int nsubspacevars /**< size of array */
666 )
667{
668 int v;
669 SCIP_Bool iszero;
670
671 assert(scip != NULL);
672 assert(raydirection != NULL);
673 iszero = TRUE;
674 for( v = nsubspacevars - 1; v >= 0; --v )
675 {
676 assert(!SCIPisInfinity(scip, raydirection[v]));
677
678 if( !SCIPisFeasZero(scip, raydirection[v]/100) )
679 iszero = FALSE;
680 else
681 raydirection[v] = 0.0;
682 }
683 return iszero;
684}
685
686
687/*
688 * Callback methods of primal heuristic
689 */
690
691/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
692static
693SCIP_DECL_HEURCOPY(heurCopyOctane)
694{ /*lint --e{715}*/
695 assert(scip != NULL);
696 assert(heur != NULL);
697
699
700 /* call inclusion method of primal heuristic */
702
703 return SCIP_OKAY;
704}
705
706/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
707static
708SCIP_DECL_HEURFREE(heurFreeOctane)
709{ /*lint --e{715}*/
711
712 assert(heur != NULL);
713 assert(scip != NULL);
714
716
717 /* free heuristic data */
719 assert(heurdata != NULL);
721 SCIPheurSetData(heur, NULL);
722
723 return SCIP_OKAY;
724}
725
726
727/** initialization method of primal heuristic (called after problem was transformed) */
728static
729SCIP_DECL_HEURINIT(heurInitOctane)
730{ /*lint --e{715}*/
732
733 assert(heur != NULL);
734
736
737 /* get heuristic data */
739 assert(heurdata != NULL);
740
741 /* create working solution */
742 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
743
744 /* initialize data */
745 heurdata->lastrule = 0;
746 heurdata->nsuccess = 0;
747
748 return SCIP_OKAY;
749}
750
751
752/** deinitialization method of primal heuristic (called before transformed problem is freed) */
753
754static
755SCIP_DECL_HEUREXIT(heurExitOctane)
756{ /*lint --e{715}*/
758
759 assert(heur != NULL);
760
762
763 /* get heuristic data */
765 assert(heurdata != NULL);
766
767 /* free working solution */
769
770 return SCIP_OKAY;
771}
772
773
774/** execution method of primal heuristic */
775static
776SCIP_DECL_HEUREXEC(heurExecOctane)
777{ /*lint --e{715}*/
779 SCIP_SOL* sol;
780 SCIP_SOL** first_sols; /* stores the first ffirst sols in order to check for common violation of a row */
781
782 SCIP_VAR** vars; /* the variables of the problem */
783 SCIP_VAR** fracvars; /* variables, that are fractional in current LP solution */
784 SCIP_VAR** subspacevars; /* the variables on which the search is performed. Either coinciding with vars or with the
785 * space of all fractional variables of the current LP solution */
786
787 SCIP_Real p; /* n/2 - <delta,x> ( for some facet delta ) */
788 SCIP_Real q; /* <delta,a> */
789
790 SCIP_Real* rayorigin; /* origin of the ray, vector x in paper */
791 SCIP_Real* raydirection; /* direction of the ray, vector a in paper */
792 SCIP_Real* negquotient; /* negated quotient of rayorigin and raydirection, vector v in paper */
793 SCIP_Real* lambda; /* stores the distance of the facets (s.b.) to the origin of the ray */
794
795 SCIP_Bool usefracspace; /* determines whether the search concentrates on fractional variables and fixes integer ones */
796 SCIP_Bool cons_viol; /* used for checking whether a linear constraint is violated by one of the possible solutions */
797 SCIP_Bool success;
798 SCIP_Bool* sign; /* signature of the direction of the ray */
799 SCIP_Bool** facets; /* list of extended facets */
800
801 int nvars; /* number of variables */
802 int nbinvars; /* number of 0-1-variables */
803 int nfracvars; /* number of fractional variables in current LP solution */
804 int nsubspacevars; /* dimension of the subspace on which the search is performed */
805 int nfacets; /* number of facets hidden by the ray that where already found */
806 int i; /* counter */
807 int j; /* counter */
808 int f_max; /* {0,1}-points to be checked */
809 int f_first; /* {0,1}-points to be generated at first in order to check whether a restart is necessary */
810 int r; /* counter */
811 int firstrule;
812
813 int* perm; /* stores the way in which the coordinates were permuted */
814 int* fracspace; /* maps the variables of the subspace to the original variables */
815
816 assert(heur != NULL);
817 assert(scip != NULL);
818 assert(result != NULL);
820
822
824
825 /* do not call heuristic of node was already detected to be infeasible */
826 if( nodeinfeasible )
827 return SCIP_OKAY;
828
829 /* only call heuristic, if an optimal LP solution is at hand */
831 return SCIP_OKAY;
832
833 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
835 return SCIP_OKAY;
836
838
839 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, NULL, NULL, NULL) );
840
841 /* OCTANE is for use in 0-1 programs only */
842 if( nvars != nbinvars )
843 return SCIP_OKAY;
844
845 /* get heuristic's data */
847 assert( heurdata != NULL );
848
849 /* don't call heuristic, if it was not successful enough in the past */
850 /*lint --e{647}*/
851 if( SCIPgetNNodes(scip) % (SCIPheurGetNCalls(heur) / (100 * SCIPheurGetNBestSolsFound(heur) + 10*heurdata->nsuccess + 1) + 1) != 0 )
852 return SCIP_OKAY;
853
854 SCIP_CALL( SCIPgetLPBranchCands(scip, &fracvars, NULL, NULL, &nfracvars, NULL, NULL) );
855
856 /* don't use integral starting points */
857 if( nfracvars == 0 )
858 return SCIP_OKAY;
859
860 /* get working pointers from heurdata */
861 sol = heurdata->sol;
862 assert( sol != NULL );
863 f_max = heurdata->f_max;
864 f_first = heurdata->f_first;
865 usefracspace = heurdata->usefracspace;
866
867 SCIP_CALL( SCIPallocBufferArray(scip, &fracspace, nvars) );
868
869 /* determine the space one which OCTANE should work either as the whole space or as the space of fractional variables */
870 if( usefracspace )
871 {
872 nsubspacevars = nfracvars;
873 SCIP_CALL( SCIPallocBufferArray(scip, &subspacevars, nsubspacevars) );
874 BMScopyMemoryArray(subspacevars, fracvars, nsubspacevars);
875 for( i = nvars - 1; i >= 0; --i )
876 fracspace[i] = -1;
877 for( i = nsubspacevars - 1; i >= 0; --i )
878 fracspace[SCIPvarGetProbindex(subspacevars[i])] = i;
879 }
880 else
881 {
882 int currentindex;
883
884 nsubspacevars = nvars;
885 SCIP_CALL( SCIPallocBufferArray(scip, &subspacevars, nsubspacevars) );
886
887 /* only copy the variables which are in the current LP */
888 currentindex = 0;
889 for( i = 0; i < nvars; ++i )
890 {
891 if( SCIPcolGetLPPos(SCIPvarGetCol(vars[i])) >= 0 )
892 {
893 subspacevars[currentindex] = vars[i];
894 fracspace[i] = currentindex;
895 ++currentindex;
896 }
897 else
898 {
899 fracspace[i] = -1;
900 --nsubspacevars;
901 }
902 }
903 }
904
905 /* nothing to do for empty search space */
906 if( nsubspacevars == 0 )
907 {
908 SCIPfreeBufferArray(scip, &subspacevars);
909 SCIPfreeBufferArray(scip, &fracspace);
910 return SCIP_OKAY;
911 }
912
913 assert(0 < nsubspacevars && nsubspacevars <= nvars);
914
915 for( i = 0; i < nsubspacevars; i++)
916 assert(fracspace[SCIPvarGetProbindex(subspacevars[i])] == i);
917
918 /* at most 2^(n-1) facets can be hit */
919 if( nsubspacevars < 30 )
920 {
921 /*lint --e{701}*/
922 assert(f_max > 0);
923 f_max = MIN(f_max, 1 << (nsubspacevars - 1) );
924 }
925
926 f_first = MIN(f_first, f_max);
927
928 /* memory allocation */
929 SCIP_CALL( SCIPallocBufferArray(scip, &rayorigin, nsubspacevars) );
930 SCIP_CALL( SCIPallocBufferArray(scip, &raydirection, nsubspacevars) );
931 SCIP_CALL( SCIPallocBufferArray(scip, &negquotient, nsubspacevars) );
932 SCIP_CALL( SCIPallocBufferArray(scip, &sign, nsubspacevars) );
933 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nsubspacevars) );
934 SCIP_CALL( SCIPallocBufferArray(scip, &lambda, f_max + 1) );
935 SCIP_CALL( SCIPallocBufferArray(scip, &facets, f_max + 1) );
936
937 for( i = f_max; i >= 0; --i )
938 {
939 /*lint --e{866}*/
940 SCIP_CALL( SCIPallocBufferArray(scip, &facets[i], nsubspacevars) );
941 }
942 SCIP_CALL( SCIPallocBufferArray(scip, &first_sols, f_first) );
943
945
946 /* starting OCTANE */
947 SCIPdebugMsg(scip, "run Octane heuristic on %s variables, which are %d vars, generate at most %d facets, using rule number %d\n",
948 usefracspace ? "fractional" : "all", nsubspacevars, f_max, (heurdata->lastrule+1)%5);
949
950 /* generate starting point in original coordinates */
951 generateStartingPoint(scip, rayorigin, subspacevars, nsubspacevars);
952 for( i = nsubspacevars - 1; i >= 0; --i )
953 rayorigin[i] -= 0.5;
954
955 firstrule = heurdata->lastrule;
956 ++firstrule;
957 for( r = firstrule; r <= firstrule + 5 && !SCIPisStopped(scip); r++ )
958 {
959 SCIP_ROW** rows;
960 int nrows;
961
962 /* generate shooting ray in original coordinates by certain rules */
963 switch(r % 5)
964 {
965 case 1:
966 if( !heurdata->useavgnbray )
967 continue;
968
969 SCIP_CALL( generateAverageNBRay(scip, raydirection, fracspace, subspacevars, nsubspacevars) );
970 break;
971 case 2:
972 if( !heurdata->useobjray )
973 continue;
974
975 SCIP_CALL( generateObjectiveRay(scip, raydirection, subspacevars, nsubspacevars) );
976 break;
977 case 3:
978 if( !heurdata->usediffray )
979 continue;
980
981 SCIP_CALL( generateDifferenceRay(scip, raydirection, subspacevars, nsubspacevars) );
982 break;
983 case 4:
984 if( !heurdata->useavgwgtray || !SCIPisLPSolBasic(scip) )
985 continue;
986
987 SCIP_CALL( generateAverageRay(scip, raydirection, subspacevars, nsubspacevars, TRUE) );
988 break;
989 case 0:
990 if( !heurdata->useavgray || !SCIPisLPSolBasic(scip) )
991 continue;
992
993 SCIP_CALL( generateAverageRay(scip, raydirection, subspacevars, nsubspacevars, FALSE) );
994 break;
995 default:
996 SCIPerrorMessage("invalid ray rule identifier\n");
997 SCIPABORT();
998 }
999
1000 /* there must be a feasible direction for the shooting ray */
1001 if( isZero(scip, raydirection, nsubspacevars) )
1002 continue;
1003
1004 /* transform coordinates such that raydirection >= 0 */
1005 flipCoords(rayorigin, raydirection, sign, nsubspacevars);
1006
1007 for( i = f_max - 1; i >= 0; --i)
1008 lambda[i] = SCIPinfinity(scip);
1009
1010 /* calculate negquotient, initialize perm, facets[0], p, and q */
1011 p = 0.5 * nsubspacevars;
1012 q = 0.0;
1013 for( i = nsubspacevars - 1; i >= 0; --i )
1014 {
1015 /* calculate negquotient, the ratio of rayorigin and raydirection, paying special attention to the case raydirection[i] == 0 */
1016 if( SCIPisFeasZero(scip, raydirection[i]) )
1017 {
1018 if( rayorigin[i] < 0 )
1019 negquotient[i] = SCIPinfinity(scip);
1020 else
1021 negquotient[i] = -SCIPinfinity(scip);
1022 }
1023 else
1024 negquotient[i] = - (rayorigin[i] / raydirection[i]);
1025
1026 perm[i] = i;
1027
1028 /* initialization of facets[0] to the all-one facet with p and q its characteristic values */
1029 facets[0][i] = TRUE;
1030 p -= rayorigin[i];
1031 q += raydirection[i];
1032 }
1033
1035
1036 /* resort the coordinates in nonincreasing order of negquotient */
1037 SCIPsortDownRealRealRealBoolPtr(negquotient, raydirection, rayorigin, sign, (void**) subspacevars, nsubspacevars);
1038
1039#ifndef NDEBUG
1040 for( i = 0; i < nsubspacevars; i++ )
1041 {
1042 assert( raydirection[i] >= 0 );
1043 assert(!SCIPisInfinity(scip, REALABS(raydirection[i])));
1044 }
1045 for( i = 1; i < nsubspacevars; i++ )
1046 assert( negquotient[i - 1] >= negquotient[i] );
1047#endif
1048 /* finished initialization */
1049
1050 /* find the first facet of the octahedron hit by a ray shot from rayorigin into direction raydirection */
1052 {
1053 facets[0][i] = FALSE;
1054 p += 2 * rayorigin[i];
1055 q -= 2 * raydirection[i];
1058 }
1059
1060 /* avoid dividing by values close to 0.0 */
1061 if( !SCIPisFeasPositive(scip, q) )
1062 continue;
1063
1064 /* assert necessary for flexelint */
1065 assert(q != 0.0);
1066 lambda[0] = p / q;
1067
1068 nfacets = 1;
1069
1070 /* find the first facets hit by the ray */
1071 for( i = 0; i < nfacets && i < f_first; ++i)
1072 generateNeighborFacets(scip, facets, lambda, rayorigin, raydirection, negquotient, nsubspacevars, f_max, i, &nfacets);
1073
1074 /* construct the first ffirst possible solutions */
1075 for( i = 0; i < nfacets && i < f_first; ++i )
1076 {
1077 SCIP_CALL( SCIPcreateSol(scip, &first_sols[i], heur) );
1078 SCIP_CALL( getSolFromFacet(scip, facets[i], first_sols[i], sign, subspacevars, nsubspacevars) );
1079 assert( first_sols[i] != NULL );
1080 }
1081
1082 /* try, whether there is a row violated by all of the first ffirst solutions */
1083 cons_viol = FALSE;
1084 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
1085 for( i = nrows - 1; i >= 0; --i )
1086 {
1087 if( !SCIProwIsLocal(rows[i]) )
1088 {
1089 SCIP_COL** cols;
1090 SCIP_Real constant;
1091 SCIP_Real lhs;
1092 SCIP_Real rhs;
1093 SCIP_Real rowval;
1094 SCIP_Real* coeffs;
1095 int nnonzerovars;
1096 int k;
1097
1098 /* get the row's data */
1099 constant = SCIProwGetConstant(rows[i]);
1100 lhs = SCIProwGetLhs(rows[i]);
1101 rhs = SCIProwGetRhs(rows[i]);
1102 coeffs = SCIProwGetVals(rows[i]);
1103 nnonzerovars = SCIProwGetNNonz(rows[i]);
1104 cols = SCIProwGetCols(rows[i]);
1105 rowval = constant;
1106
1107 for( j = nnonzerovars - 1; j >= 0; --j )
1108 rowval += coeffs[j] * SCIPgetSolVal(scip, first_sols[0], SCIPcolGetVar(cols[j]));
1109
1110 /* if the row's lhs is violated by the first sol, test, whether it is violated by the next ones, too */
1111 if( lhs > rowval )
1112 {
1113 cons_viol = TRUE;
1114 for( k = MIN(f_first, nfacets) - 1; k > 0; --k )
1115 {
1116 rowval = constant;
1117 for( j = nnonzerovars - 1; j >= 0; --j )
1118 rowval += coeffs[j] * SCIPgetSolVal(scip, first_sols[k], SCIPcolGetVar(cols[j]));
1119 if( lhs <= rowval )
1120 {
1121 cons_viol = FALSE;
1122 break;
1123 }
1124 }
1125 }
1126 /* dito for the right hand side */
1127 else if( rhs < rowval )
1128 {
1129 cons_viol = TRUE;
1130 for( k = MIN(f_first, nfacets) - 1; k > 0; --k )
1131 {
1132 rowval = constant;
1133 for( j = nnonzerovars - 1; j >= 0; --j )
1134 rowval += coeffs[j] * SCIPgetSolVal(scip, first_sols[k], SCIPcolGetVar(cols[j]));
1135 if( rhs >= rowval )
1136 {
1137 cons_viol = FALSE;
1138 break;
1139 }
1140 }
1141 }
1142 /* break as soon as one row is violated by all of the ffirst solutions */
1143 if( cons_viol )
1144 break;
1145 }
1146 }
1147
1148 if( !cons_viol )
1149 {
1150 /* if there was no row violated by all solutions, try whether one or more of them are feasible */
1151 for( i = MIN(f_first, nfacets) - 1; i >= 0; --i )
1152 {
1153 assert(first_sols[i] != NULL);
1154 SCIP_CALL( SCIPtrySol(scip, first_sols[i], FALSE, FALSE, TRUE, FALSE, TRUE, &success) );
1155 if( success )
1157 }
1158 /* search for further facets and construct and try solutions out of facets fixed as closest ones */
1159 for( i = f_first; i < f_max; ++i)
1160 {
1161 if( i >= nfacets )
1162 break;
1163 generateNeighborFacets(scip, facets, lambda, rayorigin, raydirection, negquotient, nsubspacevars, f_max, i, &nfacets);
1164 SCIP_CALL( getSolFromFacet(scip, facets[i], sol, sign, subspacevars, nsubspacevars) );
1165 SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, TRUE, FALSE, TRUE, &success) );
1166 if( success )
1168 }
1169 }
1170
1171 /* finished OCTANE */
1172 for( i = MIN(f_first, nfacets) - 1; i >= 0; --i )
1173 {
1174 SCIP_CALL( SCIPfreeSol(scip, &first_sols[i]) );
1175 }
1176 }
1177 heurdata->lastrule = r;
1178
1179 if( *result == SCIP_FOUNDSOL )
1180 ++(heurdata->nsuccess);
1181
1182 /* free temporary memory */
1183 SCIPfreeBufferArray(scip, &first_sols);
1184 for( i = 0; i <= f_max; ++i )
1185 SCIPfreeBufferArray(scip, &facets[i]);
1186 SCIPfreeBufferArray(scip, &facets);
1187 SCIPfreeBufferArray(scip, &lambda);
1188 SCIPfreeBufferArray(scip, &perm);
1189 SCIPfreeBufferArray(scip, &sign);
1190 SCIPfreeBufferArray(scip, &negquotient);
1191 SCIPfreeBufferArray(scip, &raydirection);
1192 SCIPfreeBufferArray(scip, &rayorigin);
1193 SCIPfreeBufferArray(scip, &subspacevars);
1194 SCIPfreeBufferArray(scip, &fracspace);
1195
1196 return SCIP_OKAY;
1197}
1198
1199
1200/*
1201 * primal heuristic specific interface methods
1202 */
1203
1204/** creates the octane primal heuristic and includes it in SCIP */
1206 SCIP* scip /**< SCIP data structure */
1207 )
1208{
1210 SCIP_HEUR* heur;
1211
1212 /* create Octane primal heuristic data */
1214
1215 /* include primal heuristic */
1218 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecOctane, heurdata) );
1219
1220 assert(heur != NULL);
1221
1222 /* primal heuristic is safe to use in exact solving mode */
1223 SCIPheurMarkExact(heur);
1224
1225 /* set non-NULL pointers to callback methods */
1226 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyOctane) );
1227 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeOctane) );
1228 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitOctane) );
1229 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitOctane) );
1230
1231 /* add octane primal heuristic parameters */
1233 "heuristics/octane/fmax",
1234 "number of 0-1-points to be tested as possible solutions by OCTANE",
1235 &heurdata->f_max, TRUE, DEFAULT_FMAX, 1, INT_MAX, NULL, NULL) );
1236
1238 "heuristics/octane/ffirst",
1239 "number of 0-1-points to be tested at first whether they violate a common row",
1240 &heurdata->f_first, TRUE, DEFAULT_FFIRST, 1, INT_MAX, NULL, NULL) );
1241
1243 "heuristics/octane/usefracspace",
1244 "execute OCTANE only in the space of fractional variables (TRUE) or in the full space?",
1245 &heurdata->usefracspace, TRUE, DEFAULT_USEFRACSPACE, NULL, NULL) );
1246
1248 "heuristics/octane/useobjray",
1249 "should the inner normal of the objective be used as one ray direction?",
1250 &heurdata->useobjray, TRUE, TRUE, NULL, NULL) );
1251
1253 "heuristics/octane/useavgray",
1254 "should the average of the basic cone be used as one ray direction?",
1255 &heurdata->useavgray, TRUE, TRUE, NULL, NULL) );
1256
1258 "heuristics/octane/usediffray",
1259 "should the difference between the root solution and the current LP solution be used as one ray direction?",
1260 &heurdata->usediffray, TRUE, FALSE, NULL, NULL) );
1261
1263 "heuristics/octane/useavgwgtray",
1264 "should the weighted average of the basic cone be used as one ray direction?",
1265 &heurdata->useavgwgtray, TRUE, TRUE, NULL, NULL) );
1266
1268 "heuristics/octane/useavgnbray",
1269 "should the weighted average of the nonbasic cone be used as one ray direction?",
1270 &heurdata->useavgnbray, TRUE, TRUE, NULL, NULL) );
1271
1272 return SCIP_OKAY;
1273}
#define NULL
Definition def.h:257
#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 TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#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)
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition scip_prob.c:2115
#define SCIPdebugMsg
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:83
SCIP_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
SCIP_RETCODE SCIPincludeHeurOctane(SCIP *scip)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
int SCIPcolGetLPPos(SCIP_COL *col)
Definition lp.c:17487
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition lp.c:17425
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_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition heur.c:1613
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:167
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition heur.c:1593
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_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition scip_lp.c:87
SCIP_RETCODE SCIPgetLPBInvACol(SCIP *scip, int c, SCIP_Real *coefs, int *inds, int *ninds)
Definition scip_lp.c:825
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
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition scip_lp.c:174
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition scip_lp.c:253
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition scip_lp.c:673
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition lp.c:17686
int SCIProwGetNNonz(SCIP_ROW *row)
Definition lp.c:17607
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition lp.c:17632
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition lp.c:17696
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition lp.c:17795
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition lp.c:17652
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition lp.c:17706
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition lp.c:17642
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_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition scip_sol.c:1569
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:23715
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:23694
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition var.c:19144
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition var.c:24696
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
void SCIPsortDownRealRealRealBoolPtr(SCIP_Real *realarray1, SCIP_Real *realarray2, SCIP_Real *realarray3, SCIP_Bool *boolarray, void **ptrarray, 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))
heurdata nsuccess
static SCIP_SOL * sol
int r
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIPlinkLPSol(scip, sol))
SCIP_VAR * var
static SCIP_RETCODE generateDifferenceRay(SCIP *scip, SCIP_Real *raydirection, SCIP_VAR **subspacevars, int nsubspacevars)
#define DEFAULT_USEFRACSPACE
Definition heur_octane.c:65
static void tryToInsert(SCIP *scip, SCIP_Bool **facets, SCIP_Real *lambda, int i, int j, int f_max, int nsubspacevars, SCIP_Real lam, int *nfacets)
Definition heur_octane.c:90
static void flipCoords(SCIP_Real *rayorigin, SCIP_Real *raydirection, SCIP_Bool *sign, int nsubspacevars)
static SCIP_RETCODE getSolFromFacet(SCIP *scip, SCIP_Bool *facet, SCIP_SOL *sol, SCIP_Bool *sign, SCIP_VAR **subspacevars, int nsubspacevars)
#define DEFAULT_FFIRST
Definition heur_octane.c:64
static SCIP_RETCODE generateObjectiveRay(SCIP *scip, SCIP_Real *raydirection, SCIP_VAR **subspacevars, int nsubspacevars)
static SCIP_Bool isZero(SCIP *scip, SCIP_Real *raydirection, int nsubspacevars)
static SCIP_RETCODE generateAverageRay(SCIP *scip, SCIP_Real *raydirection, SCIP_VAR **subspacevars, int nsubspacevars, SCIP_Bool weighted)
#define DEFAULT_FMAX
Definition heur_octane.c:63
static void generateStartingPoint(SCIP *scip, SCIP_Real *rayorigin, SCIP_VAR **subspacevars, int nsubspacevars)
static SCIP_RETCODE generateAverageNBRay(SCIP *scip, SCIP_Real *raydirection, int *fracspace, SCIP_VAR **subspacevars, int nsubspacevars)
static void generateNeighborFacets(SCIP *scip, SCIP_Bool **facets, SCIP_Real *lambda, SCIP_Real *rayorigin, SCIP_Real *raydirection, SCIP_Real *negquotient, int nsubspacevars, int f_max, int i, int *nfacets)
octane primal heuristic based on Balas, Ceria, Dawande, Margot, and Pataki
static SCIP_VAR ** vars
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
public methods for primal heuristics
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
methods for sorting joint arrays of various types
public methods for problem variables
public methods for branching rule plugins and branching
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 solutions
public methods for querying solving statistics
#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
struct SCIP_Col SCIP_COL
Definition type_lp.h:99
@ SCIP_LPSOLSTAT_OPTIMAL
Definition type_lp.h:44
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_DELAYED
Definition type_result.h:43
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_FOUNDSOL
Definition type_result.h:56
@ 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