I would like to know whether the following use-case is intended to be solved with Optaplanner.
Problem description
Problem picture
There is a vehicle that needs to go from Start to End (location to location) over a mesh of nodes.
Nodes are connected with "nodeConnection" and there can be many nodeConnections between two nodes. NodeConnection also contains the price of that route.
I need a solution that tells me list of nodeConnections to take.
Number of NodeConnections that the vehicle will take is unknown. vehicle might go A - B and only take 1 NodeConnection, or go A - D and take 3 NodeConnections ( A-B connection B-C connection and then C-D connection)
What is required
Basically I'd like to give Optaplanner an input of 2 Nodes (locations) and a list of available NodeConnections and get back an "optimal" route for that input.
I'd like to know which route is cheapest, eg. in the provided image it's the one marked with a green line because total trip cost is 150.
What I tried
I thought that I could have NodeConnection collection as a #PlanningProperty, however that is currently not supported by OptaPlanner.
Then I came across planning variable not support Collect and tried to have a RouteNodeConnection as a many-to-many relation between a Route and a NodeConnection, eg. 1 route would have N NodeConnections - but we do not know how much, we just want the "best" route.
The problem at the moment is "telling" OptaPlanner what we want and setting up the Constraints.
VRP repository seemed similar but there are differences:
I only use 1 vehicle, not an entire fleet
no need to go back to the starting point
no need to calculate various distances since NodeConnection prices/distances are already defined
I read about chained #PlanningVariables and it seems that that approach must be taken here to create a chain of NodeConnections, however I am not sure how to setup the constraints and get OptaPlanner to actually return the best route.
Is this something that can be done with OptaPlanner or a more simpler solution might be enough here. I looked at Dijkstra's Algorithm to get the shortest path and then we'd have to figure out how to "weight" other constraints I will introduce later and so on but OptaPlanner seems more fit for this problem - especially considering the fact that other than price, we're most likely going to have additional 5 hard and over 10 soft constraints that would be hard to "weigh" in graph algorithms.
Any tips on how to approach this problem are very welcome.
Classes for reference:
public class Node {
private String Name;
}
public class NodeConnection {
private Node StartPosition;
private Node EndPosition;
private BigDecimal Price;
}
public class Route {
private Node Start;
private Node End;
private BigDecimal RoutePrice;
private List<NodeConnection> NodeConnections;
}
// "Many-to-many" relation
public class RouteNodeConnection {
private Route Route;
private NodeConnection NodeConnection;
}
Related
TL;DR
How to model a process where the duration of one task depends on the finish time of its predecessor task in chained through time pattern. For more details please read the following description:
Planning Problem Description
First of all I want to describe my planning problem:
Constraints
A machine has x slots and can produce or cool different types of products in each of its slots.
A machine could not produces and cool at the same time, but it could produces first and than cool afterwards.
A machine can produce only one type of product at a time, but it can produce different types of products one after the other.
A machine could produces multiple products of the same type at the same time
A machine could cool different types of products at the same time
The products are consumed at a target time
Produced products must be cooled until target time
Planning Goals
Minimize production time
Determine the latest time at which the production must be started
Examples of valid processes
The following picture illustrates two valid production processes. The Machines are on the right end of the process because the PlanningEntities are chained through time backwards starting with the target time.
Domain Model
I have modeled the problem with the chained through time pattern since the shortest duration of a production job is less than a minute. So I have to plan in seconds. Maybe this would be to fine grained for the time grain pattern.
The following code is an excerpt from my domain model.The abstract class JobOrSlot is used to model the chain of jobs anchored by a slot.
#PlanningEntity
public abstract class JobOrSlot {
#Id
private UUID id = UUID.randomUUID();
#InverseRelationShadowVariable(sourceVariableName = "previousJobOrSlot")
protected Job nextJob;
public abstract Integer getStartOffset();
}
#PlanningEntity
public class Job extends JobOrSlot {
#PlanningVariable(valueRangeProviderRefs = { "slotRange", "jobRange" }, graphType = PlanningVariableGraphType.CHAINED)
private JobOrSlot previousJobOrSlot;
#AnchorShadowVariable(sourceVariableName = "previousJobOrSlot")
private Slot slot;
#ShadowVariable(variableListenerClass = EndTimeUpdatingVariableListener.class, sourceVariableName = "previousJobOrSlot")
private Integer startOffset;
#PiggybackShadowVariable(shadowVariableName = "startOffset")
private Integer endOffset;
// problem facts
#Nullable
private Job predecessor;
#Nullable
private Job successor;
private Duration duration;
private JobType type; // produce, hold
// ... unecessary problemfacts and getter and setter omitted
}
The EndTimeUpdatingVariableListener.class iterates through the chains of jobs and calculates the start and end times of the jobs based on their duration and their position in the chain.
The Problem
The challenge is, that the duration of the cooling job is not known before the planning starts. The duration of the cooling job can only be calculated in the moment the production job is placed. It is targetTime - cookingJob.endTime. So placing a production job must change the duration of the cooling job and I can't find a good solution to model this in Optaplanner. I have evaluate two possible soloutions but maybe you have a better idea to implement this.
One Solution would be to update the associated cooling job start and end times in the EndTimeUpdatingVariableListener every time its production job changes, but this could create effects which are hard to tackle. E.G. Placing another job between the production job and its cooling job like produce A -> someOtherJob -> cool A -> Slot would create an infinite update loop. This could be tackled by implementing a MoveFilter to forbid such invalid moves but its still pain.
Another solution could be to implement CustomMoves that add or remove cooling jobs from the planning problem. Every time a cooling job is added it gets the current valid duration. Hence the duration of the Entity is fixed during planning.
Both implementation getting pretty complex. Is there a better way to model such a planning entity depedency in optaplanner?
I have to write a code which involves making a web service call to a backend asynchronously and returning a toll free number in round robin from a list of TFNs to the caller. Below is my code
#Stateless
public class TollFreeServiceBean {
#EJB
private AsyncBackendService asyncBean;
public long getTollFreeNumber(Request request) {
//Validate request
asyncBean.callBackend(request);
return TFNUtil.getNext();
}
}
#Stateless
public class AsyncBackendService {
#Asynchronous
public void callBackend(Request request) {
// Call web service and inform a caller with `Request` is going to call
}
}
public class TFNUtil {
private static int index = 0;
private TFNUtil(){}
public static synchronized long getNext() {
// Get TFN list from cache
if(tfnList.size() >= index) {
index = 0;
}
long tfn = tfnList.get(index);
index++;
return tfn;
}
}
The idea is that the customers will get a different TFN each until the TFNs in the cache are completed. Once completed, the next customer should get the first TFN again. For example if there are 10 TFNs and 11 customers, 11th customer should receive 1st TFN. 12th customer should receive 2nd TFN and so on.
The backend system is complaining that two different simultaneous customers are landing on the same TFN. So I think my TFNUtil.getNext() logic is not right.
Can anyone please point out the bug here?
Your statements are contradicting themselves.
On the one hand, you are worried that no two customers should receive the same number.
On the other hand, you purposely put a system into place that will exactly do that.
You see, depending on how many elements your list tfnList has ... your method getNext() might "spill over" pretty quickly. And what do you think will happen then?
To me, it sounds like the real solution is more complex: you might have to re-design your system. Instead of just rotating that list of numbers, you might need a system that is able to block/reserve a number for some time. And while a number is reserved, it is not handed out again.
A simple version of that would be "time" based only; meaning that a reservation "vanishes" automatically after some X minutes/hours. If that doesn't work; you would have to go one step further: and find something/somebody in your workflow that to unreserve numbers to render them "available" again.
And beyond that, it seems that you didn't fully consider what should happen when your have N numbers available, but N+x customers coming in at the same time! No round-robin'ing/rotating ... whatever can help you there! If that situation is possible, then you have to deal with it and define what should happen then!
My problem is a modification of the Capacitated Vehicle Routing Problem (CVRP) that will eventually include time windows as well.
Since time windows are already built into the examples, it shouldn't be too hard for me to figure them out. However, I need to change one of the core constraints of the CVRP examples, and I'm a bit lost on how to do it.
My Model
In the system I'm trying to model, a Vehicle can leave its Depot, go to several different Customers, and load up on material. However, where my model differs from the examples is that the Vehicle can visit any Depot mid-chain to deposit its current load.
Issues
I've been going over the documentation trying to figure out how to do this, and my basic understanding so far is that I'd have to change the definition of Depot (maybe by implementing Standstill) to be able to be part of the chain of places the vehicle visits, and/or maybe just integrate Depot into Customer with some kind of special rule that a visit to a Depot empties the vehicle instead of increasing the demand.
I've also been looking at shadow variables and variable listeners, but I don't know if that's the right way to go. It's all a little confusing.
Can anyone offer some tips or advice, or point me in the right direction as to where to start before I dig myself too far into a hole?
Based on Geoffrey's suggestion, rename your Vehicle class to VehicleTrip and let it point to the previous and the next trip by giving it a value previousVehicleTrip and nextVehicleTrip, and give it a variable start time and end time (code examples in Kotlin):
class VehicleTrip(
...,
var startTime: LocalDateTime? = null,
var endTime: LocalDateTime? = null,
val previousVehicleTrip?: VehicleTrip = null,
val nextVehicleTrip?: VehicleTrip = null
) : Standstill {
...
}
You can set these values when initiating your VehicleTrips. When you get a StackOverFlowError based on the VehicleTrip.hashCode(), simply override the hashCode() function of the VehicleTrip class. (Maybe someone has a better suggestion for dealing with this?)
Updating the shadow variables.
In your Customer class, you should have a variable arrivalTime (like in the CVRPTW example) which is a custom shadow variable. In the listener class of this variable you usually only update the arrival time of a vehicle at a customer, and the arrival times of the customers that come next in this trip. Now, you also need to update all the times of the trips that come after the trip your current customer is in.
For example, you might have two trips VT1 and VT2, and three customers C1, C2, and C3. When changing from
VT1 - C1 - VT2 - C2 - C3
to
VT1 - C2 - C1 - VT2 - C3
the things you want updated are (in order)
C2.arrivalTime
C1.arrivalTime
VT1.endTime
VT2.startTime
C3.arrivalTime
VT2.endTime
Notice that in the TimeWindowedCustomer example, the variable listener only does steps 1. and 2., so we have to add steps 3. until 6.
To do this, start by adding #CustomShadowVariable annotations to the start and end times of VehicleTrip (and don't forget to mark VehicleTrip as a planning entity), which uses the same variable listener class as the time windowed customer:
class VehicleTrip(
...,
#CustomShadowVariable(
variableListenerRef = PlanningVariableReference(
entityClass = TimeWindowedCustomer::class,
variableName = "arrivalTime"
))
var startTime: LocalDateTime? = null,
...
) : Standstill {
...
}
Now in the ArrivalTimeUpdatingVariableListener class, you can add steps 3. until 6. similar to how steps 1. and 2. are implemented. Make sure that you keep the order of updating these variables, and that you notify the ScoreDirector when changing a variable with the beforeVariableChanged() and afterVariableChanged() methods.
My question is about scalable logic branching.
Is there an elegant way to do branching logic trees in java (although I've always thought that they look more like root systems, but that's beside the point). I'm trying to develop a very simple text based adventure game as a side project to my studies, but I'm not sure what the best way to go about navigating these large logic systems is.
What I'm trying currently is an array that holds four values: stage, location, step, choice.
[EDIT - added choice variable to store user choice, changed name to reflect actual name in my code so that I don't get confused later]
int[] decisionPoint = {stage, location, step, choice};
A stage is supposed to represent a single major part of the tree.
A location is supposed to represent my location within the tree.
A step is supposed to represent my progress through a given location.
Choice is the user input
At the moment, since I'm only dealing with a single tree, stage isn't being used much. Location and step are working well, but any time I get into a decision within a step the system breaks down.
I could keep creating more and more variables to represent deeper and deeper layers into the tree, but I feel like Java probably provides a better solution somewhere.
Currently, I'm using switch statements to figure out where in the program I am based on the values stored in nextQuestion. Is there something better? Or, is there a way to extend the array beyond what I'm using here to make it a bit more polymorphic (in the methods for the individual questions/text/whatever could I just have it create a larger array from a smaller one? Could I pass a smaller array as an argument but define the parameter as a larger array?)
//Switch example
switch(LocationTracker.getLocation()) { //start location finding switch
case 1 : //Location 1
switch (LocationTracker.getStep()) {//start location1 switch
case 1 :
location1s1(graphicsStuff);
break;
case 2 :
location1s2(graphicsStuff);
break;
} break; //end location1 switch
case 2 : //Location 2
switch (LocationTracker.getStep()) {
//same stuff that happened above
} break;
Everything I find online just brings me to irrelevant pages about different online survey creators that I can use. If I could view their source-code that'd be kind of nice, but since I can't, I'm hoping you guys can help. :)
[EDIT]
Wow, what a nice response in such a short time at such an early hour!
I'll try to go into very explicit detail about how I'm solving the problem right now. It's worth mentioning that this does technically work, it's just that every time I need a branch inside a branch I have to create another variable inside a string array to keep track of my position, and really I'm just fishing for a solution that doesn't need an infinitely expanding string as the program becomes more and more complex.
Right now I have a program with 5 classes:
The Main Class which starts the GUI
The GUI class which provides three services: userInput, userOptions, and outputArea.
The DecisionTreeStage1 class which handles the logic of my problem at the moment (using switch statements).
The LocationTracker class which is designed to track my location within the DecisionTreeStage1 class
The DialogueToOutput class which changes the options that the users have, and also updates the output fields with the results of their actions.
Special point of interest:
I want to have multiple decision branches at some point, and one main tree (maybe call it Yggdrasil? :D). For now, the DecisionTreeStage1 represents a very isolated system that isn't planning to go anywhere. I hope to use the stage variable stored in my array to move from one major branch to the next (climbing the tree if you will). My current implementation for this just uses nested switch statements to decide where I'm going. This imposes an annoying limitation: every time my path gets deeper and deeper I need another variable in my array to store that data. For example:
//Switch example deeper
switch(LocationTracker.getLocation()) { //start location finding switch
case 1 : //Location 1
switch (LocationTracker.getStep()) {//start location1 switch
case 1 :
switch(LocationTracker.getChoice()) {//Make a decision at this step based on the user choice
Given this example, what if the user choice doesn't just lead to some logic? (In this case, just an update to the outputArea) What if it leads to ANOTHER branching path? And that leads to another branching path? Eventually, I would want all paths to converge on the same spot so that I could move to the next "stage."
My real hope is to make this problem infinitely scalable. I want to be able to go as deep into one branch as I need to, without having to create a static and arbitrary number of variable declarations in my decisionPoint array every time.
I haven't been able to find much information about this, like I said.
Let me try presenting this question: Are there any other branching logic statements other than:
if(something)
stuff;
else
otherStuff;
and
switch(something) {
case 1:
stuff;
break;
case 2:
otherStuff;
break;
And if so, what are they?
PS - I know about the ternary if statement in Java, but it doesn't seem useful to what I'm doing. :)
You can build normal tree structures in Java, similar to the trees that can be built in C. Regardless if object references are theoretically pointers or not, they substitute pointers nicely in the tree constructions:
class Node {
Node left;
Node right;
Node parent;
}
You can also build graphs (cyclic graphs including) and linked lists no problem. There is no any obvious reason why large structures should have problems (apart from that object reference uses some memory).
Instead of returning a value, you could return an Callable which just needs to be executed. This can then be chained (theoretically infinitely)
You can have a LocationEvaluation for example which could return a SpecificLocationEvaluator which in turns returns one of StepEvaluation or ChoiceEvaluator or somesuch. All of these would implement the Callable interface.
Depending on how you do it, you could have strict type checking so that a LocationEvaluation always returns a SpecificLocationEvaluator or it can generic and then you can chain any of then in any order.
Once you build the structure, out, you would essentially have a tree which would be traversed to solve it.
I don't understand the problem adequately to be able to provide more concrete implementation details - and apologies if I misunderstood some of the branching (i.e. the names of the classes / steps above)
I'm missing some kind of collection functionality for a specific problem.
I'd like to start with a few informations about the problem's background - maybe there's a more elegant way to solve it, which doesn't end in the specific problem I'm stuck with:
I'm modelling a volume mesh made of tetrahedral cells (the 2D-analog would be a triangle mesh). Two tetrahedrons are considered to be adjacent if they share one triangle-face (which occupies three vertices). My application has to be able to navigate from cell to cell via their common face.
To meet some other requirements I had to split the faces into two so-called half-faces which share the same vertices but are belonging to different cells and have opposite orientation.
The application needs to be able to do calls like this (where Face models a half-face):
Cell getAdjacentCell(Cell cell, int faceIndex) {
Face face = cell.getFace(faceIndex);
Face partnerFace = face.getPartner();
if (partnerFace == null) return null; // no adjacent cell present
Cell adjacentCell = partnerFace.getCell();
return adjacentCell;
}
The implementation of the getPartner()-method is the method in question. My approach is as follows:
Face-objects can create some kind of a immutable Signature-object containing merely the vertex-configuration, the orientation (clockwise (cw) or counter-clockwise (ccw)) and a back-reference to the originating Face-object. Face.Signature-objects are considered to be equal (#Override equals()) if they occupy the same three vertices - regardless of their orientation and their associated cell.
I created two sets in the Mesh-objects to contain all half-faces grouped by their orientation:
Set<Face.Signature> faceSignatureCcw = new HashSet<Face.Signature>();
Set<Face.Signature> faceSignatureCw = new HashSet<Face.Signature>();
Now I'm able to determine if a partner exists ...
class Face {
public Face getPartner() {
if (this.getSignature().isCcw()) {
boolean partnerExists = this.getMesh().faceSignatureCw.contains(this);
} else {
boolean partnerExists = this.getMesh().faceSignatureCcw.contains(this);
}
}
}
... but Set does not allow to retrieve the specific object it contains! It merely confirms that it contains an object that matches via .equals().
(end of background informations)
I need a Collection-concept which provides the following functionality:
add a Face-Object to the Collection (duplicates are prohibited by the application and thus cannot occur)
retrieve the partner from the Collection for a given Face-Object that .equals() but has the opposite orientation
A possible (but way to slow) solution would be:
class PartnerCollection {
List<Face.Signature> faceSignatureCcw = new ArrayList<Face.Signature>();
List<Face.Signature> faceSignatureCw = new ArrayList<Face.Signature>();
void add(Face.Signature faceSignature) {
(faceSignature.isCcw() ? faceSignatureCw : faceSignatureCcw).add(faceSignature);
}
Face.Signature getPartner(Face.Signature faceSignature) {
List<Face.Signature> partnerList = faceSignature.isCcw() ? faceSignatureCw : faceSignatureCcw;
for (Face.Signature partnerSignature : partnerList) {
if (faceSignature.equals(partnerSignature)) return partnerSignature;
}
return null;
}
}
To be complete: The final application will have to handle hundreds of thousands of Face-Objects in a real-time environment. So performance is an issue.
Thanks in advance to anyone who at least tried to follow me up to this point :)
I hope there's anyone out there having the right idea to solve this.
Anything wrong with using two Map<Face.Signature, Face.Signature>?
One for each direction?
That's what I'd do. There's practically no code to it.
It's late night here and I haven't ready your question completely. So, I apologize if this doesn't make any sense, but do have you considered using a graph data structure? If the graph data structure is indeed a possible solution, you might want to check out jGraphT
Have you considered just giving each Face a partner data member? As in,
public class Face
{
Face partner;
//whatever else
}
The Face.Signature construct is a bit hairy and really shouldn't be needed. If every face has a partner (or enough Face objects can have a partner that it makes sense to think that there is a has-a relationship between a Face and a partner Face), the connection should just be an instance variable. If you can use this approach, it should vastly simplify your code. If not, post back the reason this doesn't work for you so that I can keep trying to help.
Using the design you have now, there is no way around something needing to iterate somewhere. The question is, where you want that iteration to occur? I suggest you do this:
List<Face.Signature> partnerList = faceSignature.isCcw() ? faceSignatureCw : faceSignatureCcw;
int idx = partnerList.indexOf(faceSignature);
if(idx == -1)
return null;
return partnerList.get(idx);
Also, as long as you are using Lists, and know that the initial size will have to be pretty big, you might as well say, new ArrayList(100000) or so.
Of course, this isn't the only method, just one that ensures the iteration will be optimal.
EDIT: After some thought, I believe the ideal data-structure for this would be an Octuply Linked List, which can make things confusing, but also very fast (comparatively).