@Override public InsertionData getInsertionData( final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) { double fixcost_contribution = getFixCostContribution(currentRoute, jobToInsert, newVehicle); if (fixcost_contribution > bestKnownPrice) { return InsertionData.createEmptyInsertionData(); } InsertionData iData = standardServiceInsertion.getInsertionData( currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice); if (iData instanceof NoInsertionFound) { return iData; } double totalInsertionCost = iData.getInsertionCost() + fixcost_contribution; InsertionData insertionData = new InsertionData( totalInsertionCost, iData.getPickupInsertionIndex(), iData.getDeliveryInsertionIndex(), newVehicle, newDriver); insertionData.setVehicleDepartureTime(newVehicleDepartureTime); insertionData.getEvents().addAll(iData.getEvents()); return insertionData; }
static ScoredJob getScoredJob( Collection<VehicleRoute> routes, Job unassignedJob, JobInsertionCostsCalculator insertionCostsCalculator, ScoringFunction scoringFunction) { InsertionData best = null; InsertionData secondBest = null; VehicleRoute bestRoute = null; double benchmark = Double.MAX_VALUE; for (VehicleRoute route : routes) { if (secondBest != null) { benchmark = secondBest.getInsertionCost(); } InsertionData iData = insertionCostsCalculator.getInsertionData( route, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark); if (iData instanceof InsertionData.NoInsertionFound) continue; if (best == null) { best = iData; bestRoute = route; } else if (iData.getInsertionCost() < best.getInsertionCost()) { secondBest = best; best = iData; bestRoute = route; } else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) { secondBest = iData; } } VehicleRoute emptyRoute = VehicleRoute.emptyRoute(); InsertionData iData = insertionCostsCalculator.getInsertionData( emptyRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark); if (!(iData instanceof InsertionData.NoInsertionFound)) { if (best == null) { best = iData; bestRoute = emptyRoute; } else if (iData.getInsertionCost() < best.getInsertionCost()) { secondBest = best; best = iData; bestRoute = emptyRoute; } else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) { secondBest = iData; } } if (best == null) { return new RegretInsertion.BadJob(unassignedJob); } double score = score(unassignedJob, best, secondBest, scoringFunction); ScoredJob scoredJob; if (bestRoute == emptyRoute) { scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, true); } else scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false); return scoredJob; }
/** * Runs insertion. * * <p> * * <p>Before inserting a job, all unassigned jobs are scored according to its best- and * secondBest-insertion plus additional scoring variables. * * @throws java.lang.RuntimeException if smth went wrong with thread execution */ @Override public Collection<Job> insertUnassignedJobs( Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) { List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size()); Iterator<Job> jobIterator = unassignedJobs.iterator(); while (jobIterator.hasNext()) { Job job = jobIterator.next(); if (job instanceof Break) { VehicleRoute route = InsertionDataUpdater.findRoute(routes, job); if (route == null) { badJobs.add(job); } else { InsertionData iData = insertionCostsCalculator.getInsertionData( route, job, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE); if (iData instanceof InsertionData.NoInsertionFound) { badJobs.add(job); } else { insertJob(job, iData, route); } } jobIterator.remove(); } } List<Job> jobs = new ArrayList<Job>(unassignedJobs); TreeSet<VersionedInsertionData>[] priorityQueues = new TreeSet[vrp.getJobs().values().size() + 2]; VehicleRoute lastModified = null; boolean firstRun = true; int updateRound = 0; Map<VehicleRoute, Integer> updates = new HashMap<VehicleRoute, Integer>(); while (!jobs.isEmpty()) { List<Job> unassignedJobList = new ArrayList<Job>(jobs); List<Job> badJobList = new ArrayList<Job>(); if (!firstRun && lastModified == null) throw new IllegalStateException("ho. this must not be."); if (firstRun) { firstRun = false; updateInsertionData(priorityQueues, routes, unassignedJobList, updateRound); for (VehicleRoute r : routes) updates.put(r, updateRound); } else { updateInsertionData( priorityQueues, Arrays.asList(lastModified), unassignedJobList, updateRound); updates.put(lastModified, updateRound); } updateRound++; ScoredJob bestScoredJob = InsertionDataUpdater.getBest( switchAllowed, initialVehicleIds, fleetManager, insertionCostsCalculator, scoringFunction, priorityQueues, updates, unassignedJobList, badJobList); if (bestScoredJob != null) { if (bestScoredJob.isNewRoute()) { routes.add(bestScoredJob.getRoute()); } insertJob( bestScoredJob.getJob(), bestScoredJob.getInsertionData(), bestScoredJob.getRoute()); jobs.remove(bestScoredJob.getJob()); lastModified = bestScoredJob.getRoute(); } else lastModified = null; for (Job bad : badJobList) { jobs.remove(bad); badJobs.add(bad); } } return badJobs; }