2016-03-29 5 views
0

Этот вопрос связан с этой темой: Related jobs in JSpritСвязанные работы в JSprit, одна перед другой случай: IllegalArgumentException

Я пытаюсь использовать «один перед другим» ограничения, но я буду испытывать Java. lang.IllegalArgumentException: arg не должно быть null. Похоже, что Cap cap2 имеет значение null при расчете Capacity max. Я не понимаю, почему.

:(

У вас есть идеи по этому поводу?

Для записи, я на 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() {} 

} 
+0

Привет @ Седрик Алексис, ваша проблема решена? Возможно, я столкнулся с той же проблемой. Спасибо. –

ответ

0

Короткий ответ: вы не можете создавать экземпляры StateId на лету. Все экземпляры StateId должны быть сгенерированы до. Алгоритм запускается. См. Более длинный ответ, почему для этого все еще не очень хорошая идея, и вы шо uld рассматривает редизайн.

Анализ: Я столкнулся с той же проблемой, и проследить его обратно к тому, как экземпляры StateId созданы в StateManager:

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 StateIds, несколько уже используемых самим JSprit). Как вы можете видеть, старые элементы не копируются, поэтому здесь происходит условие гонки между UpdateLoads, которое устанавливает состояние, используемое как cap2, ваш код, который генерирует новый StateId и перезаписывает текущее состояние и UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute, который читает состояние (которое больше не существует).

Учитывая, что этот код только расширяет массивы на один, это очень неэффективно, чтобы иметь много StateIds, так как для каждого нового StateId все массивы должны быть воссозданы. Для смягчения этого я использовал только один StateId в моем коде и хранится в нем Map<String, VehicleRoute>:

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

Таким образом, вы не бежите из экземпляров StateId и все еще может сохранить отношения между неограниченным количеством рабочих мест.