1

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}
Brannon
  • 5,324
  • 4
  • 35
  • 83

1 Answers1

1
  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.
Leon
  • 1,588
  • 1
  • 7
  • 16
  • When I use the transformed variables, there are a few of my original variables that no longer exist. How should I handle the missing originals? When I query them, getVarLbLocal != getVarUbLocal, so it seems that they were not converted to constants. – Brannon Jul 22 '22 at 14:58
  • They are most likely aggregated (happens, e.g. if x + y = 2, SCIP will replace x by (2 - y) everywhere) and so they are not relevant in the transformed problem – Leon Jul 22 '22 at 15:00
  • Dear @Leon, I am pretty new to using callbacks in Pyscipopt. Would you say please, where can I find an appropriate doc to read and benchmark some examples in detailed explanations on various methods? – A.Omidi May 29 '23 at 19:17
  • Although this does not really fit in this thread: In the tests subfolder there are all types of different examples for plugins. For the other stuff I suggest you create a new thread with more detailed explanation what you actually want to know. – Leon May 30 '23 at 05:51
  • @Leon, many thanks. I actually asked there, but as I have seen you answered related questions with such details that are very similar to what I look for to learn, I appreciate it if you can hint at some good resources to start. The SCIP host just pointed out many of those in the few introductions. That needs a hard time to understand and apply. – A.Omidi May 30 '23 at 07:23
  • Also, many of the samples in the mentioned dic have not been completed yet and need to work to update. – A.Omidi May 30 '23 at 07:34