Step 14: Statistics: Collect & Display
So, our warehouse model is already functional.
Simulation modeling is often used to collect data about the behavior of a modeled object under various conditions and gain insights.
Let’s see how we can use the Amalgama Platform to collect and display online statistics for:
-
Forklift Utilization
-
Average Truck (un)loading time
1. Collecting Forklift Utilization
First, we will look deeper into the amount of time the forklifts are busy and idle.
public class Forklift extends GraphAgent<Node, Arc> {
...
private final SingleStateStatistics<IEquipmentState> stateStats = new SingleStateStatistics<>();
...
public double getUtilizedTime() {
return stateStats.getEverEnteredStates().stream()
.filter(s -> s.isUtilized())
.mapToDouble(s -> stateStats.getStateDuration(s, time()))
.sum();
}
...
Add one line at the beginning of the putStatsSlot()
method:
public void putStatsSlot(IEquipmentState state) {
stateStats.onEnteredState(state, time());
...
We employ the SingleStateStatistics
class from the Amalgama Platform.
It can be used to collect the statistics for the states the modeled object is in.
Recall that each task state has the isUtilized()
method that indicates that
some 'useful job' is being done when an object is in such a state.
The SingleStateStatistics.getStateDuration()
gives the time spent in each state.
Now we can calculate the average utilization over all forklifts in the Model
:
public class Model extends com.amalgamasimulation.engine.Model {
...
public double getForkliftUtilization() {
final double avgUtilizationTime = forklifts.stream()
.mapToDouble(f -> f.getUtilizedTime())
.average().orElse(0);
return Utils.zidz(avgUtilizationTime, time());
}
...
The Utils.zidz() method helps to safely handle division by zero.
2. Collecting average truck (un)loading time
Let’s find out how much time trucks spend at the gates.
public class Model extends com.amalgamasimulation.engine.Model {
...
private final Map<Direction, DoubleSummaryStatistics> truckLoadingDuration = Map.of(
Direction.IN, new DoubleSummaryStatistics(),
Direction.OUT, new DoubleSummaryStatistics()
);
...
public DoubleSummaryStatistics getTruckLoadingDuration(Direction direction) {
return truckLoadingDuration.get(direction);
}
...
DoubleSummaryStatistics
is one of the standard JDK classes. We will use it to calculate the average of a series of truck loading durations.
Modify the Dispatcher.handleTruck()
method to collect the values:
...
private void handleTruck(Truck truck, Gate gate, Runnable onComplete) {
gate.parkTruck(truck);
final double parkedTime = engine.time();
requestForklift((forklift, forkliftReleaser) ->
new HandleTruckTask(engine, truck, gate, forklift).start(() -> {
forkliftReleaser.run();
gate.unparkTruck(truck);
model.getTruckLoadingDuration(truck.getDirection()).accept(engine.time() - parkedTime);
onComplete.run();
})
);
}
...
3. Statistics visualization
Go to the SimulationStatisticsPart
class (in the 'application' bundle, in the 'simulation' package).
Replace its onShowModel()
method with the following:
...
protected void onShowModel(Model model) {
if(model != null) {
List<Indicator> data = List.of(
new Indicator(messages.INDICATOR_ARCS, () -> (double)appData.getScenario().getArcs().size(), Formats.getDefaultFormats()::noDecimals, false),
new Indicator(messages.INDICATOR_NODES, () -> (double)appData.getScenario().getNodes().size(), Formats.getDefaultFormats()::noDecimals, false),
new Indicator("Truck average unloading time", () -> model.getTruckLoadingDuration(Direction.IN).getAverage(), Formats.getDefaultFormats()::twoDecimals, false),
new Indicator("Truck average loading time", () -> model.getTruckLoadingDuration(Direction.OUT).getAverage(), Formats.getDefaultFormats()::twoDecimals, false),
new Indicator("Forklift utilization", () -> model.getForkliftUtilization(), Formats.getDefaultFormats()::percent, false)
);
tableView.setData(data);
} else {
tableView.setData(Collections.emptyList());
}
}
...
Make sure you import the Direction class.
|
4. Statistics is updated in real time
Run the simulation.
In the bottom-left corner of the application window, the collected statistics are shown:
5. Happy end
Our intro into the world of the Amalgama Platform has come to a close.
You can find the complete source code for this tutorial here: https://github.com/amalgama-llc/warehouse-tutorial
We wish you insightful simulation modeling!
Amalgama Team