我要解决的问题包括大约800 个任务,这些任务必须分配给大约120 个工人。工人必须有资格完成这项任务,并且每周只有一定数量的可用小时数。大约 80% 的作业已经预先分配。这意味着它们应该被保留,但如果其他 20% 无法解决,则可能违反预分配。
我已经有一个使用 Choco 求解器的模型,如果违反了预分配,它会使用惩罚,并且目标是最小化惩罚。然而,我认为这不是很有效,因为求解器不会通过分配预先分配的变量来启动搜索策略。我已经在这里专门针对 Choco 提出了这个问题(如何在 Choco 3.3 中定义传播起点)。
但是是否有另一个求解器可以更轻松地完成此操作?最好写我自己的求解器吗?我将不胜感激任何建议。
编辑:我尝试编写自己的 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;
}
}