@@ -849,42 +849,37 @@ SCIP_RETCODE nodeAssignParent(
849
849
return SCIP_OKAY ;
850
850
}
851
851
852
- /** decreases number of children of the parent, frees it if no children are left */
852
+ /** frees node memory, decreases number of children of the parent, and replaces node with parent if no children left */
853
853
static
854
854
SCIP_RETCODE nodeReleaseParent (
855
- SCIP_NODE * node , /**< child node */
855
+ SCIP_NODE * * node , /**< child node */
856
856
BMS_BLKMEM * blkmem , /**< block memory buffer */
857
857
SCIP_SET * set , /**< global SCIP settings */
858
- SCIP_STAT * stat , /**< problem statistics */
859
- SCIP_EVENTQUEUE * eventqueue , /**< event queue */
860
- SCIP_EVENTFILTER * eventfilter , /**< global event filter */
861
- SCIP_TREE * tree , /**< branch and bound tree */
862
- SCIP_LP * lp /**< current LP data */
858
+ SCIP_TREE * tree /**< branch and bound tree */
863
859
)
864
860
{
865
861
SCIP_NODE * parent ;
862
+ SCIP_Bool freeParent = FALSE;
866
863
867
- assert (node != NULL );
868
- assert (blkmem != NULL );
869
864
assert (tree != NULL );
865
+ assert (node != NULL );
866
+ assert (* node != NULL );
870
867
871
868
SCIPsetDebugMsg (set , "releasing parent-child relationship of node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d with parent #%" SCIP_LONGINT_FORMAT " of type %d\n" ,
872
- SCIPnodeGetNumber (node ), SCIPnodeGetDepth (node ), SCIPnodeGetType (node ),
873
- node -> parent != NULL ? SCIPnodeGetNumber (node -> parent ) : -1 ,
874
- node -> parent != NULL ? (int )SCIPnodeGetType (node -> parent ) : -1 );
875
- parent = node -> parent ;
869
+ SCIPnodeGetNumber (* node ), SCIPnodeGetDepth (* node ), SCIPnodeGetType (* node ),
870
+ ( * node ) -> parent != NULL ? SCIPnodeGetNumber (( * node ) -> parent ) : -1 ,
871
+ ( * node ) -> parent != NULL ? (int )SCIPnodeGetType (( * node ) -> parent ) : -1 );
872
+ parent = ( * node ) -> parent ;
876
873
if ( parent != NULL )
877
874
{
878
- SCIP_Bool freeParent = FALSE;
879
-
880
875
switch ( SCIPnodeGetType (parent ) )
881
876
{
882
877
case SCIP_NODETYPE_FOCUSNODE :
883
878
assert (parent -> active );
884
- assert (SCIPnodeGetType (node ) == SCIP_NODETYPE_CHILD || SCIPnodeGetType (node ) == SCIP_NODETYPE_PROBINGNODE
885
- || SCIPnodeGetType (node ) == SCIP_NODETYPE_LEAF );
886
- if ( SCIPnodeGetType (node ) == SCIP_NODETYPE_CHILD )
887
- treeRemoveChild (tree , node );
879
+ assert (SCIPnodeGetType (* node ) == SCIP_NODETYPE_CHILD || SCIPnodeGetType (* node ) == SCIP_NODETYPE_PROBINGNODE
880
+ || SCIPnodeGetType (* node ) == SCIP_NODETYPE_LEAF );
881
+ if ( SCIPnodeGetType (* node ) == SCIP_NODETYPE_CHILD )
882
+ treeRemoveChild (tree , * node );
888
883
/* don't kill the focus node at this point => freeParent = FALSE */
889
884
break ;
890
885
case SCIP_NODETYPE_PROBINGNODE :
@@ -931,23 +926,18 @@ SCIP_RETCODE nodeReleaseParent(
931
926
* we don't want to free the refocused node, because we first have to convert it back to its original
932
927
* type (where it possibly has children) => freeParent = FALSE
933
928
*/
934
- assert (SCIPnodeGetType (node ) == SCIP_NODETYPE_PROBINGNODE );
929
+ assert (SCIPnodeGetType (* node ) == SCIP_NODETYPE_PROBINGNODE );
935
930
assert (!SCIPtreeProbing (tree ));
936
931
break ;
937
932
default :
938
933
SCIPerrorMessage ("unknown node type %d\n" , SCIPnodeGetType (parent ));
939
934
return SCIP_INVALIDDATA ;
940
935
}
941
936
942
- /* free parent if it is not on the current active path */
943
- if ( freeParent && !parent -> active )
944
- {
945
- SCIP_CALL ( SCIPnodeFree (& node -> parent , blkmem , set , stat , eventqueue , eventfilter , tree , lp ) );
946
- }
947
937
/* update the effective root depth if active parent has children and neither reoptimization nor certificate
948
938
* printing is enabled
949
939
*/
950
- else if ( freeParent == ! parent -> active && !set -> reopt_enable && !SCIPisCertified (set -> scip ) )
940
+ if ( ! freeParent && parent -> active && !set -> reopt_enable && !SCIPisCertified (set -> scip ) )
951
941
{
952
942
SCIP_Bool singleChild = FALSE;
953
943
int focusdepth = SCIPtreeGetFocusDepth (tree );
@@ -1005,13 +995,19 @@ SCIP_RETCODE nodeReleaseParent(
1005
995
1006
996
SCIPsetDebugMsg (set ,
1007
997
"unlinked node #%" SCIP_LONGINT_FORMAT " in depth %d -> new effective root depth: %d\n" ,
1008
- SCIPnodeGetNumber (node ), SCIPnodeGetDepth (node ), tree -> updatedeffectiverootdepth );
998
+ SCIPnodeGetNumber (* node ), SCIPnodeGetDepth (* node ), tree -> updatedeffectiverootdepth );
1009
999
}
1010
1000
1011
1001
assert (!singleChild || tree -> updatedeffectiverootdepth == SCIPtreeGetFocusDepth (tree ));
1012
1002
}
1013
1003
}
1014
1004
1005
+ BMSfreeBlockMemory (blkmem , node );
1006
+
1007
+ /* free parent iteratively if it is not on the current active path */
1008
+ if ( freeParent && !parent -> active )
1009
+ * node = parent ;
1010
+
1015
1011
return SCIP_OKAY ;
1016
1012
}
1017
1013
@@ -1115,7 +1111,7 @@ SCIP_Bool SCIPtreeWasNodeLastBranchParent(
1115
1111
return FALSE;
1116
1112
}
1117
1113
1118
- /** frees node */
1114
+ /** frees node and inactive path iteratively */
1119
1115
SCIP_RETCODE SCIPnodeFree (
1120
1116
SCIP_NODE * * node , /**< node data */
1121
1117
BMS_BLKMEM * blkmem , /**< block memory buffer */
@@ -1129,130 +1125,132 @@ SCIP_RETCODE SCIPnodeFree(
1129
1125
{
1130
1126
SCIP_Bool isroot ;
1131
1127
1128
+ assert (tree != NULL );
1132
1129
assert (node != NULL );
1133
1130
assert (* node != NULL );
1134
- assert (!(* node )-> active );
1135
- assert (blkmem != NULL );
1136
- assert (tree != NULL );
1137
-
1138
- SCIPsetDebugMsg (set , "free node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d\n" , SCIPnodeGetNumber (* node ), SCIPnodeGetDepth (* node ), SCIPnodeGetType (* node ));
1139
-
1140
- /* if certificate is active, unsplit current node and free the memory in hashmap of certificate */
1141
- SCIP_CALL ( SCIPcertificatePrintUnsplitting (set , stat -> certificate , * node ) );
1142
-
1143
- /* check lower bound w.r.t. debugging solution */
1144
- SCIP_CALL ( SCIPdebugCheckGlobalLowerbound (blkmem , set ) );
1145
1131
1146
- if ( SCIPnodeGetType ( * node ) != SCIP_NODETYPE_PROBINGNODE )
1132
+ do
1147
1133
{
1148
- SCIP_EVENT event ;
1134
+ assert (!( * node ) -> active ) ;
1149
1135
1150
- /* trigger a node deletion event */
1151
- SCIP_CALL ( SCIPeventChgType (& event , SCIP_EVENTTYPE_NODEDELETE ) );
1152
- SCIP_CALL ( SCIPeventChgNode (& event , * node ) );
1153
- SCIP_CALL ( SCIPeventProcess (& event , set , NULL , NULL , NULL , eventfilter ) );
1154
- }
1136
+ SCIPsetDebugMsg (set , "free node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d\n" , SCIPnodeGetNumber (* node ), SCIPnodeGetDepth (* node ), SCIPnodeGetType (* node ));
1155
1137
1156
- /* inform solution debugger, that the node has been freed */
1157
- SCIP_CALL ( SCIPdebugRemoveNode ( blkmem , set , * node ) );
1138
+ /* if certificate is active, unsplit current node and free the memory in hashmap of certificate */
1139
+ SCIP_CALL ( SCIPcertificatePrintUnsplitting ( set , stat -> certificate , * node ) );
1158
1140
1159
- /* check, if the node to be freed is the root node */
1160
- isroot = ( SCIPnodeGetDepth ( * node ) == 0 );
1141
+ /* check lower bound w.r.t. debugging solution */
1142
+ SCIP_CALL ( SCIPdebugCheckGlobalLowerbound ( blkmem , set ) );
1161
1143
1162
- /* free nodetype specific data, and release no longer needed LPI states */
1163
- switch ( SCIPnodeGetType (* node ) )
1164
- {
1165
- case SCIP_NODETYPE_FOCUSNODE :
1166
- assert (tree -> focusnode == * node );
1167
- assert (!SCIPtreeProbing (tree ));
1168
- SCIPerrorMessage ("cannot free focus node - has to be converted into a dead end first\n" );
1169
- return SCIP_INVALIDDATA ;
1170
- case SCIP_NODETYPE_PROBINGNODE :
1171
- assert (SCIPtreeProbing (tree ));
1172
- assert (SCIPnodeGetDepth (tree -> probingroot ) <= SCIPnodeGetDepth (* node ));
1173
- assert (SCIPnodeGetDepth (* node ) > 0 );
1174
- SCIP_CALL ( probingnodeFree (& ((* node )-> data .probingnode ), blkmem , lp ) );
1175
- break ;
1176
- case SCIP_NODETYPE_SIBLING :
1177
- assert ((* node )-> data .sibling .arraypos >= 0 );
1178
- assert ((* node )-> data .sibling .arraypos < tree -> nsiblings );
1179
- assert (tree -> siblings [(* node )-> data .sibling .arraypos ] == * node );
1180
- if ( tree -> focuslpstatefork != NULL )
1144
+ if ( SCIPnodeGetType (* node ) != SCIP_NODETYPE_PROBINGNODE )
1181
1145
{
1182
- assert (SCIPnodeGetType (tree -> focuslpstatefork ) == SCIP_NODETYPE_FORK
1183
- || SCIPnodeGetType (tree -> focuslpstatefork ) == SCIP_NODETYPE_SUBROOT );
1184
- SCIP_CALL ( SCIPnodeReleaseLPIState (tree -> focuslpstatefork , blkmem , lp ) );
1185
- }
1186
- treeRemoveSibling (tree , * node );
1187
- break ;
1188
- case SCIP_NODETYPE_CHILD :
1189
- assert ((* node )-> data .child .arraypos >= 0 );
1190
- assert ((* node )-> data .child .arraypos < tree -> nchildren );
1191
- assert (tree -> children [(* node )-> data .child .arraypos ] == * node );
1192
- /* The children capture the LPI state at the moment, where the focus node is
1193
- * converted into a junction, pseudofork, fork, or subroot, and a new node is focused.
1194
- * At the same time, they become siblings or leaves, such that freeing a child
1195
- * of the focus node doesn't require to release the LPI state;
1196
- * we don't need to call treeRemoveChild(), because this is done in nodeReleaseParent()
1197
- */
1198
- break ;
1199
- case SCIP_NODETYPE_LEAF :
1200
- if ( (* node )-> data .leaf .lpstatefork != NULL )
1201
- {
1202
- SCIP_CALL ( SCIPnodeReleaseLPIState ((* node )-> data .leaf .lpstatefork , blkmem , lp ) );
1146
+ SCIP_EVENT event ;
1147
+
1148
+ /* trigger a node deletion event */
1149
+ SCIP_CALL ( SCIPeventChgType (& event , SCIP_EVENTTYPE_NODEDELETE ) );
1150
+ SCIP_CALL ( SCIPeventChgNode (& event , * node ) );
1151
+ SCIP_CALL ( SCIPeventProcess (& event , set , NULL , NULL , NULL , eventfilter ) );
1203
1152
}
1204
- break ;
1205
- case SCIP_NODETYPE_DEADEND :
1206
- case SCIP_NODETYPE_JUNCTION :
1207
- break ;
1208
- case SCIP_NODETYPE_PSEUDOFORK :
1209
- SCIP_CALL ( pseudoforkFree (& ((* node )-> data .pseudofork ), blkmem , set , lp ) );
1210
- break ;
1211
- case SCIP_NODETYPE_FORK :
1212
1153
1213
- /* release special root LPI state capture which is used to keep the root LPI state over the whole solving
1214
- * process
1215
- */
1216
- if ( isroot )
1154
+ /* inform solution debugger, that the node has been freed */
1155
+ SCIP_CALL ( SCIPdebugRemoveNode (blkmem , set , * node ) );
1156
+
1157
+ /* check, if the node to be freed is the root node */
1158
+ isroot = (SCIPnodeGetDepth (* node ) == 0 );
1159
+
1160
+ /* free nodetype specific data, and release no longer needed LPI states */
1161
+ switch ( SCIPnodeGetType (* node ) )
1217
1162
{
1218
- SCIP_CALL ( SCIPnodeReleaseLPIState (* node , blkmem , lp ) );
1163
+ case SCIP_NODETYPE_FOCUSNODE :
1164
+ assert (tree -> focusnode == * node );
1165
+ assert (!SCIPtreeProbing (tree ));
1166
+ SCIPerrorMessage ("cannot free focus node - has to be converted into a dead end first\n" );
1167
+ return SCIP_INVALIDDATA ;
1168
+ case SCIP_NODETYPE_PROBINGNODE :
1169
+ assert (SCIPtreeProbing (tree ));
1170
+ assert (SCIPnodeGetDepth (tree -> probingroot ) <= SCIPnodeGetDepth (* node ));
1171
+ assert (SCIPnodeGetDepth (* node ) > 0 );
1172
+ SCIP_CALL ( probingnodeFree (& ((* node )-> data .probingnode ), blkmem , lp ) );
1173
+ break ;
1174
+ case SCIP_NODETYPE_SIBLING :
1175
+ assert ((* node )-> data .sibling .arraypos >= 0 );
1176
+ assert ((* node )-> data .sibling .arraypos < tree -> nsiblings );
1177
+ assert (tree -> siblings [(* node )-> data .sibling .arraypos ] == * node );
1178
+ if ( tree -> focuslpstatefork != NULL )
1179
+ {
1180
+ assert (SCIPnodeGetType (tree -> focuslpstatefork ) == SCIP_NODETYPE_FORK
1181
+ || SCIPnodeGetType (tree -> focuslpstatefork ) == SCIP_NODETYPE_SUBROOT );
1182
+ SCIP_CALL ( SCIPnodeReleaseLPIState (tree -> focuslpstatefork , blkmem , lp ) );
1183
+ }
1184
+ treeRemoveSibling (tree , * node );
1185
+ break ;
1186
+ case SCIP_NODETYPE_CHILD :
1187
+ assert ((* node )-> data .child .arraypos >= 0 );
1188
+ assert ((* node )-> data .child .arraypos < tree -> nchildren );
1189
+ assert (tree -> children [(* node )-> data .child .arraypos ] == * node );
1190
+ /* The children capture the LPI state at the moment, where the focus node is
1191
+ * converted into a junction, pseudofork, fork, or subroot, and a new node is focused.
1192
+ * At the same time, they become siblings or leaves, such that freeing a child
1193
+ * of the focus node doesn't require to release the LPI state;
1194
+ * we don't need to call treeRemoveChild(), because this is done in nodeReleaseParent()
1195
+ */
1196
+ break ;
1197
+ case SCIP_NODETYPE_LEAF :
1198
+ if ( (* node )-> data .leaf .lpstatefork != NULL )
1199
+ {
1200
+ SCIP_CALL ( SCIPnodeReleaseLPIState ((* node )-> data .leaf .lpstatefork , blkmem , lp ) );
1201
+ }
1202
+ break ;
1203
+ case SCIP_NODETYPE_DEADEND :
1204
+ case SCIP_NODETYPE_JUNCTION :
1205
+ break ;
1206
+ case SCIP_NODETYPE_PSEUDOFORK :
1207
+ SCIP_CALL ( pseudoforkFree (& ((* node )-> data .pseudofork ), blkmem , set , lp ) );
1208
+ break ;
1209
+ case SCIP_NODETYPE_FORK :
1210
+ /* release special root LPI state capture which is used to keep the root LPI state over the whole solving
1211
+ * process
1212
+ */
1213
+ if ( isroot )
1214
+ {
1215
+ SCIP_CALL ( SCIPnodeReleaseLPIState (* node , blkmem , lp ) );
1216
+ }
1217
+ SCIP_CALL ( forkFree (& ((* node )-> data .fork ), blkmem , set , lp ) );
1218
+ break ;
1219
+ case SCIP_NODETYPE_SUBROOT :
1220
+ SCIP_CALL ( subrootFree (& ((* node )-> data .subroot ), blkmem , set , lp ) );
1221
+ break ;
1222
+ case SCIP_NODETYPE_REFOCUSNODE :
1223
+ SCIPerrorMessage ("cannot free node as long it is refocused\n" );
1224
+ return SCIP_INVALIDDATA ;
1225
+ default :
1226
+ SCIPerrorMessage ("unknown node type %d\n" , SCIPnodeGetType (* node ));
1227
+ return SCIP_INVALIDDATA ;
1219
1228
}
1220
- SCIP_CALL ( forkFree (& ((* node )-> data .fork ), blkmem , set , lp ) );
1221
- break ;
1222
- case SCIP_NODETYPE_SUBROOT :
1223
- SCIP_CALL ( subrootFree (& ((* node )-> data .subroot ), blkmem , set , lp ) );
1224
- break ;
1225
- case SCIP_NODETYPE_REFOCUSNODE :
1226
- SCIPerrorMessage ("cannot free node as long it is refocused\n" );
1227
- return SCIP_INVALIDDATA ;
1228
- default :
1229
- SCIPerrorMessage ("unknown node type %d\n" , SCIPnodeGetType (* node ));
1230
- return SCIP_INVALIDDATA ;
1231
- }
1232
1229
1233
- /* free common data */
1234
- SCIP_CALL ( SCIPconssetchgFree (& (* node )-> conssetchg , blkmem , set ) );
1235
- SCIP_CALL ( SCIPdomchgFree (& (* node )-> domchg , blkmem , set , eventqueue , lp ) );
1236
- SCIP_CALL ( nodeReleaseParent (* node , blkmem , set , stat , eventqueue , eventfilter , tree , lp ) );
1230
+ /* free common data */
1231
+ SCIP_CALL ( SCIPconssetchgFree (& (* node )-> conssetchg , blkmem , set ) );
1232
+ SCIP_CALL ( SCIPdomchgFree (& (* node )-> domchg , blkmem , set , eventqueue , lp ) );
1237
1233
1238
- /* check, if the node is the current probing root */
1239
- if ( * node == tree -> probingroot )
1240
- {
1241
- assert (SCIPnodeGetType (* node ) == SCIP_NODETYPE_PROBINGNODE );
1242
- tree -> probingroot = NULL ;
1243
- }
1234
+ /* check, if the node is the current probing root */
1235
+ if ( * node == tree -> probingroot )
1236
+ {
1237
+ assert (SCIPnodeGetType (* node ) == SCIP_NODETYPE_PROBINGNODE );
1238
+ tree -> probingroot = NULL ;
1239
+ }
1244
1240
1245
- if ( set -> exact_enable )
1246
- SCIPrationalFreeBlock (blkmem , & (* node )-> lowerboundexact );
1241
+ if ( set -> exact_enable )
1242
+ SCIPrationalFreeBlock (blkmem , & (* node )-> lowerboundexact );
1247
1243
1248
- BMSfreeBlockMemory (blkmem , node );
1244
+ /* delete the tree's root node pointer, if the freed node was the root */
1245
+ if ( isroot )
1246
+ tree -> root = NULL ;
1249
1247
1250
- /* delete the tree's root node pointer, if the freed node was the root */
1251
- if ( isroot )
1252
- tree -> root = NULL ;
1248
+ SCIP_CALL ( nodeReleaseParent ( node , blkmem , set , tree ) );
1249
+ }
1250
+ while ( * node ! = NULL ) ;
1253
1251
1254
1252
return SCIP_OKAY ;
1255
- }
1253
+ } /*lint !e715*/
1256
1254
1257
1255
/** cuts off node and whole sub tree from branch and bound tree
1258
1256
*
0 commit comments