120#define EVENTHDLR_SYMMETRY_NAME "symmetry_orbital"
121#define EVENTHDLR_SYMMETRY_DESC "filter global variable bound reduction event handler for orbital reduction"
151struct SCIP_OrbitalReductionData
185 int* varorbitidssort;
189 int maxnsymbrokenvarids;
199 maxnsymbrokenvarids = 0;
203 for (p = 0; p < orcdata->
nperms; ++p)
205 perm = orcdata->
perms[p];
233 for (orbitbegin = 0; orbitbegin < orcdata->
npermvars; orbitbegin = orbitend)
236 orbitid = varorbitids[varorbitidssort[orbitbegin]];
239 orbitsymbroken =
FALSE;
240 j = varorbitidssort[orbitbegin];
245 j = varorbitidssort[
i];
248 if ( varorbitids[j] != orbitid )
251 if ( !orbitsymbroken )
255 orbitsymbroken =
TRUE;
260 assert( orbitsymbroken ||
i == orcdata->
npermvars || varorbitids[j] != orbitid );
263 if ( orbitsymbroken )
265 while (
i < orcdata->npermvars && varorbitids[j] == orbitid )
266 j = varorbitidssort[++
i];
271 if ( orbitsymbroken )
274 if ( orcdata->
nsymbrokenvarids + orbitend - orbitbegin > maxnsymbrokenvarids )
290 maxnsymbrokenvarids, newsize) );
293 maxnsymbrokenvarids = newsize;
297 for (
i = orbitbegin;
i < orbitend; ++
i)
299 j = varorbitidssort[
i];
300 assert( varorbitids[j] == orbitid );
323 "Orbital fixing symmetry for %p broken before symmetry. Requires fixing %d/%d affected variables.\n",
349 int* branchedvarindices,
352 int nbranchedvarindices
368 assert( nbranchedvarindices >= 0 );
374 for (p = 0; p < orcdata->
nperms; ++p)
376 perm = orcdata->
perms[p];
383 assert( varid < orcdata->npermvars );
385 varidimage = perm[varid];
386 assert( varidimage >= 0 );
387 assert( varidimage < orcdata->npermvars );
391 if ( varidimage == varid )
412 for (
i = 0;
i < nbranchedvarindices; ++
i)
414 varid = branchedvarindices[
i];
416 assert( varid < orcdata->npermvars );
418 varidimage = perm[varid];
419 assert( varidimage >= 0 );
420 assert( varidimage < orcdata->npermvars );
424 if ( varidimage == varid )
434 if (
i < nbranchedvarindices )
438 chosenperms[(*nchosenperms)++] = perm;
463 origframeleft = frameleft;
464 origframeright = frameright;
470 assert( frameright >= frameleft );
473 if ( frameright == frameleft )
476 while (frameright - frameleft >= 2)
479 center = frameleft + ((frameright - frameleft) / 2);
480 assert( center > frameleft );
481 assert( center < frameright );
482 id = idssort[center];
483 if ( ids[
id] < findid )
495 assert( frameright - frameleft == 1 );
496 id = idssort[frameleft];
497 if ( ids[
id] < findid )
500 assert( frameleft >= origframeleft );
501 assert( frameright <= origframeright );
502 assert( frameleft >= origframeright || ids[idssort[frameleft]] >= findid );
503 assert( frameleft - 1 < origframeleft || ids[idssort[frameleft - 1]] < findid );
520 int* varorbitidssort,
551 for (orbitbegin = 0; orbitbegin < orcdata->
npermvars; orbitbegin = orbitend)
554 orbitid = varorbitids[varorbitidssort[orbitbegin]];
555 for (orbitend = orbitbegin + 1; orbitend < orcdata->
npermvars; ++orbitend)
557 if ( varorbitids[varorbitidssort[orbitend]] != orbitid )
562 if ( orbitend - orbitbegin <= 1 )
568 for (
i = orbitbegin;
i < orbitend; ++
i)
570 varid = varorbitidssort[
i];
572 assert( varid < orcdata->npermvars );
592 for (
i = orbitbegin;
i < orbitend; ++
i)
594 varid = varorbitidssort[
i];
596 assert( varid < orcdata->npermvars );
598 if ( varlbs !=
NULL )
601 varlbs[varid] = orbitlb;
616 if ( varubs !=
NULL )
619 varubs[varid] = orbitub;
662 int* branchedvarindices;
664 int nbranchedvarindices;
667 int branchingdecisionvarid;
673 int* varorbitidssort;
678 int orbitsetcomponentid;
697 if ( orcdata->
lastnode == focusnode )
704 if ( parentnode ==
NULL )
710 if ( shadowfocusnode ==
NULL )
715 " (and suppressing future warnings for this component)\n");
724 tmpshadownode = shadowfocusnode;
727 tmpshadownode = tmpshadownode->
parent;
730 while ( tmpshadownode !=
NULL );
734 tmpshadownode = shadowfocusnode;
737 rootedshadowpath[--
i] = tmpshadownode;
739 tmpshadownode = tmpshadownode->
parent;
758 nbranchedvarindices = 0;
761 tmpshadownode = rootedshadowpath[
depth];
768 assert( varid < orcdata->npermvars || varid == INT_MAX );
770 if ( varid < orcdata->npermvars )
795 assert( varid < orcdata->npermvars || varid == INT_MAX );
797 if ( varid < orcdata->npermvars )
799 if ( inbranchedvarindices[varid] )
801 branchedvarindices[nbranchedvarindices++] = varid;
802 inbranchedvarindices[varid] =
TRUE;
818 assert( branchingdecisionvarid < orcdata->npermvars || branchingdecisionvarid == INT_MAX );
819 assert( branchingdecisionvarid >= 0 );
822 if ( branchingdecisionvarid >= orcdata->
npermvars )
824 assert( branchingdecisionvarid >= 0 && branchingdecisionvarid < orcdata->npermvars );
835 varlbs, varubs, branchedvarindices, inbranchedvarindices, nbranchedvarindices) );
842 for (p = 0; p < nchosenperms; ++p)
844 perm = chosenperms[p];
867 varorbitidssort, varlbs, varubs) );
888 varlbs[branchingdecisionvarid] = branchingdecision->
newbound;
899 varubs[branchingdecisionvarid] = branchingdecision->
newbound;
915 orbitsetcomponentid);
916 assert( orbitbegin >= 0 && orbitbegin < orcdata->npermvars );
917 assert( varorbitids[varorbitidssort[orbitbegin]] == orbitsetcomponentid );
918 assert( orbitbegin == 0 || varorbitids[varorbitidssort[orbitbegin - 1]] < orbitsetcomponentid );
921 orbitsetcomponentid + 1);
922 assert( orbitend > 0 && orbitend <= orcdata->npermvars && orbitend > orbitbegin );
923 assert( orbitend == orcdata->
npermvars || varorbitids[varorbitidssort[orbitend]] > orbitsetcomponentid );
924 assert( varorbitids[varorbitidssort[orbitend - 1]] == orbitsetcomponentid );
927 for (idx = orbitbegin; idx < orbitend; ++idx)
929 varid = varorbitidssort[idx];
930 assert( varorbitids[varid] == orbitsetcomponentid );
933 if ( varid == branchingdecisionvarid )
945 ||
SCIPsymGE(
scip, varlbs[branchingdecisionvarid], varlbs[varid]) );
947 ||
SCIPsymLE(
scip, varubs[branchingdecisionvarid], varubs[varid]) );
955 varubs[varid] = varubs[branchingdecisionvarid];
960 infeasible, &tightened) );
983 if ( !inbranchedvarindices[branchingdecisionvarid] )
985 assert( nbranchedvarindices < orcdata->npermvars );
986 branchedvarindices[nbranchedvarindices++] = branchingdecisionvarid;
987 inbranchedvarindices[branchingdecisionvarid] =
TRUE;
993 for (
i = 0;
i < nbranchedvarindices; ++
i)
995 varid = branchedvarindices[
i];
997 assert( varid < orcdata->npermvars );
998 assert( inbranchedvarindices[varid] );
999 inbranchedvarindices[varid] =
FALSE;
1033 int* branchedvarindices;
1035 int nbranchedvarindices;
1043 int* varorbitidssort;
1070 nbranchedvarindices = 0;
1071 tmpshadownode = shadowfocusnode;
1072 while ( tmpshadownode !=
NULL )
1079 assert( varid < orcdata->npermvars || varid == INT_MAX );
1081 if ( varid < orcdata->npermvars )
1083 if ( inbranchedvarindices[varid] )
1085 branchedvarindices[nbranchedvarindices++] = varid;
1086 inbranchedvarindices[varid] =
TRUE;
1089 tmpshadownode = tmpshadownode->
parent;
1096 NULL,
NULL, branchedvarindices, inbranchedvarindices, nbranchedvarindices) );
1097 assert( nchosenperms >= 0 );
1100 if ( nchosenperms == 0 )
1109 for (p = 0; p < nchosenperms; ++p)
1111 perm = chosenperms[p];
1136 for (
i = 0;
i < nbranchedvarindices; ++
i)
1138 varid = branchedvarindices[
i];
1140 assert( varid < orcdata->npermvars );
1141 assert( inbranchedvarindices[varid] );
1142 inbranchedvarindices[varid] =
FALSE;
1266 for (
i = 0;
i < npermvars; ++
i)
1269 for (p = 0; p < nperms; ++p)
1271 if ( perms[p][
i] !=
i )
1295 for (
i = 0;
i < npermvars; ++
i)
1301 for (p = 0; p < nperms; ++p)
1303 if ( perms[p][
i] !=
i )
1318 orcdata->
nperms = nperms;
1320 for (p = 0; p < nperms; ++p)
1323 origperm = perms[p];
1324 newperm = orcdata->
perms[p];
1326 for (
i = 0;
i < npermvars; ++
i)
1332 assert( newidx < orcdata->npermvars );
1335 assert( newpermidx >= 0 );
1336 assert( newidx < orcdata->npermvars );
1339 newperm[newidx] = newpermidx;
1368 assert( orbireddata->ncomponents >= 0 );
1369 assert( (orbireddata->ncomponents == 0) == (orbireddata->componentdatas ==
NULL) );
1370 assert( orbireddata->ncomponents <= orbireddata->maxncomponents );
1371 if ( orbireddata->ncomponents == orbireddata->maxncomponents )
1378 if ( orbireddata->ncomponents == 0 )
1385 orbireddata->ncomponents, newsize) );
1388 orbireddata->maxncomponents = newsize;
1395 assert( orbireddata->ncomponents < orbireddata->maxncomponents );
1396 orbireddata->componentdatas[orbireddata->ncomponents++] = orcdata;
1419 assert( (*orcdata)->nperms > 0 );
1420 assert( (*orcdata)->npermvars > 0 );
1424 assert( (*orcdata)->npermvars > 0 );
1429 if ( (*orcdata)->symmetrybrokencomputed )
1431 assert( ((*orcdata)->nsymbrokenvarids == 0) == ((*orcdata)->symbrokenvarids ==
NULL) );
1439 for (
i = (*orcdata)->npermvars - 1;
i >= 0; --
i)
1443 orbireddata->globalfixeventhdlr, (
SCIP_EVENTDATA*) (*orcdata), -1) );
1450 for (p = (*orcdata)->nperms -1; p >= 0; --p)
1457 for (
i = 0;
i < (*orcdata)->npermvars; ++
i)
1490 orcdata = (
ORCDATA*) eventdata;
1544 *nred = orbireddata->nred;
1545 *ncutoff = orbireddata->ncutoff;
1561 if ( orbireddata->ncomponents == 0 )
1568 " orbital reduction: %4d components of sizes ", orbireddata->ncomponents);
1569 for (
i = 0;
i < orbireddata->ncomponents; ++
i)
1597 assert( (orbireddata->componentdatas ==
NULL) == (orbireddata->ncomponents == 0) );
1598 assert( orbireddata->ncomponents >= 0 );
1599 assert( orbireddata->ncomponents <= orbireddata->maxncomponents );
1604 *infeasible =
FALSE;
1609 if ( orbireddata->ncomponents == 0 )
1620 assert( orbireddata->shadowtreeeventhdlr !=
NULL );
1624 for (
c = 0;
c < orbireddata->ncomponents; ++
c)
1626 orcdata = orbireddata->componentdatas[
c];
1638 orbireddata->nred += *nred;
1640 ++orbireddata->ncutoff;
1682 assert( orbireddata->ncomponents >= 0 );
1683 assert( (orbireddata->ncomponents == 0) == (orbireddata->componentdatas ==
NULL) );
1684 assert( orbireddata->ncomponents <= orbireddata->maxncomponents );
1685 assert( orbireddata->shadowtreeeventhdlr !=
NULL );
1687 while ( orbireddata->ncomponents > 0 )
1692 assert( orbireddata->ncomponents == 0 );
1694 orbireddata->componentdatas =
NULL;
1695 orbireddata->maxncomponents = 0;
1737 (*orbireddata)->componentdatas =
NULL;
1738 (*orbireddata)->ncomponents = 0;
1739 (*orbireddata)->maxncomponents = 0;
1740 (*orbireddata)->shadowtreeeventhdlr = shadowtreeeventhdlr;
1741 (*orbireddata)->nred = 0;
1742 (*orbireddata)->ncutoff = 0;
#define SCIPcheckStage(scip, method, init, problem, transforming, transformed, initpresolve, presolving, exitpresolve, presolved, initsolve, solving, solved, exitsolve, freetrans, freescip)
#define SCIP_STRINGEQ(name, reference, retcode)
SCIP_RETCODE SCIPactivateShadowTree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr)
SCIP_SHADOWTREE * SCIPgetShadowTree(SCIP_EVENTHDLR *eventhdlr)
SCIP_SHADOWNODE * SCIPshadowTreeGetShadowNode(SCIP_SHADOWTREE *shadowtree, SCIP_NODE *node)
struct SCIP_ShadowBoundUpdate SCIP_SHADOWBOUNDUPDATE
struct SCIP_ShadowTree SCIP_SHADOWTREE
struct SCIP_ShadowNode SCIP_SHADOWNODE
void SCIPfreeDisjointset(SCIP *scip, SCIP_DISJOINTSET **djset)
int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
void SCIPdisjointsetUnion(SCIP_DISJOINTSET *djset, int p, int q, SCIP_Bool forcerepofp)
SCIP_RETCODE SCIPcreateDisjointset(SCIP *scip, SCIP_DISJOINTSET **djset, int ncomponents)
SCIP_Bool SCIPisTransformed(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
#define SCIPfreeCleanBufferArray(scip, ptr)
#define SCIPallocCleanBufferArray(scip, ptr, num)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
int SCIPcalcMemGrowSize(SCIP *scip, int num)
#define SCIPallocBufferArray(scip, ptr, num)
#define SCIPfreeBufferArray(scip, ptr)
#define SCIPallocBlockMemoryArray(scip, ptr, num)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
#define SCIPfreeBlockMemory(scip, ptr)
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
#define SCIPallocBlockMemory(scip, ptr)
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
SCIP_Bool SCIPinProbing(SCIP *scip)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Bool SCIPsymGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPsymEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPsymLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPsymGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPsymLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
assert(minobj< SCIPgetCutoffbound(scip))
memory allocation routines
public methods for managing constraints
public methods for message output
public methods for problem variables
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for SCIP variables
SCIP_Bool symmetrybrokencomputed
SCIP_HASHMAP * permvarmap
SCIP_Bool treewarninggiven
SCIP_BOUNDTYPE boundchgtype
SCIP_SHADOWBOUNDUPDATE * branchingdecisions
SCIP_SHADOWBOUNDUPDATE * propagations
struct SCIP_ShadowNode * parent
datastructures for block memory pools and memory buffers
SCIP main data structure.
data structures for branch and bound tree
datastructures for problem variables
methods for handling symmetries
static SCIP_RETCODE applyOrbitalReductionPropagations(SCIP *scip, ORCDATA *orcdata, SCIP_SHADOWTREE *shadowtree, SCIP_Bool *infeasible, int *nred)
static SCIP_RETCODE applyOrbitalBranchingPropagations(SCIP *scip, ORCDATA *orcdata, SCIP_SHADOWTREE *shadowtree, SCIP_Bool *infeasible, int *nred)
SCIP_RETCODE SCIPorbitalReductionFree(SCIP *scip, SCIP_ORBITALREDDATA **orbireddata)
SCIP_RETCODE SCIPorbitalReductionGetStatistics(SCIP *scip, SCIP_ORBITALREDDATA *orbireddata, int *nred, int *ncutoff)
SCIP_RETCODE SCIPincludeOrbitalReduction(SCIP *scip, SCIP_ORBITALREDDATA **orbireddata, SCIP_EVENTHDLR *shadowtreeeventhdlr)
SCIP_RETCODE SCIPorbitalReductionPrintStatistics(SCIP *scip, SCIP_ORBITALREDDATA *orbireddata)
static SCIP_RETCODE orbitalReductionGetSymmetryStabilizerSubgroup(SCIP *scip, ORCDATA *orcdata, int **chosenperms, int *nchosenperms, SCIP_Real *varlbs, SCIP_Real *varubs, int *branchedvarindices, SCIP_Bool *inbranchedvarindices, int nbranchedvarindices)
SCIP_RETCODE SCIPorbitalReductionAddComponent(SCIP *scip, SCIP_ORBITALREDDATA *orbireddata, SCIP_VAR **permvars, int npermvars, int **perms, int nperms, SCIP_Bool *success)
static SCIP_RETCODE applyOrbitalReductionPart(SCIP *scip, ORCDATA *orcdata, SCIP_Bool *infeasible, int *nred, int *varorbitids, int *varorbitidssort, SCIP_Real *varlbs, SCIP_Real *varubs)
SCIP_RETCODE SCIPorbitalReductionReset(SCIP *scip, SCIP_ORBITALREDDATA *orbireddata)
struct OrbitalReductionComponentData ORCDATA
#define EVENTHDLR_SYMMETRY_NAME
SCIP_RETCODE SCIPorbitalReductionPropagate(SCIP *scip, SCIP_ORBITALREDDATA *orbireddata, SCIP_Bool *infeasible, int *nred, SCIP_Bool *didrun)
static SCIP_RETCODE identifyOrbitalSymmetriesBroken(SCIP *scip, ORCDATA *orcdata)
static SCIP_RETCODE orbitalReductionPropagateComponent(SCIP *scip, ORCDATA *orcdata, SCIP_SHADOWTREE *shadowtree, SCIP_Bool *infeasible, int *nred)
static int bisectSortedArrayFindFirstGEQ(int *ids, int *idssort, int frameleft, int frameright, int findid)
static SCIP_RETCODE freeComponent(SCIP *scip, SCIP_ORBITALREDDATA *orbireddata, ORCDATA **orcdata)
#define EVENTHDLR_SYMMETRY_DESC
static SCIP_RETCODE addComponent(SCIP *scip, SCIP_ORBITALREDDATA *orbireddata, SCIP_VAR **permvars, int npermvars, int **perms, int nperms, SCIP_Bool *success)
struct SCIP_OrbitalReductionData SCIP_ORBITALREDDATA
struct SCIP_Eventhdlr SCIP_EVENTHDLR
#define SCIP_EVENTTYPE_GUBCHANGED
struct SCIP_EventData SCIP_EVENTDATA
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
#define SCIP_DECL_EVENTEXEC(x)
#define SCIP_EVENTTYPE_GLBCHANGED
struct SCIP_HashMap SCIP_HASHMAP
struct SCIP_DisjointSet SCIP_DISJOINTSET
enum SCIP_Retcode SCIP_RETCODE
struct SCIP_Node SCIP_NODE
type definitions for problem variables