## 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.