【问题标题】:Solving an assignment with many preassignments解决具有许多预分配的任务
【发布时间】:2016-06-28 16:24:04
【问题描述】:

我要解决的问题包括大约 800 个任务,这些任务必须分配给大约 120 名工人。工人必须有资格完成这项任务,并且每周只有一定数量的可用小时数。大约 80% 的作业已经预先分配。这意味着它们应该被保留,但如果其他 20% 无法解决,则可能违反预分配。
我已经有一个使用 Choco 求解器的模型,如果违反了预分配,它会使用惩罚,并且目标是最小化惩罚。然而,我认为这不是很有效,因为求解器不会通过分配预先分配的变量来启动搜索策略。我已经在这里(How to define propagation starting point in Choco 3.3)专门针对 Choco 提出了这个问题。

但是是否有其他求解器可以更轻松地完成此操作?最好写我自己的求解器吗? 如有任何建议,我将不胜感激。

编辑: 我曾尝试编写自己的 Choco 策略。对于一个小问题它可以正常工作,但对于大问题它没有找到解决方案。我不确定是否允许我在 getDecision 中所做的一切(例如检查 isInstantiated),并且我找不到任何有关如何编写扩展 AbstractStrategy 的策略的文档或教程。我会很感激任何关于可能是什么问题的指示。 (prios矩阵中的绝对优先级越高,越早分配变量。如果优先级为负,则分配0,如果为正,则分配1。最高优先级为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;
        }

    }

【问题讨论】:

  • 可能分两个阶段进行。首先修复所有预先分配的任务,看看你是否可以解决剩下的部分(这应该很快)。如果失败,请取消修复,并使用您的惩罚方法。
  • 我一定会试试这个,但如果不是所有的预先分配都可以遵守,这会给我带来非常糟糕的表现。我宁愿让求解器始终从所有预分配开始。
  • 如果您担心性能问题,我可能会考虑使用 LP/MIP 求解器,该求解器通常可以非常快速地解决此类问题。

标签: modeling solver constraint-programming choco


【解决方案1】:

为什么不改变求解器的搜索策略,让它从预先分配的变量开始呢?文档中对此进行了描述。

【讨论】:

  • 您的意思是描述了如何让搜索策略从预先分配的变量开始,或者只是如何定义自定义搜索策略?因为我找不到任何关于预分配的信息。我目前正在尝试编写自己的策略,但在文档中只有一个变量选择器的示例,而不是整个策略的示例。因为我会使用一个数组来保存应该首先预分配哪些变量并找到正确的顺序,所以我认为定义自定义变量和值选择器是不够的,是吗?
  • 您可以实现 AbstractStrategy(参见源代码)或使用选择器(使用映射或 var 名称来检索索引)。或者您可以简单地将 inputOrderUB 应用于具体化变量(在决策变量分支之前)。这会将布尔变量设置为 1 (UB),因此它将应用预分配。您还可以在惩罚变量上进行分支(这次首先是 LB,因为您想将其最小化)。
  • 我尝试实现 AbstractStrategy,但我不确定我是否正确(参见问题编辑)。
  • 在 getDecision 中检查 isInstantiated() 是否明智?还是会干扰传播?但除此之外,我怎样才能按静态优先级的顺序选择变量?如果我不检查它们是否被实例化,我总是会得到具有最高优先级的变量,对吧?
  • 你可以随时调用var.isInstantiated(),而且你肯定需要在搜索策略中调用它。它不会干扰传播。
猜你喜欢
  • 1970-01-01
  • 2023-03-28
  • 2010-11-02
  • 1970-01-01
  • 2012-02-09
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 2014-09-09
相关资源
最近更新 更多