scippropagationconstraint-satisfactionpyscipopt

custom propagator via pyscipopt


I'm trying to write a custom value propagator for SCIP. I have some complex logic that can detect additional values that can also be fixed whenever one or several are fixed (via the branching mechanism). I have the code below that apparently makes everything be infeasible (which is not correct). My questions for it:

  1. Is the value propagator the right place for this? Or should I be using a constraint handler's propagation mechanism (with nothing else in the constraint handler)?
  2. getCurrentNode works in a value propagator? I have it registered with freq=1.
  3. Should I use transformed=True in the getVars call? My check_constraints function is built with the original (non-transformed) variables. I think I can correlate them by removing "t_" in the name, but are the original variables just as valid in this context?
  4. Is getVars even node-specific? Is there some better way to get the variables that have been fixed as part of the presolver and the branching?
    class MyPropagator(scip.Prop):
        def propexec(self, proptiming):
            vars = self.model.getVars(transformed=False)
            hit_some = False
            node = self.model.getCurrentNode()
            for var in vars:
                if self.model.isFeasEQ(var.getLbLocal(), var.getUbLocal()):  # is fixed in subtree?
                    impossible, wants_fix = self.check_constraints(var.name)
                    if impossible:
                        return {"result": scip.scip.PY_SCIP_RESULT.CUTOFF}
                    for key_var, value in wants_fix:  # fix each of these in the subtree
                        self.model.chgVarLbNode(node, key_var, value)
                        self.model.chgVarUbNode(node, key_var, value)
                        hit_some = True
    
            if hit_some:
                return {"result": scip.scip.PY_SCIP_RESULT.REDUCEDDOM}
            return {"result": scip.scip.PY_SCIP_RESULT.DIDNOTFIND}

Solution

    1. Yes, no need to use a constraint handler for this
    2. It works but you don't need it. You should use chgVarLb instead of chgVarLbNoode. It will automatically add the bound change correctly as a local change to the current node.
    3. You should be doing everything inside the tree with the transformed variables. It is probably not wrong to use the original ones but will be very inefficient. (SCIP will transform them anyway in all things you do since you are in the solving stage here)
    4. getVars is fine, as long as you use the transformed ones.