Java 使用HardActivityConstraint在Jsprit中强制执行命令

Java 使用HardActivityConstraint在Jsprit中强制执行命令,java,jsprit,Java,Jsprit,在重新解决以前解决的问题的场景中(当然,使用一些新数据),通常不可能在车辆的第一次分配完成后重新分配。驱动程序已在路上,任何新的解决方案都必须考虑: 工作必须由他负责(不能分配给其他车辆) 在未来的解决方案中,首先分配给他的活动必须保持不变 为了简单起见,我使用了一个单一的车辆场景,并且只尝试使用第二个项目(即确保某个活动将是解决方案中的第一个) 我是这样定义约束的: new HardActivityConstraint() { @Override public Constr

在重新解决以前解决的问题的场景中(当然,使用一些新数据),通常不可能在车辆的第一次分配完成后重新分配。驱动程序已在路上,任何新的解决方案都必须考虑:

  • 工作必须由他负责(不能分配给其他车辆)
  • 在未来的解决方案中,首先分配给他的活动必须保持不变
为了简单起见,我使用了一个单一的车辆场景,并且只尝试使用第二个项目(即确保某个活动将是解决方案中的第一个)

我是这样定义约束的:

new HardActivityConstraint()
{
    @Override
    public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct,
                                       double prevActDepTime)
    {
        String locationId = newAct.getLocation().getId();

        //  we want to make sure that any solution will have "C1" as its first activity
        boolean activityShouldBeFirst = locationId.equals("C1");

        boolean attemptingToInsertFirst = (prevAct instanceof Start);

        if (activityShouldBeFirst && !attemptingToInsertFirst)
            return ConstraintsStatus.NOT_FULFILLED_BREAK;

        if (!activityShouldBeFirst && attemptingToInsertFirst)
            return ConstraintsStatus.NOT_FULFILLED;

        return ConstraintsStatus.FULFILLED;
    }
}
这就是我构建算法的方式:

VehicleRoutingAlgorithmBuilder vraBuilder;
vraBuilder = new VehicleRoutingAlgorithmBuilder(vrpProblem, "schrimpf.xml"); 
vraBuilder.addCoreConstraints();
vraBuilder.addDefaultCostCalculators();

StateManager stateManager = new StateManager(vrpProblem);
ConstraintManager constraintManager = new ConstraintManager(vrpProblem, stateManager);
constraintManager.addConstraint(new HardActivityConstraint() { ... }, Priority.HIGH);
vraBuilder.setStateAndConstraintManager(stateManager, constraintManager);

VehicleRoutingAlgorithm algorithm = vraBuilder.build();
结果并不好。我只得到分配了一个任务的解决方案(具有所需活动的任务)。在调试中,显然,作业插入迭代考虑了许多可行的选项,这些选项似乎完全解决了问题,但在最后,算法返回的最佳解决方案不包括其他作业。p> 更新:更令人惊讶的是,当我在超过5辆车的场景中使用约束时,它工作正常(最差的结果是1辆车)

如果需要,我很乐意附上更多信息

谢谢
Zach

首先,您可以使用初始路线来确保某些作业需要从一开始就分配给特定的车辆(请参阅)

其次,为了确保在开始和初始作业(位置)(例如示例中的“C1”)之间不会插入任何活动,您需要按照定义HardActConstraint的方式禁止它,只需修改它,使newAct永远不会在prevAct=start和nextAct=act(C1)之间


第三,关于您的更新,请记住,算法的本质是破坏部分解决方案(删除大量作业)并重新创建解决方案(插入未分配的作业)。目前,schrimpf算法破坏了相对于作业总数的大量作业,即,对于随机破产,无作业=0.5*totalNoJobs,对于径向破产,无作业=0.3*totalNoJobs。如果你的问题很小,那么被解雇的工作岗位可能还不够。这将随着下一版本而改变,在下一版本中,您可以使用一种开箱即用的算法来定义需要删除的作业的绝对最小值。目前,请修改algorithmConfig.xml中的共享。

谢谢您快速而详尽的回复,Stefan。但是,如果我错了,请纠正我,addInitialVehicleRoute()的工作方式似乎仅限于装运-如果我将装运的提货部分添加到初始VehicleRoute,我还需要包括交货部分,这违背了让algo找出将交付部分包括在未来路线中的最佳方式的目的。同样,关于你的第二点,建议修改约束,使newAct永远不会出现在Start和C1之间-事实上,我所做的更一般,不让非C1 newAct出现在Start之后(无论nextAct如何)。从逻辑上讲,这两种口味应该达到相同的效果,除了更一般的形式应该让我们更快到达那里。你为什么建议削弱约束?你是对的,你实施约束的方式比我建议的更聪明。