0

The problem I want to solve consists of about 800 tasks that have to be assigned to about 120 workers. The workers have to be qualified to do the task and only have a certain number of hours per week available. About 80% of the assignments are already preassigned. This means they should be kept, but if the other 20% cannot be solved, the preassignments can be violated.
I already have a model using the Choco solver that uses penalties if a preassignment is violated and the objective is to minimize the penalty. I however think that this is not very efficient, because the solver will not start the search strategy with assigning the preassigned variables. I already asked the question specifically for Choco here (How to define propagation starting point in Choco 3.3).

But is there another solver where this can be done easier? May it be best to write my own solver? I would appreciate any suggestions.

EDIT: I have tried writing my own Choco strategy. For a small problem it works fine, but for the big one it does not find a solution. I am not sure if everything I do in getDecision is allowed (eg check for isInstantiated) and I can't find any documentation or tutorial on how to write a strategy extending AbstractStrategy. I'd appreciate any pointers on what could be the problem. (The higher the absolute priority in the prios matrix is, the earlier the variable should be assigned. If the priority is negative, a 0 should be assigned, if it is positive a 1 should be assigned. The highest priority is 9999)

    public class PriorityStrategy extends AbstractStrategy<IntVar> {

        int[] prios;

        // Search strategy parameters
        VariableSelector<IntVar> variableSelector;
        IntValueSelector valueSelectorLB;
        IntValueSelector valueSelectorUB;
        DecisionOperator<IntVar> decisionOperator;

        // object recycling management
        PoolManager<IntDecision> decisionPool;

        int currentIndex = -1;
        HashMap<IntVar, Integer> bestsMap = new HashMap<IntVar, Integer>();

        public PriorityStrategy(IntVar[] vars, int[] prios) {
            super(vars);
            this.prios = prios;
            valueSelectorLB = new IntDomainMin();
            valueSelectorUB = new IntDomainMax();
            variableSelector = new Random<IntVar>(123); //new Occurrence<IntVar>();
            this.decisionPool = new PoolManager<>();
        }

        @Override
        public Decision<IntVar> getDecision() {
             IntVar next = null;
             List<IntVar> bests = new ArrayList<IntVar>();

             int bestPrio = 0;
             for (int i = 0; i < vars.length; i++) {
                int currentPrio = Math.abs(prios[i]);
                if (currentPrio >= bestPrio && !vars[i].isInstantiated() || 
                        (next == null && !vars[i].isInstantiated())) {
                    if(currentPrio == 9999) {
                        currentIndex = i;
                        bests.clear();
                        bestsMap.clear();
                        return computeDecision(vars[i]);
                    }
                    if(currentPrio > bestPrio) {
                        bestPrio = currentPrio;
                        bests.clear();
                        bestsMap.clear();
                    }
                    bests.add(vars[i]);
                    bestsMap.put(vars[i], i);
                }
            }
            if(bests.size()>0) {
                next = variableSelector.getVariable(bests.toArray(new IntVar[bests.size()]));
                currentIndex = bestsMap.get(next);
            }
            return computeDecision(next);
        }

        @Override
        public Decision<IntVar> computeDecision(IntVar variable) {
            if (variable == null || variable.isInstantiated()) {
                return null;
            }
            int currentVal;
            if(prios[currentIndex] > 0){
                currentVal = valueSelectorUB.selectValue(variable);
            } else {
                currentVal = valueSelectorLB.selectValue(variable);         
            }
            System.out.println("Idx " + currentIndex);
            IntDecision current = decisionPool.getE();
            if (current == null) {
                current = new IntDecision(decisionPool);
            }
            current.set(variable, currentVal, DecisionOperator.int_eq);
            return current;
        }

    }
Community
  • 1
  • 1
Dora
  • 47
  • 1
  • 8
  • May be do it in two phases. First fix all preassigned assignments and see if you can solve for the remaining part (this should be fast). If this fails unfix, and use your penalty method. – Erwin Kalvelagen Jun 29 '16 at 12:17
  • I will definetely try this, but this will give me pretty bad performance if not all preassignments can be obeyed. I would rather have the solver always start with all preassignments. – Dora Jul 01 '16 at 14:32
  • If you are worried about performance I would probably look into a LP/MIP solver which are usually very fast for these kind of problems. – Erwin Kalvelagen Jul 02 '16 at 10:42

1 Answers1

0

Why don't you change the search strategy of the solver so that it starts with preassigned variables? It is described in the documentation.

  • Do you mean it is described how to have the search strategy start with preassigned variables or just how to define a custom search strategy? Because I could not find anything about preassignments. I am currently trying to write my own strategy, but in the documentation there is only an example for a variableSelector, not for a whole strategy. Because I would use an array to save which variables should be preassigned first and to find the correct order, I don't think it is enough to define custom variable and value selectors, is it? – Dora Jul 01 '16 at 15:34
  • You can implement AbstractStrategy (see source code) or use selectors (use a map or the var name to retrieve the index). or you can simply apply inputOrderUB to the reification variables (before branching on decision vars). That will set the boolvar to 1 (UB) so it will apply the preassignment. You can also branch on the penalty variable (LB first this time as you want to minimize it). – Jean-Guillaume Fages Jul 02 '16 at 16:25
  • I tried implementing the AbstractStrategy, but I'm not sure if I did it correctly (see edit of question). – Dora Jul 07 '16 at 09:13
  • Is it sensible to check for isInstantiated() in getDecision? Or will it mess with the propagation? But otherwise, how can I select variables in the order of there static priority? If I don't check if they are instantiated I will always get the variable with the highest priority, right? – Dora Jul 12 '16 at 10:53
  • You can call var.isInstantiated() whenever you want, and you definitely need to call it in the search strategy. It will not mess with propagation. – Jean-Guillaume Fages Jul 21 '16 at 08:17