Optaplanner: How to calculate score delta for move - optaplanner

I'm using Optaplanner to automatically solve school timetables. After a timetable has been solved the user will manually change some lessons and will get feedback on how this affects the score via the following call:
scoreManager.updateScore(timetable);
This call takes some 200ms and will, I assume, do a complete evaluation. Im trying to optimize this and want to only pass in a Move object so that Optaplanner only has to recalculate the delta, like:
scoreManager.updateScore(previousTimetable,changeMove);
Is there a way to do this?

There really is no way how to do just a single move. You don't do moves - the solver does moves. You can only make external problem changes to the solution. You should look into the ProblemChange interface and its use in the SolverManager.
However, the problem change will likely reset the entire working solution anyway. And after the external change is done, you're not guaranteed that the solution will still make sense. (What if it breaks hard constraints now?) You simply need to expect and account for the fact that, after users submit their changes, the solver will need to run; possibly even for a prolonged period of time.

Related

Getting ScoreExplanation during/after a Custom Move

My solution is for VRPTW and I've created a Custom Move.
After a custom move has been tried (prior to being accepted), I would like to see a score breakdown of it (not just the score itself).
Where is a good location to use ScoreExplanation to see the detailed score breakdown? Eg. in my AbstractMove implementation somewhere?
I have TRACE mode on and can see the score. I've tried pulling it up upon the next custom move being run and it seemed to be working since it was retrieving the correct score from the previous custom move, but when I looked at the ScoreExplanation, it looks completely off (it doesn't add up to the score).
Score explanations are not designed to be used inside of a step, they are far too slow for that. You are free to use the ScoreManager API any time you like, but you will pay a heavy performance penalty if you do that on the solver thread or the move threads.

Does shadow variable help optaplanner to make a better initial solution?

I’m using Optaplanner to make a schedule and it works quite good.
After reading the documentation I have realised that I should use at least 1 (or more) shadow variables since my drool-file is calling methods that does a lot of calculations based on the value of the planningVariable.
I spent a couple of hours rewriting my code to have a shadow variable, but then I notice that the initial solution was really bad (compared to not having shadow variables) and I had to wait severals of minutes just to get an OK result. Is this normal? It did not look like the initial solution used the shadow variable at all.
The question is very generic, and so my answer will be, too.
Sometimes you can simplify the problem by introducing shadow variables or other forms of caching. If you find the right balance, you can indeed speed up the Drools calculation and - as a result - get to the same solution in a shorter amount of time. And therefore, reach better solutions in the same amount of time.
That said, introducing shadow variables shouldn't really change your scores - only how quickly they're calculated. If you're seeing different scores for the same #PlanningSolution, you have in fact changed your problem and the relative performance is no longer comparable.
Also, you may want to check out environment modes to make sure you haven't inadvertently introduced score corruptions into your problem.

Is there a way to save all feasible scores found?

I'm building a student schedule generator and I need a way of producing more than one solution. Is there some way to save off feasible scores or scores of Xhard/Ysoft?
I need to be able to output more than one potential schedule, that way the student will have a choice for one schedule over the other if for whatever reason they don't want the "best" schedule (maybe they don't like one of the professors, maybe they don't want an 8am class, whatever)
My original idea was to save off all feasible solutions using the bestSolutionChanged event listener. The problem with this, is that once it finds a 0hard/0soft score, it ignores all scores after that, including scores that are equal.
Ideally I'd like to save off all scores of 0hard/-3soft or better, but just being able to save any feasible scores or force optaplanner to look for a new best score would be useful as well.
This is not a solution, but an analysis of the problem:
Hacking the BestSolutionRecaller is obviously not just a big pain, it's also behaviour we don't want to encourage as it makes upgrading to newer version an even bigger pain. So don't expect us to solve this by adding an easy way to configure that in the solver config any time soon. That being said, a solution for this common problem is clearly needed.
When a new best solution is found, it is planning cloned (see docs for definition) from the working solution (the internal solution in OptaPlanner). This allow us to remember that new best solution as the working solution solution changes. That also means the BestSolutionChangedEvents gets a plannng clone and can safely ship it to another thread, for example to marshal it to a client (presuming any ProblemFactChanges you create do copies instead of alterations), without being corrupted by the solver thread that modifies the working solution.
New best solution imply that workingScore > bestScore. The moment it instead does workingScore >= bestScore, we need far more planning clones (which are a bit CPU expensive), but we could then just send out BestSolutionChangedEvents for that too, if and only if a flag is enabled of course, because most users (unlike yourself) don't want this behaviour.
One proposal is to create a separate BestSolutionChangedOrSameEvent, next to the BestSolutionChangedEvent. This might not be ideal, because we need to be able to detect whether or not someone needs those extra planning clones.
Another proposal is to just have a flag in the <solver> config that switches from > to >= behavior for BestSolutionChangedEvent.
Please create a jira (see "get help" on webpage) and link it it here, or create a support ticket (also see "get help" on webpage).

OptaPlanner - is there a way to trigger code at each Move in CH phase?

I'm currently using OptaPlanner 6.2.0 but can update if it can help.
I need to keep some data of chaining between variables and entities outside the planner, as well as some precalculated data and I need a way to update it after each move but before the rules are fired. I use that data when check the rules. I know it's a hacky way but there are complex rules which need separate data storing, can't think of the way to avoid it. Also this way the Planner has shown good performance.
So the thing is I need a way to trigger some code on each move which would update that separately stored data with the changes from current move, before the rules are applied for this move and decision about how good is the move is taken (because the rules address that data), so in fact before the score for this move gets recalculated. On Local Search phase it's pretty simple because all of my moves are custom, so I can do it inside of doMove. But I really need to do the same thing in CH phase.
I'm aware that we can't change move type to custom in CH phase. I also find it very difficult to implement a full analogue of CH phase in CustomPhaseCommand for this little change. Removing CH phase and replacing it with simple custom phase reduces the quality of allocation for this specific task significantly even thought I had an example where it worked better without CH at all. I've also tried adding PhaseLifecycleListener to my Solver but it only listens to steps and phases, not to separate moves. The closest effort so far was implementing a VariableListener which indeed happens to fire beforeVariableChanged, afterVariableChanged at each move, even on CH phase. But in beforeVariableChanged I can only see the old variable, not the new one (I need both to update my data), and afterVariableChanged seems to fire AFTER the rules where fired and checked so it's useless to update the data in this method (by the way how do shadow variables get updated then on CH phase usually? I thought it should fire after, update the shadow variables there and then recheck the rules with updated shadow variables?)
I also tried to look at the chaining but I'm not sure it can fully cover my complex case with storing data separately and using it in rules...
So is there a way to correctly update my structure at each CH move? Or is there a simple way to handle the complex data dependencies other than moving it to separate structure outside of Planner?
Thanks in advance!

Solving VRPTW using OptaPlanner

I have tried to run example https://github.com/droolsjbpm/optaplanner/tree/master/optaplanner-examples/src/main/java/org/optaplanner/examples/vehiclerouting
as it is written here:
http://docs.jboss.org/optaplanner/release/6.3.0.Final/optaplanner-docs/html_single/index.html#downloadAndRunTheExamples with data set cvrptw-25customers.xml . When I changed readyTime and dueTime in some customers, it didn't result in any change in score. It looks like this program doesn't care about time windows. Should I change something in Java classes? My goal is to get time needed to drive to all customers, taking into account all time windows.
This should work, I 've done it several times myself. Potential causes:
Did you load the xml file again? Try changing the VehicleRoutingPanel code so it's obvious which customer you changed and if indeed the values changed. Compare the screenshot of before and after your change (or duplicate the xml file so you keep the original).
If some arrival times and dueTimes change, the score doesn't need to change. Try making very small time windows, at annoying times, that should definitely impact the score and make it worse.