Scippy

    SCIP

    Solving Constraint Integer Programs

    cons_components.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_components.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief constraint handler for handling independent components
    28 * @author Gerald Gamrath
    29 *
    30 * This constraint handler looks for independent components.
    31 */
    32/*#define DETAILED_OUTPUT*/
    33/*#define SCIP_DEBUG*/
    34/*#define SCIP_MORE_DEBUG*/
    35/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    36
    39#include "scip/debug.h"
    40#include "scip/pub_cons.h"
    41#include "scip/pub_heur.h"
    42#include "scip/pub_message.h"
    43#include "scip/pub_misc.h"
    44#include "scip/pub_misc_sort.h"
    45#include "scip/pub_sol.h"
    46#include "scip/pub_tree.h"
    47#include "scip/pub_var.h"
    48#include "scip/scip_cons.h"
    49#include "scip/scip_copy.h"
    51#include "scip/scip_general.h"
    52#include "scip/scip_heur.h"
    53#include "scip/scip_mem.h"
    54#include "scip/scip_message.h"
    55#include "scip/scip_numerics.h"
    56#include "scip/scip_param.h"
    57#include "scip/scip_pricer.h"
    58#include "scip/scip_prob.h"
    59#include "scip/scip_probing.h"
    60#include "scip/scip_sol.h"
    61#include "scip/scip_solve.h"
    63#include "scip/scip_timing.h"
    64#include "scip/scip_tree.h"
    65#include "scip/scip_var.h"
    66#include <string.h>
    67
    68#define CONSHDLR_NAME "components"
    69#define CONSHDLR_DESC "independent components constraint handler"
    70#define CONSHDLR_ENFOPRIORITY 0 /**< priority of the constraint handler for constraint enforcing */
    71#define CONSHDLR_CHECKPRIORITY -9999999 /**< priority of the constraint handler for checking feasibility */
    72#define CONSHDLR_EAGERFREQ -1 /**< frequency for using all instead of only the useful constraints in separation,
    73 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    74#define CONSHDLR_NEEDSCONS FALSE /**< should the constraint handler be skipped, if no constraints are available? */
    75
    76#define CONSHDLR_PROPFREQ -1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    77#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    78#define CONSHDLR_DELAYPROP TRUE /**< should propagation method be delayed, if other propagators found reductions? */
    79
    80#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FINAL /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
    81#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
    82
    83#define DEFAULT_MAXDEPTH INT_MAX /**< maximum depth of a node to run components detection (-1: disable component detection during solving) */
    84#define DEFAULT_MAXINTVARS 200 /**< maximum number of integer (or binary) variables to solve a subproblem directly in presolving (-1: no solving) */
    85#define DEFAULT_MINSIZE 50 /**< minimum absolute size (in terms of variables) to solve a component individually during branch-and-bound */
    86#define DEFAULT_MINRELSIZE 0.1 /**< minimum relative size (in terms of variables) to solve a component individually during branch-and-bound */
    87#define DEFAULT_NODELIMIT 10000LL /**< maximum number of nodes to be solved in subproblems during presolving */
    88#define DEFAULT_MAXCOMPWEIGHT 200.0 /**< The maximum weight of a component to be presolved*/
    89#define DEFAULT_INTFACTOR 1.0 /**< the weight of an integer variable compared to binary variables */
    90#define DEFAULT_CONTFACTOR 0.2 /**< the weight of a continuous variable compared to a binary variable */
    91#define DEFAULT_FEASTOLFACTOR 1.0 /**< default value for parameter to increase the feasibility tolerance in all sub-SCIPs */
    92
    93/*
    94 * Data structures
    95 */
    96
    97/** data related to one problem (see below) */
    98typedef struct Problem PROBLEM;
    99
    100/** data related to one component */
    101typedef struct Component
    102{
    103 PROBLEM* problem; /**< the problem this component belongs to */
    104 SCIP* subscip; /**< sub-SCIP representing the component */
    105 SCIP_SOL* workingsol; /**< working solution for transferring solutions into the sub-SCIP */
    106 SCIP_VAR** vars; /**< variables belonging to this component (in complete problem) */
    107 SCIP_VAR** subvars; /**< variables belonging to this component (in subscip) */
    108 SCIP_VAR** fixedvars; /**< variables in the original SCIP which were copied while copying the component's
    109 * constraints, but do not count to the subvars, because they were locally fixed */
    110 SCIP_VAR** fixedsubvars; /**< variables in the sub-SCIP which were copied while copying the component's
    111 * constraints, but do not count to the subvars, because they were locally fixed */
    112 SCIP_Real fixedvarsobjsum; /**< objective contribution of all locally fixed variables */
    113 SCIP_Real lastdualbound; /**< dual bound after last optimization call for this component */
    114 SCIP_Real lastprimalbound; /**< primal bound after last optimization call for this component */
    115 SCIP_STATUS laststatus; /**< solution status of last optimization call for the sub-SCIP of this component */
    116 SCIP_Bool solved; /**< was this component solved already? */
    117 int ncalls; /**< number of optimization calls for this component */
    118 int lastsolindex; /**< index of best solution after last optimization call for this component */
    119 int lastbestsolindex; /**< index of last best solution transferred to this component from the main problem */
    120 int nvars; /**< number of variables belonging to this component */
    121 int nfixedvars; /**< number of fixed variables copied during constraint copying */
    122 int fixedvarssize; /**< size of fixedvars and fixedsubvars arrays */
    123 int number; /**< component number */
    125
    126/** data related to one problem
    127 * (corresponding to one node in the branch-and-bound tree and consisting of multiple components)
    128 */
    129struct Problem
    130{
    131 SCIP* scip; /**< the SCIP instance this problem belongs to */
    132 COMPONENT* components; /**< independent components into which the problem can be divided */
    133 SCIP_PQUEUE* compqueue; /**< priority queue for components */
    134 SCIP_SOL* bestsol; /**< best solution found so far for the problem */
    135 char* name; /**< name of the problem */
    136 SCIP_Real fixedvarsobjsum; /**< objective contribution of all locally fixed variables */
    137 SCIP_Real lowerbound; /**< lower bound of the problem */
    138 int ncomponents; /**< number of independent components into which the problem can be divided */
    139 int componentssize; /**< size of components array */
    140 int nfeascomps; /**< number of components for which a feasible solution was found */
    141 int nsolvedcomps; /**< number of components solved to optimality */
    142 int nlowerboundinf; /**< number of components with lower bound equal to -infinity */
    143};
    144
    145
    146/** constraint handler data */
    147struct SCIP_ConshdlrData
    148{
    149 SCIP_Longint nodelimit; /**< maximum number of nodes to be solved in subproblems */
    150 SCIP_Real maxcompweight; /**< The maximum weight sum of a component */
    151 SCIP_Real intfactor; /**< the weight of an integer variable compared to binary variables */
    152 SCIP_Real contfactor; /**< the weight of a continuous variable compared to binary variables */
    153 SCIP_Real feastolfactor; /**< parameter to increase the feasibility tolerance in all sub-SCIPs */
    154 int maxintvars; /**< maximum number of integer (or binary) variables to solve a subproblem
    155 * directly (-1: no solving) */
    156 int maxdepth; /**< maximum depth of a node to run components detection (-1: disable
    157 * component detection during solving) */
    158 int minsize; /**< minimum absolute size (in terms of variables) to solve a component
    159 * individually during branch-and-bound */
    160 SCIP_Real minrelsize; /**< minimum relative size (in terms of variables) to solve a component
    161 * individually during branch-and-bound */
    162 int subscipdepth; /**< depth offset of the current (sub-)problem compared to the original
    163 * problem */
    164};
    165
    166
    167/** comparison method for sorting components */
    168static
    170{
    171 SCIP* scip;
    172 COMPONENT* comp1;
    173 COMPONENT* comp2;
    174 SCIP_Real gap1;
    175 SCIP_Real gap2;
    176
    177 assert(elem1 != NULL);
    178 assert(elem2 != NULL);
    179
    180 comp1 = (COMPONENT*)elem1;
    181 comp2 = (COMPONENT*)elem2;
    182
    183 if( comp1->ncalls == 0 )
    184 if( comp2->ncalls == 0 )
    185 return comp1->number - comp2->number;
    186 else
    187 return -1;
    188 else if( comp2->ncalls == 0 )
    189 return 1;
    190
    191 /* the main sorting criterion is the absolute gap; however, we divide it by the number of solving calls for this
    192 * component to diversify the search if one component does not improve
    193 * @todo investigate other sorting criteria
    194 */
    195 gap1 = SQR(comp1->lastprimalbound - comp1->lastdualbound) / comp1->ncalls;
    196 gap2 = SQR(comp2->lastprimalbound - comp2->lastdualbound) / comp2->ncalls;
    197
    198 assert(comp1->problem != NULL);
    199 assert(comp1->problem == comp2->problem);
    200 assert(comp1->problem->scip == comp2->problem->scip);
    201
    202 scip = comp1->problem->scip;
    203 assert(scip != NULL);
    204
    205 if( SCIPisFeasGT(scip, gap1, gap2) )
    206 return -1;
    207 else if( SCIPisFeasLT(scip, gap1, gap2) )
    208 return +1;
    209 else
    210 return comp1->number - comp2->number;
    211}
    212
    213/** returns minimum size of components to be solved individually during the branch-and-bound search */
    214static
    216 SCIP* scip, /**< main SCIP data structure */
    217 SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */
    218 )
    219{
    220 int minsize;
    221
    222 assert(conshdlrdata != NULL);
    223
    224 minsize = (int)(conshdlrdata->minrelsize * SCIPgetNVars(scip));
    225 minsize = MAX(minsize, conshdlrdata->minsize);
    226
    227 return minsize;
    228}
    229
    230/** initialize component structure */
    231static
    233 PROBLEM* problem /**< subproblem structure */
    234 )
    235{
    236 COMPONENT* component;
    237 SCIP* scip;
    238
    239 assert(problem != NULL);
    240 assert(problem->ncomponents < problem->componentssize);
    241
    242 scip = problem->scip;
    243 assert(scip != NULL);
    244
    245 component = &problem->components[problem->ncomponents];
    246
    247 component->problem = problem;
    248 component->subscip = NULL;
    249 component->workingsol = NULL;
    250 component->vars = NULL;
    251 component->subvars = NULL;
    252 component->fixedvars = NULL;
    253 component->fixedsubvars = NULL;
    254 component->fixedvarsobjsum = 0.0;
    255 component->lastdualbound = -SCIPinfinity(scip);
    256 component->lastprimalbound = SCIPinfinity(scip);
    257 component->laststatus = SCIP_STATUS_UNKNOWN;
    258 component->solved = FALSE;
    259 component->ncalls = 0;
    260 component->lastsolindex = -1;
    261 component->lastbestsolindex = -1;
    262 component->nvars = 0;
    263 component->nfixedvars = 0;
    264 component->fixedvarssize = 0;
    265 component->number = problem->ncomponents;
    266
    267 ++problem->ncomponents;
    268
    269 return SCIP_OKAY;
    270}
    271
    272/** free component structure */
    273static
    275 COMPONENT* component /**< pointer to component structure */
    276 )
    277{
    278 PROBLEM* problem;
    279 SCIP* scip;
    280
    281 assert(component != NULL);
    282
    283 problem = component->problem;
    284 assert(problem != NULL);
    285
    286 scip = problem->scip;
    287 assert(scip != NULL);
    288
    289 SCIPdebugMsg(scip, "freeing component %d of problem <%s>\n", component->number, component->problem->name);
    290
    291 assert((component->vars != NULL) == (component->subvars != NULL));
    292 if( component->vars != NULL )
    293 {
    294 SCIPfreeBlockMemoryArray(scip, &component->vars, component->nvars);
    295 SCIPfreeBlockMemoryArray(scip, &component->subvars, component->nvars);
    296 }
    297
    298 assert((component->fixedvars != NULL) == (component->fixedsubvars != NULL));
    299 if( component->fixedvars != NULL )
    300 {
    302 SCIPfreeBlockMemoryArray(scip, &component->fixedvars, component->fixedvarssize);
    303 }
    304
    305 /* free sub-SCIP belonging to this component and the working solution */
    306 if( component->subscip != NULL )
    307 {
    308 if( component->workingsol != NULL )
    309 {
    310 SCIP_CALL( SCIPfreeSol(component->subscip, &component->workingsol) );
    311 }
    312
    313 SCIP_CALL( SCIPfree(&component->subscip) );
    314 }
    315
    316 return SCIP_OKAY;
    317}
    318
    319
    320/** create the working solution for a given component, store fixed variables and the corresponding objective offset */
    321static
    323 COMPONENT* component, /**< component structure */
    324 SCIP_HASHMAP* varmap /**< variable hashmap */
    325 )
    326{
    327 SCIP* subscip;
    328
    329 assert(component != NULL);
    330
    331 subscip = component->subscip;
    332 assert(subscip != NULL);
    333 assert(SCIPgetStage(subscip) == SCIP_STAGE_PROBLEM);
    334
    335 /* the solution should live in the primal, not the origprimal, of the sub-SCIP, so we need to transform it first */
    336 SCIP_CALL( SCIPtransformProb(subscip) );
    337 SCIP_CALL( SCIPcreateOrigSol(subscip, &(component->workingsol), NULL) );
    338
    339 /* the number of variables was increased by copying the constraints */
    340 if( SCIPgetNOrigVars(subscip) > component->nvars )
    341 {
    342 PROBLEM* problem;
    343 SCIP* scip;
    344 SCIP_VAR** sourcevars;
    345 SCIP_VAR* subvar;
    346 int nsourcevars;
    347 int nnewvars;
    348 int idx = 0;
    349 int nvars;
    350 int v;
    351
    352 problem = component->problem;
    353 assert(problem != NULL);
    354
    355 scip = problem->scip;
    356 assert(scip != NULL);
    357
    358 sourcevars = SCIPgetVars(scip);
    359 nsourcevars = SCIPgetNVars(scip);
    360 nnewvars = SCIPgetNOrigVars(subscip);
    361 nvars = component->nvars;
    362
    363 component->fixedvarssize = nnewvars - nvars;
    366
    367 for( v = 0; v < nsourcevars; ++v )
    368 {
    369 subvar = (SCIP_VAR*)SCIPhashmapGetImage(varmap, sourcevars[v]);
    370 if( subvar != NULL && SCIPvarGetIndex(subvar) >= nvars )
    371 {
    372 /* the variable is either locally fixed or could be an inactive variable present in a constraint
    373 * for which an aggregation constraint linking it to the active variable was created in the subscip
    374 */
    375 assert(SCIPisZero(subscip, SCIPvarGetObj(subvar)) ||
    376 SCIPisEQ(subscip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar)));
    377
    378 /* variable is globally fixed in sub-SCIP, so it was locally fixed in the main-SCIP */
    379 if( SCIPisEQ(subscip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar)) )
    380 {
    381 assert(SCIPisEQ(scip, SCIPvarGetLbLocal(sourcevars[v]), SCIPvarGetUbLocal(sourcevars[v])));
    382
    383 component->fixedvarsobjsum += SCIPvarGetLbGlobal(subvar) * SCIPvarGetObj(subvar);
    384 component->fixedvars[idx] = sourcevars[v];
    385 component->fixedsubvars[idx] = subvar;
    386 ++idx;
    387
    388 SCIP_CALL( SCIPsetSolVal(subscip, component->workingsol, subvar, SCIPvarGetLbGlobal(subvar)) );
    389 }
    390 /* inactive variable */
    391 else
    392 {
    393 assert(SCIPisZero(subscip, SCIPvarGetObj(subvar)));
    394 }
    395 }
    396 else
    397 {
    398 assert(subvar == NULL || SCIPisLT(scip, SCIPvarGetLbGlobal(sourcevars[v]), SCIPvarGetUbGlobal(sourcevars[v])));
    399 assert(subvar == NULL || SCIPisLT(subscip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar)));
    400 }
    401 }
    402 component->nfixedvars = idx;
    403 assert(component->nfixedvars <= component->fixedvarssize);
    404 SCIPdebugMsg(scip, "%d locally fixed variables have been copied, objective contribution: %g\n",
    405 component->nfixedvars, component->fixedvarsobjsum);
    406 }
    407
    408 /* set up debug solution */
    409#ifdef WITH_DEBUG_SOLUTION
    410 if( SCIPdebugSolIsEnabled(component->problem->scip) )
    411 {
    412 PROBLEM* problem;
    413 SCIP* scip;
    414 SCIP_Bool isvalid = FALSE;
    415
    416 problem = component->problem;
    417 assert(problem != NULL);
    418
    419 scip = problem->scip;
    420 assert(scip != NULL);
    421
    423
    424 if( isvalid )
    425 {
    426 SCIP_Real val;
    427 int i;
    428
    429 SCIPdebugSolEnable(component->subscip);
    430
    431 for( i = 0; i < component->nvars; ++i )
    432 {
    433 if( component->subvars[i] != NULL )
    434 {
    435 SCIP_CALL( SCIPdebugGetSolVal(scip, component->vars[i], &val) );
    436 SCIP_CALL( SCIPdebugAddSolVal(component->subscip, component->subvars[i], val) );
    437 }
    438 }
    439 for( i = 0; i < component->nfixedvars; ++i )
    440 {
    441 if( component->fixedsubvars[i] != NULL )
    442 {
    443 SCIP_CALL( SCIPdebugGetSolVal(scip, component->fixedvars[i], &val) );
    444 SCIP_CALL( SCIPdebugAddSolVal(component->subscip, component->fixedsubvars[i], val) );
    445 }
    446 }
    447 }
    448 }
    449#endif
    450
    451 return SCIP_OKAY;
    452}
    453
    454/** create a sub-SCIP for the given variables and constraints */
    455static
    457 SCIP* scip, /**< main SCIP data structure */
    458 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    459 SCIP** subscip /**< pointer to store created sub-SCIP */
    460 )
    461{
    462 SCIP_Bool success;
    463
    464 assert(conshdlrdata != NULL);
    465
    466 /* create a new SCIP instance */
    467 SCIP_CALL( SCIPcreate(subscip) );
    468
    469 /* copy plugins, we omit pricers (because we do not run if there are active pricers) and dialogs */
    470#ifdef SCIP_MORE_DEBUG /* we print statistics later, so we need to copy statistics tables */
    472 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, &success) );
    473#else
    475 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    476#endif
    477
    478 /* the plugins were successfully copied */
    479 if( success )
    480 {
    481 SCIP_CONSHDLR* newconshdlr;
    482 SCIP_CONSHDLRDATA* newconshdlrdata;
    483#ifdef WITH_DEBUG_SOLUTION
    484 SCIP_Bool isvalid = FALSE;
    485#endif
    486
    487 /* copy parameter settings */
    489
    490 /* some general settings should not be fixed */
    491 assert(!SCIPisParamFixed(*subscip, "limits/solutions"));
    492 assert(!SCIPisParamFixed(*subscip, "limits/bestsol"));
    493 assert(!SCIPisParamFixed(*subscip, "misc/usevartable"));
    494 assert(!SCIPisParamFixed(*subscip, "misc/useconstable"));
    495 assert(!SCIPisParamFixed(*subscip, "numerics/feastol"));
    496 assert(!SCIPisParamFixed(*subscip, "misc/usesmalltables"));
    497
    498 /* disable solution limits */
    499 SCIP_CALL( SCIPsetIntParam(*subscip, "limits/solutions", -1) );
    500 SCIP_CALL( SCIPsetIntParam(*subscip, "limits/bestsol", -1) );
    501
    502 /* disable bound limits */
    503 SCIP_CALL( SCIPsetRealParam(*subscip, "limits/primal", SCIP_INVALID) );
    504 SCIP_CALL( SCIPsetRealParam(*subscip, "limits/dual", SCIP_INVALID) );
    505
    506 /* reduce the effort spent for hash tables; however, if the debug solution is enabled and valid in this subtree,
    507 * hash tables are needed for installing the debug solution
    508 */
    509#ifdef WITH_DEBUG_SOLUTION
    511 if( !isvalid && SCIPgetStage(scip) > SCIP_STAGE_PRESOLVING )
    512#endif
    513 {
    514 SCIP_CALL( SCIPsetBoolParam(*subscip, "misc/usevartable", FALSE) );
    515 SCIP_CALL( SCIPsetBoolParam(*subscip, "misc/useconstable", FALSE) );
    516 }
    517
    518 /* disable presolving */
    520
    521 /* disable component presolving and fix the parameter */
    522 SCIP_CALL( SCIPsetIntParam(*subscip, "constraints/" CONSHDLR_NAME "/maxprerounds", 0) );
    523 SCIP_CALL( SCIPfixParam(*subscip, "constraints/" CONSHDLR_NAME "/maxprerounds") );
    524
    525 /* find the components constraint handler in the sub-SCIP and inform it about the actual depth in the tree */
    526 newconshdlr = SCIPfindConshdlr(*subscip, CONSHDLR_NAME);
    527 assert(newconshdlr != NULL);
    528
    529 newconshdlrdata = SCIPconshdlrGetData(newconshdlr);
    530 assert(newconshdlrdata != NULL);
    531 newconshdlrdata->subscipdepth = conshdlrdata->subscipdepth + SCIPgetDepth(scip);
    532
    533 /* disable output, unless in extended debug mode */
    534#ifndef SCIP_MORE_DEBUG
    535 SCIP_CALL( SCIPsetIntParam(*subscip, "display/verblevel", 0) );
    536#endif
    537 }
    538 else
    539 {
    540 SCIP_CALL( SCIPfree(subscip) );
    541 *subscip = NULL;
    542 }
    543
    544 return SCIP_OKAY;
    545}
    546
    547/** copies the given variables and constraints to the given sub-SCIP */
    548static
    550 SCIP* scip, /**< source SCIP */
    551 SCIP* subscip, /**< target SCIP */
    552 const char* name, /**< name for copied problem */
    553 SCIP_VAR** vars, /**< array of variables to copy */
    554 SCIP_VAR** subvars, /**< array to fill with copied vars */
    555 SCIP_CONS** conss, /**< constraint to copy */
    556 SCIP_HASHMAP* varmap, /**< hashmap used for the copy process of variables */
    557 SCIP_HASHMAP* consmap, /**< hashmap used for the copy process of constraints */
    558 int nvars, /**< number of variables to copy */
    559 int nconss, /**< number of constraints to copy */
    560 SCIP_Bool* success /**< pointer to store whether copying was successful */
    561 )
    562{
    563 SCIP_CONS* newcons;
    564 int i;
    565
    566 assert(scip != NULL);
    567 assert(subscip != NULL);
    568 assert(vars != NULL);
    569 assert(subvars != NULL);
    570 assert(conss != NULL);
    571 assert(varmap != NULL);
    572 assert(consmap != NULL);
    573 assert(success != NULL);
    574
    575 *success = TRUE;
    576
    577 /* create problem in sub-SCIP */
    578 SCIP_CALL( SCIPcopyProb(scip, subscip, varmap, consmap, FALSE, name) );
    579
    580 /* copy variables */
    581 for( i = 0; i < nvars; ++i )
    582 {
    583 SCIP_CALL( SCIPgetVarCopy(scip, subscip, vars[i], &subvars[i], varmap, consmap, FALSE, success) );
    584
    585 /* abort if variable was not successfully copied */
    586 if( !(*success) )
    587 return SCIP_OKAY;
    588 }
    589
    590 /* copy constraints */
    591 for( i = 0; i < nconss; ++i )
    592 {
    593 assert(!SCIPconsIsModifiable(conss[i]));
    594
    595 /* copy the constraint */
    596 SCIP_CALL( SCIPgetConsCopy(scip, subscip, conss[i], &newcons, SCIPconsGetHdlr(conss[i]), varmap, consmap, NULL,
    597 SCIPconsIsInitial(conss[i]), SCIPconsIsSeparated(conss[i]), SCIPconsIsEnforced(conss[i]),
    598 SCIPconsIsChecked(conss[i]), SCIPconsIsPropagated(conss[i]), FALSE, FALSE,
    599 SCIPconsIsDynamic(conss[i]), SCIPconsIsRemovable(conss[i]), FALSE, FALSE, success) );
    600
    601 /* abort if constraint was not successfully copied */
    602 if( !(*success) )
    603 return SCIP_OKAY;
    604
    605 SCIP_CALL( SCIPaddCons(subscip, newcons) );
    606 SCIP_CALL( SCIPreleaseCons(subscip, &newcons) );
    607 }
    608
    609 return SCIP_OKAY;
    610}
    611
    612/** create the sub-SCIP for a given component */
    613static
    615 COMPONENT* component, /**< component structure */
    616 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    617 SCIP_HASHMAP* varmap, /**< variable hashmap used to improve performance */
    618 SCIP_HASHMAP* consmap, /**< constraint hashmap used to improve performance */
    619 SCIP_CONS** conss, /**< constraints contained in this component */
    620 int nconss, /**< number of constraints contained in this component */
    621 SCIP_Bool* success /**< pointer to store whether the copying process was successful */
    622 )
    623{
    624 char name[SCIP_MAXSTRLEN];
    625 PROBLEM* problem;
    626 SCIP* scip;
    627 int minsize;
    628
    629 assert(component != NULL);
    630 assert(consmap != NULL);
    631 assert(conss != NULL);
    632 assert(success != NULL);
    633 assert(component->nvars > 0);
    634
    635 problem = component->problem;
    636 assert(problem != NULL);
    637
    638 scip = problem->scip;
    639 assert(scip != NULL);
    640
    641 (*success) = TRUE;
    642
    643 SCIP_CALL( createSubscip(scip, conshdlrdata, &component->subscip) );
    644
    645 if( component->subscip != NULL )
    646 {
    647 /* get minimum size of components to solve individually and set the parameter in the sub-SCIP */
    648 minsize = getMinsize(scip, conshdlrdata);
    649
    650 SCIP_CALL( SCIPsetIntParam(component->subscip, "constraints/" CONSHDLR_NAME "/minsize", minsize) );
    651
    652 /* get name of the original problem and add "comp_nr" */
    653 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_comp_%d", problem->name, component->number);
    654
    655 SCIP_CALL( copyToSubscip(scip, component->subscip, name, component->vars, component->subvars,
    656 conss, varmap, consmap, component->nvars, nconss, success) );
    657
    658 if( !(*success) )
    659 {
    660 SCIP_CALL( SCIPfree(&component->subscip) );
    661 component->subscip = NULL;
    662 }
    663 }
    664 else
    665 (*success) = FALSE;
    666
    667 return SCIP_OKAY;
    668}
    669
    670/** solve a given sub-SCIP up to the given limits */
    671static
    673 SCIP* scip, /**< main SCIP */
    674 SCIP* subscip, /**< sub-SCIP to solve */
    675 SCIP_Longint nodelimit, /**< node limit */
    676 SCIP_Real gaplimit /**< gap limit */
    677 )
    678{
    679 SCIP_Real timelimit;
    680 SCIP_Real memorylimit;
    681 SCIP_Bool avoidmemout;
    682
    683 assert(scip != NULL);
    684 assert(subscip != NULL);
    685
    686 /* set time limit */
    687 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
    688 if( !SCIPisInfinity(scip, timelimit) )
    689 {
    690 timelimit -= SCIPgetSolvingTime(scip);
    691 timelimit += SCIPgetSolvingTime(subscip);
    692 }
    693
    694 /* subtract the memory already used by the main SCIP and the estimated memory usage of external software */
    695 /* @todo count memory of other components */
    696 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
    697 if( !SCIPisInfinity(scip, memorylimit) )
    698 {
    699 memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
    700 memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
    701 }
    702
    703 /* check if mem limit needs to be avoided */
    704 SCIP_CALL( SCIPgetBoolParam(scip, "misc/avoidmemout", &avoidmemout) );
    705
    706 /* abort if no time is left or not enough memory (we don't abort in this case if misc_avoidmemout == TRUE)
    707 * to create a copy of SCIP, including external memory usage */
    708 if( avoidmemout && memorylimit <= 0.0 )
    709 {
    710 SCIPdebugMsg(scip, "--> not solved (not enough memory left)\n");
    711 return SCIP_OKAY;
    712 }
    713 else if( timelimit <= 0.0 )
    714 {
    715 SCIPdebugMsg(scip, "--> not solved (not enough time left)\n");
    716 return SCIP_OKAY;
    717 }
    718
    719 /* SCIP copy limits will set wrong time limits since it does not take into account time spent already in the
    720 * sub-SCIP; nevertheless, we call it to set the memory limit and unset all other limits, if set in the main SCIP
    721 */
    722 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
    723
    724 /* set time and memory limit for the subproblem */
    725 SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
    726
    727 /* only set soft time limit if it exists */
    728 if( SCIPgetParam(scip, "limits/softtime") != NULL )
    729 {
    730 SCIP_Real softtimelimit;
    731
    732 /* set soft time limit, if specified in main SCIP and if it exists */
    733 SCIP_CALL( SCIPgetRealParam(scip, "limits/softtime", &softtimelimit) );
    734 if( softtimelimit > -0.5 )
    735 {
    736 softtimelimit -= SCIPgetSolvingTime(scip);
    737 softtimelimit += SCIPgetSolvingTime(subscip);
    738 softtimelimit = MAX(softtimelimit, 0.0);
    739 }
    740
    741 SCIP_CALL( SCIPsetRealParam(subscip, "limits/softtime", softtimelimit) );
    742 }
    743
    744 /* set gap limit */
    745 SCIP_CALL( SCIPsetRealParam(subscip, "limits/gap", gaplimit) );
    746
    747 /* set node limit */
    748 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit) );
    749
    750 /* solve the subproblem */
    751 SCIP_CALL( SCIPsolve(subscip) );
    752
    753#ifdef SCIP_MORE_DEBUG
    754 SCIP_CALL( SCIPprintBestSol(subscip, NULL, FALSE) );
    756#endif
    757
    758 return SCIP_OKAY;
    759}
    760
    761/** solve a connected component during presolving and evaluate the result */
    762static
    764 SCIP* scip, /**< SCIP main data structure */
    765 SCIP_CONSHDLRDATA* conshdlrdata, /**< the components constraint handler data */
    766 SCIP* subscip, /**< sub-SCIP to be solved */
    767 SCIP_VAR** vars, /**< array of variables copied to this component */
    768 SCIP_VAR** subvars, /**< array of sub-SCIP variables corresponding to the vars array */
    769 SCIP_CONS** conss, /**< array of constraints copied to this component */
    770 int nvars, /**< number of variables copied to this component */
    771 int nconss, /**< number of constraints copied to this component */
    772 int* ndeletedconss, /**< pointer to store the number of deleted constraints */
    773 int* nfixedvars, /**< pointer to store the number of fixed variables */
    774 int* ntightenedbounds, /**< pointer to store the number of bound tightenings */
    775 SCIP_RESULT* result, /**< pointer to store the result of the component solving */
    776 SCIP_Bool* solved /**< pointer to store if the problem was solved to optimality */
    777 )
    778{
    779 int i;
    780
    781 assert(scip != NULL);
    782 assert(conshdlrdata != NULL);
    783 assert(subscip != NULL);
    784 assert(vars != NULL);
    785 assert(conss != NULL);
    786 assert(ndeletedconss != NULL);
    787 assert(nfixedvars != NULL);
    788 assert(ntightenedbounds != NULL);
    789 assert(result != NULL);
    790
    791 *solved = FALSE;
    792
    793 SCIP_CALL( solveSubscip(scip, subscip, conshdlrdata->nodelimit, 0.0) );
    794
    795 if( SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL )
    796 {
    797 SCIP_SOL* sol;
    798 SCIP_VAR* var;
    799 SCIP_VAR* subvar;
    800 SCIP_Real* fixvals;
    801 SCIP_Bool feasible;
    802 SCIP_Bool infeasible;
    803 SCIP_Bool fixed;
    804
    805 sol = SCIPgetBestSol(subscip);
    806
    807#ifdef SCIP_DEBUG
    808 SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, TRUE, TRUE) );
    809#else
    810 SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, FALSE, FALSE) );
    811#endif
    812
    813 SCIPdebugMsg(scip, "--> solved to optimality: time = %.2f, solution is%s feasible\n", SCIPgetSolvingTime(subscip), feasible ? "" : " not");
    814
    815 SCIP_CALL( SCIPallocBufferArray(scip, &fixvals, nvars) );
    816
    817 if( feasible )
    818 {
    819 SCIP_Real glb;
    820 SCIP_Real gub;
    821
    822 /* get values of variables in the optimal solution */
    823 for( i = 0; i < nvars; ++i )
    824 {
    825 var = vars[i];
    826 subvar = subvars[i];
    827
    828 /* get global bounds */
    829 glb = SCIPvarGetLbGlobal(var);
    830 gub = SCIPvarGetUbGlobal(var);
    831
    832 if( subvar != NULL )
    833 {
    834 /* get solution value from optimal solution of the sub-SCIP */
    835 fixvals[i] = SCIPgetSolVal(subscip, sol, subvar);
    836
    837 assert(SCIPisFeasLE(scip, fixvals[i], SCIPvarGetUbLocal(var)));
    838 assert(SCIPisFeasGE(scip, fixvals[i], SCIPvarGetLbLocal(var)));
    839
    840 /* checking a solution is done with a relative tolerance of feasibility epsilon, if we really want to
    841 * change the bounds of the variables by fixing them, the old bounds must not be violated by more than
    842 * the absolute epsilon; therefore, we change the fixing values, if needed, and mark that the solution
    843 * has to be checked again
    844 */
    845 if( SCIPisGT(scip, fixvals[i], gub) )
    846 {
    847 SCIPdebugMsg(scip, "variable <%s> fixval: %f violates global upperbound: %f\n",
    848 SCIPvarGetName(var), fixvals[i], gub);
    849 fixvals[i] = gub;
    850 feasible = FALSE;
    851 }
    852 else if( SCIPisLT(scip, fixvals[i], glb) )
    853 {
    854 SCIPdebugMsg(scip, "variable <%s> fixval: %f violates global lowerbound: %f\n",
    855 SCIPvarGetName(var), fixvals[i], glb);
    856 fixvals[i] = glb;
    857 feasible = FALSE;
    858 }
    859 assert(SCIPisLE(scip, fixvals[i], SCIPvarGetUbLocal(var)));
    860 assert(SCIPisGE(scip, fixvals[i], SCIPvarGetLbLocal(var)));
    861 }
    862 else
    863 {
    864 /* the variable was not copied, so it was cancelled out of constraints during copying;
    865 * thus, the variable is not constrained and we fix it to its best bound
    866 */
    868 fixvals[i] = glb;
    869 else if( SCIPisNegative(scip, SCIPvarGetObj(var)) )
    870 fixvals[i] = gub;
    871 else
    872 {
    873 fixvals[i] = 0.0;
    874 fixvals[i] = MIN(fixvals[i], gub);
    875 fixvals[i] = MAX(fixvals[i], glb);
    876 }
    877 }
    878 }
    879
    880 /* the solution value of at least one variable is feasible with a relative tolerance of feasibility epsilon,
    881 * but infeasible with an absolute tolerance of epsilon; try to set the variables to the bounds and check
    882 * solution again in the original space (changing the values might now introduce infeasibilities of constraints)
    883 */
    884 if( !feasible )
    885 {
    886 SCIP_Real origobj;
    887
    888 SCIPdebugMsg(scip, "solution violates bounds by more than epsilon, check the corrected solution...\n");
    889
    890 origobj = SCIPgetSolOrigObj(subscip, SCIPgetBestSol(subscip));
    891
    892 SCIP_CALL( SCIPfreeTransform(subscip) );
    893
    894 SCIP_CALL( SCIPcreateOrigSol(subscip, &sol, NULL) );
    895
    896 /* set solution values of variables */
    897 for( i = 0; i < nvars; ++i )
    898 {
    899 if( subvars[i] != NULL )
    900 {
    901 SCIP_CALL( SCIPsetSolVal(subscip, sol, subvars[i], fixvals[i]) );
    902 }
    903 }
    904
    905 /* check the solution; integrality and bounds should be fulfilled and do not have to be checked */
    906 SCIP_CALL( SCIPcheckSol(subscip, sol, FALSE, FALSE, FALSE, FALSE, TRUE, &feasible) );
    907
    908#ifndef NDEBUG
    909 /* in debug mode, we additionally check integrality and bounds */
    910 if( feasible )
    911 {
    912 SCIP_CALL( SCIPcheckSol(subscip, sol, FALSE, FALSE, TRUE, TRUE, FALSE, &feasible) );
    913 assert(feasible);
    914 }
    915#endif
    916
    917 SCIPdebugMsg(scip, "--> corrected solution is%s feasible\n", feasible ? "" : " not");
    918
    919 if( !SCIPisFeasEQ(subscip, SCIPsolGetOrigObj(sol), origobj) )
    920 {
    921 SCIPdebugMsg(scip, "--> corrected solution has a different objective value (old = %.9g, corrected = %.9g)\n",
    922 origobj, SCIPsolGetOrigObj(sol));
    923
    924 feasible = FALSE;
    925 }
    926
    927 SCIP_CALL( SCIPfreeSol(subscip, &sol) );
    928 }
    929
    930 /* if the solution is feasible, fix variables and delete constraints of the component */
    931 if( feasible )
    932 {
    933 /* fix variables */
    934 for( i = 0; i < nvars; ++i )
    935 {
    936 assert(SCIPisLE(scip, fixvals[i], SCIPvarGetUbLocal(vars[i])));
    937 assert(SCIPisGE(scip, fixvals[i], SCIPvarGetLbLocal(vars[i])));
    938 assert(SCIPisLE(scip, fixvals[i], SCIPvarGetUbGlobal(vars[i])));
    939 assert(SCIPisGE(scip, fixvals[i], SCIPvarGetLbGlobal(vars[i])));
    940
    941 SCIP_CALL( SCIPfixVar(scip, vars[i], fixvals[i], &infeasible, &fixed) );
    943 assert(!infeasible);
    944 assert(fixed);
    945 (*nfixedvars)++;
    946 }
    947
    948 /* delete constraints */
    949 for( i = 0; i < nconss; ++i )
    950 {
    951 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
    952 (*ndeletedconss)++;
    953 }
    954
    955 *result = SCIP_SUCCESS;
    956 *solved = TRUE;
    957 }
    958 }
    959
    960 SCIPfreeBufferArray(scip, &fixvals);
    961 }
    962 else if( SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE )
    963 {
    964 *result = SCIP_CUTOFF;
    965 }
    966 else if( SCIPgetStatus(subscip) == SCIP_STATUS_UNBOUNDED || SCIPgetStatus(subscip) == SCIP_STATUS_INFORUNBD )
    967 {
    968 /* TODO: store unbounded ray in original SCIP data structure */
    969 *result = SCIP_UNBOUNDED;
    970 }
    971 else
    972 {
    973 SCIPdebugMsg(scip, "--> solving interrupted (status = %d, time = %.2f)\n",
    974 SCIPgetStatus(subscip), SCIPgetSolvingTime(subscip));
    975
    976 /* transfer global fixings to the original problem; we can only do this, if we did not find a solution in the
    977 * subproblem, because otherwise, the primal bound might lead to dual reductions that cannot be transferred to
    978 * the original problem without also transferring the possibly suboptimal solution (which is currently not
    979 * possible)
    980 */
    981 if( SCIPgetNSols(subscip) == 0 )
    982 {
    983 SCIP_Bool infeasible;
    984 SCIP_Bool tightened;
    985 int ntightened;
    986
    987 ntightened = 0;
    988
    989 for( i = 0; i < nvars; ++i )
    990 {
    991 if( subvars[i] == NULL )
    992 continue;
    993
    995 &infeasible, &tightened) );
    996 assert(!infeasible);
    997 if( tightened )
    998 ntightened++;
    999
    1000 SCIP_CALL( SCIPtightenVarUb(scip, vars[i], SCIPvarGetUbGlobal(subvars[i]), FALSE,
    1001 &infeasible, &tightened) );
    1002 assert(!infeasible);
    1003 if( tightened )
    1004 ntightened++;
    1005 }
    1006
    1007 *result = SCIP_SUCCESS;
    1008
    1009 *ntightenedbounds += ntightened;
    1010
    1011 SCIPdebugMsg(scip, "--> tightened %d bounds of variables due to global bounds in the sub-SCIP\n", ntightened);
    1012 }
    1013 }
    1014
    1015 return SCIP_OKAY;
    1016}
    1017
    1018/** (continues) solving a connected component */
    1019static
    1021 COMPONENT* component, /**< component structure */
    1022 SCIP_Bool lastcomponent, /**< is this the last component to be solved? */
    1023 SCIP_RESULT* result /**< pointer to store the result of the solving process */
    1024 )
    1025{
    1026 PROBLEM* problem;
    1027 SCIP* scip;
    1028 SCIP* subscip;
    1029 SCIP_SOL* bestsol;
    1030 SCIP_Longint nodelimit;
    1031 SCIP_Longint lastnnodes;
    1032 SCIP_Real gaplimit;
    1033 SCIP_STATUS status;
    1034
    1035 assert(component != NULL);
    1036
    1037 problem = component->problem;
    1038 assert(problem != NULL);
    1039
    1040 scip = problem->scip;
    1041 assert(scip != NULL);
    1042
    1043 subscip = component->subscip;
    1044 assert(subscip != NULL);
    1045
    1046 *result = SCIP_DIDNOTRUN;
    1047
    1048 SCIPdebugMsg(scip, "solve component <%s> (ncalls = %d, absgap = %.9g)\n",
    1049 SCIPgetProbName(subscip), component->ncalls, component->lastprimalbound - component->lastdualbound);
    1050
    1051 bestsol = SCIPgetBestSol(scip);
    1052
    1053 /* update best solution of component */
    1054 if( bestsol != NULL && SCIPsolGetIndex(bestsol) != component->lastbestsolindex )
    1055 {
    1056 SCIP_SOL* compsol = component->workingsol;
    1057 SCIP_VAR** vars = component->vars;
    1058 SCIP_VAR** subvars = component->subvars;
    1059 int nvars = component->nvars;
    1060 int v;
    1061
    1062 component->lastbestsolindex = SCIPsolGetIndex(bestsol);
    1063
    1064 /* set solution values of component variables */
    1065 for( v = 0; v < nvars; ++v )
    1066 {
    1067 if( subvars[v] != NULL )
    1068 {
    1069 SCIP_CALL( SCIPsetSolVal(subscip, compsol, subvars[v], SCIPgetSolVal(scip, bestsol, vars[v])) );
    1070 }
    1071 }
    1072#ifndef NDEBUG
    1073 for( v = 0; v < component->nfixedvars; ++v )
    1074 {
    1075 if( component->fixedsubvars[v] != NULL )
    1076 assert(SCIPisEQ(scip, SCIPgetSolVal(subscip, compsol, component->fixedsubvars[v]),
    1077 SCIPvarGetLbGlobal(component->fixedsubvars[v])));
    1078 }
    1079#endif
    1080
    1081 if( SCIPgetStage(subscip) == SCIP_STAGE_PROBLEM
    1082 || SCIPisLT(subscip, SCIPgetSolOrigObj(subscip, compsol), SCIPgetPrimalbound(subscip)) )
    1083 {
    1084 SCIP_Bool feasible;
    1085
    1086 SCIPdebugMsg(scip, "checking new solution in component <%s> inherited from problem <%s>: primal bound %.9g --> %.9g\n",
    1087 SCIPgetProbName(subscip), problem->name,
    1088 SCIPgetStage(subscip) == SCIP_STAGE_PROBLEM ? SCIPinfinity(subscip) : SCIPgetPrimalbound(subscip),
    1089 SCIPgetSolOrigObj(subscip, compsol));
    1090
    1091 SCIP_CALL( SCIPcheckSolOrig(subscip, compsol, &feasible, FALSE, FALSE) );
    1092 if( feasible )
    1093 {
    1094 SCIPdebugMsg(scip,"... feasible, adding solution.\n");
    1095
    1096 SCIP_CALL( SCIPaddSol(subscip, compsol, &feasible) );
    1097 }
    1098
    1099 /* We cannot take the value of compsol as a cutoff bound if it was not feasible; some of the fixed connecting
    1100 * variables are different and might not allow for a better solution in this component, but still for far
    1101 * better solutions in other components. Therefore, the only cutoffbound we can apply is the cutoffbound
    1102 * of the problem reduced by the dual bounds of the other components
    1103 */
    1104 if( problem->nlowerboundinf == 0 || (problem->nlowerboundinf == 1
    1105 && SCIPisInfinity(scip, -component->lastdualbound)) )
    1106 {
    1107 SCIP_Real newcutoffbound = SCIPgetSolTransObj(scip, bestsol);
    1108
    1109 assert(problem->nlowerboundinf > 0 || SCIPisGE(scip, newcutoffbound, problem->lowerbound));
    1110
    1111 newcutoffbound = newcutoffbound - problem->lowerbound + component->fixedvarsobjsum;
    1112
    1113 if( problem->nlowerboundinf == 0 )
    1114 newcutoffbound += component->lastdualbound;
    1115
    1116 if( SCIPisSumLT(subscip, newcutoffbound, SCIPgetCutoffbound(subscip)) )
    1117 {
    1118 SCIPdebugMsg(scip, "update cutoff bound to %.9g\n", newcutoffbound);
    1119
    1120 SCIP_CALL( SCIPupdateCutoffbound(subscip, newcutoffbound) );
    1121 }
    1122 }
    1123 }
    1124 }
    1125
    1126 assert(component->laststatus != SCIP_STATUS_OPTIMAL);
    1127
    1128 SCIPdebugMsg(scip, "solve sub-SCIP for component <%s> (ncalls = %d, absgap = %.9g)\n",
    1129 SCIPgetProbName(component->subscip), component->ncalls, component->lastprimalbound - component->lastdualbound);
    1130
    1131 if( component->ncalls == 0 )
    1132 {
    1133 nodelimit = 1LL;
    1134 gaplimit = 0.0;
    1135
    1136 lastnnodes = 0;
    1137 }
    1138 else
    1139 {
    1140 SCIP_Longint mainnodelimit;
    1141
    1142 lastnnodes = SCIPgetNNodes(component->subscip);
    1143
    1144 SCIP_CALL( SCIPgetLongintParam(scip, "limits/nodes", &mainnodelimit) );
    1145
    1146 nodelimit = 2 * lastnnodes;
    1147 nodelimit = MAX(nodelimit, 10LL);
    1148
    1149 if( mainnodelimit != -1 )
    1150 {
    1151 assert(mainnodelimit >= lastnnodes);
    1152 nodelimit = MIN(nodelimit, mainnodelimit - lastnnodes);
    1153 }
    1154
    1155 /* set a gap limit of half the current gap (at most 10%) */
    1156 if( SCIPgetGap(component->subscip) < 0.2 )
    1157 gaplimit = 0.5 * SCIPgetGap(component->subscip);
    1158 else
    1159 gaplimit = 0.1;
    1160
    1161 if( lastcomponent )
    1162 gaplimit = 0.0;
    1163 }
    1164
    1165 SCIP_CALL( solveSubscip(scip, subscip, nodelimit, gaplimit) );
    1166
    1167 SCIPaddNNodes(scip, SCIPgetNNodes(subscip) - lastnnodes);
    1168
    1170
    1171 status = SCIPgetStatus(subscip);
    1172
    1173 component->laststatus = status;
    1174 ++component->ncalls;
    1175
    1176 SCIPdebugMsg(scip, "--> (status = %d, nodes = %lld, time = %.2f): gap = %.5g%%, absgap = %.9g\n",
    1177 status, SCIPgetNNodes(subscip), SCIPgetSolvingTime(subscip), 100.0*SCIPgetGap(subscip),
    1178 SCIPgetPrimalbound(subscip) - SCIPgetDualbound(subscip));
    1179
    1180 *result = SCIP_SUCCESS;
    1181
    1182 switch( status )
    1183 {
    1185 component->solved = TRUE;
    1186 break;
    1188 component->solved = TRUE;
    1189
    1190 /* the problem is really infeasible */
    1191 if( SCIPisInfinity(subscip, SCIPgetPrimalbound(subscip)) )
    1192 {
    1193 *result = SCIP_CUTOFF;
    1194 }
    1195 /* the cutoff bound was reached; no solution better than the cutoff bound exists */
    1196 else
    1197 {
    1198 *result = SCIP_SUCCESS;
    1199 component->laststatus = SCIP_STATUS_OPTIMAL;
    1200 assert(SCIPisLE(subscip, SCIPgetDualbound(subscip), SCIPgetPrimalbound(subscip)));
    1201 }
    1202 break;
    1205 /* TODO: store unbounded ray in original SCIP data structure */
    1206 *result = SCIP_UNBOUNDED;
    1207 component->solved = TRUE;
    1208 break;
    1211 break;
    1225 default:
    1226 break;
    1227 }
    1228
    1229 /* evaluate call */
    1230 if( *result == SCIP_SUCCESS )
    1231 {
    1232 SCIP_SOL* sol = SCIPgetBestSol(subscip);
    1233 SCIP_VAR* var;
    1234 SCIP_VAR* subvar;
    1235 SCIP_Real newdualbound;
    1236 int v;
    1237
    1238 /* get dual bound as the minimum of SCIP dual bound and sub-problems dual bound */
    1239 newdualbound = SCIPgetDualbound(subscip) - component->fixedvarsobjsum;
    1240
    1241 /* update dual bound of problem */
    1242 if( !SCIPisEQ(scip, component->lastdualbound, newdualbound) )
    1243 {
    1244 assert(!SCIPisInfinity(scip, -newdualbound));
    1245
    1246 /* first finite dual bound: decrease inf counter and add dual bound to problem dualbound */
    1247 if( SCIPisInfinity(scip, -component->lastdualbound) )
    1248 {
    1249 --problem->nlowerboundinf;
    1250 problem->lowerbound += newdualbound;
    1251 }
    1252 /* increase problem dual bound by dual bound delta */
    1253 else
    1254 {
    1255 problem->lowerbound += (newdualbound - component->lastdualbound);
    1256 }
    1257
    1258 /* update problem dual bound if all problem components have a finite dual bound */
    1259 if( problem->nlowerboundinf == 0 )
    1260 {
    1261 SCIPdebugMsg(scip, "component <%s>: dual bound increased from %.9g to %.9g, new dual bound of problem <%s>: %.9g (gap = %.9g, absgap = %.9g)\n",
    1262 SCIPgetProbName(subscip), component->lastdualbound, newdualbound, problem->name,
    1263 SCIPretransformObj(scip, problem->lowerbound),
    1264 problem->nfeascomps == problem->ncomponents ?
    1265 (SCIPgetSolOrigObj(scip, problem->bestsol) - SCIPretransformObj(scip, problem->lowerbound)) /
    1266 MAX( ABS( SCIPretransformObj(scip, problem->lowerbound) ), SCIPgetSolOrigObj(scip, problem->bestsol) ) /*lint !e666*/
    1267 : SCIPinfinity(scip),
    1268 problem->nfeascomps == problem->ncomponents ?
    1269 SCIPgetSolOrigObj(scip, problem->bestsol) - SCIPretransformObj(scip, problem->lowerbound) : SCIPinfinity(scip));
    1270 SCIP_CALL( SCIPupdateLocalLowerbound(scip, problem->lowerbound) );
    1271 }
    1272
    1273 /* store dual bound of this call */
    1274 component->lastdualbound = newdualbound;
    1275 }
    1276
    1277 /* update primal solution of problem */
    1278 if( sol != NULL && component->lastsolindex != SCIPsolGetIndex(sol) )
    1279 {
    1280 component->lastsolindex = SCIPsolGetIndex(sol);
    1281
    1282 if( SCIPsolGetHeur(sol) != NULL )
    1284 else
    1285 SCIPsolSetHeur(problem->bestsol, NULL);
    1286
    1287 /* increase counter for feasible problems if no solution was known before */
    1288 if( SCIPisInfinity(scip, component->lastprimalbound) )
    1289 ++(problem->nfeascomps);
    1290
    1291 /* update working best solution in problem */
    1292 for( v = 0; v < component->nvars; ++v )
    1293 {
    1294 var = component->vars[v];
    1295 subvar = component->subvars[v];
    1296 assert(var != NULL);
    1297 assert(SCIPvarIsActive(var));
    1298
    1299 if( subvar == NULL )
    1300 continue;
    1301
    1302 SCIP_CALL( SCIPsetSolVal(scip, problem->bestsol, var, SCIPgetSolVal(subscip, sol, subvar)) );
    1303 }
    1304
    1305 /* if we have a feasible solution for each component, add the working solution to the main problem */
    1306 if( problem->nfeascomps == problem->ncomponents )
    1307 {
    1308 SCIP_Bool feasible;
    1309#ifdef SCIP_MORE_DEBUG
    1310 SCIP_CALL( SCIPcheckSol(scip, problem->bestsol, TRUE, FALSE, TRUE, TRUE, TRUE, &feasible) );
    1311 assert(feasible);
    1312#endif
    1313 SCIP_CALL( SCIPaddSol(scip, problem->bestsol, &feasible) );
    1314
    1315 SCIPdebugMsg(scip, "component <%s>: primal bound decreased from %.9g to %.9g, new primal bound of problem <%s>: %.9g (gap = %.9g, absgap = %.9g)\n",
    1316 SCIPgetProbName(subscip), component->lastprimalbound, SCIPgetPrimalbound(subscip), problem->name,
    1317 SCIPgetSolOrigObj(scip, problem->bestsol),
    1318 problem->nfeascomps == problem->ncomponents ?
    1319 (SCIPgetSolOrigObj(scip, problem->bestsol) - SCIPretransformObj(scip, problem->lowerbound)) /
    1320 MAX( ABS( SCIPretransformObj(scip, problem->lowerbound) ),SCIPgetSolOrigObj(scip, problem->bestsol) ) /*lint !e666*/
    1321 : SCIPinfinity(scip),
    1322 problem->nfeascomps == problem->ncomponents ?
    1323 SCIPgetSolOrigObj(scip, problem->bestsol) - SCIPretransformObj(scip, problem->lowerbound) : SCIPinfinity(scip));
    1324 }
    1325
    1326 /* store primal bound of this call */
    1327 component->lastprimalbound = SCIPgetPrimalbound(subscip) - component->fixedvarsobjsum;
    1328 }
    1329
    1330 /* if the component was solved to optimality, we increase the respective counter and free the subscip */
    1331 if( component->laststatus == SCIP_STATUS_OPTIMAL || component->laststatus == SCIP_STATUS_INFEASIBLE ||
    1332 component->laststatus == SCIP_STATUS_UNBOUNDED || component->laststatus == SCIP_STATUS_INFORUNBD )
    1333 {
    1334 ++(problem->nsolvedcomps);
    1335 component->solved = TRUE;
    1336
    1337 /* free working solution and component */
    1338 SCIP_CALL( SCIPfreeSol(subscip, &component->workingsol) );
    1339
    1340 SCIP_CALL( SCIPfree(&subscip) );
    1341 component->subscip = NULL;
    1342 }
    1343 }
    1344
    1345 return SCIP_OKAY;
    1346}
    1347
    1348/** initialize subproblem structure */
    1349static
    1351 SCIP* scip, /**< SCIP data structure */
    1352 PROBLEM** problem, /**< pointer to subproblem structure */
    1353 SCIP_Real fixedvarsobjsum, /**< objective contribution of all locally fixed variables */
    1354 int ncomponents /**< number of independent components */
    1355 )
    1356{
    1357 char name[SCIP_MAXSTRLEN];
    1358 SCIP_VAR** vars;
    1359 int nvars;
    1360 int v;
    1361
    1362 assert(scip != NULL);
    1363 assert(problem != NULL);
    1364
    1365 vars = SCIPgetVars(scip);
    1366 nvars = SCIPgetNVars(scip);
    1367
    1368 SCIP_CALL( SCIPallocBlockMemory(scip, problem) );
    1369 assert(*problem != NULL);
    1370
    1371 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*problem)->components, ncomponents) );
    1372
    1373 /* create a priority queue for the components: we need exactly ncomponents slots in the queue so it should never be
    1374 * resized
    1375 */
    1376 SCIP_CALL( SCIPpqueueCreate(&(*problem)->compqueue, ncomponents, 1.2, componentSort, NULL) );
    1377
    1378 (*problem)->scip = scip;
    1379 (*problem)->lowerbound = fixedvarsobjsum;
    1380 (*problem)->fixedvarsobjsum = fixedvarsobjsum;
    1381 (*problem)->ncomponents = 0;
    1382 (*problem)->componentssize = ncomponents;
    1383 (*problem)->nlowerboundinf = ncomponents;
    1384 (*problem)->nfeascomps = 0;
    1385 (*problem)->nsolvedcomps = 0;
    1386
    1387 if( SCIPgetDepth(scip) == 0 )
    1388 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPgetProbName(scip));
    1389 else
    1391
    1392 SCIP_CALL( SCIPduplicateMemoryArray(scip, &(*problem)->name, name, strlen(name)+1) );
    1393
    1394 SCIP_CALL( SCIPcreateSol(scip, &(*problem)->bestsol, NULL) );
    1395
    1396 for( v = 0; v < nvars; v++ )
    1397 {
    1398 if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v])) )
    1399 {
    1400 SCIP_CALL( SCIPsetSolVal(scip, (*problem)->bestsol, vars[v],
    1401 (SCIPvarGetUbLocal(vars[v]) + SCIPvarGetLbLocal(vars[v]))/2) );
    1402 }
    1403 }
    1404
    1405 SCIPdebugMsg(scip, "initialized problem <%s>\n", (*problem)->name);
    1406
    1407 return SCIP_OKAY;
    1408}
    1409
    1410/** free subproblem structure */
    1411static
    1413 PROBLEM** problem /**< pointer to problem to free */
    1414 )
    1415{
    1416 SCIP* scip;
    1417 int c;
    1418
    1419 assert(problem != NULL);
    1420 assert(*problem != NULL);
    1421
    1422 scip = (*problem)->scip;
    1423 assert(scip != NULL);
    1424
    1425 /* free best solution */
    1426 if( (*problem)->bestsol != NULL )
    1427 {
    1428 SCIP_CALL( SCIPfreeSol(scip, &(*problem)->bestsol) );
    1429 }
    1430
    1431 /* free all components */
    1432 for( c = (*problem)->ncomponents - 1; c >= 0; --c )
    1433 {
    1434 SCIP_CALL( freeComponent(&(*problem)->components[c]) );
    1435 }
    1436 if( (*problem)->components != NULL )
    1437 {
    1438 SCIPfreeBlockMemoryArray(scip, &(*problem)->components, (*problem)->componentssize);
    1439 }
    1440
    1441 /* free priority queue */
    1442 SCIPpqueueFree(&(*problem)->compqueue);
    1443
    1444 /* free problem name */
    1445 SCIPfreeMemoryArray(scip, &(*problem)->name);
    1446
    1447 /* free PROBLEM struct and set the pointer to NULL */
    1448 SCIPfreeBlockMemory(scip, problem);
    1449 *problem = NULL;
    1450
    1451 return SCIP_OKAY;
    1452}
    1453
    1454/** creates and captures a components constraint */
    1455static
    1457 SCIP* scip, /**< SCIP data structure */
    1458 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    1459 const char* name, /**< name of constraint */
    1460 PROBLEM* problem /**< problem to be stored in the constraint */
    1461 )
    1462{
    1463 SCIP_CONSHDLR* conshdlr;
    1464
    1465 /* find the components constraint handler */
    1466 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    1467 if( conshdlr == NULL )
    1468 {
    1469 SCIPerrorMessage("components constraint handler not found\n");
    1470 return SCIP_PLUGINNOTFOUND;
    1471 }
    1472
    1473 /* create constraint */
    1474 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, (SCIP_CONSDATA*)problem,
    1476 TRUE, FALSE, FALSE, FALSE, TRUE) );
    1477
    1478 return SCIP_OKAY;
    1479}
    1480
    1481
    1482/** sort the components by size and sort vars and conss arrays by component numbers */
    1483static
    1485 SCIP* scip, /**< SCIP data structure */
    1486 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    1487 SCIP_DIGRAPH* digraph, /**< directed graph */
    1488 SCIP_CONS** conss, /**< constraints */
    1489 SCIP_VAR** vars, /**< variables */
    1490 int* varcomponent, /**< component numbers for the variables */
    1491 int* conscomponent, /**< array to store component numbers for the constraints */
    1492 int nconss, /**< number of constraints */
    1493 int nvars, /**< number of variables */
    1494 int* firstvaridxpercons, /**< array with index of first variable in vars array for each constraint */
    1495 int* ncompsminsize, /**< pointer to store the number of components not exceeding the minimum size */
    1496 int* ncompsmaxsize /**< pointer to store the number of components not exceeding the maximum size */
    1497 )
    1498{
    1499 SCIP_Real* compsize;
    1500 int* permu;
    1501 int ncomponents;
    1502 int nbinvars;
    1503 int nintvars;
    1504 int ndiscvars;
    1505 int ncontvars;
    1506 int minsize;
    1507 int v;
    1508 int c;
    1509
    1510 assert(scip != NULL);
    1511 assert(conshdlrdata != NULL);
    1512 assert(digraph != NULL);
    1513 assert(conss != NULL);
    1514 assert(vars != NULL);
    1515 assert(firstvaridxpercons != NULL);
    1516
    1517 /* compute minimum size of components to solve individually */
    1518 minsize = getMinsize(scip, conshdlrdata);
    1519
    1520 ncomponents = SCIPdigraphGetNComponents(digraph);
    1521 *ncompsminsize = 0;
    1522 *ncompsmaxsize = 0;
    1523
    1524 /* We want to sort the components in increasing complexity (number of discrete variables,
    1525 * integer weighted with factor intfactor, continuous used as tie-breaker).
    1526 * Therefore, we now get the variables for each component, count the different variable types
    1527 * and compute a size as described above. Then, we rename the components
    1528 * such that for i < j, component i has no higher complexity than component j.
    1529 */
    1530 SCIP_CALL( SCIPallocBufferArray(scip, &compsize, ncomponents) );
    1531 SCIP_CALL( SCIPallocBufferArray(scip, &permu, ncomponents) );
    1532
    1533 /* get number of variables in the components */
    1534 for( c = 0; c < ncomponents; ++c )
    1535 {
    1536 int* cvars;
    1537 int ncvars;
    1538
    1539 SCIPdigraphGetComponent(digraph, c, &cvars, &ncvars);
    1540 permu[c] = c;
    1541 nbinvars = 0;
    1542 nintvars = 0;
    1543
    1544 for( v = 0; v < ncvars; ++v )
    1545 {
    1546 if( SCIPvarIsImpliedIntegral(vars[cvars[v]]) )
    1547 continue;
    1548 /* check whether variable is of binary or integer type */
    1549 if( SCIPvarGetType(vars[cvars[v]]) == SCIP_VARTYPE_BINARY )
    1550 nbinvars++;
    1551 else if( SCIPvarGetType(vars[cvars[v]]) == SCIP_VARTYPE_INTEGER )
    1552 nintvars++;
    1553 }
    1554 ncontvars = ncvars - nintvars - nbinvars;
    1555 /* TODO: come up with a more reasonable formula based on data.
    1556 * This formula weights integer variables very strongly, but ignores the impact of continuous variables somewhat*/
    1557 ndiscvars = (int)(nbinvars + conshdlrdata->intfactor * nintvars);
    1558 compsize[c] = nbinvars + conshdlrdata->intfactor * nintvars + conshdlrdata->contfactor * ncontvars;
    1559
    1560 /* component fulfills the maxsize and maxcompweight requirement */
    1561 if( ndiscvars <= conshdlrdata->maxintvars && compsize[c] <= conshdlrdata->maxcompweight )
    1562 ++(*ncompsmaxsize);
    1563
    1564 /* component fulfills the minsize requirement */
    1565 if( ncvars >= minsize )
    1566 ++(*ncompsminsize);
    1567 }
    1568
    1569 /* get permutation of component numbers such that the size of the components is increasing */
    1570 SCIPsortRealInt(compsize, permu, ncomponents);
    1571
    1572 /* now, we need the reverse direction, i.e., for each component number, we store its new number
    1573 * such that the components are sorted; for this, we abuse the conscomponent array
    1574 */
    1575 for( c = 0; c < ncomponents; ++c )
    1576 conscomponent[permu[c]] = c;
    1577
    1578 /* for each variable, replace the old component number by the new one */
    1579 for( c = 0; c < nvars; ++c )
    1580 varcomponent[c] = conscomponent[varcomponent[c]];
    1581
    1582 SCIPfreeBufferArray(scip, &permu);
    1583 SCIPfreeBufferArray(scip, &compsize);
    1584
    1585 /* do the mapping from calculated components per variable to corresponding
    1586 * constraints and sort the component-arrays for faster finding the
    1587 * actual variables and constraints belonging to one component
    1588 */
    1589 for( c = 0; c < nconss; c++ )
    1590 conscomponent[c] = (firstvaridxpercons[c] == -1 ? -1 : varcomponent[firstvaridxpercons[c]]);
    1591
    1592 SCIPsortIntPtr(varcomponent, (void**)vars, nvars);
    1593 SCIPsortIntPtr(conscomponent, (void**)conss, nconss);
    1594
    1595 return SCIP_OKAY;
    1596}
    1597
    1598
    1599
    1600/** create PROBLEM structure for the current node and split it into components */
    1601static
    1603 SCIP* scip, /**< SCIP data structure */
    1604 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    1605 SCIP_Real fixedvarsobjsum, /**< objective contribution of all locally fixed variables */
    1606 SCIP_VAR** sortedvars, /**< array of unfixed variables sorted by components */
    1607 SCIP_CONS** sortedconss, /**< array of (checked) constraints sorted by components */
    1608 int* compstartsvars, /**< start points of components in sortedvars array */
    1609 int* compstartsconss, /**< start points of components in sortedconss array */
    1610 int ncomponents, /**< number of components */
    1611 PROBLEM** problem /**< pointer to store problem structure */
    1612 )
    1613{
    1614 COMPONENT* component;
    1615 SCIP_HASHMAP* consmap;
    1616 SCIP_HASHMAP* varmap;
    1617 SCIP_VAR** compvars;
    1618 SCIP_CONS** compconss;
    1619 SCIP_Bool success = TRUE;
    1620 int nfixedvars = SCIPgetNVars(scip) - compstartsvars[ncomponents];
    1621 int ncompconss;
    1622 int comp;
    1623
    1624 /* init subproblem data structure */
    1625 SCIP_CALL( initProblem(scip, problem, fixedvarsobjsum, ncomponents) );
    1626 assert((*problem)->components != NULL);
    1627
    1628 /* hashmap mapping from original constraints to constraints in the sub-SCIPs (for performance reasons) */
    1629 SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), compstartsconss[ncomponents]) );
    1630
    1631 /* loop over all components */
    1632 for( comp = 0; comp < ncomponents; comp++ )
    1633 {
    1634 SCIP_CALL( initComponent(*problem) );
    1635 assert((*problem)->ncomponents == comp+1);
    1636
    1637 component = &(*problem)->components[comp];
    1638
    1639 /* get component variables and store them in component structure */
    1640 compvars = &(sortedvars[compstartsvars[comp]]);
    1641 component->nvars = compstartsvars[comp + 1 ] - compstartsvars[comp];
    1642 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &component->vars, compvars, component->nvars) );
    1643 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &component->subvars, component->nvars) );
    1644 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(scip), component->nvars + nfixedvars) );
    1645
    1646 /* get component constraints */
    1647 compconss = &(sortedconss[compstartsconss[comp]]);
    1648 ncompconss = compstartsconss[comp + 1] - compstartsconss[comp];
    1649
    1650#ifdef DETAILED_OUTPUT
    1651 /* print details about the component including its size */
    1652 if( component->nvars > 1 && ncompconss > 1 )
    1653 {
    1654 int nbinvars = 0;
    1655 int nintvars = 0;
    1656 int ncontvars = 0;
    1657 int i;
    1658
    1659 for( i = 0; i < component->nvars; ++i )
    1660 {
    1661 if( SCIPvarGetType(compvars[i]) == SCIP_VARTYPE_BINARY )
    1662 ++nbinvars;
    1663 else if( SCIPvarGetType(compvars[i]) == SCIP_VARTYPE_INTEGER )
    1664 ++nintvars;
    1665 else
    1666 ++ncontvars;
    1667 }
    1668 SCIPdebugMsg(scip, "component %d at node %lld, depth %d (%d): %d vars (%d bin, %d int, %d cont), %d conss\n",
    1669 comp, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), SCIPgetDepth(scip), SCIPgetDepth(scip) + conshdlrdata->subscipdepth,
    1670 component->nvars, nbinvars, nintvars, ncontvars, ncompconss);
    1671 }
    1672#endif
    1673 assert(ncompconss > 0 || component->nvars == 1);
    1674
    1675 SCIPdebugMsg(scip, "build sub-SCIP for component %d of problem <%s>: %d vars, %d conss\n",
    1676 component->number, (*problem)->name, component->nvars, ncompconss);
    1677
    1678#ifndef NDEBUG
    1679 {
    1680 int i;
    1681 for( i = 0; i < component->nvars; ++i )
    1682 assert(SCIPvarIsActive(component->vars[i]));
    1683 }
    1684#endif
    1685
    1686 /* build subscip for component */
    1687 SCIP_CALL( componentCreateSubscip(component, conshdlrdata, varmap, consmap, compconss, ncompconss, &success) );
    1688
    1689 if( success )
    1690 {
    1691 SCIP_CALL( componentSetupWorkingSol(component, varmap) );
    1692
    1693 /* add component to the priority queue of the problem structure */
    1694 SCIP_CALL( SCIPpqueueInsert((*problem)->compqueue, component) );
    1695 }
    1696
    1697 SCIPhashmapFree(&varmap);
    1698
    1699 if( !success )
    1700 break;
    1701 }
    1702
    1703 SCIPhashmapFree(&consmap);
    1704
    1705 if( !success )
    1706 {
    1707 /* free subproblem data structure since not all component could be copied */
    1708 SCIP_CALL( freeProblem(problem) );
    1709 }
    1710
    1711 return SCIP_OKAY;
    1712}
    1713
    1714/** continue solving a problem */
    1715static
    1717 PROBLEM* problem, /**< problem structure */
    1718 SCIP_RESULT* result /**< result pointer for the problem solve */
    1719 )
    1720{
    1721 COMPONENT* component;
    1722 SCIP_RESULT subscipresult;
    1723
    1724 assert(problem != NULL);
    1725
    1726 *result = SCIP_SUCCESS;
    1727
    1728 component = (COMPONENT*)SCIPpqueueRemove(problem->compqueue);
    1729
    1730 /* continue solving the component */
    1731 SCIP_CALL( solveComponent(component, SCIPpqueueNElems(problem->compqueue) == 0, &subscipresult) );
    1732
    1733 /* if infeasibility or unboundedness was detected, return this */
    1734 if( subscipresult == SCIP_CUTOFF || subscipresult == SCIP_UNBOUNDED )
    1735 {
    1736 *result = subscipresult;
    1737 }
    1738 /* the component was not solved to optimality, so we need to re-insert it in the components queue */
    1739 else if( !component->solved )
    1740 {
    1741 SCIP_CALL( SCIPpqueueInsert(problem->compqueue, component) );
    1742 *result = SCIP_DELAYNODE;
    1743 }
    1744 /* no unsolved components are left, so this problem has be completely evaluated and the node can be pruned */
    1745 else if( SCIPpqueueNElems(problem->compqueue) == 0 )
    1746 *result = SCIP_CUTOFF;
    1747 /* there are some unsolved components left, so we delay this node */
    1748 else
    1749 *result = SCIP_DELAYNODE;
    1750
    1751 return SCIP_OKAY;
    1752}
    1753
    1754/*
    1755 * Local methods
    1756 */
    1757
    1758/** loop over constraints, get active variables and fill directed graph */
    1759static
    1761 SCIP* scip, /**< SCIP data structure */
    1762 SCIP_DIGRAPH* digraph, /**< directed graph */
    1763 SCIP_CONS** conss, /**< constraints */
    1764 int nconss, /**< number of constraints */
    1765 int* unfixedvarpos, /**< mapping from variable problem index to unfixed var index */
    1766 int nunfixedvars, /**< number of unfixed variables */
    1767 int* firstvaridxpercons, /**< array to store for each constraint the index in the local vars array
    1768 * of the first variable of the constraint */
    1769 SCIP_Bool* success /**< flag indicating successful directed graph filling */
    1770 )
    1771{
    1772 SCIP_VAR** consvars;
    1773 int requiredsize;
    1774 int nconsvars;
    1775 int nvars;
    1776 int idx1;
    1777 int idx2;
    1778 int c;
    1779 int v;
    1780
    1781 assert(scip != NULL);
    1782 assert(digraph != NULL);
    1783 assert(conss != NULL);
    1784 assert(firstvaridxpercons != NULL);
    1785 assert(success != NULL);
    1786
    1787 *success = TRUE;
    1788
    1789 nconsvars = 0;
    1790 requiredsize = 0;
    1791 nvars = SCIPgetNVars(scip);
    1792
    1793 /* allocate buffer for storing active variables per constraint; size = nvars ensures that it will be big enough */
    1794 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nvars) );
    1795
    1796 for( c = 0; c < nconss; ++c )
    1797 {
    1798 /* check for reached timelimit */
    1799 if( (c % 1000 == 0) && SCIPisStopped(scip) )
    1800 {
    1801 *success = FALSE;
    1802 break;
    1803 }
    1804
    1805 /* get number of variables for this constraint */
    1806 SCIP_CALL( SCIPgetConsNVars(scip, conss[c], &nconsvars, success) );
    1807
    1808 if( !(*success) )
    1809 break;
    1810
    1811 /* reallocate consvars array, if needed */
    1812 if( nconsvars > nvars )
    1813 {
    1814 nvars = nconsvars;
    1815 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, nvars) );
    1816 }
    1817
    1818#ifndef NDEBUG
    1819 /* clearing variables array to check for consistency */
    1820 if( nconsvars == nvars )
    1821 {
    1822 BMSclearMemoryArray(consvars, nconsvars);
    1823 }
    1824 else
    1825 {
    1826 assert(nconsvars < nvars);
    1827 BMSclearMemoryArray(consvars, nconsvars + 1);
    1828 }
    1829#endif
    1830
    1831 /* get variables for this constraint */
    1832 SCIP_CALL( SCIPgetConsVars(scip, conss[c], consvars, nvars, success) );
    1833
    1834 if( !(*success) )
    1835 {
    1836#ifndef NDEBUG
    1837 /* it looks strange if returning the number of variables was successful but not returning the variables */
    1838 SCIPwarningMessage(scip, "constraint <%s> returned number of variables but returning variables failed\n", SCIPconsGetName(conss[c]));
    1839#endif
    1840 break;
    1841 }
    1842
    1843#ifndef NDEBUG
    1844 /* check if returned variables are consistent with the number of variables that were returned */
    1845 for( v = nconsvars - 1; v >= 0; --v )
    1846 assert(consvars[v] != NULL);
    1847 if( nconsvars < nvars )
    1848 assert(consvars[nconsvars] == NULL);
    1849#endif
    1850
    1851 /* transform given variables to active variables */
    1852 SCIP_CALL( SCIPgetActiveVars(scip, consvars, &nconsvars, nvars, &requiredsize) );
    1853 assert(requiredsize <= nvars);
    1854
    1855 firstvaridxpercons[c] = -1;
    1856
    1857 /* store the index of the first unfixed variable and add edges to the directed graph */
    1858 if( nconsvars > 0 )
    1859 {
    1860 v = 0;
    1861 idx1 = -1;
    1862
    1863 /* go through variables until the first unfixed one is reached (which has unfixedvarpos >= 0) */
    1864 while( idx1 == -1 && v < nconsvars )
    1865 {
    1866 idx1 = SCIPvarGetProbindex(consvars[v]);
    1867 assert(idx1 >= 0);
    1868 idx1 = unfixedvarpos[idx1];
    1869 assert(idx1 < nunfixedvars);
    1870 ++v;
    1871 }
    1872
    1873 if( idx1 >= 0 )
    1874 {
    1875 /* save index of the first variable for later component assignment */
    1876 firstvaridxpercons[c] = idx1;
    1877
    1878 /* create sparse directed graph; sparse means to add only those edges necessary for component calculation,
    1879 * i.e., add edges from the first variable to all others
    1880 */
    1881 for(; v < nconsvars; ++v )
    1882 {
    1883 idx2 = SCIPvarGetProbindex(consvars[v]);
    1884 assert(idx2 >= 0);
    1885 idx2 = unfixedvarpos[idx2];
    1886 assert(idx2 < nunfixedvars);
    1887
    1888 /* variable is fixed */
    1889 if( idx2 < 0 )
    1890 continue;
    1891
    1892 /* we add only one directed edge, because the other direction is automatically added for component computation */
    1893 SCIP_CALL( SCIPdigraphAddArc(digraph, idx1, idx2, NULL) );
    1894 }
    1895 }
    1896 }
    1897 }
    1898
    1899 SCIPfreeBufferArray(scip, &consvars);
    1900
    1901 return SCIP_OKAY;
    1902}
    1903
    1904/** search for components in the problem */
    1905static
    1907 SCIP* scip, /**< SCIP main data structure */
    1908 SCIP_CONSHDLRDATA* conshdlrdata, /**< the components constraint handler data */
    1909 SCIP_Real* fixedvarsobjsum, /**< objective contribution of all locally fixed variables, or NULL if
    1910 * fixed variables should not be disregarded */
    1911 SCIP_VAR** sortedvars, /**< array to store variables sorted by components, should have enough size
    1912 * for all variables */
    1913 SCIP_CONS** sortedconss, /**< array to store (checked) constraints sorted by components, should have
    1914 * enough size for all constraints */
    1915 int* compstartsvars, /**< start points of components in sortedvars array */
    1916 int* compstartsconss, /**< start points of components in sortedconss array */
    1917 int* nsortedvars, /**< pointer to store the number of variables belonging to any component */
    1918 int* nsortedconss, /**< pointer to store the number of (checked) constraints in components */
    1919 int* ncomponents, /**< pointer to store the number of components */
    1920 int* ncompsminsize, /**< pointer to store the number of components not exceeding the minimum size */
    1921 int* ncompsmaxsize /**< pointer to store the number of components not exceeding the maximum size */
    1922
    1923 )
    1924{
    1925 SCIP_CONS** tmpconss;
    1926 SCIP_VAR** vars;
    1927 SCIP_Bool success;
    1928 int ntmpconss;
    1929 int nvars;
    1930 int c;
    1931
    1932 assert(scip != NULL);
    1933 assert(conshdlrdata != NULL);
    1934 assert(sortedvars != NULL);
    1935 assert(sortedconss != NULL);
    1936 assert(compstartsvars != NULL);
    1937 assert(compstartsconss != NULL);
    1938 assert(nsortedvars != NULL);
    1939 assert(nsortedconss != NULL);
    1940 assert(ncomponents != NULL);
    1941 assert(ncompsminsize != NULL);
    1942 assert(ncompsmaxsize != NULL);
    1943
    1944 vars = SCIPgetVars(scip);
    1945 nvars = SCIPgetNVars(scip);
    1946
    1947 if( fixedvarsobjsum != NULL )
    1948 *fixedvarsobjsum = 0.0;
    1949
    1950 *ncomponents = 0;
    1951 *ncompsminsize = 0;
    1952 *ncompsmaxsize = 0;
    1953
    1954 /* collect checked constraints for component detection */
    1955 ntmpconss = SCIPgetNConss(scip);
    1956 tmpconss = SCIPgetConss(scip);
    1957 (*nsortedconss) = 0;
    1958 for( c = 0; c < ntmpconss; c++ )
    1959 {
    1960 sortedconss[(*nsortedconss)] = tmpconss[c];
    1961 (*nsortedconss)++;
    1962 }
    1963
    1964 if( nvars > 1 && *nsortedconss > 1 )
    1965 {
    1966 int* unfixedvarpos;
    1967 int* firstvaridxpercons;
    1968 int* varlocks;
    1969 int nunfixedvars = 0;
    1970 int v;
    1971
    1972 /* arrays for storing the first variable in each constraint (for later component assignment), the number of
    1973 * variable locks, and the positions in the sortedvars array for all unfixed variables
    1974 */
    1975 SCIP_CALL( SCIPallocBufferArray(scip, &firstvaridxpercons, *nsortedconss) );
    1976 SCIP_CALL( SCIPallocBufferArray(scip, &varlocks, nvars) );
    1977 SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvarpos, nvars) );
    1978
    1979 /* count number of varlocks for each variable (up + down locks) and multiply it by 2;
    1980 * that value is used as an estimate of the number of arcs incident to the variable's node in the digraph
    1981 * to be safe, we double this value
    1982 */
    1983 for( v = 0; v < nvars; ++v )
    1984 {
    1985 /* variable is not fixed or we do not want to disregard fixed variables */
    1986 if( (fixedvarsobjsum == NULL) || SCIPisLT(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v])) )
    1987 {
    1988 assert(nunfixedvars <= v);
    1989 sortedvars[nunfixedvars] = vars[v];
    1990 varlocks[nunfixedvars] = 4 * (SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL)
    1992 unfixedvarpos[v] = nunfixedvars;
    1993 ++nunfixedvars;
    1994 }
    1995 /* variable is fixed; update the objective sum of all fixed variables */
    1996 else
    1997 {
    1998 unfixedvarpos[v] = -1;
    1999 (*fixedvarsobjsum) += SCIPvarGetObj(vars[v]) * SCIPvarGetLbLocal(vars[v]);
    2000 }
    2001 }
    2002 *nsortedvars = nunfixedvars;
    2003
    2004 if( nunfixedvars > 0 )
    2005 {
    2006 SCIP_DIGRAPH* digraph;
    2007
    2008 /* create and fill directed graph */
    2009 SCIP_CALL( SCIPcreateDigraph(scip, &digraph, nunfixedvars) );
    2010 SCIP_CALL( SCIPdigraphSetSizes(digraph, varlocks) );
    2011 SCIP_CALL( fillDigraph(scip, digraph, sortedconss, *nsortedconss, unfixedvarpos, nunfixedvars, firstvaridxpercons, &success) );
    2012
    2013 if( success )
    2014 {
    2015 int* varcomponent;
    2016 int* conscomponent;
    2017
    2018 SCIP_CALL( SCIPallocBufferArray(scip, &varcomponent, nunfixedvars) );
    2019 SCIP_CALL( SCIPallocBufferArray(scip, &conscomponent, MAX(nunfixedvars,*nsortedconss)) );
    2020
    2021 /* compute independent components */
    2022 SCIP_CALL( SCIPdigraphComputeUndirectedComponents(digraph, 1, varcomponent, ncomponents) );
    2023
    2024 if( *ncomponents > 1 )
    2025 {
    2026 int nconss = *nsortedconss;
    2027 int i;
    2028
    2029 nvars = *nsortedvars;
    2030
    2032 "cons components found %d undirected components at node %lld, depth %d (%d)\n",
    2033 *ncomponents, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), SCIPgetDepth(scip), SCIPgetDepth(scip) + conshdlrdata->subscipdepth);
    2034
    2035 /* sort components by size and sort variables and constraints by component number */
    2036 SCIP_CALL( sortComponents(scip, conshdlrdata, digraph, sortedconss, sortedvars, varcomponent, conscomponent, nconss, *nsortedvars,
    2037 firstvaridxpercons, ncompsminsize, ncompsmaxsize) );
    2038
    2039 /* determine start indices of components in sortedvars and sortedconss array */
    2040 i = 0;
    2041
    2042 while( i < nconss && conscomponent[i] == -1 )
    2043 ++i;
    2044
    2045 for( c = 0; c < *ncomponents + 1; ++c )
    2046 {
    2047 assert(i == nconss || conscomponent[i] >= c);
    2048
    2049 compstartsconss[c] = i;
    2050
    2051 while( i < nconss && conscomponent[i] == c )
    2052 ++i;
    2053 }
    2054
    2055 for( c = 0, i = 0; c < *ncomponents + 1; ++c )
    2056 {
    2057 assert(i == nvars || varcomponent[i] >= c);
    2058
    2059 compstartsvars[c] = i;
    2060
    2061 while( i < nvars && varcomponent[i] == c )
    2062 ++i;
    2063 }
    2064
    2065#ifndef NDEBUG
    2066 for( c = 0; c < *ncomponents; ++c )
    2067 {
    2068 for( i = compstartsconss[c]; i < compstartsconss[c+1]; ++i )
    2069 assert(conscomponent[i] == c);
    2070 for( i = compstartsvars[c]; i < compstartsvars[c+1]; ++i )
    2071 assert(varcomponent[i] == c);
    2072 }
    2073#endif
    2074 }
    2075
    2076 SCIPfreeBufferArray(scip, &conscomponent);
    2077 SCIPfreeBufferArray(scip, &varcomponent);
    2078 }
    2079
    2080 SCIPdigraphFree(&digraph);
    2081 }
    2082
    2083 SCIPfreeBufferArray(scip, &unfixedvarpos);
    2084 SCIPfreeBufferArray(scip, &varlocks);
    2085 SCIPfreeBufferArray(scip, &firstvaridxpercons);
    2086 }
    2087
    2088 return SCIP_OKAY;
    2089}
    2090
    2091
    2092/*
    2093 * Callback methods of constraint handler
    2094 */
    2095
    2096/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    2097static
    2098SCIP_DECL_CONSHDLRCOPY(conshdlrCopyComponents)
    2099{ /*lint --e{715}*/
    2100 assert(scip != NULL);
    2101 assert(conshdlr != NULL);
    2102 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2103
    2104 /* call inclusion method of constraint handler */
    2106
    2107 *valid = TRUE;
    2108
    2109 return SCIP_OKAY;
    2110}
    2111
    2112/** destructor of constraint handler to free user data (called when SCIP is exiting) */
    2113static
    2114SCIP_DECL_CONSFREE(conshdlrFreeComponents)
    2115{ /*lint --e{715}*/
    2116 SCIP_CONSHDLRDATA* conshdlrdata;
    2117
    2118 /* free constraint handler data */
    2119 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2120 assert(conshdlrdata != NULL);
    2121
    2122 SCIPfreeBlockMemory(scip, &conshdlrdata);
    2123 SCIPconshdlrSetData(conshdlr, NULL);
    2124
    2125 return SCIP_OKAY;
    2126}
    2127
    2128/** domain propagation method of constraint handler */
    2129static
    2130SCIP_DECL_CONSPROP(consPropComponents)
    2131{ /*lint --e{715}*/
    2132 PROBLEM* problem;
    2133 SCIP_CONSHDLRDATA* conshdlrdata;
    2134 SCIP_Longint nodelimit;
    2135
    2136 assert(conshdlr != NULL);
    2137 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2138 assert(result != NULL);
    2139 assert(SCIPconshdlrGetNActiveConss(conshdlr) >= 0);
    2140 assert(SCIPconshdlrGetNActiveConss(conshdlr) <= 1);
    2141
    2142 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2143 assert(conshdlrdata != NULL);
    2144
    2145 *result = SCIP_DIDNOTRUN;
    2146
    2147 /* do not try to detect independent components if the depth is too high */
    2148 if( SCIPgetDepth(scip) + conshdlrdata->subscipdepth > conshdlrdata->maxdepth
    2149 && SCIPconshdlrGetNActiveConss(conshdlr) == 0 )
    2150 return SCIP_OKAY;
    2151
    2152 /* don't run in probing or in repropagation */
    2154 return SCIP_OKAY;
    2155
    2156 /* do not run, if not all variables are explicitly known */
    2157 if( SCIPgetNActivePricers(scip) > 0 )
    2158 return SCIP_OKAY;
    2159
    2160 /* we do not want to run, if there are no variables left */
    2161 if( SCIPgetNVars(scip) == 0 )
    2162 return SCIP_OKAY;
    2163
    2164 /* check for a reached timelimit */
    2165 if( SCIPisStopped(scip) )
    2166 return SCIP_OKAY;
    2167
    2168 /* the components constraint handler does kind of dual reductions */
    2170 return SCIP_OKAY;
    2171
    2172 problem = NULL;
    2173 *result = SCIP_DIDNOTFIND;
    2174
    2175 /* the current node already has a components constraint storing a problem split into individual components */
    2176 if( SCIPconshdlrGetNActiveConss(conshdlr) >= 1 )
    2177 {
    2178 assert(SCIPconshdlrGetNActiveConss(conshdlr) == 1);
    2179
    2180 problem = (PROBLEM*)SCIPconsGetData(SCIPconshdlrGetConss(conshdlr)[0]);
    2181 }
    2182 /* no components constraint at the current node, search for components */
    2183 else
    2184 {
    2185 SCIP_Real fixedvarsobjsum;
    2186 SCIP_VAR** sortedvars;
    2187 SCIP_CONS** sortedconss;
    2188 int* compstartsvars;
    2189 int* compstartsconss;
    2190 int nsortedvars;
    2191 int nsortedconss;
    2192 int ncomponents;
    2193 int ncompsminsize;
    2194 int ncompsmaxsize;
    2195
    2196 assert(SCIPconshdlrGetNActiveConss(conshdlr) == 0);
    2197
    2198 /* allocate memory for sorted components */
    2201 SCIP_CALL( SCIPallocBufferArray(scip, &compstartsvars, SCIPgetNVars(scip) + 1) );
    2202 SCIP_CALL( SCIPallocBufferArray(scip, &compstartsconss, SCIPgetNVars(scip) + 1) );
    2203
    2204 /* search for components */
    2205 SCIP_CALL( findComponents(scip, conshdlrdata, &fixedvarsobjsum, sortedvars, sortedconss, compstartsvars,
    2206 compstartsconss, &nsortedvars, &nsortedconss, &ncomponents, &ncompsminsize, &ncompsmaxsize) );
    2207
    2208 if( ncompsminsize > 1 )
    2209 {
    2210 SCIP_CONS* cons;
    2211
    2212 SCIPdebugMsg(scip, "found %d components (%d fulfilling the minsize requirement) at node %lld at depth %d (%d)\n",
    2213 ncomponents, ncompsminsize, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), SCIPgetDepth(scip),
    2214 SCIPgetDepth(scip) + conshdlrdata->subscipdepth);
    2215
    2216 /* if there are components with size smaller than the limit, we merge them with the smallest component */
    2217 if( ncomponents > ncompsminsize )
    2218 {
    2219 int minsize;
    2220 int size;
    2221 int c;
    2222 int m = 0;
    2223
    2224 /* compute minimum size of components to solve individually */
    2225 minsize = getMinsize(scip, conshdlrdata);
    2226
    2227 for( c = 0; c < ncomponents; ++c )
    2228 {
    2229 size = compstartsvars[c+1] - compstartsvars[c];
    2230
    2231 if( size >= minsize )
    2232 {
    2233 ++m;
    2234 compstartsvars[m] = compstartsvars[c+1];
    2235 compstartsconss[m] = compstartsconss[c+1];
    2236 }
    2237 /* the last component is too small */
    2238 else if( c == ncomponents - 1 )
    2239 {
    2240 assert(m == ncompsminsize);
    2241 compstartsvars[m] = compstartsvars[c+1];
    2242 compstartsconss[m] = compstartsconss[c+1];
    2243 }
    2244 }
    2245 assert(m == ncompsminsize);
    2246 assert(compstartsvars[m] == nsortedvars);
    2247 assert(compstartsconss[m] == nsortedconss);
    2248
    2249 ncomponents = m;
    2250 }
    2251
    2252 SCIP_CALL( createAndSplitProblem(scip, conshdlrdata, fixedvarsobjsum, sortedvars, sortedconss, compstartsvars,
    2253 compstartsconss, ncomponents, &problem) );
    2254
    2255 /* if the problem is not NULL, copying worked fine */
    2256 if( problem != NULL )
    2257 {
    2258 SCIP_CALL( createConsComponents(scip, &cons, problem->name, problem) );
    2260 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    2261 }
    2262 }
    2263
    2264 SCIPfreeBufferArray(scip, &compstartsconss);
    2265 SCIPfreeBufferArray(scip, &compstartsvars);
    2266 SCIPfreeBufferArray(scip, &sortedconss);
    2267 SCIPfreeBufferArray(scip, &sortedvars);
    2268 }
    2269
    2270 /* (continue to) solve the problem
    2271 *
    2272 * If the problem was not solved to optimality yet, the result code is set to SCIP_DELAYNODE, so that after the
    2273 * propagation is finished, the node is put back into the queue of open nodes and solving the components of the
    2274 * problem will be continued when the node is focused and propagated the next time.
    2275 * However, if we are at the root node, we continue solving the problem until it is solved or some limit is reached
    2276 * since there are no other nodes to process and we want to avoid calling other propagation methods or heuristics
    2277 * again and again
    2278 */
    2279 SCIP_CALL( SCIPgetLongintParam(scip, "limits/nodes", &nodelimit) );
    2280 if( nodelimit == -1 )
    2281 nodelimit = SCIP_LONGINT_MAX;
    2282
    2283 do
    2284 {
    2285 if( problem != NULL )
    2286 {
    2287 SCIP_CALL( solveProblem(problem, result) );
    2288 }
    2289 } while( *result == SCIP_DELAYNODE && SCIPgetDepth(scip) == 0 && !SCIPisStopped(scip) && SCIPgetNNodes(scip) < nodelimit);
    2290
    2291 return SCIP_OKAY;
    2292}
    2293
    2294/** presolving method of constraint handler */
    2295static
    2296SCIP_DECL_CONSPRESOL(consPresolComponents)
    2297{ /*lint --e{715}*/
    2298 SCIP_CONSHDLRDATA* conshdlrdata;
    2299 SCIP_VAR** sortedvars;
    2300 SCIP_CONS** sortedconss;
    2301 int* compstartsvars;
    2302 int* compstartsconss;
    2303 int nsortedvars;
    2304 int nsortedconss;
    2305 int ncomponents;
    2306 int ncompsminsize;
    2307 int ncompsmaxsize;
    2308 int nvars;
    2309
    2310 assert(conshdlr != NULL);
    2311 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2312 assert(result != NULL);
    2313 assert(SCIPconshdlrGetNActiveConss(conshdlr) >= 0);
    2314 assert(SCIPconshdlrGetNActiveConss(conshdlr) <= 1);
    2315
    2316 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2317 assert(conshdlrdata != NULL);
    2318
    2319 *result = SCIP_DIDNOTRUN;
    2320
    2322 return SCIP_OKAY;
    2323
    2324 /* do not run, if not all variables are explicitly known */
    2325 if( SCIPgetNActivePricers(scip) > 0 )
    2326 return SCIP_OKAY;
    2327
    2328 nvars = SCIPgetNVars(scip);
    2329
    2330 /* we do not want to run, if there are no variables left */
    2331 if( nvars == 0 )
    2332 return SCIP_OKAY;
    2333
    2334 /* only call the components presolving, if presolving would be stopped otherwise */
    2336 return SCIP_OKAY;
    2337
    2338 /* the components constraint handler does kind of dual reductions */
    2340 return SCIP_OKAY;
    2341
    2342 /* check for a reached timelimit */
    2343 if( SCIPisStopped(scip) )
    2344 return SCIP_OKAY;
    2345
    2346 *result = SCIP_DIDNOTFIND;
    2347
    2348 assert(SCIPconshdlrGetNActiveConss(conshdlr) == 0);
    2349
    2350 /* allocate memory for sorted components */
    2353 SCIP_CALL( SCIPallocBufferArray(scip, &compstartsvars, SCIPgetNVars(scip) + 1) );
    2354 SCIP_CALL( SCIPallocBufferArray(scip, &compstartsconss, SCIPgetNVars(scip) + 1) );
    2355
    2356 /* search for components */
    2357 SCIP_CALL( findComponents(scip, conshdlrdata, NULL, sortedvars, sortedconss, compstartsvars,
    2358 compstartsconss, &nsortedvars, &nsortedconss, &ncomponents, &ncompsminsize, &ncompsmaxsize) );
    2359
    2360 if( ncompsmaxsize > 0 )
    2361 {
    2362 char name[SCIP_MAXSTRLEN];
    2363 SCIP* subscip;
    2364 SCIP_HASHMAP* consmap;
    2365 SCIP_HASHMAP* varmap;
    2366 SCIP_VAR** compvars;
    2367 SCIP_VAR** subvars;
    2368 SCIP_CONS** compconss;
    2369 SCIP_Bool success;
    2370 SCIP_Bool solved;
    2371 int nsolved = 0;
    2372 int ncompvars;
    2373 int ncompconss;
    2374 int comp;
    2375
    2376 SCIPdebugMsg(scip, "found %d components (%d with small size) during presolving; overall problem size: %d vars (%d int, %d bin, %d cont), %d conss\n",
    2378
    2379 /* build subscip */
    2380 SCIP_CALL( createSubscip(scip, conshdlrdata, &subscip) );
    2381
    2382 if( subscip == NULL )
    2383 goto TERMINATE;
    2384
    2385 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/usesmalltables", TRUE) );
    2386 SCIP_CALL( SCIPsetIntParam(subscip, "constraints/" CONSHDLR_NAME "/propfreq", -1) );
    2387
    2388 /* hashmap mapping from original constraints to constraints in the sub-SCIPs (for performance reasons) */
    2389 SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), nsortedconss) );
    2390
    2391 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nsortedvars) );
    2392
    2393 /* loop over all components */
    2394 for( comp = 0; comp < ncompsmaxsize && !SCIPisStopped(scip); comp++ )
    2395 {
    2396#ifdef WITH_DEBUG_SOLUTION
    2397 if( SCIPgetStage(subscip) > SCIP_STAGE_INIT )
    2398 {
    2399 SCIP_CALL( SCIPfree(&subscip) );
    2400 SCIP_CALL( createSubscip(scip, conshdlrdata, &subscip) );
    2401 }
    2402#endif
    2403 /* get component variables */
    2404 compvars = &(sortedvars[compstartsvars[comp]]);
    2405 ncompvars = compstartsvars[comp + 1 ] - compstartsvars[comp];
    2406
    2407 /* get component constraints */
    2408 compconss = &(sortedconss[compstartsconss[comp]]);
    2409 ncompconss = compstartsconss[comp + 1] - compstartsconss[comp];
    2410
    2411 /* if we have an unlocked variable, let duality fixing do the job! */
    2412 if( ncompconss == 0 )
    2413 {
    2414 assert(ncompvars == 1);
    2415 continue;
    2416 }
    2417
    2418 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(scip), ncompvars) );
    2419#ifdef DETAILED_OUTPUT
    2420 {
    2421 int nbinvars = 0;
    2422 int nintvars = 0;
    2423 int ncontvars = 0;
    2424 int i;
    2425
    2426 for( i = 0; i < ncompvars; ++i )
    2427 {
    2428 if( SCIPvarGetType(compvars[i]) == SCIP_VARTYPE_BINARY )
    2429 ++nbinvars;
    2430 else if( SCIPvarGetType(compvars[i]) == SCIP_VARTYPE_INTEGER )
    2431 ++nintvars;
    2432 else
    2433 ++ncontvars;
    2434 }
    2435 SCIPdebugMsg(scip, "solve component %d: %d vars (%d bin, %d int, %d cont), %d conss\n",
    2436 comp, ncompvars, nbinvars, nintvars, ncontvars, ncompconss);
    2437 }
    2438#endif
    2439#ifndef NDEBUG
    2440 {
    2441 int i;
    2442 for( i = 0; i < ncompvars; ++i )
    2443 assert(SCIPvarIsActive(compvars[i]));
    2444 }
    2445#endif
    2446
    2447 /* get name of the original problem and add "comp_nr" */
    2448 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_comp_%d", SCIPgetProbName(scip), comp);
    2449
    2450 SCIP_CALL( copyToSubscip(scip, subscip, name, compvars, subvars,
    2451 compconss, varmap, consmap, ncompvars, ncompconss, &success) );
    2452
    2453 if( !success )
    2454 {
    2455 SCIPhashmapFree(&varmap);
    2456 continue;
    2457 }
    2458
    2459 /* set up debug solution */
    2460#ifdef WITH_DEBUG_SOLUTION
    2462 {
    2463 SCIP_SOL* debugsol;
    2464 SCIP_Real val;
    2465 int i;
    2466
    2467 SCIP_CALL( SCIPdebugGetSol(scip, &debugsol) );
    2468
    2469 /* set solution values in the debug solution if it is available */
    2470 if( debugsol != NULL )
    2471 {
    2472 SCIPdebugSolEnable(subscip);
    2473
    2474 for( i = 0; i < ncompvars; ++i )
    2475 {
    2476 if( subvars[i] != NULL )
    2477 {
    2478 SCIP_CALL( SCIPdebugGetSolVal(scip, compvars[i], &val) );
    2479 SCIP_CALL( SCIPdebugAddSolVal(subscip, subvars[i], val) );
    2480 }
    2481 }
    2482 }
    2483 }
    2484#endif
    2485
    2486 /* solve the subproblem and evaluate the result, i.e. apply fixings of variables and remove constraints */
    2487 SCIP_CALL( solveAndEvalSubscip(scip, conshdlrdata, subscip, compvars, subvars, compconss,
    2488 ncompvars, ncompconss, ndelconss, nfixedvars, nchgbds, result, &solved) );
    2489
    2490 /* free variable hash map */
    2491 SCIPhashmapFree(&varmap);
    2492
    2493 if( solved )
    2494 ++nsolved;
    2495
    2496 /* if the component is unbounded or infeasible, this holds for the complete problem as well */
    2497 if( *result == SCIP_UNBOUNDED || *result == SCIP_CUTOFF )
    2498 break;
    2499 /* if there is only one component left, let's solve this in the main SCIP */
    2500 else if( nsolved == ncomponents - 1 )
    2501 break;
    2502 }
    2503
    2504 SCIPfreeBufferArray(scip, &subvars);
    2505 SCIPhashmapFree(&consmap);
    2506
    2507 SCIP_CALL( SCIPfree(&subscip) );
    2508 }
    2509
    2510 TERMINATE:
    2511 SCIPfreeBufferArray(scip, &compstartsconss);
    2512 SCIPfreeBufferArray(scip, &compstartsvars);
    2513 SCIPfreeBufferArray(scip, &sortedconss);
    2514 SCIPfreeBufferArray(scip, &sortedvars);
    2515
    2516 return SCIP_OKAY;
    2517}
    2518
    2519/** frees specific constraint data */
    2520static
    2521SCIP_DECL_CONSDELETE(consDeleteComponents)
    2522{ /*lint --e{715}*/
    2523 assert(conshdlr != NULL);
    2524 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2525 assert(consdata != NULL);
    2526 assert(*consdata != NULL);
    2527
    2528 SCIP_CALL( freeProblem((PROBLEM**) consdata) );
    2529
    2530 return SCIP_OKAY;
    2531}
    2532
    2533/** constraint enforcing method of constraint handler for relaxation solutions */
    2534static
    2535SCIP_DECL_CONSENFORELAX(consEnforelaxComponents)
    2536{ /*lint --e{715}*/
    2537 assert(result != NULL);
    2538
    2539 /* no enforcement is performed, but the callback is needed for all constraint handlers with needscons = FALSE */
    2540 *result = SCIP_FEASIBLE;
    2541
    2542 return SCIP_OKAY;
    2543}
    2544
    2545/** variable rounding lock method of constraint handler */
    2546static
    2547SCIP_DECL_CONSLOCK(consLockComponents)
    2548{ /*lint --e{715}*/
    2549 return SCIP_OKAY;
    2550}
    2551
    2552#ifndef NDEBUG
    2553/** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
    2554static
    2555SCIP_DECL_CONSINITSOL(consInitsolComponents)
    2556{ /*lint --e{715}*/
    2557 assert(nconss == 0);
    2558
    2559 return SCIP_OKAY;
    2560}
    2561#endif
    2562
    2563#define consEnfolpComponents NULL
    2564#define consEnfopsComponents NULL
    2565#define consCheckComponents NULL
    2566
    2567/** creates the components constraint handler and includes it in SCIP */
    2569 SCIP* scip /**< SCIP data structure */
    2570 )
    2571{
    2572 SCIP_CONSHDLRDATA* conshdlrdata;
    2573 SCIP_CONSHDLR* conshdlr;
    2574
    2575 /* create components constraint data */
    2576 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
    2577 conshdlrdata->subscipdepth = 0;
    2578
    2579 /* include constraint handler */
    2583 conshdlrdata) );
    2584 assert(conshdlr != NULL);
    2585
    2586 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropComponents,
    2588 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolComponents,
    2590
    2591 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, conshdlrFreeComponents) );
    2592 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxComponents) );
    2593#ifndef NDEBUG
    2594 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolComponents) );
    2595#endif
    2596 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyComponents, NULL) );
    2597 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteComponents) );
    2598
    2600 "constraints/" CONSHDLR_NAME "/maxdepth",
    2601 "maximum depth of a node to run components detection (-1: disable component detection during solving)",
    2602 &conshdlrdata->maxdepth, FALSE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL) );
    2604 "constraints/" CONSHDLR_NAME "/maxintvars",
    2605 "maximum number of integer (or binary) variables to solve a subproblem during presolving (-1: unlimited)",
    2606 &conshdlrdata->maxintvars, TRUE, DEFAULT_MAXINTVARS, -1, INT_MAX, NULL, NULL) );
    2608 "constraints/" CONSHDLR_NAME "/minsize",
    2609 "minimum absolute size (in terms of variables) to solve a component individually during branch-and-bound",
    2610 &conshdlrdata->minsize, TRUE, DEFAULT_MINSIZE, 0, INT_MAX, NULL, NULL) );
    2612 "constraints/" CONSHDLR_NAME "/minrelsize",
    2613 "minimum relative size (in terms of variables) to solve a component individually during branch-and-bound",
    2614 &conshdlrdata->minrelsize, TRUE, DEFAULT_MINRELSIZE, 0.0, 1.0, NULL, NULL) );
    2616 "constraints/" CONSHDLR_NAME "/nodelimit",
    2617 "maximum number of nodes to be solved in subproblems during presolving",
    2618 &conshdlrdata->nodelimit, FALSE, DEFAULT_NODELIMIT, -1LL, SCIP_LONGINT_MAX, NULL, NULL) );
    2620 "constraints/" CONSHDLR_NAME "/maxcompweight",
    2621 "the maximum weight of a component, in terms of the used factors",
    2622 &conshdlrdata->maxcompweight, FALSE, DEFAULT_MAXCOMPWEIGHT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    2624 "constraints/" CONSHDLR_NAME "/intfactor",
    2625 "the weight of an integer variable compared to binary variables",
    2626 &conshdlrdata->intfactor, FALSE, DEFAULT_INTFACTOR, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    2628 "constraints/" CONSHDLR_NAME "/contfactor",
    2629 "the weight of a continuous variable compared to binary variables",
    2630 &conshdlrdata->contfactor, FALSE, DEFAULT_CONTFACTOR, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    2632 "constraints/" CONSHDLR_NAME "/feastolfactor",
    2633 "factor to increase the feasibility tolerance of the main SCIP in all sub-SCIPs, default value 1.0",
    2634 &conshdlrdata->feastolfactor, TRUE, DEFAULT_FEASTOLFACTOR, 0.0, 1000000.0, NULL, NULL) );
    2635
    2636 return SCIP_OKAY;
    2637}
    static SCIP_RETCODE copyToSubscip(SCIP *scip, SCIP *subscip, const char *name, SCIP_VAR **vars, SCIP_VAR **subvars, SCIP_CONS **conss, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, int nvars, int nconss, SCIP_Bool *success)
    #define CONSHDLR_NEEDSCONS
    #define CONSHDLR_CHECKPRIORITY
    #define DEFAULT_CONTFACTOR
    #define CONSHDLR_DESC
    #define DEFAULT_MINRELSIZE
    static SCIP_RETCODE createConsComponents(SCIP *scip, SCIP_CONS **cons, const char *name, PROBLEM *problem)
    static SCIP_RETCODE createAndSplitProblem(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Real fixedvarsobjsum, SCIP_VAR **sortedvars, SCIP_CONS **sortedconss, int *compstartsvars, int *compstartsconss, int ncomponents, PROBLEM **problem)
    static SCIP_RETCODE initComponent(PROBLEM *problem)
    static SCIP_RETCODE fillDigraph(SCIP *scip, SCIP_DIGRAPH *digraph, SCIP_CONS **conss, int nconss, int *unfixedvarpos, int nunfixedvars, int *firstvaridxpercons, SCIP_Bool *success)
    static int getMinsize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata)
    #define CONSHDLR_PROP_TIMING
    #define DEFAULT_FEASTOLFACTOR
    #define consEnfolpComponents
    static SCIP_DECL_CONSDELETE(consDeleteComponents)
    #define CONSHDLR_MAXPREROUNDS
    #define consEnfopsComponents
    #define DEFAULT_MAXINTVARS
    static SCIP_RETCODE componentSetupWorkingSol(COMPONENT *component, SCIP_HASHMAP *varmap)
    static SCIP_DECL_SORTPTRCOMP(componentSort)
    static SCIP_RETCODE freeProblem(PROBLEM **problem)
    static SCIP_DECL_CONSENFORELAX(consEnforelaxComponents)
    #define DEFAULT_MAXDEPTH
    static SCIP_RETCODE componentCreateSubscip(COMPONENT *component, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_CONS **conss, int nconss, SCIP_Bool *success)
    static SCIP_RETCODE createSubscip(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP **subscip)
    #define DEFAULT_INTFACTOR
    #define DEFAULT_NODELIMIT
    static SCIP_DECL_CONSFREE(conshdlrFreeComponents)
    static SCIP_RETCODE sortComponents(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DIGRAPH *digraph, SCIP_CONS **conss, SCIP_VAR **vars, int *varcomponent, int *conscomponent, int nconss, int nvars, int *firstvaridxpercons, int *ncompsminsize, int *ncompsmaxsize)
    #define DEFAULT_MAXCOMPWEIGHT
    #define consCheckComponents
    static SCIP_RETCODE solveProblem(PROBLEM *problem, SCIP_RESULT *result)
    static SCIP_DECL_CONSPROP(consPropComponents)
    #define CONSHDLR_PROPFREQ
    static SCIP_RETCODE solveSubscip(SCIP *scip, SCIP *subscip, SCIP_Longint nodelimit, SCIP_Real gaplimit)
    static SCIP_RETCODE solveComponent(COMPONENT *component, SCIP_Bool lastcomponent, SCIP_RESULT *result)
    #define CONSHDLR_PRESOLTIMING
    static SCIP_DECL_CONSINITSOL(consInitsolComponents)
    static SCIP_RETCODE freeComponent(COMPONENT *component)
    static SCIP_DECL_CONSLOCK(consLockComponents)
    #define CONSHDLR_EAGERFREQ
    #define DEFAULT_MINSIZE
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyComponents)
    #define CONSHDLR_ENFOPRIORITY
    struct Problem PROBLEM
    static SCIP_DECL_CONSPRESOL(consPresolComponents)
    static SCIP_RETCODE solveAndEvalSubscip(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP *subscip, SCIP_VAR **vars, SCIP_VAR **subvars, SCIP_CONS **conss, int nvars, int nconss, int *ndeletedconss, int *nfixedvars, int *ntightenedbounds, SCIP_RESULT *result, SCIP_Bool *solved)
    static SCIP_RETCODE findComponents(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Real *fixedvarsobjsum, SCIP_VAR **sortedvars, SCIP_CONS **sortedconss, int *compstartsvars, int *compstartsconss, int *nsortedvars, int *nsortedconss, int *ncomponents, int *ncompsminsize, int *ncompsmaxsize)
    static SCIP_RETCODE initProblem(SCIP *scip, PROBLEM **problem, SCIP_Real fixedvarsobjsum, int ncomponents)
    #define CONSHDLR_NAME
    struct Component COMPONENT
    #define CONSHDLR_DELAYPROP
    constraint handler for handling independent components
    methods for debugging
    #define SCIPdebugGetSolVal(scip, var, val)
    Definition: debug.h:312
    #define SCIPdebugSolEnable(scip)
    Definition: debug.h:314
    #define SCIPdebugAddSolVal(scip, var, val)
    Definition: debug.h:311
    #define SCIPdebugSolIsEnabled(scip)
    Definition: debug.h:316
    #define SCIPdebugSolIsValidInSubtree(scip, isvalidinsubtree)
    Definition: debug.h:313
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define ABS(x)
    Definition: def.h:216
    #define SQR(x)
    Definition: def.h:199
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPincludeConshdlrComponents(SCIP *scip)
    SCIP_RETCODE SCIPcopyPlugins(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool copyreaders, SCIP_Bool copypricers, SCIP_Bool copyconshdlrs, SCIP_Bool copyconflicthdlrs, SCIP_Bool copypresolvers, SCIP_Bool copyrelaxators, SCIP_Bool copyseparators, SCIP_Bool copycutselectors, SCIP_Bool copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copyiisfinders, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copytables, SCIP_Bool copyexprhdlrs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:276
    SCIP_RETCODE SCIPgetConsCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_CONS *sourcecons, SCIP_CONS **targetcons, SCIP_CONSHDLR *sourceconshdlr, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *name, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
    Definition: scip_copy.c:1580
    SCIP_RETCODE SCIPcopyProb(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, const char *name)
    Definition: scip_copy.c:529
    SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:2547
    SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3292
    SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
    Definition: scip_copy.c:713
    SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
    Definition: misc.c:8165
    void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
    Definition: misc.c:8374
    SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
    Definition: misc.c:7739
    SCIP_RETCODE SCIPdigraphSetSizes(SCIP_DIGRAPH *digraph, int *sizes)
    Definition: misc.c:7621
    void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
    Definition: misc.c:7645
    int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
    Definition: misc.c:8361
    SCIP_RETCODE SCIPcreateDigraph(SCIP *scip, SCIP_DIGRAPH **digraph, int nnodes)
    SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
    Definition: scip_general.c:668
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    int SCIPgetNImplVars(SCIP *scip)
    Definition: scip_prob.c:2387
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    SCIP_CONS ** SCIPgetConss(SCIP *scip)
    Definition: scip_prob.c:3666
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    int SCIPgetNConss(SCIP *scip)
    Definition: scip_prob.c:3620
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNOrigVars(SCIP *scip)
    Definition: scip_prob.c:2838
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
    Definition: scip_prob.c:4289
    SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3901
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
    Definition: scip_param.c:250
    SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:111
    SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
    Definition: scip_param.c:219
    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_PARAM * SCIPgetParam(SCIP *scip, const char *name)
    Definition: scip_param.c:234
    SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    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 SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:956
    SCIP_RETCODE SCIPgetLongintParam(SCIP *scip, const char *name, SCIP_Longint *value)
    Definition: scip_param.c:288
    SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPfixParam(SCIP *scip, const char *name)
    Definition: scip_param.c:367
    SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
    Definition: scip_param.c:603
    void SCIPpqueueFree(SCIP_PQUEUE **pqueue)
    Definition: misc.c:1324
    SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
    Definition: misc.c:1396
    int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1529
    SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)))
    Definition: misc.c:1297
    void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1495
    void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: cons.c:4346
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
    Definition: scip_cons.c:281
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
    Definition: scip_cons.c:444
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4336
    int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4812
    SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4735
    SCIP_RETCODE SCIPgetConsNVars(SCIP *scip, SCIP_CONS *cons, int *nvars, SCIP_Bool *success)
    Definition: scip_cons.c:2621
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8419
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8648
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8558
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8588
    SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
    Definition: scip_cons.c:2577
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8578
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8608
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8638
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8568
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8658
    SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
    Definition: scip_heur.c:263
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
    Definition: scip_mem.c:126
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    SCIP_Longint SCIPgetMemUsed(SCIP *scip)
    Definition: scip_mem.c:100
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:76
    #define SCIPfreeMemoryArray(scip, ptr)
    Definition: scip_mem.h:80
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8483
    int SCIPgetNActivePricers(SCIP *scip)
    Definition: scip_pricer.c:348
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_RETCODE SCIPcheckSolOrig(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *feasible, SCIP_Bool printreason, SCIP_Bool completely)
    Definition: scip_sol.c:4380
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2981
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_Real SCIPsolGetOrigObj(SCIP_SOL *sol)
    Definition: sol.c:4170
    SCIP_RETCODE SCIPprintBestSol(SCIP *scip, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:3047
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
    Definition: sol.c:4259
    SCIP_RETCODE SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:831
    SCIP_RETCODE SCIPaddSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *stored)
    Definition: scip_sol.c:3842
    int SCIPsolGetIndex(SCIP_SOL *sol)
    Definition: sol.c:4290
    SCIP_RETCODE SCIPcheckSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
    Definition: scip_sol.c:4312
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1892
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2005
    SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
    Definition: scip_sol.c:2132
    void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
    Definition: sol.c:4304
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3462
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3548
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    void SCIPaddNNodes(SCIP *scip, SCIP_Longint nnodes)
    SCIP_Real SCIPgetPrimalbound(SCIP *scip)
    SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
    SCIP_Real SCIPgetGap(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Real SCIPgetDualbound(SCIP *scip)
    SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_RETCODE SCIPprintDisplayLine(SCIP *scip, FILE *file, SCIP_VERBLEVEL verblevel, SCIP_Bool endline)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    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 SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisSumLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(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_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPinRepropagation(SCIP *scip)
    Definition: scip_tree.c:146
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6401
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4386
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6651
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23652
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
    Definition: var.c:23570
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_RETCODE SCIPgetActiveVars(SCIP *scip, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
    Definition: scip_var.c:2574
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4328
    SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
    Definition: scip_var.c:10998
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    void SCIPsortIntPtr(int *intarray, void **ptrarray, int len)
    void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public methods for managing constraints
    public methods for primal heuristics
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for primal CIP solutions
    public methods for branch and bound tree
    public methods for problem variables
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for data structures
    general public methods
    public methods for primal heuristic plugins and divesets
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for variable pricer plugins
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    public methods for timing
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    SCIP_VAR ** fixedsubvars
    PROBLEM * problem
    SCIP_Real lastdualbound
    SCIP_SOL * workingsol
    SCIP_VAR ** subvars
    SCIP_STATUS laststatus
    SCIP_Real fixedvarsobjsum
    SCIP_Real lastprimalbound
    SCIP_VAR ** vars
    SCIP_VAR ** fixedvars
    SCIP * subscip
    int lastbestsolindex
    SCIP_Bool solved
    char * name
    Definition: struct_cons.h:49
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    @ SCIP_VERBLEVEL_NORMAL
    Definition: type_message.h:60
    @ SCIP_VERBLEVEL_FULL
    Definition: type_message.h:62
    @ SCIP_PARAMSETTING_OFF
    Definition: type_paramset.h:63
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_UNBOUNDED
    Definition: type_result.h:47
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_DELAYNODE
    Definition: type_result.h:59
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PROBLEM
    Definition: type_set.h:45
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_STAGE_INIT
    Definition: type_set.h:44
    @ SCIP_STATUS_OPTIMAL
    Definition: type_stat.h:43
    @ SCIP_STATUS_TOTALNODELIMIT
    Definition: type_stat.h:50
    @ SCIP_STATUS_BESTSOLLIMIT
    Definition: type_stat.h:60
    @ SCIP_STATUS_SOLLIMIT
    Definition: type_stat.h:59
    @ SCIP_STATUS_UNBOUNDED
    Definition: type_stat.h:45
    @ SCIP_STATUS_UNKNOWN
    Definition: type_stat.h:42
    @ SCIP_STATUS_PRIMALLIMIT
    Definition: type_stat.h:57
    @ SCIP_STATUS_GAPLIMIT
    Definition: type_stat.h:56
    @ SCIP_STATUS_USERINTERRUPT
    Definition: type_stat.h:47
    @ SCIP_STATUS_TERMINATE
    Definition: type_stat.h:48
    @ SCIP_STATUS_INFORUNBD
    Definition: type_stat.h:46
    @ SCIP_STATUS_STALLNODELIMIT
    Definition: type_stat.h:52
    @ SCIP_STATUS_TIMELIMIT
    Definition: type_stat.h:54
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44
    @ SCIP_STATUS_NODELIMIT
    Definition: type_stat.h:49
    @ SCIP_STATUS_DUALLIMIT
    Definition: type_stat.h:58
    @ SCIP_STATUS_MEMLIMIT
    Definition: type_stat.h:55
    @ SCIP_STATUS_RESTARTLIMIT
    Definition: type_stat.h:62
    enum SCIP_Status SCIP_STATUS
    Definition: type_stat.h:64
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141