Simulations and experiments
So far, attention has focused on the Chi language, and how to use it for modeling a discrete-event system.
In this chapter, the focus shifts to performing simulations, in particular for systems with infinite behavior. Also, how to perform multiple model simulations is explained.
Simulating finite systems
For systems that have simple cyclic behavior, the simulation can be 'exhaustive', for example:
proc G(chan! real a):
a!time
end
proc M(chan? real a, chan! real b):
real x;
a?x; delay 5.0; b!x
end
proc E(chan? real a):
real x;
a?x;
writeln("Flow time: %.2f", time - x);
end
model M():
chan real gm, me;
run G(gm), M(gm, me), E(me);
end
This simulation sends a single product through the line, prints the flow time, and exits. (All processes end, which makes that the run
statement and the model end as well.)
In this case, the answer is even obvious without running the simulation.
Simulating infinite systems
For other systems, it is much harder to decide when enough has been simulated. Typically, a process (E
in the example below), collects values of the property of interest (for example flow time of products), until it has collected enough samples to draw a conclusion, and compute the resulting value.
After doing so, the problem arises to let all processes know the simulation should be stopped. This can be programmed in the model (such as adding channels to signal termination of the simulation to all processes). A simpler alternative is to use the exit
statement, in the following way:
proc real E(chan? real a, int N):
real total, x;
for n in range(N):
a?x;
total = total + time - x;
end;
exit total / N
end
model real M(... int N):
...
run ..., E(..., N);
end
In process E
, the average flow time is calculated and given as argument of the exit
statement. At the moment this statement is executed, the model and all processes are killed, and the computed value becomes the exit value (the result) of the simulation. The real
type before the name E
denotes that the process may perform an exit
statement returning a real value. The model runs the E
process, so it may also give an exit value as result. These types are called exit type. Exit values are printed to the screen by the simulator when it ends the model simulation.
Another option is to use write
to output the computed value, and use exit
without argument. In that case, the exit value is of type void
.
Simulating several scenarios
The above works nicely for single model simulations. The model is started one time, and it derives a result for a single scenario.
Often however, you want to perform several model simulations. This can be the exact same scenario when the model has stochastic behavior, or it can be with different parameter values each time (to investigate system behavior under different circumstances). In such cases, you can use an experiment, like below:
xper X():
real v;
int n;
for n in range(5, 10):
v = M(n);
write("%2d: %.2f\n", n, v)
end
end
The experiment X
looks just like a function, except that it has no return
statement. It can however 'call' a model like a function. In the example above M(n)
starts a simulation with model M
and the given value for n
. When the model exits by means of the exit
statement (this is required!), the computed exit value of the (model) simulation is assigned to variable v
. In the experiment, this value can be used for post-processing, or in this case, get printed as result value in a table.