GraphHopper.com | Forum | GitHub | Maps | Blog

Problem with state manager


#1

Hi Folks

I am writing a Soft Constraint to implement a minimum load rule.

The jobs look something like

P1, P2, P3, D1, D2, D3, P4, D4 etc.
The constraint looks at the load level at the end of each pickup sequence to check that the load is not under the minimum. So it looks like this.

Start
P1
P2
P3
D1 <=== check to see if the sum of the loads of P1,P2,P3 was too small.
D2
D3
P4
D4 <=== check to see if the load of P4 was too small
End
My code is below.

The thing is it does not work and what I found is that the call to: Capacity prevLoad = stateManager.getActivityState(prevAct, InternalStates.LOAD, Capacity.class ); always returns null.

I can’t work out why as yet.

input is appreciated.

regards
Grant

public class SC_MinimumLoad implements SoftActivityConstraint {
private final StateManager stateManager;

public SC_MinimumLoad(StateManager stateManager) {
	this.stateManager = stateManager;
	Utils.LOGGER.log(Level.INFO, "Initialising Soft Route Constraint for minimum load   with DONT_LIKE="+Constants.MINIMUM_LOAD_VIOLATION);
}


@Override
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
	if(!((TourActivity)newAct instanceof PickupShipment) && ((TourActivity)prevAct instanceof PickupShipment)){
		int[] vehicleData =(int[]) iFacts.getNewVehicle().getUserData();
		int minimumLoad = 0;
		if(vehicleData == null){
			Utils.LOGGER.log(Level.INFO, "UserData was null: " +iFacts.getNewVehicle().getId());
		} else 
			minimumLoad = vehicleData[Constants.VEHICLE_MINIMUM_LOAD];
		if(getLoadAtAct(prevAct) != -1 && getLoadAtAct(prevAct) < minimumLoad){
			return Constants.REJECT;
		}
	} 
	return Constants.MINIMUM_LOAD_OK;
}
private int getLoadAtAct(TourActivity act){
	Capacity load = stateManager.getActivityState(act, InternalStates.LOAD, Capacity.class );
	if(load != null){
		return (load.get(VehicleTypes.CONSTRAINT_CAPACITY));
	} else {
		Utils.LOGGER.log(Level.INFO, "Activity load was null: " + act.getClass().getName());
		return -1;
	}
}

}


#2

Hi Grant,

Your constraint applies when newAct is a DeliverShipment. The first position at which a DeliverShipment is evaluated is right after its corresponding PickupShipment, that is, when you check the constraint for D1, the first position you evaluate is right after P1.

Now, P1-D1 is the shipment you are evaluating, so it is not in any route when you update the states, which means that your state updater could never have an activity state for P1 or D1. Thus, when you try to get the load at activity P1, it will always return null.

Also bear in mind that, when you get the load at downstream activities in the route, you will need to add the load of P1, because it is not considered when the state is updated.

Best regards,
He


#3

Thankyou He. Your comments around the job not being in the route at the time of evaluation and also zero length routes was very helpful.

Unfortunately I am getting deeper and deeper in to the mire with how to achieve this minimum load. As the topic is now not specifically state manager I’ll open a new topic.

Again - thanks.

regards
Grant