An example of the case is:
I have 50 service shipment, 4 delivery in the same point and in the same time window, and 3 pickup in the same point in the same time window ,establishing a list of 3 services that deliver with 3services that pickup (one to one) to asignt in the same Route (both) and if only one service is used and not the one related, the two are not assigned.
My code is:
the VAR serviciosimul is a hashmap with: KEY: id from first shipment, and Value is id from second shipment
vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
StateManager stateManager = new StateManager(vrp);
stateManager.updateLoadStates();
stateManager.updateTimeWindowStates();
stateManager.updateSkillStates();
stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
stateManager.addStateUpdater(new UpdateFutureWaitingTimes(stateManager, vrp.getTransportCosts()));
stateManager.addStateUpdater(new JobsInRouteMemorizer(stateManager, serviciosimul)); // modificado para optimizar memoria
ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager);
constraintManager.addTimeWindowConstraint();
constraintManager.addLoadConstraint();
constraintManager.addConstraint(new TramosSimultaneosConstraint(stateManager, serviciosimul), ConstraintManager.Priority.CRITICAL);
constraintManager.addConstraint(new PuntosConsecutivosConstraint(stateManager, serviciopunto));
final RewardAndPenaltiesThroughSoftConstraints softConstraintContributionToOverallObjective = new RewardAndPenaltiesThroughSoftConstraints(vrp, serviciosimul, stateManager);
VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp).setStateAndConstraintManager(stateManager, constraintManager)
.setProperty(Jsprit.Parameter.THREADS, nhilos) //5
// .setProperty(Jsprit.Parameter.FAST_REGRET, "true")
.setProperty(Jsprit.Parameter.FIXED_COST_PARAM, "1.5")
.setProperty(Jsprit.Strategy.CLUSTER_REGRET, "0.3")
.setProperty(Jsprit.Strategy.CLUSTER_BEST, factor_agrupamiento) //"0.9")
// .setProperty(Jsprit.Strategy.WORST_BEST, "0.5").setProperty(Jsprit.Strategy.RANDOM_BEST, "0.5")
.setProperty(Jsprit.Parameter.VEHICLE_SWITCH, "false")
.setProperty(Jsprit.Parameter.THRESHOLD_ALPHA, "0.0")
.setProperty(Jsprit.Parameter.MAX_TRANSPORT_COSTS, Double.toString(1.0E8))
.setObjectiveFunction(new SolutionCostCalculator() {
@Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.;
for (VehicleRoute route : solution.getRoutes()) {
costs += route.getVehicle().getType().getVehicleCostParams().fix;
TourActivity prevAct = route.getStart();
String puntoAnt = route.getStart().getLocation().getId();
for (TourActivity act : route.getActivities()) {
costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), act.getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle());
costs += vrp.getActivityCosts().getActivityCost(act, act.getArrTime(), route.getDriver(), route.getVehicle());
// String puntoAct = act.getLocation().getName();
String puntoAct = serviciopunto.get(act.getLocation().getId());
if (!puntoAnt.equalsIgnoreCase(puntoAct) && vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), act.getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle()) < 3) { // calculo el costo si no son iguales y la distancia es mnenos de 2 metros
costs += 100000; // costo por el ingreso la primera vez al punto
}
// if ((act.getTheoreticalEarliestOperationStartTime() - act.getArrTime()) > 0.8) {
// costs += 100000 * Math.floor(act.getTheoreticalEarliestOperationStartTime() - act.getArrTime());
// }
prevAct = act;
puntoAnt = puntoAct;
}
costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), route.getEnd().getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle());
costs += softConstraintContributionToOverallObjective.getCosts(route);
if (route.getTourActivities().getActivities().size() < 9) {
costs += 100000;
}
}
costs += solution.getUnassignedJobs().size() * costo_servicio_no_asignado;
return costs;
}
})
.buildAlgorithm();
...............
..........
static class RewardAndPenaltiesThroughSoftConstraints {
private VehicleRoutingProblem vrp;
Map<String, String> serviciocomp = new HashMap<String, String>();
private StateManager stateManager;
public RewardAndPenaltiesThroughSoftConstraints(VehicleRoutingProblem vrp, Map<String, String> serviciocompb, StateManager stateManager) {
super();
this.vrp = vrp;
this.serviciocomp = serviciocompb;
this.stateManager = stateManager;
}
public double getCosts(VehicleRoute route) {
int costo = 0;
TourActivity lastAct = route.getStart();
for (TourActivity act : route.getActivities()) {
String servicio1 = act.getLocation().getId();
String servicio2 = serviciocomp.get(servicio1);
if (servicio2 != null) {
VehicleRoute route0 = stateManager.getProblemState(stateManager.createStateId(servicio2), VehicleRoute.class);
if (route0 == null) {
costo += 100000000;
continue;
}
if (route0 != route) {
costo += 100000000;
continue;
}
if (act instanceof JobActivity && lastAct instanceof JobActivity) {
if (((JobActivity) act).getJob().getId().equals(servicio1)) {
if (((JobActivity) lastAct).getJob().getId().equals(servicio2)) {
costo += 0;
} else {
costo += 100000000;
continue;
}
}
}
}
lastAct = act;
}
return costo;
}
private Job getJob(String string) {
return vrp.getJobs().get(string);
}
}
static class TramosSimultaneosConstraint implements HardActivityConstraint {
private StateManager stateManager;
Map<String, String> servicioasoc = new HashMap<String, String>();
public TramosSimultaneosConstraint(StateManager stateManager, Map<String, String> serviciocompb) {
super();
this.stateManager = stateManager;
this.servicioasoc = serviciocompb;
}
@Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
String servicio1 = newAct.getLocation().getId();
String servicio2 = servicioasoc.get(servicio1);
if (servicio2 != null) {
if (prevAct instanceof JobActivity && newAct instanceof JobActivity) {
if (((JobActivity) prevAct).getJob().getId().equals(servicio1) && ((JobActivity) newAct).getJob().getId().equals(servicio2)) {
return ConstraintsStatus.FULFILLED;
}
if (((JobActivity) newAct).getJob().getId().equals(servicio2)) {
return ConstraintsStatus.NOT_FULFILLED_BREAK;
}
}
if (newAct instanceof JobActivity && nextAct instanceof JobActivity) {
if (((JobActivity) newAct).getJob().getId().equals(servicio2) && ((JobActivity) nextAct).getJob().getId().equals(servicio1)) {
return ConstraintsStatus.FULFILLED;
}
if (((JobActivity) nextAct).getJob().getId().equals(servicio1)) {
return ConstraintsStatus.NOT_FULFILLED_BREAK;
}
}
}
return ConstraintsStatus.FULFILLED;
}
}