Optaplanner - timewindow is not fulfilled - optaplanner

I am using OptaPlanner for a business related optimization.
Concerning 6.1.0. Final version: When I modify the optimization problem, so that a vehicle has to arrive inside of a time window (with earliest possible and latest possible arrival time, punished by hardscores when too early or too late) and when I take only 1 vehicle with two customers, whereby timewindow 1 is much earlier than timewindow 2 (end of timewindow 1 + travelling time to customer 2 < start of timewindow 2) then the vehicle meets the timewindow 1 exactly at earliest time, but the arrival at customer 2 is too early.
The vehicle (2363) starts from depot 270 first to customer 13 (time window is 8:50-10:50) and arrives exactly at 8:50. The working duration there is 75 min. The departure is at 10:05 and the vehicle arrives at 10:12 at customer 16 (time window is 15:45-17:45).
In some business cases it is better to wait instead to arrive too early.
How can I force the vehicle to WAIT, so that it arrives at the location of next customer in time?
PS: The circles show the time window of possible arrival time (inner circle: 0-12h, outer circle: 12-24h). Times and distances between locations are determined from GraphHopper

So you want to wait at the previous standstill (= the previous customer or the depot), instead of at the current customer?
In the OptaPlanner VRP example, departureTime = arrivalTime + duration. So arrivalTime is a shadow variable (based on previousStandstill) and departureTime is just a calculation on top of that (so departureTime itself is not shadow variable, because it isn't even a field (or put differently because it's not a java variable it's cannot be a planning variable (genuine or shadow)).
In your variant, make departureTime a shadow variable too, defined as follows: departureTime = Math.max((arrivalTime + duration), nextCustomer.readyTime - drivingTime). That new shadow variable (and therefor it's VariableListener) depends on the planning variables arrivalTime and nextCustomer. So a shadow var depending on shadow vars.
Notice how there's NO cycle in this proposal: nextCustomer.readyTime is used, but readyTime is a problem fact.
You might need to upgrade to 6.2.0.CR2 or higher for this, because 6.1 might not yet support shadow variables that depend on shadow variables (I don't recall any more). I also fear that optaplanner doesn't automatically reorder variable listener triggering yet to follow the hierarchy (feel free to make a jira about that), so that means you'll have to declare the getters with variable listeners as follows: previousStandstill, nextCustomer, arrivalTime, departureTime.
VariableListener triggering order will be formalized more in future versions.

Related

How to model a time-dependent vehicle routing problem with time windows in octapy?

I am looking to model a vehicle routing problem with time windows on OctaPy. Specifically, this problem involves traffic enforcement on public roads, so parking wardens need to survey carparks and road segments and visit them more than once during a 24-hour period.
I refer to the answer in the following question as foundation to develop my problem:
Is it possible to create a VRP solution using NetworkX?
I have a few questions regarding the modelling:
How does OctaPy model time-dependency, that is a different edge weight representing travel duration depending on the time of day?
How do I model the demand points if each point needs to be visited X times?
If a demand point is to be visited X times, how can I enforce a time window gap such that the duration between visits is at least a fixed duration (e.g. 1 hour)?
OptaPy models time-dependency the way you model time-dependency. That is, whatever you use to model time-dependency (may it be an edge, a list, a matrix, a class, etc.), OptaPy can use it in its constraints.
If X is known in advance, for each demand point, you create X copies of it and put it in the #problem_fact_collection_property field. If X is not known in advance, consider using real-time planning (https://www.optapy.org/docs/latest/repeated-planning/repeated-planning.html#realTimePlanning).
This depends on how you implement your time dependency. This would be easier when OptaPy supports the new VariableListener API for List Variable (as well as the builtin list shadow variables) that OptaPlanner has. Until then, you need to do the calculation in a function. Make Edge a #planning_entity and give it a inverse relation shadow variable (https://www.optapy.org/docs/latest/shadow-variable/shadow-variable.html#bidirectionalVariable). Add a method get_arrival_time(edge) to Vehicle that get the estimated time of visit for a given Edge in its visited_edges_list.
def less_than_one_hour_between(visit_1: Edge, visit_2: Edge):
visit_1_arrival_time = visit_1.vehicle.get_arrival_time(visit_1)
visit_2_arrival_time = visit_2.vehicle.get_arrival_time(visit_2)
duration = visit_2_arrival_time - visit_1_arrival_time
return timedelta(hours=0) <= duration <= timedelta(hours=1)
def one_hour_between_consecutive_visits(constraint_factory):
return (
constraint_factory.for_each(Edge)
.join(Edge, Joiners.equal(lambda edge: edge.graph_from_node),
Joiners.equal(lambda edge: edge.graph_to_node))
.filter(lambda a, b: a is not b and less_than_one_hour_between(a, b))
.penalize('less than 1 hour between visits', HardSoftScore.ONE_HARD)

Optaplanner Score calculation types questions

Solve the doubts on the use of OptaPlanner.
OptaPlanner uses the following score calculation types: Drools score calculation or Constraint streams score calculation. Both methods support incremental calculation of scores.
One doubt about incremental calculation of scores:
Demo:
import org.optaplanner.examples.cloudbalancing.domain.CloudBalance;
import org.optaplanner.examples.cloudbalancing.domain.CloudComputer;
import org.optaplanner.examples.cloudbalancing.domain.CloudProcess;
global HardSoftScoreHolder scoreHolder;
// ############################################################################
// Hard constraints
// ############################################################################
rule "requiredCpuPowerTotal"
when
$computer : CloudComputer($cpuPower : cpuPower)
accumulate(
CloudProcess(
computer == $computer,
$requiredCpuPower : requiredCpuPower);
$requiredCpuPowerTotal : sum($requiredCpuPower);
$requiredCpuPowerTotal > $cpuPower
)
then
scoreHolder.addHardConstraintMatch(kcontext, $cpuPower - $requiredCpuPowerTotal);
end
Assuming that the requiredCpuPowerTotal condition is established, the then logic is executed, and the hard score is added, assuming -100.
At this time, the CloudProcess solution has been changed. CloudComputer has reduced some of the CloudProcess reception so that it will not exceed the cpu limit of this computer CloudComputer. This condition does not hold.
My questions are:
If the condition is met for the first time, computer A allocates 2 threads to a computer with a total of 4 core CPUs, but the first time computer A has 2 cores, so this time the solution is a negative score of hard -100 .
The second program A computer allocates 1 thread, if the current conditions are not met, the negative score will not be increased. The result is hard 0. Questions: 1. But how did the previous negative score be deleted?
Or does it mean that the score will be recalculated every new solution?
The previous negative score will be deleted because addHardConstraintMatch() is doing some black magic: it registers a rule unmatch listener to undo that negative addition when the score no longer matches.
scoreDRL is incremental, so only the delta of the score change will be recalculated.
PS: Take a look at ConstraintStreams too, they are also incremental :)

How to determine when to accelerate and decelerate to reach a given destination?

I'm creating a computer game in which there is a computer-controlled car that needs to travel along a straight line (thus making this problem effectively 1-dimensional) and reach a destination coming to a rest at 0 velocity. This car "thinks" every second and decides whether (and by how much) to accelerate or decelerate.
To summarize, I want the car to accelerate as strongly as possible and then stop as rapidly as possible.
Here are the variables that the car must respect:
- RemainingDistance = Our current remaining distance to the destination in meters.
- Velocity = Our current velocity towards the destination in meters/second.
- MaxVelocity = The maximum speed the car can reach.
- Acceleration = The change in velocity per second. The car can change its acceleration every second to any number in the range [0, Acceleration].
- Deceleration = The change in velocity per second. The car can change its deceleration every second to any number in the range [0, Deceleration].
So to be as clear as I can, here's the math that runs every second to update the car simulation:
Acceleration = some amount between [Deceleration, Acceleration] as chosen by the computer
Velocity = Velocity + Acceleration
RemainingDistance = RemainingDistance - Velocity
So my question is: Every time the car "thinks", what formula(s) should it use to determine the ideal value of Acceleration in order to reach its destination (with a 0 final velocity) in as little time as possible?
(In the event that the car's initial velocity is too high and it can't decelerate fast enough to achieve 0 velocity by the time it reaches its destination, then it should come to a rest as close as possible to the destination.)
Please let me know if you have any questions.

Confusion with writing a game loop

I'm working on a 2D video game framework, and I've never written a game loop before. Most frameworks I've ever looked in to seem to implement both a draw and update methods.
For my project I implemented a loop that calls these 2 methods. I noticed with other frameworks, these methods don't always get called alternating. Some frameworks will have update run way more than draw does. Also, most of these types of frameworks will run at 60FPS. I figure I'll need some sort of sleep in here.
My question is, what is the best method for implementing this type of loop? Do I call draw then update, or vice versa? In my case, I'm writing a wrapper around SDL2, so maybe that library requires something to be setup in a certain way?
Here's some "pseudo" code I'm thinking of for the implementation.
loop do
clear_screen
draw
update
sleep(16.milliseconds)
break if window_is_closed
end
Though my project is being written in Crystal-Lang, I'm more looking for a general concept that could be applied to any language.
It depends what you want to achieve. Some games prefer the game logic to run more frequently than the frame rate (I believe Source games do this), for some games you may want the game logic to run less frequently (the only example of this I can think of is the servers of some multiplayer games, quite famously Overwatch).
It's important to consider as well that this is a question of resolution, not speed. A game with logic rate 120 and frame rate 60 is not necessarily running at x2 speed, any time critical operations within the game logic should be done relative to the clock*, not the tic rate, or your game will literally go into slow motion if the frames take too long to render.
I would recommend writing a loop like this:
loop do
time_until_update = (update_interval + time_of_last_update) - current_time
time_until_draw = (draw_interval + time_of_last_draw) - current_time
work_done = false
# Update the game if it's been enough time
if time_until_update <= 0
update
time_of_last_update = current_time
work_done = true
end
# Draw the screen if it's been enough time
if time_until_draw <= 0
clear_screen
draw
time_of_last_draw = current_time
work_done = true
end
# Nothing to do, sleep for the smallest period
if work_done == false
smaller = time_until_update
if time_until_draw < smaller
smaller = time_until_draw
end
sleep_for(smaller)
end
# Leave, maybe
break if window_is_closed
end
You don't want to wait for 16ms every frame otherwise you might end up over-waiting if the frame takes a non-trivial amount of time to complete. The work_done variable is so that we know whether or not the intervals we calculated at the start of the loop are still valid, we may have done 5ms of work, which would throw our sleeping completely off so in that scenario we go back around and calculate fresh values.
* You may want to abstractify the clock, using the clock directly can have some weird effects, for example if you save the game and you save the last time you used a magical power as a clock time, it will instantly come off cooldown when you load the save, as that is now minutes, hours or even days in the past. Similar issues exist with the process being suspended by the operating system.

Optaplanner, How to catch the current time at the beginning of the rule to use it in score?

I have something like that:
scoreHolder.addSoftConstraintMatch(kcontext, (System.currentTimeMillis()-$time.getTime()));
I want to use the current time at the beginning of firing the rule only, and not to be updated during running the rule. just to catch the current time at the first moment the rule is fired and does not change till the end of solving.
I'm using optaplanner 6.1.
thanks in advance.
That would break OptaPlanner, as the Score of the same Solution would change over time (which also implies that comparing 2 different Solutions can not be done fairly - so if a new working score is compared to the best score (which was calculated x seconds ago) it breaks).
Instead, before the solver starts, set the current time millis in a singleton:
myParametrization.setStartingMillis(System.currentMillis());
... = solver.solve(...);
and add that as a problem fact and use it in the score rules (see examination example's InstitutionParameterization).