[SCIP] questions on custom branching

Marc Pfetsch pfetsch at mathematik.tu-darmstadt.de
Thu Jun 13 21:11:07 CEST 2024


Hi Brannon!

> 1. When I call branchvar from branchexeclp, does the left/right nodes
> returned from that have their relaxed LP computed as part of that
> call?

No, this would be too expensive in general. The nodes are put in the 
list of open nodes.

> The instructions on custom branching say that you can call
> updateNodeLowerBound right after branchvar, meaning it did not yet run
> the relaxation for the two new nodes? Can I force it to run the
> relaxation right there?

I don't think you can do so easily. But all of the strong branching rule 
implementation do something similar. They tentatively solve relaxations 
for candidate branching variables.

> 2. How do I get the dual bound from my newly created nodes inside the
> brancher so that I can propagate my losses?

You would need to perform some strong branching - see above.

> 3. Does it only call one brancher per node (if that brancher returns BRANCHED)?

Yes. If you return something different from BRANCHED it will continue to 
the next branching rule.

> 4. Suppose I only want two branching options: my custom brancher and
> strong branching for when the custom brancher can't succeed. With both
> of them, though, I need to update my ML model according to the newly
> found costs. Should I just have one brancher that falls back to strong
> branching inside it?

You can pass the call on - see above.
But if you need to update something you might need to include everything 
in the same branching rule.

> Is there sample code for that somewhere in python
> & pyscipopt?

I am not aware for such code.

> What's the best approach here? Would it be better to use
> a MIPNode callback to backpropagate bounds?

See above. If I understood correctly your branching rule wants to update 
its own data structures.

> 5. Outside of the branching callback, can I know which variable was
> most-recently fixed in a MIPNode? What decision created that node?

For the first you can have a look at SCIPprintBranchingStatistics(). For 
the second you would need to follow the domain changes:

if ( SCIPnodeGetDepth(node) != 0 )
{
    SCIP_BOUNDCHG* boundchg;
    SCIP_DOMCHG* domchg;
    int nboundchgs;

    /* get domain changes of current node */
    domchg = SCIPnodeGetDomchg(node);
    assert( domchg != NULL );

    /* loop through all bound changes */
    nboundchgs = SCIPdomchgGetNBoundchgs(domchg);
    for (int i = 0; i < nboundchgs; ++i)
    {
       /* get bound change info */
       boundchg = SCIPdomchgGetBoundchg(domchg, i);
       assert( boundchg != 0 );

       /* branching decisions have to be in the beginning of the bound 
change array */
       if ( SCIPboundchgGetBoundchgtype(boundchg) != 
SCIP_BOUNDCHGTYPE_BRANCHING )
          break;

       /* get corresponding branching variable */
       SCIP_VAR* branchvar = SCIPboundchgGetVar(boundchg);

...

> Thanks for your time. I've got the src/scip/branch_fullstrong.c file
> up, so I'll keep studying that.

Yes, good idea.

Best

Marc


More information about the Scip mailing list