0

この質問は、このトピックに関連しています: JSprit の関連ジョブ

「one before another」制約を使用しようとしていますが、java.lang.IllegalArgumentException: arg must not be null が発生しています。容量の最大値を計算すると、容量の上限 2 が null のように見えます。理由がよくわかりません。

:(

これについて何か考えはありますか?

記録のために、私は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 自体によって既に使用されています)。 )。ご覧のとおり、古い要素はコピーされていないため、ここで発生するのは、cap2 として使用される状態を設定する UpdateLoads、新しい StateId を生成して現在の状態を上書きするコード、および読み取る UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute 間の競合状態です。状態 (もう存在しません)。

このコードが配列を 1 つだけ拡張することを考えると、新しい StateId ごとにすべての配列を再作成する必要があるため、多くの StateId を持つことは非常に非効率的です。これを軽減するために、コードで StateId を 1 つだけ使用し、その中に a を格納しMap<String, VehicleRoute>ました。

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

このようにして、StateId インスタンスが不足することはなく、ジョブ間の関係を無制限に保存できます。

于 2016-08-23T07:15:35.420 に答える