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-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file 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
    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
    2104
    2105 /* call inclusion method of constraint handler */
    2107
    2108 *valid = TRUE;
    2109
    2110 return SCIP_OKAY;
    2111}
    2112
    2113/** destructor of constraint handler to free user data (called when SCIP is exiting) */
    2114static
    2115SCIP_DECL_CONSFREE(conshdlrFreeComponents)
    2116{ /*lint --e{715}*/
    2117 SCIP_CONSHDLRDATA* conshdlrdata;
    2118
    2119 /* free constraint handler data */
    2120 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2121 assert(conshdlrdata != NULL);
    2122
    2123 SCIPfreeBlockMemory(scip, &conshdlrdata);
    2124 SCIPconshdlrSetData(conshdlr, NULL);
    2125
    2126 return SCIP_OKAY;
    2127}
    2128
    2129/** domain propagation method of constraint handler */
    2130static
    2131SCIP_DECL_CONSPROP(consPropComponents)
    2132{ /*lint --e{715}*/
    2133 PROBLEM* problem;
    2134 SCIP_CONSHDLRDATA* conshdlrdata;
    2135 SCIP_Longint nodelimit;
    2136
    2137 assert(conshdlr != NULL);
    2138 assert(result != NULL);
    2139 assert(SCIPconshdlrGetNActiveConss(conshdlr) >= 0);
    2140 assert(SCIPconshdlrGetNActiveConss(conshdlr) <= 1);
    2141
    2143
    2144 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2145 assert(conshdlrdata != NULL);
    2146
    2147 *result = SCIP_DIDNOTRUN;
    2148
    2149 /* do not try to detect independent components if the depth is too high */
    2150 if( SCIPgetDepth(scip) + conshdlrdata->subscipdepth > conshdlrdata->maxdepth
    2151 && SCIPconshdlrGetNActiveConss(conshdlr) == 0 )
    2152 return SCIP_OKAY;
    2153
    2154 /* don't run in probing or in repropagation */
    2156 return SCIP_OKAY;
    2157
    2158 /* do not run, if not all variables are explicitly known */
    2159 if( SCIPgetNActivePricers(scip) > 0 )
    2160 return SCIP_OKAY;
    2161
    2162 /* we do not want to run, if there are no variables left */
    2163 if( SCIPgetNVars(scip) == 0 )
    2164 return SCIP_OKAY;
    2165
    2166 /* check for a reached timelimit */
    2167 if( SCIPisStopped(scip) )
    2168 return SCIP_OKAY;
    2169
    2170 /* the components constraint handler does kind of dual reductions */
    2172 return SCIP_OKAY;
    2173
    2174 problem = NULL;
    2175 *result = SCIP_DIDNOTFIND;
    2176
    2177 /* the current node already has a components constraint storing a problem split into individual components */
    2178 if( SCIPconshdlrGetNActiveConss(conshdlr) >= 1 )
    2179 {
    2180 assert(SCIPconshdlrGetNActiveConss(conshdlr) == 1);
    2181
    2182 problem = (PROBLEM*)SCIPconsGetData(SCIPconshdlrGetConss(conshdlr)[0]);
    2183 }
    2184 /* no components constraint at the current node, search for components */
    2185 else
    2186 {
    2187 SCIP_Real fixedvarsobjsum;
    2188 SCIP_VAR** sortedvars;
    2189 SCIP_CONS** sortedconss;
    2190 int* compstartsvars;
    2191 int* compstartsconss;
    2192 int nsortedvars;
    2193 int nsortedconss;
    2194 int ncomponents;
    2195 int ncompsminsize;
    2196 int ncompsmaxsize;
    2197
    2198 assert(SCIPconshdlrGetNActiveConss(conshdlr) == 0);
    2199
    2200 /* allocate memory for sorted components */
    2203 SCIP_CALL( SCIPallocBufferArray(scip, &compstartsvars, SCIPgetNVars(scip) + 1) );
    2204 SCIP_CALL( SCIPallocBufferArray(scip, &compstartsconss, SCIPgetNVars(scip) + 1) );
    2205
    2206 /* search for components */
    2207 SCIP_CALL( findComponents(scip, conshdlrdata, &fixedvarsobjsum, sortedvars, sortedconss, compstartsvars,
    2208 compstartsconss, &nsortedvars, &nsortedconss, &ncomponents, &ncompsminsize, &ncompsmaxsize) );
    2209
    2210 if( ncompsminsize > 1 )
    2211 {
    2212 SCIP_CONS* cons;
    2213
    2214 SCIPdebugMsg(scip, "found %d components (%d fulfilling the minsize requirement) at node %lld at depth %d (%d)\n",
    2215 ncomponents, ncompsminsize, SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), SCIPgetDepth(scip),
    2216 SCIPgetDepth(scip) + conshdlrdata->subscipdepth);
    2217
    2218 /* if there are components with size smaller than the limit, we merge them with the smallest component */
    2219 if( ncomponents > ncompsminsize )
    2220 {
    2221 int minsize;
    2222 int size;
    2223 int c;
    2224 int m = 0;
    2225
    2226 /* compute minimum size of components to solve individually */
    2227 minsize = getMinsize(scip, conshdlrdata);
    2228
    2229 for( c = 0; c < ncomponents; ++c )
    2230 {
    2231 size = compstartsvars[c+1] - compstartsvars[c];
    2232
    2233 if( size >= minsize )
    2234 {
    2235 ++m;
    2236 compstartsvars[m] = compstartsvars[c+1];
    2237 compstartsconss[m] = compstartsconss[c+1];
    2238 }
    2239 /* the last component is too small */
    2240 else if( c == ncomponents - 1 )
    2241 {
    2242 assert(m == ncompsminsize);
    2243 compstartsvars[m] = compstartsvars[c+1];
    2244 compstartsconss[m] = compstartsconss[c+1];
    2245 }
    2246 }
    2247 assert(m == ncompsminsize);
    2248 assert(compstartsvars[m] == nsortedvars);
    2249 assert(compstartsconss[m] == nsortedconss);
    2250
    2251 ncomponents = m;
    2252 }
    2253
    2254 SCIP_CALL( createAndSplitProblem(scip, conshdlrdata, fixedvarsobjsum, sortedvars, sortedconss, compstartsvars,
    2255 compstartsconss, ncomponents, &problem) );
    2256
    2257 /* if the problem is not NULL, copying worked fine */
    2258 if( problem != NULL )
    2259 {
    2260 SCIP_CALL( createConsComponents(scip, &cons, problem->name, problem) );
    2262 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    2263 }
    2264 }
    2265
    2266 SCIPfreeBufferArray(scip, &compstartsconss);
    2267 SCIPfreeBufferArray(scip, &compstartsvars);
    2268 SCIPfreeBufferArray(scip, &sortedconss);
    2269 SCIPfreeBufferArray(scip, &sortedvars);
    2270 }
    2271
    2272 /* (continue to) solve the problem
    2273 *
    2274 * If the problem was not solved to optimality yet, the result code is set to SCIP_DELAYNODE, so that after the
    2275 * propagation is finished, the node is put back into the queue of open nodes and solving the components of the
    2276 * problem will be continued when the node is focused and propagated the next time.
    2277 * However, if we are at the root node, we continue solving the problem until it is solved or some limit is reached
    2278 * since there are no other nodes to process and we want to avoid calling other propagation methods or heuristics
    2279 * again and again
    2280 */
    2281 SCIP_CALL( SCIPgetLongintParam(scip, "limits/nodes", &nodelimit) );
    2282 if( nodelimit == -1 )
    2283 nodelimit = SCIP_LONGINT_MAX;
    2284
    2285 do
    2286 {
    2287 if( problem != NULL )
    2288 {
    2289 SCIP_CALL( solveProblem(problem, result) );
    2290 }
    2291 } while( *result == SCIP_DELAYNODE && SCIPgetDepth(scip) == 0 && !SCIPisStopped(scip) && SCIPgetNNodes(scip) < nodelimit);
    2292
    2293 return SCIP_OKAY;
    2294}
    2295
    2296/** presolving method of constraint handler */
    2297static
    2298SCIP_DECL_CONSPRESOL(consPresolComponents)
    2299{ /*lint --e{715}*/
    2300 SCIP_CONSHDLRDATA* conshdlrdata;
    2301 SCIP_VAR** sortedvars;
    2302 SCIP_CONS** sortedconss;
    2303 int* compstartsvars;
    2304 int* compstartsconss;
    2305 int nsortedvars;
    2306 int nsortedconss;
    2307 int ncomponents;
    2308 int ncompsminsize;
    2309 int ncompsmaxsize;
    2310 int nvars;
    2311
    2312 assert(conshdlr != NULL);
    2313 assert(result != NULL);
    2314 assert(SCIPconshdlrGetNActiveConss(conshdlr) >= 0);
    2315 assert(SCIPconshdlrGetNActiveConss(conshdlr) <= 1);
    2316
    2318
    2319 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2320 assert(conshdlrdata != NULL);
    2321
    2322 *result = SCIP_DIDNOTRUN;
    2323
    2325 return SCIP_OKAY;
    2326
    2327 /* do not run, if not all variables are explicitly known */
    2328 if( SCIPgetNActivePricers(scip) > 0 )
    2329 return SCIP_OKAY;
    2330
    2331 nvars = SCIPgetNVars(scip);
    2332
    2333 /* we do not want to run, if there are no variables left */
    2334 if( nvars == 0 )
    2335 return SCIP_OKAY;
    2336
    2337 /* only call the components presolving, if presolving would be stopped otherwise */
    2339 return SCIP_OKAY;
    2340
    2341 /* the components constraint handler does kind of dual reductions */
    2343 return SCIP_OKAY;
    2344
    2345 /* check for a reached timelimit */
    2346 if( SCIPisStopped(scip) )
    2347 return SCIP_OKAY;
    2348
    2349 *result = SCIP_DIDNOTFIND;
    2350
    2351 assert(SCIPconshdlrGetNActiveConss(conshdlr) == 0);
    2352
    2353 /* allocate memory for sorted components */
    2356 SCIP_CALL( SCIPallocBufferArray(scip, &compstartsvars, SCIPgetNVars(scip) + 1) );
    2357 SCIP_CALL( SCIPallocBufferArray(scip, &compstartsconss, SCIPgetNVars(scip) + 1) );
    2358
    2359 /* search for components */
    2360 SCIP_CALL( findComponents(scip, conshdlrdata, NULL, sortedvars, sortedconss, compstartsvars,
    2361 compstartsconss, &nsortedvars, &nsortedconss, &ncomponents, &ncompsminsize, &ncompsmaxsize) );
    2362
    2363 if( ncompsmaxsize > 0 )
    2364 {
    2365 char name[SCIP_MAXSTRLEN];
    2366 SCIP* subscip;
    2367 SCIP_HASHMAP* consmap;
    2368 SCIP_HASHMAP* varmap;
    2369 SCIP_VAR** compvars;
    2370 SCIP_VAR** subvars;
    2371 SCIP_CONS** compconss;
    2372 SCIP_Bool success;
    2373 SCIP_Bool solved;
    2374 int nsolved = 0;
    2375 int ncompvars;
    2376 int ncompconss;
    2377 int comp;
    2378
    2379 SCIPdebugMsg(scip, "found %d components (%d with small size) during presolving; overall problem size: %d vars (%d bin, %d int, %d cont), %d conss\n",
    2381
    2382 /* build subscip */
    2383 SCIP_CALL( createSubscip(scip, conshdlrdata, &subscip) );
    2384
    2385 if( subscip == NULL )
    2386 goto TERMINATE;
    2387
    2388 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/usesmalltables", TRUE) );
    2389 SCIP_CALL( SCIPsetIntParam(subscip, "constraints/" CONSHDLR_NAME "/propfreq", -1) );
    2390
    2391 /* hashmap mapping from original constraints to constraints in the sub-SCIPs (for performance reasons) */
    2392 SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), nsortedconss) );
    2393
    2394 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nsortedvars) );
    2395
    2396 /* loop over all components */
    2397 for( comp = 0; comp < ncompsmaxsize && !SCIPisStopped(scip); comp++ )
    2398 {
    2399 /* if there is only one component left, let's solve this in the main SCIP */
    2400 if( nsolved == ncomponents - 1 )
    2401 {
    2402 SCIPdebugMsg(scip, "Solve one remaining component in main SCIP ...\n");
    2403 break;
    2404 }
    2405
    2406#ifdef WITH_DEBUG_SOLUTION
    2407 if( SCIPgetStage(subscip) > SCIP_STAGE_INIT )
    2408 {
    2409 SCIP_CALL( SCIPfree(&subscip) );
    2410 SCIP_CALL( createSubscip(scip, conshdlrdata, &subscip) );
    2411 }
    2412#endif
    2413 /* get component variables */
    2414 compvars = &(sortedvars[compstartsvars[comp]]);
    2415 ncompvars = compstartsvars[comp + 1 ] - compstartsvars[comp];
    2416
    2417 /* get component constraints */
    2418 compconss = &(sortedconss[compstartsconss[comp]]);
    2419 ncompconss = compstartsconss[comp + 1] - compstartsconss[comp];
    2420
    2421 /* if we have an unlocked variable, let duality fixing do the job! */
    2422 if( ncompconss == 0 )
    2423 {
    2424 assert(ncompvars == 1);
    2425 SCIPdebugMsg(scip, "Skipping component %d of size %d without constraints.\n", comp, ncompvars);
    2426 ++nsolved;
    2427 continue;
    2428 }
    2429
    2430 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(scip), ncompvars) );
    2431#ifdef DETAILED_OUTPUT
    2432 {
    2433 int nbinvars = 0;
    2434 int nintvars = 0;
    2435 int ncontvars = 0;
    2436 int i;
    2437
    2438 for( i = 0; i < ncompvars; ++i )
    2439 {
    2440 if( SCIPvarGetType(compvars[i]) == SCIP_VARTYPE_BINARY )
    2441 ++nbinvars;
    2442 else if( SCIPvarGetType(compvars[i]) == SCIP_VARTYPE_INTEGER )
    2443 ++nintvars;
    2444 else
    2445 ++ncontvars;
    2446 }
    2447 SCIPdebugMsg(scip, "solve component %d: %d vars (%d bin, %d int, %d cont), %d conss\n",
    2448 comp, ncompvars, nbinvars, nintvars, ncontvars, ncompconss);
    2449 }
    2450#endif
    2451#ifndef NDEBUG
    2452 {
    2453 int i;
    2454 for( i = 0; i < ncompvars; ++i )
    2455 assert(SCIPvarIsActive(compvars[i]));
    2456 }
    2457#endif
    2458
    2459 /* get name of the original problem and add "comp_nr" */
    2460 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_comp_%d", SCIPgetProbName(scip), comp);
    2461
    2462 SCIP_CALL( copyToSubscip(scip, subscip, name, compvars, subvars,
    2463 compconss, varmap, consmap, ncompvars, ncompconss, &success) );
    2464
    2465 if( !success )
    2466 {
    2467 SCIPhashmapFree(&varmap);
    2468 continue;
    2469 }
    2470
    2471 /* set up debug solution */
    2472#ifdef WITH_DEBUG_SOLUTION
    2474 {
    2475 SCIP_SOL* debugsol;
    2476 SCIP_Real val;
    2477 int i;
    2478
    2479 SCIP_CALL( SCIPdebugGetSol(scip, &debugsol) );
    2480
    2481 /* set solution values in the debug solution if it is available */
    2482 if( debugsol != NULL )
    2483 {
    2484 SCIPdebugSolEnable(subscip);
    2485
    2486 for( i = 0; i < ncompvars; ++i )
    2487 {
    2488 if( subvars[i] != NULL )
    2489 {
    2490 SCIP_CALL( SCIPdebugGetSolVal(scip, compvars[i], &val) );
    2491 SCIP_CALL( SCIPdebugAddSolVal(subscip, subvars[i], val) );
    2492 }
    2493 }
    2494 }
    2495 }
    2496#endif
    2497
    2498 /* solve the subproblem and evaluate the result, i.e. apply fixings of variables and remove constraints */
    2499 SCIP_CALL( solveAndEvalSubscip(scip, conshdlrdata, subscip, compvars, subvars, compconss,
    2500 ncompvars, ncompconss, ndelconss, nfixedvars, nchgbds, result, &solved) );
    2501
    2502 /* free variable hash map */
    2503 SCIPhashmapFree(&varmap);
    2504
    2505 if( solved )
    2506 ++nsolved;
    2507
    2508 /* if the component is unbounded or infeasible, this holds for the complete problem as well */
    2509 if( *result == SCIP_UNBOUNDED || *result == SCIP_CUTOFF )
    2510 break;
    2511 }
    2512
    2513 SCIPfreeBufferArray(scip, &subvars);
    2514 SCIPhashmapFree(&consmap);
    2515
    2516 SCIP_CALL( SCIPfree(&subscip) );
    2517 }
    2518
    2519 TERMINATE:
    2520 SCIPfreeBufferArray(scip, &compstartsconss);
    2521 SCIPfreeBufferArray(scip, &compstartsvars);
    2522 SCIPfreeBufferArray(scip, &sortedconss);
    2523 SCIPfreeBufferArray(scip, &sortedvars);
    2524
    2525 return SCIP_OKAY;
    2526}
    2527
    2528/** frees specific constraint data */
    2529static
    2530SCIP_DECL_CONSDELETE(consDeleteComponents)
    2531{ /*lint --e{715}*/
    2532 assert(conshdlr != NULL);
    2533 assert(consdata != NULL);
    2534 assert(*consdata != NULL);
    2535
    2537
    2538 SCIP_CALL( freeProblem((PROBLEM**) consdata) );
    2539
    2540 return SCIP_OKAY;
    2541}
    2542
    2543/** constraint enforcing method of constraint handler for relaxation solutions */
    2544static
    2545SCIP_DECL_CONSENFORELAX(consEnforelaxComponents)
    2546{ /*lint --e{715}*/
    2547 assert(result != NULL);
    2548
    2549 /* no enforcement is performed, but the callback is needed for all constraint handlers with needscons = FALSE */
    2550 *result = SCIP_FEASIBLE;
    2551
    2552 return SCIP_OKAY;
    2553}
    2554
    2555/** variable rounding lock method of constraint handler */
    2556static
    2557SCIP_DECL_CONSLOCK(consLockComponents)
    2558{ /*lint --e{715}*/
    2559 return SCIP_OKAY;
    2560}
    2561
    2562#ifndef NDEBUG
    2563/** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
    2564static
    2565SCIP_DECL_CONSINITSOL(consInitsolComponents)
    2566{ /*lint --e{715}*/
    2567 assert(nconss == 0);
    2568
    2569 return SCIP_OKAY;
    2570}
    2571#endif
    2572
    2573#define consEnfolpComponents NULL
    2574#define consEnfopsComponents NULL
    2575#define consCheckComponents NULL
    2576
    2577/** creates the components constraint handler and includes it in SCIP */
    2579 SCIP* scip /**< SCIP data structure */
    2580 )
    2581{
    2582 SCIP_CONSHDLRDATA* conshdlrdata;
    2583 SCIP_CONSHDLR* conshdlr;
    2584
    2585 /* create components constraint data */
    2586 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
    2587 conshdlrdata->subscipdepth = 0;
    2588
    2589 /* include constraint handler */
    2593 conshdlrdata) );
    2594 assert(conshdlr != NULL);
    2595
    2596 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropComponents,
    2598 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolComponents,
    2600
    2601 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, conshdlrFreeComponents) );
    2602 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxComponents) );
    2603#ifndef NDEBUG
    2604 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolComponents) );
    2605#endif
    2606 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyComponents, NULL) );
    2607 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteComponents) );
    2608
    2610 "constraints/" CONSHDLR_NAME "/maxdepth",
    2611 "maximum depth of a node to run components detection (-1: disable component detection during solving)",
    2612 &conshdlrdata->maxdepth, FALSE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL) );
    2614 "constraints/" CONSHDLR_NAME "/maxintvars",
    2615 "maximum number of integer (or binary) variables to solve a subproblem during presolving (-1: unlimited)",
    2616 &conshdlrdata->maxintvars, TRUE, DEFAULT_MAXINTVARS, -1, INT_MAX, NULL, NULL) );
    2618 "constraints/" CONSHDLR_NAME "/minsize",
    2619 "minimum absolute size (in terms of variables) to solve a component individually during branch-and-bound",
    2620 &conshdlrdata->minsize, TRUE, DEFAULT_MINSIZE, 0, INT_MAX, NULL, NULL) );
    2622 "constraints/" CONSHDLR_NAME "/minrelsize",
    2623 "minimum relative size (in terms of variables) to solve a component individually during branch-and-bound",
    2624 &conshdlrdata->minrelsize, TRUE, DEFAULT_MINRELSIZE, 0.0, 1.0, NULL, NULL) );
    2626 "constraints/" CONSHDLR_NAME "/nodelimit",
    2627 "maximum number of nodes to be solved in subproblems during presolving",
    2628 &conshdlrdata->nodelimit, FALSE, DEFAULT_NODELIMIT, -1LL, SCIP_LONGINT_MAX, NULL, NULL) );
    2630 "constraints/" CONSHDLR_NAME "/maxcompweight",
    2631 "the maximum weight of a component, in terms of the used factors",
    2632 &conshdlrdata->maxcompweight, FALSE, DEFAULT_MAXCOMPWEIGHT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    2634 "constraints/" CONSHDLR_NAME "/intfactor",
    2635 "the weight of an integer variable compared to binary variables",
    2636 &conshdlrdata->intfactor, FALSE, DEFAULT_INTFACTOR, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    2638 "constraints/" CONSHDLR_NAME "/contfactor",
    2639 "the weight of a continuous variable compared to binary variables",
    2640 &conshdlrdata->contfactor, FALSE, DEFAULT_CONTFACTOR, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    2642 "constraints/" CONSHDLR_NAME "/feastolfactor",
    2643 "factor to increase the feasibility tolerance of the main SCIP in all sub-SCIPs, default value 1.0",
    2644 &conshdlrdata->feastolfactor, TRUE, DEFAULT_FEASTOLFACTOR, 0.0, 1000000.0, NULL, NULL) );
    2645
    2646 return SCIP_OKAY;
    2647}
    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:313
    #define SCIPdebugSolEnable(scip)
    Definition: debug.h:315
    #define SCIPdebugAddSolVal(scip, var, val)
    Definition: debug.h:312
    #define SCIPdebugSolIsEnabled(scip)
    Definition: debug.h:317
    #define SCIPdebugSolIsValidInSubtree(scip, isvalidinsubtree)
    Definition: debug.h:314
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define ABS(x)
    Definition: def.h:225
    #define SQR(x)
    Definition: def.h:208
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_LONGINT_MAX
    Definition: def.h:151
    #define SCIP_CALL(x)
    Definition: def.h:364
    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:1581
    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:2548
    SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3293
    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:676
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    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:4350
    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:4320
    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:4340
    int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4816
    SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4739
    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:8423
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    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:8582
    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:8612
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    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:8513
    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:4385
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_Real SCIPsolGetOrigObj(SCIP_SOL *sol)
    Definition: sol.c:4185
    SCIP_RETCODE SCIPprintBestSol(SCIP *scip, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:3052
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2887
    SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
    Definition: sol.c:4274
    SCIP_RETCODE SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:829
    SCIP_RETCODE SCIPaddSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *stored)
    Definition: scip_sol.c:3847
    int SCIPsolGetIndex(SCIP_SOL *sol)
    Definition: sol.c:4305
    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:4317
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1890
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1569
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2003
    SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
    Definition: scip_sol.c:2134
    void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
    Definition: sol.c:4319
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3475
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3561
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2611
    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:23674
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23530
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    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:23485
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23684
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23694
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
    Definition: var.c:23602
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    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:4322
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    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