I have 4 jobs and all jobs must be done in same route. I cant use soft activity as I am not sure how much penalty/rewards will be useful for that.
I have used below objective function:
stateManager.addStateUpdater(new UpdateJobRouteAssignment(stateManager)); HardActivityConstraint sameRouteServicesConstraint = new HardActivityConstraint() {
@Override public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
Collection<Job> jobs = iFacts.getRoute().getTourActivities().getJobs(); List<String> jobNames = new ArrayList<String>(); for (Job j : jobs){ jobNames.add(j.getId()); } if(newAct instanceof TourActivity.JobActivity) { jobNames.add(((TourActivity.JobActivity) newAct).getJob().getId()); } if(nextAct instanceof TourActivity.JobActivity) { jobNames.add(((TourActivity.JobActivity) nextAct).getJob().getId()); } if(prevAct instanceof TourActivity.JobActivity) { jobNames.add(((TourActivity.JobActivity) prevAct).getJob().getId()); }
Set set = new HashSet(jobNames); jobNames = new ArrayList(set);
if(jobNames.size() > 1) { if (jobNames.containsAll(inSameRoute)) { return ConstraintsStatus.FULFILLED; } else { boolean isDisjoint = Collections.disjoint(jobNames,inSameRoute); if(isDisjoint){ return ConstraintsStatus.FULFILLED; } else { List<String> common = new ArrayList<String>(jobNames); common.retainAll(inSameRoute); if(common.size() == inSameRoute.size()){ return ConstraintsStatus.FULFILLED; } else { return ConstraintsStatus.NOT_FULFILLED; } } } } else { return ConstraintsStatus.FULFILLED; } } }; constraintManager.addConstraint(sameRouteServicesConstraint, ConstraintManager.Priority.HIGH); }
I have used memorizer here:
static class UpdateJobRouteAssignment implements StateUpdater,JobInsertedListener,InsertionStartsListener {
StateManager stateManager;
UpdateJobRouteAssignment(StateManager stateManager) { this.stateManager = stateManager; }
@Override public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { stateManager.putProblemState(stateManager.createStateId(job2insert.getId()), VehicleRoute.class, inRoute); }
@Override public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) { for(VehicleRoute r : vehicleRoutes){ for(Job j : r.getTourActivities().getJobs()){ informJobInserted(j,r,0.,0.); } } } }
The problem I am facing is:
It gives 4 different routes for the 4 jobs in same route.