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.