2016-03-29 14 views
0

Diese Frage zu diesem Thema ist: Related jobs in JSpritähnliche Jobs in JSprit, Eine vor einem anderen Fall: Illegal

Ich versuche, die „ein, bevor eine andere“ Einschränkung zu verwenden, aber ich bin ein java erleben. lang.IllegalArgumentException: arg darf nicht null sein. Es sieht so aus, als ob Capacity cap2 bei der Berechnung von Capacity max null ist. Ich verstehe nicht wirklich warum.

:(

Haben Sie eine Idee zu diesem?

Für das Protokoll, ich bin auf der 1.6.2 Version. TY für Ihre Hilfe.

 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

Hallo @ Cédric Alexis, wurde Ihr Problem gelöst? Ich könnte auf dasselbe Problem gestoßen sein. Danke. –

Antwort

0

Kurze Antwort: Sie können keine StateId-Instanzen im laufenden Betrieb erstellen.Alle StateId-Instanzen müssen generiert werden, bevor der Algorithmus ausgeführt wird.Siehe längere Antwort, warum dies noch keine gute Idee ist und Sie sho A lle über ein Redesign nachdenken.

Analyse: Ich lief in das gleiche Problem und verfolgen sie zurück auf die Art und Weise StateID Instanzen in State erstellt:

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; 
} 

Jedes Mal, wenn Sie eine neue StateID erstellen und es ist kein Platz mehr für die Staaten zur Verfügung des Alte State-Arrays werden mit einer längeren Version überschrieben, um Platz für Ihren neuen Status zu schaffen (zu Beginn gibt es Platz für 30 StateIds, einige davon bereits von JSprit selbst verwendet). Wie Sie sehen können, werden die alten Elemente nicht kopiert. Es handelt sich also um eine Race-Bedingung zwischen UpdateLoads, die den Status cap2 setzt, Ihrem Code, der eine neue StateId generiert und den aktuellen Status überschreibt und UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute, die liest der Staat (der nicht mehr existiert).

Da dieser Code nur die Arrays um eins erweitert, ist es sehr ineffizient viele StateIds zu haben, da für jede neue StateId alle Arrays neu erstellt werden müssen. Zur Milderung dieses ich nur eine StateID in meinem Code verwendet und ein Map<String, VehicleRoute> darin gespeichert:

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

Auf diese Weise können nicht aus StateID Instanzen laufen und können noch speichern Beziehungen zwischen einer unbegrenzten Anzahl von Arbeitsplätzen.