OptaPlanner Bin Packing with Three Planning Entities: Is my Model an Efficient Modeling Approach? - modeling

I am concerned I am not modeling my problem well. I think I may be able to get away without using shadow variables and that I should be able to have aliquots and boxes as the only planning entities. Could you all suggest changes to improve my approach?
I am optimizing the assignment of sample aliquots into boxes and then these boxes into the racks of available freezers. There are hundreds of thousands of aliquots, hundreds of boxes, and tens of freezers.
More aliquots are collected over time and the number of boxes used to store these aliquots cannot be known ahead of time because there are two vial heights, each requiring a different height box. The taller box takes up the room of two shorter boxes on a rack. Aliquots also have a sample type.
Main constraints are:
Storing as few sample types per freezer as possible (i.e., ideal = all aliquots in Freezer1 are the same sample type)
Each sample draw event produces multiple aliquots. These aliquots from the same draw event should be split between two, and only two, freezers to prevent loss due to freezer failure.
Respect capacities of Racks and Boxes.
Each aliquot and box must be stored.
Storing a taller box in a rack requires removing a row divider in a rack. This results in that row only be used for taller boxes. Rows on a rack have 5 columns so for every 5 taller boxes, we loose capcity for 5 shorter boxes.
Domain Model
#PlanningEntity
public class Rack {
#InverseRelationShadowVariable(sourceVariableName = "box")
private List<Box> boxes = new ArrayList<>();
private Long boxCapacity;
}
#PlanningEntity
public class Box {
#PlanningVariable(valueRangeProviderRefs = "rackRange", nullable = true)
private Rack rack;
#InverseRelationShadowVariable(sourceVariableName = "aliquot")
private List<Aliquot> aliquots = new ArrayList<>();
private Long boxHeight;
private Long aliquotCapacity;
}
#PlanningEntity
public class Aliquot {
#PlanningVariable(valueRangeProviderRefs = "boxRange", nullable = true)
private Box box;
private Long aliquotHeight;
private SampleType sampleType;
}
public class SampleType {
private String name;
}
#PlanningSolution
public class AliquotMap {
#ValueRangeProvider(id = "rackRange")
#ProblemFactCollectionProperty
private List<Rack> rackList;
#ValueRangeProvider(id = "boxRange")
#PlanningEntityCollectionProperty
private List<Box> boxList;
#ValueRangeProvider(id = "aliquotRange")
#PlanningEntityCollectionProperty
private List<Aliquot> aliquotList;
}
This is the model I am proposing. My use of shadow variables and planning entities seems to make the model more complex than it needs to be though. Could this model be made without them or is there an entirely different modeling approach I should take?

Related

Prime Faces - Select Many Check Box with multiple Selected List

I want to implement a select many check box. The source of list items are three different lists. I can handle the items to show in select list but the selected items also needs to be stored in three different Lists. How could we achieve this.
public class CheckBoxView {
private List<String> asianNames, americanNames, africanNames;
private List<String> selectedAsianNames, selectedAmericanNames, selectedAfricanNames;
}

How can i with Axon re-initialize some value with the same first InitAvailableQuantityCommand?

assume we have an stock. this stock should persist product id and available quantity. the user of this stock can frequently update(InitAvailableQuantityCommand) available quantity.
if some product has been sold, our system will get a soldEvent(DecreaseAvailableQuantityCommand) and available quantity for sold product should be decress.
it works well with aggregate below, until one thing,
if i try again to re-initialize stock with InitAvailableQuantityCommand, the event will be ignored and an error is thrown
An event for aggregate [3333] at sequence [0] was already inserted"
What i try to achive is following:
InitAvailableQuantityCommand (productId =1, quantity = 10)
DecreaseAvailableQuantityCommand (productId =1, quantity = 1)
DecreaseAvailableQuantityCommand (productId =1, quantity = 1)
now hier we have 8 available products more.
and it this moment user will re-initialize stock with 20 available products for productId 1. the user will send a new InitAvailableQuantityCommand (productId =1, quantity = 20) and it this moment it fail and doesn't work.
What do i wrong?
thx.
#NoArgsConstructor
#Aggregate
#Data
public class AvailableQuantityAggregate {
private String partnerId;
private String productId;
#AggregateIdentifier
private String productVariationId;
private int quantity;
#CommandHandler
public AvailableQuantityAggregate(InitAvailableQuantityCommand cmd) {
final ApplyMore apply = AggregateLifecycle.apply(AvailableQuantityInitializedEvent.builder()
.partnerId(cmd.getPartnerId())
.productId(cmd.getProductId())
.productVariationId(cmd.getProductVariationId())
.quantity(cmd.getQuantity())
.build());
}
#CommandHandler
public void handle(DecreaseAvailableQuantityCommand cmd) {
AggregateLifecycle.apply(AvailableQuantityDecreasedEvent.builder()
.productVariationId(cmd.getProductVariationId())
.quantity(cmd.getQuantity())
.build());
}
#EventSourcingHandler
protected void on(AvailableQuantityInitializedEvent event) {
this.productVariationId = event.getProductVariationId();
this.partnerId = event.getPartnerId();
this.productId = event.getProductId();
this.quantity = event.getQuantity();
}
#EventSourcingHandler
protected void on(AvailableQuantityDecreasedEvent event) {
this.quantity = this.quantity-event.getQuantity();
}
}
The InitAvailableQuantityCommand instantiates an Aggregate. Aggregates inherently have identity. As such, the Aggregate Identifier is in place to denote whom/what it is. When you are event sourcing, which you are by default in Axon, the Event Store will ensure that you will not add events with the same aggregate id and sequence number. When you are publishing the InitAvailableQuantityCommand a second time however, you are telling the framework to publish an event with the same aggregate id and sequence number.
Hence, your modelling solution should be a little different. The action (aka, the command) of instantiating the aggregate is different from resetting it. Thus I'd suggest to add a different command to reset your aggregate to it's initial values.
Judging from your code snippet, the InitAvailableQuantityCommand is handled by a constructor. This means that Axon expects to need to create a new instance of an aggregate. But as you are expecting to load an instance, there is a collision of identifiers (fortunately).
What you'd need to do, is create a different command that contains the same information, but is handled by an instance method. This might be what you want to do anyway, because there a conceptual/functional different between first-time initialization, and "resetting".
In future versions of Axon, we will support "create-or-update" kind functionality, where a single Command could fulfill both roles.

DDD collection: include version control in model

In my DDD attempt I've defined the following ubiquitous language:
A product can have multiple drawings. A drawing consists of a drawing number, a revision number* and multiple attachments**. A drawing can be revised by a new drawing with a different revision number.
Invariants:
for every drawing number a product has, there can only be one current revision.
there can be no drawings with the same drawing number and revision
*sometimes initially empty
**the attachments are the actual product drawings, can be .jpg, .pdf, .stp, etc.
Is there a mismatch in the language? These attachments can also be called the actual drawings where the above properties are merely metadata to programmatically distinguish them.
Some context, the application should help the business with the development of products. The drawings are concepts that after discussion and revisions will form a sample that must be approved by the customer. For this context, I've chosen an event-sourcing architecture because of the business value to evaluate the incremental development of products.
The problem I'm having is whether to put these past revisions in the model. This could be done by adding a boolean property to the drawings that indicate if they are the currently used drawing. This however goes against my gut-feeling to model drawings as immutable value objects (now the drawing has a mutable property). In my mind I've supported this gut-feeling with the argument that once a drawing is changed this results in a new drawing with a different revision number.
Another gut-feeling I have though, is that I should put the past revisions in the model as they have business value. Is it a good solution to let a product have a list of current drawings and past drawings?
How should I think about when a user wants to correct a drawing? For example, when someone didn't attach all correct files to the drawing and you later want to correct this by adding more files, or removing some?
Code example
To give a brief example with some code, this is one of the things I came up with, the drawing as an value-object that uses the drawing number and revision in the equals method:
public class Product {
private Set<Drawing> currentDrawings;
private Set<Drawing> oldDrawings;
}
public class Drawing {
private String drawingNumber;
private String revision;
private Set<URL> files;
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Drawing)) return false;
Drawing other = (Drawing ) o;
if (this.drawingNumber != other.drawingNumber) return false;
if (this.revision != other.revision) return false;
return true;
}
//getters and constructor omitted for brevity
}
Not enough reputation to answer Luiz E's comment, so I'll put it here instead: in some cases a product consists of different parts, materials, and so forth. Sometimes there's a clear parent drawing that referenced other subdrawings, other times there are just a bunch of drawings of parts that will be assembled later.
I tend to adhere to the "KISS" principle, instead of modeling all these different relations between the drawings that will only confuse the users (they are not the creators of the drawings).
For future references, when designing an aggregate according to DDD
principles, one should keep the aggregate clean and not pollute the
model with earlier versions of (parts of) the aggregate. Keep in mind
that you want the model to represent the current state of the
aggregate.
If earlier states of (parts of) the aggregate have some sort of
business value, you should consider event-sourcing or other patterns
that allow an audit log or version control.
For this specific question, the Product aggregate and the Drawing value-object might look like this:
public class Product {
private Map<String, Drawing> drawings;
}
public class Drawing {
private String drawingNumber;
private String revision;
private Set<URL> files;
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Drawing)) return false;
Drawing other = (Drawing ) o;
if (this.drawingNumber != other.drawingNumber) return false;
if (this.revision != other.revision) return false;
return true;
}
//getters and constructor omitted for brevity
}
The reason I would prefer Map over Set here is that you want to have only one revision per drawing number and every Drawing must have an unique drawing number. This is easy to achieve if you use the drawing number as the Key value in a Map and simply put the revised Drawing on the drawing number Key, as this will replace the old Value object.
As a drawing should be considered equal by comparing their drawing number and revision, it would be harder (not impossible) to check if there are no duplicate drawing numbers. You can solve this by only comparing Drawings to their drawing number, but this would undermine the definition of a revision (an correction to the Drawing, which makes it a different Drawing).

Scout Eclipse label positions

In Scout Eclipse with every field comes label for it. But my problem is that is a lot of free space there and because of that fields are smaller that they should be.
For example :
I tried :
To set label width in pixel: It works, but you should set and calculate it for every field and you can forget about translations, because text don't have same size in other languages.
To set Label Horizontal Alignment to Right - text is positioned by fields but then free space is on the left side.
How to handle that?
P.S.
I don't need label without any free space, but with smaller one.
EDIT :
With spy tool it look like :
I have no idea what your problem really is, here some generic advices I can give you (based on some guesses I have made. I will be happy to extend this answer, when I know more about your use case).
From-To fields:
When you have 2 fields for “From” and “To”, a good practice is to use a sequence box.
Here an example for a “from-to date” sequence box (taken in the Widgets Demo Application):
#Order(50.0)
public class DateBox extends AbstractSequenceBox {
#Override
protected String getConfiguredLabel() {
return TEXTS.get("DateColumn");
}
#Order(10.0)
public class DateFrom extends AbstractDateField {
#Override
protected String getConfiguredLabel() {
return TEXTS.get("from");
}
}
#Order(20.0)
public class DateTo extends AbstractDateField {
#Override
protected String getConfiguredLabel() {
return TEXTS.get("to");
}
}
}
Money field:
We have discussed how you can combine an amount and currency field in a sequence box in order to look like this.
See this solution: Amount and currency field.

Modelling Time Series data with tags

I'm currently working on a poc to model time series data.
The initial datapoint structure:
- the name of a sensor: 192.168.1.1:readCount
- a timestamp
- a value
I use the sensor name as rowid, the timestamp as column id. This approach works very fine.
However I want to add tags to add additional data.
public class Datapoint {
public String metricName;
public long timestampMs;
public long value;
public Map<String, String> tags = new HashMap<String, String>();
}
Datapoint datapoint = new Datapoint();
datapoint.metricName = "IMap.readCount";
datapoint.value = 10;
datapoint.timestampMs = System.currentTimeMillis();
datapoint.tags.put("cluster", "dev");
datapoint.tags.put("member", "192.168.1.1:5701");
datapoint.tags.put("id", "map1");
datapoint.tags.put("company", "Foobar");
I want to use it to say:
- aggregate all metrics for all different machines with the same id. E.g. if machine 1 has 10 writes for mapx, and machine2 did 20 writes for mapx, I want to know that 30.
- aggregate metrics for for all maps: if machine 1 did 20 writes on mapx and 30 writes on mapy, I want to know the total of 50.
The question is how I should model this.
I know that a composite can be used for the column id. So in theory I could add each tag as a an element in that composite. But can a column be efficiently searched for when it has a variable number of elements in the composite?
I know my question is a bit foggy, but I think this reflects my understanding of Cassandra since I just started with it.
#pveentjer
"I know that a composite can be used for the column id. So in theory I could add each tag as a an element in that composite. But can a column be efficiently searched for when it has a variable number of elements in the composite?"
There are some rules and restrictions when using multiple composites, read here and here
For CQL3, there are further limitations, read here

Resources