Updating shadow variables of multiple chains - optaplanner

I'm trying to solve a cooperative team orienteering problem and thus implementing an Auto-Delay. I use shadow variables to store arrival and starting time as explained in the documentation.
My chains are as follows :
Vehicule 1 : [Vehicule1, TaskA(1/3), TaskB(2/3),...] Arrival on A : 10, Start of A : 20
Vehicule 2 : [Vehicule2, TaskA(2/3),TaskB(1/3),...] Arrival on A : 20, Start of A : 20
Vehicule 3 : [Vehicule3, TaskB(3/3),...]
The fact that TaskA cannot be completed is punished in the score calculation.
Optaplanner is now adding TaskA(3/3) before TaskB(3/3). Its Arrival time is 30
I wish to change the starting time of TaskA(1/3) and TaskA(2/3) to 30. BUT i also want to change the consequent arrival and starting time of TaskB(1/3) and TaskB(2/3) and tasks that are placed after.
TaskB(3/3) is in the source chain so it will be taken care of normally.
Ending time is based only on starting time in my problem.
What is the best way to do that ?

Related

pg_stat_statements_calls in Grafana

The problem with pg_stat_statements_calls in Grafana, the Count for a certain period is not displayed. I have tried various rate and irate functions. But when I choose the time "The last 5, 10, 15 minutes and so on."The values don't seem to change, they remain the same huge. I also added interval it didn't help.
My request looks like this:
topk(30, (pg_stat_statements_calls{datname!~"template.*", datname!~"postgres", instance=~"$server.+", datname=~"$database", short_query!~"(BEGIN|COMMIT|SET.*|ROLLBACK|BEGIN ISOLATION LEVEL READ COMMITTED)"}))
enter image description here
I tried:
rate
irate
delta
interval
But my Count does not adjust to the time range

How to speed up construction phase whilst having an trivial overlapping constraint

We're are trying to put together a proof of concept planning constraints solver using OptaPlanner. However the construction phase seems slow for even a trivial set of constraints i.e. assign to one User with no overlapping Tasks for that User.
Problem overview:
We are assigning Tasks to Users
Only one Task can be assigned to User
The Tasks can be variable length: 1-16 hours
Users can only do one Task at a time
Users have 8 hours per day
We are using the Time Grain pattern - 1 grain = 1 hour.
See constraints configuration below.
This works fine (returns in a 20 seconds) for a small number of Users and Tasks e.g. 30 Users / 1000 Tasks but when we start scaling up the performance rapidly drops off. Simply increasing the number of Users without increasing the number of Tasks (300 Users / 1000 Tasks) increases the solve time to 120 seconds.
But we hope to scale up to 300 Users / 10000 Tasks and incorporate much more elaborate constraints.
Is there a way to optimise the constraints/configuration?
Constraint constraint1 = constraintFactory.forEach(Task.class)
.filter(st -> st.getUser() == null)
.penalize("Assign Task", HardSoftLongScore.ONE_HARD);
Constraint constraint2 = constraintFactory.forEach(Task.class)
.filter(st -> st.getStartDate() == null)
.penalize("Assign Start Date", HardSoftLongScore.ONE_HARD);
Constraint constraint3 = constraintFactory
.forEachUniquePair(Task.class,
equal(Task::getUser),
overlapping(st -> st.getStartDate().getId(),
st -> st.getStartDate().getId() + st.getDurationInHours()))
.penalizeLong("Crew conflict", HardSoftLongScore.ONE_HARD,
(st1, st2) -> {
int x1 = st1.getStartDate().getId() > st2.getStartDate().getId() ? st1.getStartDate().getId(): st2.getStartDate().getId();
int x2 = st1.getStartDate().getId() + st1.getDurationInHours() < st2.getStartDate().getId() + st2.getDurationInHours() ?
st1.getStartDate().getId() + st1.getDurationInHours(): st2.getStartDate().getId() + + st2.getDurationInHours();
return Math.abs(x2-x1);
});
constraint1 and constraint2 seem redundant to me. The Construction Heuristic phase will initialize all planning variables (automatically, without being penalized for not doing so) and Local Search will never set a planning variable to null (unless you're optimizing an over-constrained problem).
You should be able to remove constraint1 and constraint2 without impact on the solution quality.
Other than that, it seems you have two planning variables (Task.user and Task.startDate). By default, in each CH step, both variables of a selected entity are initialized "together". That means OptaPlanner looks for the best initial pair of values for that entity in the Cartesian product of all users and all time grains. This scales poorly.
See the Scaling construction heuristics chapter to learn how to change that default behavior and for other ways how to make Construction Heuristic algorithms scale better.

How to add time instances to ontology

I have created a time ontology in protege, in which I have to add minute, seconds and hour values as 09,19, etc. At output I want to show time as 11:30:00. When I added instances to hour and then seconds it showed me that individual already added. How to resolve that issue?
If I understand correctly what you are trying to achieve is to have a single class, say Time, for which you can specify the hours, minutes and seconds. This is in fact an example of an n-ary relation, where you model the time relation as a class. A way to model this then is:
DataProperty: hours
Domain: Time
Range: xsd:byte[>= "0"^^xsd:byte , <= "24"^^xsd:byte]
DataProperty: minutes>
Domain: Time
Range: xsd:byte[>= "0"^^xsd:byte , <= "60"^^xsd:byte]
DataProperty: seconds>
Domain: Time
Range: xsd:byte[>= "60"^^xsd:byte , <= "0"^^xsd:byte]
Class: Time
Then to specify, let say the opening time of some store, as 8:30, you can create the following individual:
Individual: openingTime
Types: Time
Facts:
hours "8"^^xsd:byte,
minutes "30"^^xsd:byte,
seconds "0"^^xsd:byte

Opta planner incorrect best score

I am trying out the optaplanner for a shift assignment problem.
It is a many to many relationship since one shift can have many employees.
In the trial run , I have two employees and three shifts .
One of the shift needs two employees.
So I have created a new ShiftAssignment class to handle the many to many relationship . ShiftAssignment is the planning entity and employee is the planning variable.
I pass the two employees and four shift assignment class ( because one shift needs two employees )
to the planning solution
I have only one hard rule in the score calculator which is basically the employee should
have the necessary skill needed for the shift
When I run the solver , I print the score in my code below ( I dont have any soft constraints so I have hard coded it to zero )
public HardSoftScore calculateScore(AuditAllocationSolution auditAllocationSolution) {
int hardScore = 0;
for (Auditor auditor : auditAllocationSolution.getAuditors()) {
for (AuditAssignment auditAssignment : auditAllocationSolution.getAuditAssignments()) {
if (auditor.equals(auditAssignment.getAuditor())) {
List<String> auditorSkils = auditor.getQualifications().stream().map(skill -> skill.getSkillName())
.collect(Collectors.toList());
String requiredSkillForThisAuditInstance = auditAssignment.getRequiredSkill().getSkillName();
if ( !auditorSkils.contains(requiredSkillForThisAuditInstance))
{
// increement hard score since skill match contraint is violated
hardScore = hardScore + 1;
}
}
}
}
System.out.println(" hardScore " + hardScore);
return HardSoftScore.valueOf(hardScore, 0);
}
When I print the values of the solution class in the score calculator , I can see that there are few solutions where hard score is zero. The solution satisfies the rules and matches the expected results . But it is not accepted as per the logs
08:16:35.549 [main] TRACE o.o.c.i.l.decider.LocalSearchDecider - Move index (0), score (0hard/0soft), accepted (false), move (AuditAssignment-2 {Auditor-1} <-> AuditAssignment-3 {Auditor-0}).
08:16:35.549 [main] TRACE o.o.c.i.l.decider.LocalSearchDecider - Move index (0), score (0hard/0soft), accepted (false), move (AuditAssignment-2 {Auditor-1} <-> AuditAssignment-3 {Auditor-0}).
One another observation which I want to clarify in the logs.
I understand that every new solution , which is the outcome of each step , is passed to score calculator . But sometimes I see that for a single step , score calculator is invoked more than once with different solution. This is my observation from the logs. Assuming this is single threaded and log sequencing is correct , why does that happen ?
The final output is incorrect . The best score that is selected is something with high hard score. And the solutions with the best score are not accepted
I also see the below line in the logs which I am not able to comprehend. Is there anything wrong in my configuration ?
23:53:01.242 [main] DEBUG o.o.c.i.l.DefaultLocalSearchPhase - LS step (26), time spent (121), score (2hard/0soft), best score (4hard/0soft), accepted/selected move count (1/1), picked move (AuditAssignment-2 {Auditor-1} <-> AuditAssignment-0 {Auditor-0}).
23:53:01.242 [main] DEBUG o.o.c.i.l.DefaultLocalSearchPhase - LS step (26), time spent (121), score (2hard/0soft), best score (4hard/0soft), accepted/selected move count (1/1), picked move (AuditAssignment-2 {Auditor-1} <-> AuditAssignment-0 {Auditor-0}).
This is a small problem size and I feel I have not set it up right . Kindly suggest.
Hard Score has to be decremented when a constraint is violated. In the above code , I had incremented the hard score which probably had led to the erroneous result.
It worked as expected once I fixed the above.

Google maps route tracking

I'm using Google Maps to generate driving directions. I'd like to have a feature that would estimate where in the route someone is, based on the elapse time, and the total time from Google, and drop a pin (possibly a moving pin) where they're estimated to by.
I know how to generate the map in Google, but that's about where the limit of my knowledge is. How would I drop the pin in the approx location.
I'm thinking converting the total time into seconds, the elapse time into seconds and divide to get the percentage completed on the route. How would I drop a pin to the route location where this would be? Moreover, could I move the pin maybe updated every 30 - 60 seconds?
The duration attribute of Maps results is already in seconds. With that in mind, you can, in a sense, follow the route -> legs -> steps duration to give you a rough idea of how far along the trip each step is.
Now that you know the rough idea of how far into the trip each step is, you can do a comparison with the elapsed time to see which step they should be on. Once you've verified the correct step, you can use the step's lat_lngs to place a marker. lat_lngs is the array of points passed during that step, so you can work out which lat_lng to place the marker at based on the elapsed time compared to the time they should have been starting the step and the time when they should be finishing it.
Here's some code that won't run on your application, and doesn't include any real elapsed time logic, so it's best to treat it as pseudocode:
// route is a directionsService (google.maps.DirectionsService()) result
route = response.routes[0];
route.legs.forEach(function(leg) {
var counter = 0;
leg.steps.forEach(function(step) {
counter = counter + step.duration.value;
console.log("Route progress in seconds: " + counter);
if (elapsed >= counter) {
// percent would take the beginning and end time for the step
// and compare it to the elapsed duration to get a percentage
// that would be used to get the index of the appropriate lat_lng
var marker = new google.maps.Marker({
position: step.lat_lngs[percent],
map: map,
title: "Current Location"
});
}
});
});
You'd have to create your own logic for actually updating the map and such, but hopefully this is a decent starting point.