Chained Through Time Implementation - optaplanner

I have been developing a project that is similar to the task assigning project which uses the chained through time pattern. I have a difficulty comparator that prioritizes the tasks that must be finished earlier. My problem is that whenever a new entity is added to the chain, it's added to the top, pushing down the tasks that must be done earlier.
Is that supposed to happen? or is my implementation bad?
This is my code in the listener. It's basically the same as in the task assigning project.
protected void updateStartTime(ScoreDirector scoreDirector,Calcado calcado){
CalcadoA calcadoAnterior = calcado.getCalcadoAnterior();
Calcado shadowCalcado = calcado;
Integer previousEndTime = (calcadoAnterior == null ? null : calcadoAnterior.getEndTime());
Integer startTime = previousEndTime;
while (shadowCalcado != null && !Objects.equals(shadowCalcado.getStartTime(), startTime)) {
scoreDirector.beforeVariableChanged(shadowCalcado, "startTime");
shadowCalcado.setStartTime(startTime);
scoreDirector.afterVariableChanged(shadowCalcado, "startTime");
previousEndTime = shadowCalcado.getEndTime();
shadowCalcado = shadowCalcado.getNextCalcado();
startTime = previousEndTime;
}
I have tried changing it to this...
protected void updateStartTime(ScoreDirector scoreDirector,Calcado calcado) {
CalcadoA calcadoAnterior = calcado.getCalcadoAnterior();
Calcado shadowCalcado = calcado;
Integer previousEndTime = (calcadoAnterior == null ? null : calcadoAnterior.getEndTime());
Integer startTime = previousEndTime;
scoreDirector.beforeVariableChanged(shadowCalcado, "startTime");
shadowCalcado.setStartTime(startTime);
scoreDirector.afterVariableChanged(shadowCalcado, "startTime");
}
but I end up getting a score corruption error.
The entity (Calcado{ 472 descricao= calcado22 tempoInicial: 2 Maquina{nome='Pos 1'}'})'s shadow variable (Calcado.startTime)'s corrupted value (1) changed to uncorrupted value (2) after all VariableListeners were triggered without changes to the genuine variables.
Maybe the VariableListener class (StartTimeUpdatingVariableListener) for that shadow variable (Calcado.startTime) forgot to update it when one of its sources changed.
Basically my goal is to whenever a entity is added to the chain, to be added to the end of the chain instead of the top.

Yes, that's suppose to happen.
An entity isn't really added to a chain, that's a side effect.
It's inserted after another entity or anchor. That entity or anchor is already in a chain, so it implies that the entity is also added to a chain.
Why does that matter? Well, given a chain of [Anchor-A, Entity-A1, Entity-A2, Entity-A3], OptaPlanner can choose to add an Entity-X after Anchor-A, Entity-A1, Entity-A2 or Entity-A3, resulting in 4 different possible new solution states. It will pick the best one. Turn on TRACE logging to see that happen.

Related

Using require() later in code and should one handle any exceptions thrown thereby

I have a kotlin class with a method
loadElements(e: Iterable<Int>) {
}
This then constructs a new copy of that Iterable as an ArrayList<Int> within the object.
It is a requirement that all the elements in that ArrayList<Int> be non-negative. It is considered a breach of contract by the caller if that is not met. I've been led to believe that "breach of contract" is something to be tested by require(), whereas check() is for testing logic internal to that method. Is this correct ?
All the examples I have seen, have the require() as the very first lines of code within the method. Is it, however, acceptable to run require() in a loop, like this ?
public fun loadElements(e: Iterable<Int>) {
elementArray.clear()
e.forEach {
require(it>=0)
elementArray.add(it)
moduleCount += it
}
if (elementCount %2 == 1)
elementArray.add(0)
check(elementCount %2 == 0)
computeInternalSizes()
}
Thing is, this means that part of the object's internals may already be set-up by the time the require() breach is detected: i.e., moduleCount will be wrong and computeInternalSizes() will never get called.
Now, of course I could just use a separate pass, with the first one checking for the require() condition, and then doing all the real work thereafter. This would mean that if the input came in as a Sequence<Int>, it would be forced to be terminal and multi-iterable.
If the require() throws, I would like to assume that the program cannot continue because a design error has occurred somewhere. However, if someone traps the resultant exception, and continues, I will end-up with an incoherent object state.
What is best practice for handling conditions where incoming parameter breaches won't be noticed until some significant unrewindable work has been done ?
I tried using a separate pass for checking for non-negativity. This worked perfectly well but, given that it could be coming from a Sequence or similar, I don't want to have to build the whole sequence, and then traverse that sequence again.
I tried using check(). This works, but it just shows up as an inconsistency in object state, rather than flagging up the incoming parameter validation, which is making a breach of contract look like an internal design fault, and just delaying the inevitable.
I've tried putting try/catch/finally all over the place, but this is an excessive amount of code for such a simple thing.
I'm not even sure if a program should attempt recovery if a require() fails.
In general you avoid situations like this, by reducing the scope of mutability in your code.
The difference between require and check is mostly a convention. They throw different Exceptions, namely IllegalArgumentException and IllegalStateException respectively. As the type of the Exceptions suggest, former is suited for validating the (user) input to a method whereas the latter is designed to check intermediate states during the runtime.
Exceptions in Kotlin should be handled as such, being an Exception that should not occur regularly. See also the Kotlin documentation why there are no checked exceptions in Kotlin.
You did not write the name of your surrounding Kotlin class, thus I'll call it Foo for the time being.
Rather than providing a function on Foo, that mutates the internal state of Foo, you could create new instances of Foo based on the Iterable<Int> / Sequence<Int>. This way, you only ever have an Foo object when its in a valid state.
private class Foo(source: Iterable<Int>) {
private val elementArray = ArrayList<Int>()
private val moduleCount: Int
init {
var internalCount = 0
for (count in source) {
require(count > 0)
elementArray.add(count)
internalCount += count
}
moduleCount = internalCount
if (elementArray.size % 2 == 1) {
elementArray.add(0)
}
check(elementArray.size % 2 == 0)
// ...
}
}
Alternatively, if you want / need to keep the interface as described in your question but also avoid the invalid state, you could make use of an intermediate copy.
As you're copying the incoming Iterable<Int> / Sequence<Int> into an ArrayList<Int> I assume you're not working with very large collections.
private class Foo(source: Iterable<Int>) {
private val elementArray = ArrayList<Int>()
private var moduleCount = 0
public fun loadElements(source: Iterable<Int>) {
val internalCopy = ArrayList<Int>()
for (count in source) {
require(count >= 0)
internalCopy.add(count)
}
elementArray.clear()
for (count in internalCopy) {
elementArray.add(count)
moduleCount += count
}
if (elementArray.size % 2 == 1) {
elementArray.add(0)
}
check(elementArray.size % 2 == 0)
// ...
}
}

Databinding is initialized in improper order by automatically generated executeBindings

Preface
I have a simple app with a viewmodel, a custom UI control, and a TextView. Databinding is setup like this:
LiveData -> control.value -> control.preValue -> TextView
When LiveData is changed, databinding notifies control.value of the new value. control.value setter has a line which also gives the new value to control.preValue. Both properties have calls to their respective databinding listeners to notify databinding that the values have changed and that the UI should be updated. The text value of TextView is bound to control.preValue, so when the listener is notified, the TextView is updated.
This works well at runtime, however there is a problem at initialization.
The Problem
When the UI is first constructed, the LiveData value is not correctly propagated to the TextView. This is because the listeners have not yet been created by the android databinding library, so when control.preValue is set by control.value's setter, the listener is still null.
Diving deeper into executeBindings we can see the cause of the problem.
executeBindings is a function which is part of the *BindingImpl file automatically generated by the databinding library based on the Binding Adapters I have defined. It is responsible for initializing databinding, e.g. creating listeners, registering livedatas, and setting initial values to the UI.
executeBindings starts like this. It initializes variables for all the databound values.
#Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
java.lang.Integer viewmodelBpmGetValue = null;
androidx.lifecycle.MutableLiveData<java.lang.Integer> viewmodelBpm = null;
int bpmPickerPreValue = 0;
androidx.lifecycle.MutableLiveData<java.lang.Boolean> viewmodelPlaying = null;
java.lang.String integerToStringBpmPickerPreValue = null;
int androidxDatabindingViewDataBindingSafeUnboxViewmodelBpmGetValue = 0;
com.okos.metronome.MetViewModel viewmodel = mViewmodel;
Next, it gets the value of control.preValue property and stores it in the earlier created variable. This is already the core of the problem. At this point control.preValue is still at the default value that is defined in the control's definition class, not the LiveData value which will be assigned to it a bit later.
if ((dirtyFlags & 0x18L) != 0) {
// read bpmPicker.preValue
bpmPickerPreValue = bpmPicker.getPreValue();
// read Integer.toString(bpmPicker.preValue)
integerToStringBpmPickerPreValue = java.lang.Integer.toString(bpmPickerPreValue);
}
Next we get the LiveData value from the viewmodel and register it with databinding
if ((dirtyFlags & 0x15L) != 0) {
if (viewmodel != null) {
// read viewmodel.bpm
viewmodelBpm = viewmodel.getBpm();
}
updateLiveDataRegistration(0, viewmodelBpm);
if (viewmodelBpm != null) {
// read viewmodel.bpm.getValue()
viewmodelBpmGetValue = viewmodelBpm.getValue();
}
// read androidx.databinding.ViewDataBinding.safeUnbox(viewmodel.bpm.getValue())
androidxDatabindingViewDataBindingSafeUnboxViewmodelBpmGetValue = androidx.databinding.ViewDataBinding.safeUnbox(viewmodelBpmGetValue);
}
Here it sets control.value to the value of the LiveData in the first if block. This line will trigger the control.value setter, which will set control.preValue, and those setters will both try to call their respective onChange listeners but they will be null because executeBindings hasn't created them yet. They are created in the 2nd if block.
if ((dirtyFlags & 0x15L) != 0) {
// api target 1
this.bpmPicker.setValue(androidxDatabindingViewDataBindingSafeUnboxViewmodelBpmGetValue);
}
if ((dirtyFlags & 0x10L) != 0) {
// api target 1
com.okos.metronome.view.DialPickerBindingAdapter.setPreValueListener(this.bpmPicker, (com.okos.metronome.view.PrePickerBase.OnValueChangeListener)null, bpmPickerpreValueAttrChanged);
com.okos.metronome.view.DialPickerBindingAdapter.setValueListener(this.bpmPicker, (com.okos.metronome.view.PrePickerBase.OnValueChangeListener)null, bpmPickervalueAttrChanged);
}
Finally, the value of the TextView is set, but it is set to the original value of preValue which we cached in a variable in the very first if block. **Not the new value which has been updated to preValue from the LiveData since then.
if ((dirtyFlags & 0x18L) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tvBpmDisplay, integerToStringBpmPickerPreValue);
}
This seems like an oversight in the databinding library, and I wonder if anyone has any ideas of getting around this? The fix seems pretty simple to just move the first if block in executeBindings down so integerToStringBpmPickerPreValue is set after the value has been set from LiveData, but because executeBindings is automatically generated, I can't do that. There are some ways of changing the order of execution in executeBindings, like which order the bindings are defined in the xaml, but none of that affects the parts I want to change.

How to repeat Mono while not empty

I have a method which returns like this!
Mono<Integer> getNumberFromSomewhere();
I need to keep calling this until it has no more items to emit. That is I need to make this as Flux<Integer>.
One option is to add repeat. the point is - I want to stop when the above method emits the first empty signal.
Is there any way to do this? I am looking for a clean way.
A built-in operator that does that (although it is intended for "deeper" nesting) is expand.
expand naturally stops expansion when the returned Publisher completes empty.
You could apply it to your use-case like this:
//this changes each time one subscribes to it
Mono<Integer> monoWithUnderlyingState;
Flux<Integer> repeated = monoWithUnderlyingState
.expand(i -> monoWithUnderlyingState);
I'm not aware of a built-in operator which would do the job straightaway. However, it can be done using a wrapper class and a mix of operators:
Flux<Integer> repeatUntilEmpty() {
return getNumberFromSomewhere()
.map(ResultWrapper::new)
.defaultIfEmpty(ResultWrapper.EMPTY)
.repeat()
.takeWhile(ResultWrapper::isNotEmpty)
}
// helper class, not necessarily needs to be Java record
record ResultWrapper(Integer value) {
public static final ResultWrapper EMPTY = new ResultWrapper(null);
public boolean isNotEmpty() {
return value != null;
}
}

Optaplanner: NullPointerException when calling scoreDirector.beforeVariableChanged in a simple custom move

I am building a Capacited Vehicle Routing Problem with Time Windows, but with one small difference when compared to the one provided in examples from the documentation: I don't have a depot. Instead, each order has a pickup step, and a delivery step, in two different locations.
(like in the Vehicle Routing example from the documentation, the previousStep planning variable has the CHAINED graph type, and its valueRangeProviderRefs includes both Drivers, and Steps)
This difference adds a couple of constraints:
the pickup and delivery steps of a given order must be handled by the same driver
the pickup must be before the delivery
After experimenting with constraints, I have found that it would be more efficient to implement two types of custom moves:
assign both steps of an order to a driver
rearrange the steps of a driver
I am currently implementing that first custom move. My solver's configuration looks like this:
SolverFactory<RoutingProblem> solverFactory = SolverFactory.create(
new SolverConfig()
.withSolutionClass(RoutingProblem.class)
.withEntityClasses(Step.class, StepList.class)
.withScoreDirectorFactory(new ScoreDirectorFactoryConfig()
.withConstraintProviderClass(Constraints.class)
)
.withTerminationConfig(new TerminationConfig()
.withSecondsSpentLimit(60L)
)
.withPhaseList(List.of(
new LocalSearchPhaseConfig()
.withMoveSelectorConfig(CustomMoveListFactory.getConfig())
))
);
My CustomMoveListFactory looks like this (I plan on migrating it to an MoveIteratorFactory later, but for the moment, this is easier to read and write):
public class CustomMoveListFactory implements MoveListFactory<RoutingProblem> {
public static MoveListFactoryConfig getConfig() {
MoveListFactoryConfig result = new MoveListFactoryConfig();
result.setMoveListFactoryClass(CustomMoveListFactory.class);
return result;
}
#Override
public List<? extends Move<RoutingProblem>> createMoveList(RoutingProblem routingProblem) {
List<Move<RoutingProblem>> moves = new ArrayList<>();
// 1. Assign moves
for (Order order : routingProblem.getOrders()) {
Driver currentDriver = order.getDriver();
for (Driver driver : routingProblem.getDrivers()) {
if (!driver.equals(currentDriver)) {
moves.add(new AssignMove(order, driver));
}
}
}
// 2. Rearrange moves
// TODO
return moves;
}
}
And finally, the move itself looks like this (nevermind the undo or the isDoable for the moment):
#Override
protected void doMoveOnGenuineVariables(ScoreDirector<RoutingProblem> scoreDirector) {
assignStep(scoreDirector, order.getPickupStep());
assignStep(scoreDirector, order.getDeliveryStep());
}
private void assignStep(ScoreDirector<RoutingProblem> scoreDirector, Step step) {
StepList beforeStep = step.getPreviousStep();
Step afterStep = step.getNextStep();
// 1. Insert step at the end of the driver's step list
StepList lastStep = driver.getLastStep();
scoreDirector.beforeVariableChanged(step, "previousStep"); // NullPointerException here
step.setPreviousStep(lastStep);
scoreDirector.afterVariableChanged(step, "previousStep");
// 2. Remove step from current chained list
if (afterStep != null) {
scoreDirector.beforeVariableChanged(afterStep, "previousStep");
afterStep.setPreviousStep(beforeStep);
scoreDirector.afterVariableChanged(afterStep, "previousStep");
}
}
The idea being that at no point I'm doing an invalid chained list manipulation:
However, as the title and the code comment indicate, I am getting a NullPointerException when I call scoreDirector.beforeVariableChanged. None of my variables are null (I've printed them to make sure). The NullPointerException doesn't occur in my code, but deep inside Optaplanner's inner workings, making it difficult for me to fix it:
Exception in thread "main" java.lang.NullPointerException
at org.drools.core.common.NamedEntryPoint.update(NamedEntryPoint.java:353)
at org.drools.core.common.NamedEntryPoint.update(NamedEntryPoint.java:338)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.update(StatefulKnowledgeSessionImpl.java:1579)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.update(StatefulKnowledgeSessionImpl.java:1551)
at org.optaplanner.core.impl.score.stream.drools.DroolsConstraintSession.update(DroolsConstraintSession.java:49)
at org.optaplanner.core.impl.score.director.stream.ConstraintStreamScoreDirector.afterVariableChanged(ConstraintStreamScoreDirector.java:137)
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.retract(SingletonInverseVariableListener.java:96)
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.beforeVariableChanged(SingletonInverseVariableListener.java:46)
at org.optaplanner.core.impl.domain.variable.listener.support.VariableListenerSupport.beforeVariableChanged(VariableListenerSupport.java:170)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:430)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:390)
at test.optaplanner.solver.AssignMove.assignStep(AssignMove.java:98)
at test.optaplanner.solver.AssignMove.doMoveOnGenuineVariables(AssignMove.java:85)
at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:35)
at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:30)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:187)
at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.doMove(LocalSearchDecider.java:132)
at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.decideNextStep(LocalSearchDecider.java:116)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:70)
at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:98)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:189)
at test.optaplanner.OptaPlannerService.testOptaplanner(OptaPlannerService.java:68)
at test.optaplanner.App.main(App.java:13)
Is there something I did wrong? It seems I am following the documentation for custom moves fairly closely, outside of the fact that I am using exclusively java code instead of drools.
The initial solution I feed to the solver has all of the steps assigned to a single driver. There are 15 drivers and 40 orders.
In order to bypass this error, I have tried a number of different things:
remove the shadow variable annotation, turn Driver into a problem fact, and handle the nextStep field myself => this makes no difference
use Simulated Annealing + First Fit Decreasing construction heuristics, and start with steps not assigned to any driver (this was inspired by looking up the example here, which is more complete than the one from the documentation) => the NullPointerException appears on afterVariableChanged instead, but it still appears.
a number of other things which were probably not very smart
But without a more helpful error message, I can't think of anything else to try.
Thank you for your help

Variable result not what it should be

I have these three implementations, that (should) do essentially the same: return the current position of Android exoplayer or 0 as integer.
But only nr. 1 works. Nr. 2 and nr.3 always return 0, even though player is instantiated. Is that expected behaviour?
1.
private var playbackPosition = 0
get() {
return if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
}
2.
private var playbackPosition = if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
3.
private var playbackPosition = when(player) {
null -> 0
else -> player?.currentPosition?.toInt() as Int / 1000
}
Number 1 are an implementation of a get function and invoked every time you access the variable.
Number 2 and 3 initialize a variable and the right side are only invoked once at creation time of the variable. Means the playback position is calculated only once.
The behavior works like designed. If you need the new position every time you access the variable you have to use an own getter function.
Because of the question, I assume you're not that familiar with Kotlin and/or Java, so I'm going to explain the difference between the two.
First of all, you need to understand the difference between a function and a variable/constant. A function can have a varying result when it's called (assuming it's not a void/Unit), but a variable has a fixed result until it's updated. Take this:
var toggle = Random().nextBoolean()
var dependent = if(toggle) 0 else 1
toggle = !toggle
If you print the variable before and after the toggle is switched, the variable will not change. When it's been assigned, it stays with that value until something updates it. So if you add print statements, it will be the same. Let's expand on that:
var toggle: Boolean = Random().nextBoolean()
fun someFunction() : Int = (if(toggle) 0 else 1).also { toggle = !toggle }
The also block here is an extension function that lets you do stuff, but still return the variable it's called on. Here, either 1 or 0 is returned, and the toggle is inverted. If you call this two times, you'll see a different result. This is because you get a different value based on a condition. Again, you see the value doesn't change even though the toggle does.
TL;DR: Variables have a given value until changed. Methods returning values can change based on conditions, because it's updated every time it's called.
Now, what does this mean for your code?
First of all, for the first snippet, you should use val instead. Kotlin is really nice like that; if you override the getter of a val, you don't need to initialize it. It's called backing fields.
Anyways, this:
private val playbackPosition
get() {
return if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
}
returns a value depending on the player variable when it is called. Where as the other examples:
private var playbackPosition = if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
private var playbackPosition = when(player) {
null -> 0
else -> player?.currentPosition?.toInt() as Int / 1000
}
Set the value when they're defined. You could change those to a val too; they aren't automatically re-assigned.
Initial assignment, that being the code you have there, is only run once, and that's when the class is initialized. If the variable is inside a method, the variable is initialized when the method is called. lateinit vars can be set at a later time, but initial assignment is only run once. For any changes you'll need to update it.
However, this is where methods come in handy. Depending on what you have, you could also create a backing field, a "cache" in a way. This isn't necessary unless object creation is heavy. You don't need to worry about this for something as simple as integers. Using a method that returns the value (in your case, the getter), is kinda like doing this:
var x: Int = updateValue()
fun updateValue() : Int = if ... // alternatively does x = instead of returning an int
...
x = updateValue()
x.let { foo bar }
Although that is a considerably harder way of doing stuff.
But only Nr. 1 works. Nr. 2 and Nr.3 always return 0, although player is instantiated.
If you get 0 all the time for 2 and 3, that means player == null when the variables were intiailized, but it wasn't null when the getter for the first example was called.
Is that expected behaivour?
Considering the code, yes. It's by design.
TL;DR: Again, variables aren't automatically updated when a creating condition (i.e. player == null) changes. You'll either need to manually update it, or use methods over variables.