Calculator
The calculator module is responsible for all calculations for Give for Good. It is modelled as state transitions due to events and may be dependent on other models so simplify calculations.
Calculator core
The model is a cross product of all submodels.
Mt = ∏imi, t
Each submodel mi, t represents a distinct aspect of the system at time t. The overall model Mt is the product of these submodels, capturing the complete state.
Submodels can be updated in response to events:
mt × E → mt + 1
Some submodels depend on the state of other submodels, allowing for more complex updates:
Mt × E → mt + 1
For models with dependencies, both the previous state and newly calculated values may be used:
Mt × mi, t + 1 × E → mj, t + 1
Circular dependencies between submodels at t + 1 are not allowed.
Because the calculation of the model is entirely dependent on the previous model and the event at the specific position in the sequence, all calculations are pure, and cacheable.
Models
The Index model tracks the position of the current event
in the sequence. Each index corresponds to an event that resulted in the
present state. At the initial position (t = 0), the system assumes the
occurrence of the NONE event.
Models are categorized as either processed or calculated: - Processed models use a processor to apply event data and, if needed, data from other models. They may also implement partitioning to optimize storage and computation. - Calculated models do not process event data directly. Instead, they use a calculator to derive their value from other models, which may themselves be processed or calculated.
Currently, calculated models are not cached; instead, they are parameterized. Parameterization allows calculated models to efficiently reference partitioned models and minimize redundant computations. This approach improves performance and flexibility when working with large or complex model structures.
A data flow graph for all the models.
Caching
When a model is requested, the calculator minimizes computation by
leveraging cached results. It checks the branch
for cached HistoryHash
models, which serve as unique identifiers for the entire event
sequence. This allows all derived model data to be efficiently indexed
and retrieved using the history hash.
The calculator uses a caching strategy, delegating storage and retrieval of model states to the Model cache.
Theories
A theory enables the calculator to compute models based on a current
state plus hypothetical events that have not yet been imported into the
Event store. The ValidationErrors
model is used to validate these events before import, ensuring
consistency and correctness. Theories also support calculations such as
MinimalExits for
investment options.
Results from theory-based calculations are not stored in the Model cache.
Partitioning
Partitioning splits a model into multiple segments, improving efficiency in storage, network transfer, and memory usage during calculation. It is especially effective for models with many indexed entries, allowing dynamic partitioning based on entry count and size. Each partitioned model includes header data for global information and to determine the required number of partitions. The goal of choosing a paritioning scheme is to minimize the number of partitions affected by any single event, maximizing performance and scalability.
By J.W. Morsink