OptaPlanner, in VariableListener change shadow variable of other entity - optaplanner

Working on my project based on optaplanner example taskassigning. In the example, StartTimeUpdatingVariableListener updateStartTime() changes the time of the source-task. Will it be OK, right in the function, change the shadow variable of the previous task instead of the source task? Because in my scenario, each task has a waiting time (shadow variable), only when a new task is added, the previous task's waiting time can be calculated. Different source task will bring different waiting time to its previous task. Eventually the sum of all employees' waiting time will be minimized in rule. Looking at the example, in the listener, only the source task time is updated, and is surrounded by beforeVariableChanged and afterVariableChanged. Will there be any problem to update other task's shadow variable?

You can't create cycles that would cause infinite loops.
Across different shadow variable declarations
A custom shadow variable (VariableListener) can trigger another custom shadow variable (VariableListener), for example in the image below C triggers E. So the VariableListener of C that changes variable C, triggers (delayed) events on the VariableListener of E.
But the dependency tree cannot contain a cycle, OptaPlanner validates this through the sources attribute.
Notice how all the variable listeners methods of C are called before the first of E is called. They are delayed. OptaPlanner give you this guarantee behind the scenes.
For a single shadow variable declaration
The VariableListener for C is triggered when A or B changes. So when it changes a C variable, no new trigger events for that VariableListeners are created.
When a single A variable changes, one event is triggered on the VariableListener for C, which can change multiple C variables. The loop that changes those multiple C variable must not be an infinite loop.
In practice, with VRP and task assignment scheduling, I 've found that they only way to guarantee the absence of an infinite loop is to only make changes forward in time. So in a chained model, follow the next variables, but not the previous.

Related

Optaplanner, update shadow variables after every step

I am trying to add moves selectors which consider the state of the current working solution. For example, suppose in the cloud balancing problem I was trying to make a move which preferentially moved a process onto a computer which already holds few processes. I have a shadow variable which tracks the number of processes on the computer, then I have a valueSelector which implements SelectionProbabilityWeightFactory that gives a higher weight to computers with fewer processes.
This setup works fine and produces the moves that I want. But it is terribly slow because it is updating the shadow variable far more often than I need it to. Since I am not using this shadow variable for scoring, I don't need it to be updated after every move attempted during the step. I only need the shadow variable to be updated after each accepted move (i.e. the end of the step).
Alternately, I could use a custom move factory, but that requires that every computer have its process count fully re-calculated at each step. This means I would lose the incremental calculation benefit I get with the shadow variables.
So is there a way to force shadow variables to update after each step, rather than after each move. Or is there a better way to track the status of the working solution for use in move selectors?
Bad news first:
It's not possible to have VariableListener only update a shadow variable per step and not per move. And it's unlikely we'll ever want to allow that particular change, as it would hurt the predictability and integrity of the state of the domain model between move iterations. This could create a lot of havoc, including multiple forms of corruptions, if used slightly incorrectly.
Good news next:
Yes, you need to calculate some state per step to generate moves efficiently. This is a common problem I've run into a few times before too.
But why put that on the domain model? It doesn't belong there.
It belongs on the the move selector. For example, if you use a MoveIteratorFactory, that has a method called phaseStarted() (called when the phase starts) and a method createRandomMoveIterator() (called when a step starts even with SelectionCacheType.JIT).
Some something like this should do the trick:
public class MyMoveIteratorFactory implements MoveIteratorFactory<...> {
default void phaseStarted(ScoreDirector<...> scoreDirector) {
}
Iterator<Move_> createRandomMoveIterator(ScoreDirector<...> scoreDirector, Random workingRandom) {
List<Computer> alreadyUsedComputerList = ...; // runs once per step
return new MyIterator(alreadyUsedComputerList, workingRandom);
}
Now, the plot thickens when multiple move selectors need to reuse the same calculation. That's where SupplyManager comes into play, which is not public API. But this is definitely a good requirement for our "move streams API" experiment that we'll do next year.

Optaplanner: check if chained planning variable has anchor

I'm modifying the vehicle routing Optaplanner example. Vehicles are replaced with individuals who have to travel around the city, but they can do so using different modes of transportation. So I have an attribute on the anchor (Vehicle in the example, Employee in my modified code) called modeOfTransportation.
When calculating the arrival time using the custom shadow variable listener from the example, I want to take the mode of transportation into account of course. But, when Optaplanner starts initialising my planning entities (consumers), it seems that they at first are not connected to an anchor. So I can't get my mode of transportation, and everything breaks down.
Any ideas on how to proceed?
Below is what I want to accomplish.
shadowVisit is my planning entity, shadowVisit.getEmployee() should give me the anchor.
Doing a shadowVisit.getEmployee()==null check seems to hang the entire solving process.
arrivalTime =
previousStopDepartureTime.plus(
shadowVisit.getLocation().getDistanceFrom(
shadowVisit.getPreviousStop().getLocation(), shadowVisit.getEmployee().getModeOfTransportation())
OK, so I figured out what the issue was.
My problem is overconstrained, and I implemented a dummy employee as the solution (see optaplanner: modifying vehicle routing to let customers be not served)
I had not set a modeOfTransportation for my dummy, causing the null pointers. Sometimes is just good to write down a problem, makes you think hard enough to solve it!
Thank you very much for your input Geoffrey
That's strange, because the chain principles guarantee that every chain has an anchor (see below).
Maybe your #CustomShadowVariable's sources attribute doesn't include the anchor shadow var, and your custom variable listener is called before the anchor shadow variable listener is called.
OptaPlanner guarantees that it will call one type of variable listener for all domain classes before calling the next type. The order of those types of variable listeners is determined by that sources attribute (see second image).

Optaplanner strange behaviour when FULL_ASSERT

I am developing an incremental solver for rostering, the two planning entities are Assignment and Employee, worker has an #InverseRelationShadowVariable collection of assignments.
I have noticed a strange behaviour when using FULL_ASSERT.
At the start of the LS phase an EmployeeSwapMove is evaluated.
After that the listener is invoked which first retracts all assignments from Employee than inserts all assignments as per the move to the shadowed collection.
After that resetWorkingSolution is invoked, but the Employee has the Assignments before the move.
Optaplanner also logs, that the above move has been selected, but the Employee state (shadow collection) does not reflect that.
After that the score gets corrupted, of course.
The issue is not there when using FAST_ASSERT.
Can someone give me a hint?
I found out at last. In my Listener I messed up the after/beforeVariableChanged calls.

SCIPincludeBranchruleMybranchingrule() called many times

I'm including my own branching rule on SCIP and I'm using the SCIPincludeBranchruleMybranchingrule() function to initialize some branching rule data. One of the things I do is to call the SCIPgetNVars() function. When I run the code, I see that the function is called many times (not once, as I thought, before the B&B algorithm starts) and I get the following error triggered by the SCIPgetNVars() function:
[src/scip/scip.c:10048] ERROR: invalid SCIP stage <0>
I'm confused about the use of SCIPincludeBranchruleMybranchingrule(), since the documentation states that this function can be use to initialize branching rule data. I would like to initialize some data that can be used at every B&B node, maybe the branching rule data is not the right way of doing it.
I'll appreciate any help!
The important thing to note here is that there is no problem available yet for which you want to access the variables.
Branching rules of SCIP provide several callbacks for data initialization. The include-
callback is only called once when SCIP starts, aka in the SCIP_STAGE_INIT stage of SCIP.
At this stage, you want the branching rule to inform SCIP that it exists, and optionally introduce some user parameters that are problem-independent.
There are two more callback-functions that allow for storing data which are better suited for what you intend to do; SCIPbranchruleInitsolMybranchingrule which is called just before the (presolved)
problem is about to be solved via branch-and-bound, and SCIPbranchruleInitMybranchingrule, which is called after a newly read problem was transformed.
Since the execution of a branching-rule is restricted to within the branch-and-bound-process, your callback is SCIPbranchruleInitSolMybranchingrule which you should implement by moving all problem specific data initialization there. Don't forget to also implement SCIPbranchruleExitsolMybranchrule to free the stored data every time the branch-and-bound search is terminated, either if search was terminated, or if a time limit was hit, or SCIP decided that it wants another restart.
FYI: Data that is allocated during the include-callback can be freed with the SCIPbranchruleFreeMybranchingrule-callback, which is executed once when SCIP is about to exit and free all left system-memory.

How to Display Data in a Control in LabVIEW

I have a numeric control( not Indicator) and a for loop(limit 5)
I need to display the [current loop Index+ value in the numeric control] in the Numeric control. I'm new to LabVIEW. Is there any idea to do this?
To write a value to a control, you need to create a local variable from it (right-click on the control's terminal on the block diagram and choose Create > Local Variable). To have it update each iteration of your For loop, put the local variable terminal inside the For loop and wire whatever you want displayed to that terminal. I'm not sure if this is going to be a good user interface design, but it's the answer to your question.
You can also use local variables to write to indicators from more than one place in your block diagram, and to read from indicators or controls. You can have more than one local variable terminal for any given control or indicator. Each local variable terminal is either for reading or writing - right-click on the local variable and choose Change to Read or Change to Write.
You should be careful about using local variables to pass data around, because program flow will no longer be controlled by data flow as it is when you pass data along a wire, and this could give you unpredictable behaviour (race conditions). Writing in one place and reading in multiple places is OK if the readers only need to know the current value at the time they execute, and so is writing to an indicator from multiple places where the indicator is only being used to display information to the user.
Is there any specific reason you need to update a control that often?
If it needs to be updated that regular it might be better to alter it into an indicator.
If you update a control that often the user will have the feeling he's not in 'control'.
As mentioned aleady you can use local variables and proerty nodes to set the value of your control or indicator. If you are trying to persist data there is a much better way.
Google "functional global" or "labview 2 style global". The basic pattern is to use a while loop hard coded to stop after one iteration. Add an unitialized shift register. Add a case structure inside the loop. Use a control (boolean, enum, or string) to select on the case structure. Drop a control/indicator pair of the same datatype on your VI. Wire the indicator to the outter-output of the right shifter on the outside of the loop. Place the control INSIDE the loop in the "set" (usually true, non-default) case and wire it out of the case into the input of the right shifter. Go to the other empty case(s) and wire the inner-output of the left shifter through the cases to the terminal that connects to the inner-input.
Becuase you did not wire the outter-input of the left shifter it is an "unitialized shift register". It will persist data from the last call to the VI. This is like declaring a variable on the heap in a c function and having the last assigned value available to you at the next function call.
The three main benefits are preservation of data flow, thread saftey, and performance. You get data flow by adding error IO to your VI. Thread saftey is ensured becasue the VI's execution is guaranteed to be atomic. Perfomance is improved becasue LV data wants to live on a wire. Every time you write data to a control's proerty node the LV runtime writes that data to the UI thread. I think there is a similar threading based performance hit for locals too but I'm not sure.
Per the first comment...
Copied here from the link for your benefit (yes you Mr Reader).
Problem:
I am considering using local or global variables; in what thread do variables execute?
Solution:
A common misunderstanding is that local and global variable operations execute in the UI thread, or require a thread swap to the UI thread - this is not true. The following describes the behavior of local and global variable write and read operations:
Write:
When you write to a local or global variable, LabVIEW does not switch to the user interface thread immediately. LabVIEW instead writes the value to the transfer buffer, which is a protected area of memory. The user interface updates at the next scheduled update time. It is possible to update a variable multiple times before a single thread switch or user interface update occurs. This is possible because variables operate solely in the execution thread.
Read:
When you read from a local or global variable, the operation will occur in the thread which the VI executes, thus, you can be sure it does not occur in the UI thread by setting the execution system in the VI properties to standard. There is a thread protection mechanism to make sure that no writer of the global is changing the data while you are reading it, but this is done via a mutex, and not by going to the UI thread. However, if the global variable panel is opened, then a message is posted to redraw the global control, and the redraw will happen in the UI thread.
nekomatic is correct. The thread swap does not occur when you write to locals.
I agree with Ton. If you are changing the value of a control programatically, then you should consider whether it should be an indicator, or maybe have a pseudo-indicator of the control.
It would be a good idea to post an isolated version of your code so we can understand what exactly is going on.
If you wanted to maintain dataflow to control the program flow, you could instead use a property node of the control and set the "Value" property.
To create the property node, right click on the control's terminal on the block diagram, and select Create » Property Node » Value. Now you can adhere to dataflow programming by using error wires to control the flow of the program.
Again, to re-emphasize Ton's point - If you are going to change the value of a control frequently, it might be worth changing it into an indicator instead.