VRP: How to list all violated constraints for a given assignment? - or-tools

I have an assignment routes for a routing problem. It is a list of lists of stop nodes. routes[1][5] == 7 is true if node 8 is the 6th stop of the 2nd vehicle (note: counting from 0).
routes is the solution to a vehicle routing problem without time windows. When I enable the time windows constraint, the routing model informs me that
ROUTING_FAIL: No solution found to the problem.
Is there a way to set routes as the initial solution of the vehicle routing problem with time windows and output all constraints that are violated? I think this would be very helpful when debugging a model. I imagine output like
constraint time_dimension.CumulVar(4) <= time_dimension.CumulVar(2) is violated!

Related

OR-Tools: Difference between Path Cheapest Arc and Global Cheapest Arc

The OR-Tools documentation (https://developers.google.com/optimization/routing/routing_options) for the VRP routing options describes the two first solution strategies the following way:
PATH_CHEAPEST_ARC: Starting from a route "start" node, connect it to the node which produces the cheapest route segment, then extend the route by iterating on the last node added to the route.
GLOBAL_CHEAPEST_ARC: Iteratively connect two nodes which produce the cheapest route segment.
Can someone explain me what the difference between the two heuristics is? Unfortunately I haven't found any other information on the internet or the documentation.
The first one grows a route by extending it.
The second one connect the closest nodes together until it creates routes.

If requirements are used instead of constraints what is the effect on the optimization performance? - AnyLogic

In the Optimization Experiment
AnyLogic allows the use of the top-level agent root on the requirements expression and does not allow the use of the top-level agent root on the constraints.
Although they mention in the AnyLogic help that root can be used in the constraints expression, the help is wrong, root can not be used. Please check the answer to this question:
Error - can not use root. in the constraints expression - AnyLogic
So, in this case, to avoid the root error: use requirements or change your constraints, so they do not need access to root.
If I change my constraints, so they do not need access to root, I will need to reduce the number of parameters (decision variables) which I'm trying to avoid as much as possible till I discover that there is no way else.
However, I'm afraid that if I used the requirements instead of the constraints, this would reduce the optimization performance. As you know, the constraints reduce the search space (this is mentioned in the help, too), but they did not mention if the requirement does the same (although they mentioned that requirements help in guiding to the solution):
"A requirement can also be a restriction on a response that requires its value to fall within a specified range."
Does this mean that the requirement is exactly the same as the constraint (in terms of reducing the search space)?
According to the above-mentioned, if I used requirement instead of constraints (because it is not allowed to use root in the constraints expression), what is the effect on the performance?
so let's review the concepts here...
CONSTRAINTS
First, the constraints are evaluated before the simulation run, and this is only used to check if your parameters fulfill certain conditions:
param1 and param2 can be evaluated between 0 and 10
but the constrain can be that the sum of both has to be below 10
This is effectively to reduce the search space since there would be no point to run the model for param1=8 and param2=8 if this is not within the search space
Requirements
Requirements are evaluated AT THE END of the simulation, that's why you can use root, so you can evaluate not only the parameters, but any variable in the simulation...
For instance if a variable ends up being above 10 when the system only allows its maximum value to be 8, then the solution is not feasible.
This means that requirements and constraints are very different, but they both find unfeasible solutions...
Other options
so from the optimization experiment side you only have these 2 options: evaluate the parameters before you run the simulation, or anything in your model after the simulation is run
Of course there's another option you can use, which is to define the restrictions inside the simulation. If your model is supposed to run for 1 day, but after 1 hour, a variable in question ends up being over 10 (which is not allowed) you can just use finishSimulation() in order to end the simulation early, and your Requirements will evaluate this variable after only 1 hour reducing the time it took to run that simulation and defining the results as unfeasible.
Conclusion
Obviously if you use requirements instead of constraints, you will have to run more simulations that you want, so the speed in which the optimization will find a solution will be much lower, so you shouldn't do that and there's no reason to do that.
Of course i have no idea what you are trying to optimize, but this is how all this works, and even though the help documentation may show an error, it wouldn't make sense to use root in the constraints.

How to fix the 'Error in the model during iteration' in anylogic

I've built a model in which a fleet of trucks delivers multiple orders to different customers. This model works fine when I perform one simulation experiment. However, when I try to run a parameter variation, the following error occurs: 'Error in the model during iteration x'. A snapshot of that particular error can be found in 2.
A question about this topic is earlier asked here:
NullPointerException during Parameter Variation Experiment with agent statistics
I have tried the tips given in that post but none of them seems to solve the problem.
I have replaced all the conditional transitions with messages in my state chart (see figure).
My data sets are stored in the database, so that cannot be the problem.
I can't get my head around why the model works with some seed values and with some not. I understand that finding the modelling flaw from just the snapshot is hard, but any tips on how I could find the mistake could be helpful.
PS: I have the learning edition so there is no debugger
Edit:
The error happens at a specific line of code written in the transitions pointing towards the state from the state "movingToClient1". The line that seems to cause the error is:
Order order = orderStore.myOrdercollection.get(0);
the iterations seem to work. However, I need it to be equal to one (to specifically measure certain KPIs of the last route). Hopefully, this helps in finding a solution.
The most likely thing to cause the problem is that your arraylist called collectionOfOrders is missused.
so at some point on the "on enter" of one of your states, you do :
collectionOfOrders.get(something)
when collectionOfOrders is actually empty.
sometimeswhat happens is that multiple things happen at the same time in your model, and when you ask if collectionOfOrders==1, another of your truck agents does the same and they both return true, which means that one of them will get the issue.
This happens only with certain seeds, because it occurs with a very low probability.
This is my guess, with the current information provided
Due to the insight given by Felipe and Benjamin, I found the problem in my model. My model starts with an import order with a specific arrival rate of one in a source block. The rate of 1 is equivalent to exponentially distributed interarrival time with mean = 1/ratedefined (https://anylogic.help/library-reference-guides/process-modeling-library/source.html). This means that it is possible for some seed values that the orders are generated at the same time. Therefore, changing the setting from 'rate' to 'interarrival time' solved the problem.

Optaplanner: extending the vrp example to tackle multi trip case

At my company we are currently using optaplanner to solve a vehicle routing problem with great results, we built a web app to manage vehicles, clientes, locations, depots and to show a graphic representation of the solution (including showing the locations in a map). We wrapped the solver in a spring java app with a rest interface to receive request and solve the problem. We are using Google maps to get distance-time data. Now we need to implement multirip....
To tackle the multitrip part I am following this approach:
1.- I added readyTime, endOfTrip and dueTime members to Vehicle class
2.- I created a rule to prevent arrivals at customers after vehicle->dueTime
3.- I modified the ArrivalTimeUpdateListener to consider the vehicle->readyTime when calculating the departureTime from a vehicle (using Math.max(depot->readyTime, vehicle->readyTime)
4.- At this point I started using the vehicle class as if it were a vehicle trip instead of a vehicle (I still don´t change the name but that is the idea )
5.- I created a member nextVehicle in vehicle to represent the next trip
6.- For testing purposes I manually link two vehicles (or vehicle trips) before sending it to solver->solve
7.- In the ArrivalTimeUpdatingVariableListener class I extended the method that updates the arrival times to consider updating the nextVehicle->readyTime and by consequence the arrival times of the customers that belong to the next trip (and so on when there are more than two trips)
I am sure this is not the most elegant solution, but I tried other approaches (using custom shadow variable on Vehicle for instance) but it couldn´t make it work.
The problem I am facing right now is that I don´t get to understand the state of the model when ArrivalTimeUpdatingVariableListener is called, maybe someone faced similar problem and can help me. What i found (after try and error) is:
the customer.getVehice() method not always returns a value (distinct from null value), it seems to get updated some time after the previousStandstill change triggers the listener "updateArrivalTime" method.
In construction fase when a customer get assign to a vehicle the customer.getVehice() method returns null (it came from "not assigned")
In construction fase when a customer "is freed" the customer.getVehice() method returns the "previous vehicle"
In local search fase when a customer get assign to a vehicle the customer.getVehice() method returns the "previous vehicle" (original vehicle)
In local search fase when a customer go back to the original vehicle the customer.getVehice() method returns the "previous assign vehicle"
Any thoughts on this? Am I making right assumptions? (because originally I considered customer.getVehicle() as the "actual" vehicle and the solutions were completely wrong...)
The order of triggering the previousStandstill change it´s kind of difficult to understand (for me). I mean when moving customers or swapping them between vehicles...any thoughts or hints on were to find info?
Can I access some variables from the "previous state of the model" when the solver makes a move?, because I am thinking I will need that if I continue with this approach (to update the vehicle->endOfTrip that is the nextVehicle->readyTime when the customer is the last one on the chain for instance)
and finally...am i doing something completely wrong conceptually ?
Any comments will be greatly appreciated (and sorry my grammar, I am native spanish speaker)
The chaotic triggering of shadow vars that you describe should not happen any more in optaplanner 6.3.0.Final or higher because it now gives the guarantee shown below.
But older versions (optaplanner 6.2 and earlier) suffer from that chaotic trigger behaviour (as fixed by PLANNER-252 - yes I know that issue number by heart - and yes, I am not the only one) could drive a developer (who's working on a complex model with multiple shadow variable(s)) insane and provide a one way ticket to the asylum.
Fortunately it has been fixed a few months ago, so upgrade to 6.3.0.Final or later and keep your sanity.

Optaplanner: Generating a partial solution to VRP where trucks and/or stops may remain unassigned based on Time windows

I am solving a variation on vehicle routing problem. The model worked until I implemented a change where certain vehicles and/or stops may remain unassigned because the construction filter does not allow the move due to time window considerations (late arrival not allowed).
The problem size is 2 trucks/3 stops. truck_1 has 2 stops (Stop_1 and Stop_2) assigned to it, and consequently 1 truck and 1 stop remain unassigned since truck_2 will arrive late to Stop_3.
I have the following error:
INFO o.o.c.i.c.DefaultConstructionHeuristicPhase - Construction Heuristic phase (0) ended: step total (2), time spent (141), best score (-164hard/19387soft).
java.lang.IllegalStateException: Local Search phase started with an uninitialized Solution. First initialize the Solution. For example, run a Construction Heuristic phase first.
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.phaseStarted(DefaultLocalSearchPhase.java:119)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:60)
at org.optaplanner.core.impl.solver.DefaultSolver.runPhases(DefaultSolver.java:213)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:176)
I tried to set the planning variable to null (nullable = true) but it seems it is not allowed in case of chained variables.
I am using Optaplanner 6.2.
Please help,
Thank you,
Piyush
Your construction filter may be too restrictive, it could prevent the construction heuristic from creating an initialized solution. You should remove the time window constraint from the construction filter and add it as a hard score constraint in your score calculator instead.
From the Optaplanner docs:
Instead of implementing a hard constraint, it can sometimes be built in. For example: If Lecture A should never be assigned to Room X, but it uses ValueRangeProvider on Solution, so the Solver will often try to assign it to Room X too (only to find out that it breaks a hard constraint). Use a ValueRangeProvider on the planning entity or filtered selection to define that Course A should only be assigned a Room different than X.
This can give a good performance gain in some use cases, not just because the score calculation is faster, but mainly because most optimization algorithms will spend less time evaluating unfeasible solutions. However, usually this not a good idea because there is a real risk of trading short term benefits for long term harm:
Many optimization algorithms rely on the freedom to break hard constraints when changing planning entities, to get out of local optima.
Both implementation approaches have limitations (feature compatiblity, disabling automatic performance optimizations, ...), as explained in their documentation.