简体   繁体   English

如何检查假定的解决方案会违反哪些约束?

[英]how to check which constraints would be violated by a presumed solution?

In some cases the solver fails to find a solution for my model, which I think is there.在某些情况下,求解器无法为我的 model 找到解决方案,我认为它就在那里。 So I would like to populate a solution, and then check which constraint is violated.所以我想填充一个解决方案,然后检查违反了哪个约束。 How to do that with choco-solver?如何用 choco-solver 做到这一点?

Using choco-solver 4.10.6.使用 choco-solver 4.10.6。

Forcing a solution强行解决

I ended up adding constraints to force variables to values of my presumed solution: eg我最终添加了约束以强制变量为我假定的解决方案的值:例如

    // constraints to force given solution 
    vehicle2FirstStop[0].eq(model.intVar(4)).post();
    vehicle2FirstStop[1].eq(model.intVar(3)).post();
    nextStop[1].eq(model.intVar(0)).post();
    nextStop[2].eq(model.intVar(1)).post();
    ...

and then接着

 model.getSolver().showContradiction();
 if (model.getSolver().solve()) { ....

Shows the first contradiction of the presumed solution, eg显示假定解决方案的第一个矛盾,例如

/!\ CONTRADICTION (PropXplusYeqZ(sum_exp_49, mul_exp_51, ...

So the next step is to find out where terms such as sum_exp_49 come from.所以下一步是找出诸如sum_exp_49 之类的术语是从哪里来的。

Matching the contradiction terms with the code将矛盾项与代码匹配

Here is a simple fix for constraints which will hopefully provide enough information.这是一个简单的约束修复,希望能提供足够的信息。 We can override the post() and associates() methods of model, so that it dumps the java source filename and line number when a constraint is posted/variable is created.我们可以覆盖 model 的 post() 和 associates() 方法,以便在发布/创建约束时转储 java 源文件名和行号。

   Model model = new Model("Vrp1RpV") {
    /**
     * retrieve the filename and line number of first caller outside of choco-solver from stacktrace
     */
    String getSource() {
        String source = null;
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();            
        // starts from 3: thread.getStackTrace() + this.getSource() + caller (post() or associates())
        for (int i = 3; i < stackTraceElements.length; i++) {                
                // keep rewinding until we get out of choco-solver packages
                if (!stackTraceElements[i].getClassName().toString().startsWith("org.chocosolver")) {
                    source = stackTraceElements[i].getFileName() + ":" + stackTraceElements[i].getLineNumber();
                    break;
                }                
        }
        return source;
    }
    @Override
    public void post(Constraint... cs) throws SolverException {
        String source=getSource();
        // dump each constraint along source location
        for (Constraint c : cs) {
            System.err.println(source + " post: " + c);
        }
        super.post(cs);
    }
    
    @Override
    public void associates(Variable variable) {
        System.err.println(getSource() + " associates: " + variable.getName());
        super.associates(variable);
    }
};

This will dump things like:这将转储以下内容:

Vrp1RpV2.java:182 post: ARITHM ([prop(EQ_exp_47.EQ.mul_exp_48)])
Vrp1RpV2.java:182 associates: sum_exp_49
Vrp1RpV2.java:182 post: ARITHM ([prop(mul_exp_48.EQ.sum_exp_49)])
Vrp1RpV2.java:182 associates: EQ_exp_50
Vrp1RpV2.java:182 post: BASIC_REIF ([(stop2vehicle[2] = 1) <=> EQ_exp_50])
...

From there it is possible to see where sum_exp_49 comes from.从那里可以看到sum_exp_49的来源。

EDIT: added associates() thanks to @cprudhom suggestion on https://gitter.im/chocoteam/choco-solver编辑:添加 associates() 感谢@cprudhom 对 https 的建议://gitter.im/chocoteam/choco-solver

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM