Simulating Real-World Systems as a Programmer cover

A collection of posts on the foundations and patterns for building simulations of the real world. Written especially for programmers and non-technical readers wanting to learn the fundamentals. All written material and non-interactive diagrams were human-generated, where some interactive elements were programmed using generative AI tools.

Collection

Simulating Real-World Systems as a Programmer

    Building a simulation engine

    Introducing the stochadex project

    The building blocks of simulations that we have discussed can now be pieced together to form a complete simulation engine.

    The stochadex project is an actual simulation engine written in Go which is based on these basic conceptual building blocks.

    Armed with the fundamentals, we can now describe how this simulation engine was built in specific detail, supported by the appropriate system diagrams.

    Interfaces and data types

    The fundamental data types in the stochadex simulation engine are Go types which can be configured as Settings (pure data) or Implementations (code which implements the provided interfaces).

    For example, we have the Iteration interface, which is based directly on the State Partition Iteration we discussed in the previous post.

    The Iteration interface can be used to implement any simulation in practice. To illustrate this point, we can show how the internal logic may be implemented to recreate some well-known stochastic processes.

    Example: Wiener process

    For example, the Wiener process has some very simple logic.

    Wiener process sample path

    Example: Itô’s lemma

    It is well-known (especially by those in finance) that Itô’s lemma can be used to adapt the model formulae for a Wiener process after a mathematical function (a.k.a. transformation) has been applied to it.

    We can demonstrate that the Iteration interface can support this kind of transformation as well, through some more complicated logic.

    Itô transform of a Wiener path
    Blue is the base path; pink is f(x)=x².

    Example: Time-Inhomogeneous Poisson process

    What about event-based processes?

    The Time-Inhomogeneous Poisson process, is an example of an event-based process which counts the cumulative number of events in Time, while its event rate varies.

    The Iteration interface can support this too.

    Inhomogeneous Poisson events
    Event ticks cluster where the rate curve is high.

    Example: Hawkes process

    Let’s give one more example.

    The Hawkes process couples the history of events to the current event rate. One may therefore categorise this process as ‘non-Markovian’.

    This means that the Hawkes process needs a memory of the State Partition History in order to calculate its Next State Values. Based on everything we have already built and discussed, the Iteration interface obviously supports this quite easily.

    Hawkes process (self-exciting events)
    Events cluster because each event lifts the intensity.

    Serial dependency graphs and modularity

    Multiple Iterations can run within the stochadex for each step in Time. In order to construct serial dependency graphs between them, we can utilise upstream-downstream Iteration relationships.

    Structuring groups of Iterations in this way can increase modularity. For example, the Time-Inhomogeneous Poisson process can be implemented serially.

    Simulation loop and embedded simulation runs

    The Simulation Run loop coordinates the serial relationships between Iterations while maximising concurrency in execution of each Iteration per step in Time.

    Given that this loop always runs for any stochadex simulation, it is sufficient to describe any simulation uniquely through the dependency diagram between its Iterations.

    Having designed the Simulation Run loop, are now finally able to implement Embedded Simulation Runs.

    As a reminder; Embedded Simulation Runs are Iterations which perform entire Simulation Runs from start to end for every Timestep. Their presence can make the diagrams a little more complex, but even more flexible.

    The Iteration interface can support these as well.