0

这个问题与这个主题有关:JSprit 中的相关工作

我正在尝试使用“一个在另一个之前”约束,但我遇到了java.lang.IllegalArgumentException: arg must not be null。在计算最大容量时,容量 cap2 似乎为空。我真的不明白为什么。

:(

你对此有什么想法吗?

作为记录,我使用的是1.6.2 版本。TY 为您提供帮助。

        String before = "2";
        String after = "11";

        final StateManager stateManager = new StateManager(problem);
        stateManager.addStateUpdater(new JobsInRouteMemorizer(stateManager));



        ConstraintManager constraintManager = new ConstraintManager(problem, stateManager);
        constraintManager.addConstraint(new OneJobBeforeAnother(stateManager, before, after));

        final RewardAndPenaltiesThroughSoftConstraints contrib = new RewardAndPenaltiesThroughSoftConstraints(problem, before, after);
        SolutionCostCalculator costCalculator = new SolutionCostCalculator() {

            @Override
            public double getCosts(VehicleRoutingProblemSolution solution) {
                double costs = 0.;
                List<VehicleRoute> routes = (List<VehicleRoute>) solution.getRoutes();
                for(VehicleRoute route : routes){
                    costs+=route.getVehicle().getType().getVehicleCostParams().fix;
                    costs+=stateManager.getRouteState(route, InternalStates.COSTS, Double.class);
                    costs+=contrib.getCosts(route);
                }
                return costs;
            }

        };
        VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(problem,
                "algorithmConfig.xml");
        vraBuilder.addCoreConstraints();
        vraBuilder.setStateAndConstraintManager(stateManager, constraintManager);
        vraBuilder.addDefaultCostCalculators();
        vraBuilder.setObjectiveFunction(costCalculator);
        algorithm = vraBuilder.build();



public class JobsInRouteMemorizer implements StateUpdater, ActivityVisitor {
private StateManager stateManager;
private VehicleRoute route;



public JobsInRouteMemorizer(StateManager stateManager) {
    super();
    this.stateManager = stateManager;
}

@Override
public void begin(VehicleRoute route) {
    this.route=route;
}

@Override
public void visit(TourActivity activity) {
    if(activity instanceof JobActivity){
        String jobId = ((JobActivity) activity).getJob().getId();
        StateId stateId = stateManager.createStateId(jobId);
        System.out.println(stateId.getIndex());
        System.out.println(stateId.toString());
        stateManager.putProblemState(stateId, VehicleRoute.class, this.route);
    }

}

@Override
public void finish() {}

}
4

1 回答 1

0

简短回答:您不能动态创建 StateId 实例。所有 StateId 实例都必须在算法运行之前生成。查看更长的答案,了解为什么这样做仍然不是一个好主意,您应该考虑重新设计。

分析:我也遇到了同样的问题,追溯到StateManager中创建StateId实例的方式:

public StateId createStateId(String name) {
    if (createdStateIds.containsKey(name)) return createdStateIds.get(name);
    if (stateIndexCounter >= activityStates[0].length) {
        activityStates = new Object[vrp.getNuActivities() + 1][stateIndexCounter + 1];
        vehicleDependentActivityStates = new Object[nuActivities][nuVehicleTypeKeys][stateIndexCounter + 1];
        routeStatesArr = new Object[vrp.getNuActivities()+1][stateIndexCounter+1];
        vehicleDependentRouteStatesArr = new Object[nuActivities][nuVehicleTypeKeys][stateIndexCounter+1];
        problemStates = new Object[stateIndexCounter+1];
    }
    StateId id = StateFactory.createId(name, stateIndexCounter);
    incStateIndexCounter();
    createdStateIds.put(name, id);
    return id;
}

每次你创建一个新的 StateId 并且没有更多的空间可用于状态时,旧的状态数组会被更长的版本覆盖,以便为你的新状态腾出空间(一开始有 30 个 StateId 的空间,JSprit 本身已经使用了一些空间)。如您所见,旧元素没有被复制,所以这里发生的是 UpdateLoads 之间的竞争条件,它将状态设置为 cap2,您的代码生成一个新的 StateId 并覆盖当前状态,而 UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute 读取状态(不再存在)。

鉴于此代码仅将数组扩展一,因此拥有多个 StateId 的效率非常低,因为对于每个新的 StateId,所有数组都必须重新创建。为了缓解这种情况,我在代码中只使用了一个 StateId 并在其中存储了一个Map<String, VehicleRoute>

Map<String, VehicleRoute> routeMapping = Optional.ofNullable(stateManager.getProblemState(stateId, Map.class)).orElse(new ConcurrentHashMap<>())

这样您就不会用完 StateId 实例,并且仍然可以存储无限数量的作业之间的关系。

于 2016-08-23T07:15:35.420 回答