[Scip] How to deal with "branching decisions"
Tobias Achterberg
achterberg at zib.de
Wed Aug 27 14:48:05 MEST 2008
Hi Egbert,
you are facing a very common problem in B&P, which you can deal nicely with using SCIP.
You have several options, some of which you already proposed yourself.
1. Add binary variables y_it for capturing "worker i works during period t". You mentioned
the problem that they are fixed in presolving, and this is certainly valid, because they
do not appear in any constraints. The correct way of dealing with this issue is to add the
constraints that describe their meaning, i.e., to add constraints
-y_it + \sum_{s covers time t} x_s <= 0
I bet that you already have constraints
\sum_{s covers time t} x_s <= 1
in order to model that you cannot choose two shifts that cover the same time slot. The
constraint with the y_it is the natural replacement for these constraints.
Of course, this may change your pricing problem, but in order to not generate shifts that
contain (or that do not contain) the time slots on which you branched, you have to be able
to deal with this anyway.
In fact, it would be more elegant to invert the role of y_it to get
y_it + \sum_{s covers time t} x_s <= 1. (*)
Then, you have a set packing constraint, and the domain propagation of the set packing
cosntraint handler will automatically fix all x_s to zero if y_it = 1. You can interpret
the y_it variables as additional shifts, that occupy a single time slot but do not satisfy
any demand.
If you do not want to modify your constraint by including the y_it variable (for example,
because you cannot interpret the dual variables anymore in your pricing), you can also use
constraints (*) in addition to your original formulation. Mark them as "initial=FALSE" and
"separate=FALSE" to forbid them to enter the LP. Domain propagation will again make sure
that the x_s variables are fixed to zero if y_it = 1.
2. Sometimes, pricing algorithms need to update their internal data structures (for
example, a graph) after the branching and undo these updates if the search leaves the
child node again.
To do this in SCIP, I usually recommend to add "marker constraints" to the branching
nodes. Create a new constraint handler with constraint data that can store the information
necessary to do/undo the changes in the pricer's data structures. All methods of the
constraint handler (check, enforcing, separation, propagation, ...) should be empty (which
means to always return status = SCIP_FEASIBLE for the fundamental callbacks), just as if
all constraints of this type are always feasible. The important callbacks are the
CONSACTIVE and CONSDEACTIVE methods.
The CONSACTIVE method is always called when a node is entered on which the constraint has
been added (i.e., the child node on which you applied your branching). Here, you will
apply the changes to your pricing data structures. The CONSDEACTIVE method will be called
if the node is left again. Since the CONSACTIVE and CONSDEACTIVE methods of different
constraints are always called in a stack-like fashion, this should be exactly what you need.
If you have such a constraint handler, just create and add constraints of this type to the
child node of your branching. Make sure to set the "stickingatnode" flag to TRUE in order
to prevent SCIP from moving the constraint around in the tree.
3. You can also use event handlers, but I think that this is not appropriate in your
application. Anyway, I will briefly explain what this means.
An event handler can watch for events like local bound changes on variables. So, if your
pricer wants to be informed whenever a local bound of a certain variable changes, add an
event handler, catch the corresponding events of the variable, and in the event handler's
execution method adjust the data structures of your pricer accordingly.
Most constraint handler use an event handler to speed up their domain propagation and
presolving capabilities. For example, the set packing constraint handler deals with
constraints
x_1 + ... + x_k <= 1
on binary variables x_j. Its associated event handler catches events for tightenings of
the lower bounds of the involved variables. If such an event occurs, it knows that this
variable has been fixed to 1 and informs the constraint handler that it can fix all other
variables to zero in its next domain propagation call. If such an event does not occur,
the constraint handler knows that it does not make sense to look at the constraint in the
domain propagation and therefore can save the time to process this constraint.
I hope that this helps. In my view, alternative 1 is the best suited for your problem, in
particular if you can just modify your packing constraints to include the additional variable.
Best, Tobias
E. van der Veen wrote:
> Hi,
>
> Thanks for your help last time with my question on
> "Deleting/fixing a SCIP variable". However, I'm now facing
> another problems with my Branch-and-Price (B&P)
> implementation in SCIP.
> I know now how to fix variables (via
> SCIPchgVarLbNode()/SCIPchgVarUbNode()), but I would like a
> way to store "branching decisions". I can probably best
> explain what I would like to do by first explaining the
> most important concepts of my problem and my solution
> approach first.
>
> I have a rostering problem, which I'm trying to solve with
> a B&P approach. In my master problem I've got shifts which
> employees can work. Each employee has his own set of
> shifts he can work (due to unavailabilities/preferences
> employees can have), of course an employee can work only
> one shift max. In my pricing problem I first choose an
> employee and than generate the best additional shift for
> this employee (if this improves the solution of the master
> problem), via shadow prices of the demand constraints in
> the master problem. I continue with generating shifts
> until no more 'improving' shifts are found. However, the
> solution of the master problem we now get need not be
> integral (e.g. an employee works two times half a shift).
> In this case branching has to be applied. I would like to
> branch on whether employee $i$ works/doesn't work during
> some period $t$. All shifts violating this should not be
> worked (and thus variables corresponding to them fixed to
> 0). Shifts generated for employee $i$ after this branching
> decision should have a working period in period $t$. The
> branching/pricing is continued until an optimal (integer)
> solution is found.
>
> Generating shifts (via a pricer) is no problem for me.
> However, the branching is. The problems I'm facing:
> 1. How to remember branching decisions (i.e. $i$
> should/should not work during $t$) in subnodes of the
> current node.
> 2. How to include this branching decisions in the
> pricer/pricing problem.
>
> I have thought about this (and tried some approaches) for
> quite a while. What I've tried is adding variables to the
> model to "store" branching decisions, i.e. adding
> variables which tell the problem whether $i$ should/should
> not work during $t$. However, these variables are not
> included in any constraint in my master problem and
> (hence) SCIP fixes them during presolving. Perhaps I could
> switch the fixing of variables during presolving off, but
> I' not sure whether this is a good idea. I can imagine
> that fixing variables can speed up the solution process,
> which I of course would like.
>
> Furthermore, I've been investigating whether I can
> implement my branching rule via constraint handlers. I
> think it is possible (seen something about constraint
> handlers being valid only 'locally'), but how do you add a
> constraint (handlers) only locally (i.e. in some node) or
> does SCIP do that automatically after calling
> SCIPcreateChild()? I also looked at the TSP example to get
> some feeling about the constraint handlers in SCIP, and
> basically understand how they work. However, I do not
> (yet) see how to apply it in a B&P approach, because in
> the TSP example no branching is applied, but 'only'
> constraints are added (as far as I can see it).
> And, furthermore, is there a way in which I can provide
> these branching decisions to the pricer (pricing problem)?
> I think I cannot simply add it to the pricing problem,
> because when the problem moves out of the current node (or
> generates a trip for another employee) this constraint is
> no longer valid. Does anyone have a clue on this?
>
> I'm sorry for the long e-mail/question. Hope anyone can
> provide me with some answers to my questions. Any help is
> appreciated very much. So if you have parts of answers to
> my questions or have some example code which might be
> useful to me, I would be very happy with it.
>
> Thanks in advance.
> Best regards,
>
> Egbert
> _______________________________________________
> Scip mailing list
> Scip at zib.de
> http://listserv.zib.de/mailman/listinfo/scip
More information about the Scip
mailing list