variate

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: AGPL-3.0 Imports: 17 Imported by: 0

README

Variate

A Monte Carlo engine for event-driven risk and cost models, in Go, with exact answers wherever the model allows them.

A model is a directed acyclic graph. Sources emit events at a rate per period; each event walks the graph from the node it enters, booking values at the nodes it passes, choosing an outcome at each, and holding for a while where the model says so. The engine simulates periods and reports the period total, its breakdown by category and source, the events and values at each node, quantiles, the exceedance curve and who the tail belongs to. Beside the simulation it computes the exact mean, variance and probability of an empty period from the graph, and for most models the exact distribution of the period total by FFT, bracketed between rigorous bounds, with no sampling at all.

What a model can say

  • Rates: a constant or an uncertain rate drawn once per period (Poisson or mixed-Poisson counts); a source that fires on every n-th arrival of its stream; a source silent for a repair after each firing; a reliability block diagram of components with mean times between failures and repairs, simulated exactly as a Markov chain of the units; and shared factors that scale several rates at once, the common shock that makes a bad year bad for every risk together; and schedules, cycles of multipliers that give a rate its season or shift pattern.
  • Nodes: values booked on entry or per unit of time held, in any of twenty-two distribution families with truncation and caps; a selection of outcomes with fixed or uncertain probabilities, as shares or tried in order; holding times, including the outage of the reliability block that fired the event; values and probabilities drawn once per period and shared by every event in it.
  • Structure: several graphs in one model, templates instanced with overrides, categories added across the model.

docs/format.md is the reference for the YAML model file, and examples/ holds seventeen complete models with a README saying what each shows, from a one-line compound loss to a register of a hundred risks, a plant as a block diagram, and a shift with its own period.

Running

go run ./cmd/variate run -f examples/compound.yaml          # simulate to the plan's criteria
go run ./cmd/variate run -f examples/compound.yaml --analytic   # with the exact distribution
go run ./cmd/variate plan -f examples/compound.yaml         # the convergence plan and work
go run ./cmd/variate stream -f examples/sequential.yaml --leaf undetected --rounds csv

run reports a table, JSON or CSV; plan says how many periods each convergence criterion needs and what the run will cost; stream writes the rounds, the path each event takes with the values it books, filtered to a node or a leaf. A run without a period count continues until every criterion is met: enough hits on every outcome, a small enough error on every mean, enough periods in the tail. The same model, seed and block size repeat a run exactly.

The browser demo

make demo builds the engine to WebAssembly with TinyGo and serves a page at http://127.0.0.1:8000/ with every example as a model with knobs, or any model pasted as YAML. A run draws the histogram and exceedance curve of the total or of any category, source or node, with return periods and the exact bounds when asked for; the sources' contributions and who the tail belongs to beyond a return period; a source's events per period against a Poisson reference; the totals over the run; and the compiled graph as a flow diagram. A run can be pinned as a baseline and the next drawn beside it, for cheaper-and-slower against faster-and-dearer. The page lives under web/; cmd/variate-wasm is the engine's browser entry point.

From Python

The variate-python repository, MIT-licensed, builds a model in Python and runs it through the variate command, the model crossing as a YAML file and the report returning as JSON. The engine runs as a separate program, so a notebook, a library or a product built on the package takes on none of the engine's obligations; embedding the engine itself is what this repository's licence and its commercial licences cover. variate plan --format json and the series in the JSON report exist for it.

Building and testing

make ci runs what runs on every push: formatting, vet, the linters and the project's own analyzers, the escape and allocation checks on the hot path, the race detector, the suite again with a 32-bit int (the width of TinyGo's wasm target), a TinyGo build of the browser engine, the fuzzers and the vulnerability scan. make stat is the long statistical suite, make bench the benchmarks against a baseline, make wasm-test the engine's tests as wasm under the wazero runtime, and make race the race detector run. The engine's test suites live in internal/suite, against the public API only; the root keeps the tests that reach inside. internal/lint is a separate module holding the project's checkers. The engine allocates nothing while a run is going, has no recursion and bounds every loop, and the build checks each of these with a tool wherever a tool can.

Licence

Copyright © 2026 Eitanity Systems VCC.

Variate is free software under the GNU Affero General Public License, version 3 (see LICENSE). Any work that links it, calls it over a network or ships it must be offered under the same terms, source included. Commercial licences are available for those terms do not suit.

Documentation

Overview

Package variate is the engine: the graph model, compilation to flat index arrays, the period-block simulation, the workspace with its fixed heap, the round stream, analytic expectations and the FFT transform.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrStop = errors.New("stop")

ErrStop is returned by an Observer to end the run cleanly.

Functions

func ChainFigures

func ChainFigures(chains []Chain) (rate, unavailability float64)

ChainFigures returns the stationary failure frequency per period of a source's chains in series and the share of time it is down.

func LayerBoundsAt

func LayerBoundsAt(b Bounds, y Layer, x float64) (lo, hi float64)

LayerBoundsAt reads a bracket on the layer's payout at x from the total's bracket: the payout reaches x when the total reaches the attachment plus x over the share, and never exceeds the share times the limit.

Types

type Accum

type Accum struct {
	Sum   stats.Neumaier // compensated sum over periods
	W     stats.Welford  // count, mean and M2 over periods
	Block stats.Welford  // over the means of full blocks
	Min   float64
	Max   float64
	Zero  int64          // periods with exactly 0
	Hist  *stats.LogHist // nil when the quantity has no histogram
}

Accum is the streamed statistics of one per-period quantity.

func (*Accum) Mean

func (a *Accum) Mean() float64

Mean is the mean per period.

func (*Accum) N

func (a *Accum) N() int64

N is the number of periods accumulated.

func (*Accum) StdDev

func (a *Accum) StdDev() float64

StdDev is the sample standard deviation over periods.

func (*Accum) StdErr

func (a *Accum) StdErr(delays bool) float64

StdErr is the standard error of the mean: from the periods without delays, from the block means with delays; NaN below 16 full blocks.

type Basis

type Basis uint8

Basis says how a function books its value: once per trigger, or as a rate multiplied by the holding time of the outcome taken.

const (
	OnEntry Basis = iota
	PerTime
)

type Bounds

type Bounds struct {
	H            float64
	Lower, Upper []float64
	DiscGap      []float64
	Alias        float64
	Roundoff     []float64
}

Bounds brackets P(T ≥ x) at x = 0, h, 2h, …, with the parts of the bracket reported separately.

func (Bounds) LayerMean

func (b Bounds) LayerMean(y Layer) (lo, hi float64)

LayerMean brackets E[payout] of a layer from a bracket on P(T ≥ x): the payout is the share times the integral of P(T ≥ t) over the band, and on each lattice cell the lower curve at the cell's end and the upper curve at its start bound the integrand.

func (Bounds) Quantile

func (b Bounds) Quantile(p float64) (lo, hi float64)

Quantile brackets the p-quantile of T: the smallest lattice points at which the upper and lower curves fall to 1 − p.

type Chain

type Chain struct {
	K, N         int
	Fail, Repair float64
}

Chain is one block of a reliability diagram the engine simulates exactly: N identical units of which K must be working, each failing at rate Fail while up and repaired at rate Repair while down, both per period. A Repair of 0 means a unit is replaced at once. A source's chains are in series: the source is up when every chain has at least K working units, and it fires when that stops being so.

type Compiled

type Compiled struct {
	// contains filtered or unexported fields
}

Compiled is a validated, flattened model.

func (*Compiled) Analytic

func (m *Compiled) Analytic() (*Expectation, error)

Analytic computes the exact expectations of the model.

func (*Compiled) Binding

func (m *Compiled) Binding() (criterion, driver string)

Binding returns the criterion and driver with the largest need.

func (*Compiled) Categories

func (m *Compiled) Categories() []string

Categories returns the category names in index order.

func (*Compiled) HasDelays

func (m *Compiled) HasDelays() bool

HasDelays reports whether any outcome has a holding time.

func (*Compiled) HasRepair

func (m *Compiled) HasRepair() bool

HasRepair reports whether a source is silent for a repair after each firing, which leaves the variance and P(T = 0) without a closed form.

func (*Compiled) LatticeUnit

func (m *Compiled) LatticeUnit() float64

LatticeUnit is the value every period total is a multiple of when each function is a constant booked on entry, or 0 when the total can take values between multiples.

func (*Compiled) Layers

func (m *Compiled) Layers() []Layer

Layers are the model's layers, with their defaults filled in.

func (*Compiled) LongestPath

func (m *Compiled) LongestPath() int

LongestPath is the number of nodes on the longest source-to-leaf path: the step capacity a round needs.

func (*Compiled) NewWorkspace

func (m *Compiled) NewWorkspace(cfg Config) (*Workspace, error)

NewWorkspace allocates everything a run needs, sized from the model and the configuration, and starts the worker pool.

Example

A fixed run of a compiled model: the workspace holds every buffer, Run fills its Result, Summarize turns the result into named statistics.

package main

import (
	"context"
	"fmt"

	"code.eitanity.com/variate"
	"code.eitanity.com/variate/dist"
)

// compoundModel is the smallest graph: a source with an uncertain rate
// feeding one node that books a value per event.
func compoundModel() variate.Graph {
	rate, _ := dist.NewPERT(2, 5, 12, dist.DefaultPERTShape)
	severity, _ := dist.NewLognormalFromMedianP90(1000, 5000)
	return variate.Graph{
		ID:      "compound",
		Sources: []variate.Source{{ID: "incident", Frequency: rate, To: "loss"}},
		Nodes: []variate.Node{{
			ID:        "loss",
			Functions: []variate.Function{{Name: "cost", Category: "money", Model: severity}},
		}},
	}
}

func main() {
	m, _, _ := compoundModel().Compile(variate.Config{})
	cfg := variate.Config{Periods: 20000}
	w, err := m.NewWorkspace(cfg)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer w.Close()
	r, err := w.Run(context.Background(), 42)
	if err != nil {
		fmt.Println(err)
		return
	}
	var s variate.Summary
	w.Summarize(&s)
	e, _ := m.Analytic()
	z := (s.Total.Mean - e.Mean) / s.Total.StdErr
	fmt.Printf("periods %d  mean within 3 standard errors of exact: %v\n", r.Periods, z > -3 && z < 3)
	fmt.Printf("p50 and p99 ordered: %v\n", s.Total.P50 < s.Total.P99)
	bands := w.Bands([]float64{0, 5000, 20000, 1e9}, make([]float64, 3))
	fmt.Printf("bands sum to one: %v\n", bands[0]+bands[1]+bands[2] > 0.999)
}
Output:
periods 20000  mean within 3 standard errors of exact: true
p50 and p99 ordered: true
bands sum to one: true

func (*Compiled) NodeIDs

func (m *Compiled) NodeIDs() []string

NodeIDs returns the node names in index order.

func (*Compiled) NodeOrder

func (m *Compiled) NodeOrder() []string

NodeOrder is the node identifiers in topological order, every node after the nodes that lead to it.

func (*Compiled) OutcomeNames

func (m *Compiled) OutcomeNames() []string

OutcomeNames returns the outcome names in index order.

func (*Compiled) Plan

func (m *Compiled) Plan() []PlanRow

Plan returns the sizing table: one row per criterion, with the periods it needs; Observed and Met are unset.

func (*Compiled) PlanPeriods

func (m *Compiled) PlanPeriods(batchPeriods int64) int64

PlanPeriods is the plan's run length: the largest need, rounded up to whole batches of blocks.

func (*Compiled) Pools

func (m *Compiled) Pools() []dist.Distribution

Pools returns the distributions by pool index.

func (*Compiled) Simulate

func (m *Compiled) Simulate(ctx context.Context, cfg Config) (*Result, error)

Simulate is the one-shot form: a workspace for cfg, one run with cfg.Seed, and the workspace closed. The Result stays valid.

Example

An adaptive run stops when every convergence criterion is met.

package main

import (
	"context"
	"fmt"

	"code.eitanity.com/variate"
	"code.eitanity.com/variate/dist"
)

// compoundModel is the smallest graph: a source with an uncertain rate
// feeding one node that books a value per event.
func compoundModel() variate.Graph {
	rate, _ := dist.NewPERT(2, 5, 12, dist.DefaultPERTShape)
	severity, _ := dist.NewLognormalFromMedianP90(1000, 5000)
	return variate.Graph{
		ID:      "compound",
		Sources: []variate.Source{{ID: "incident", Frequency: rate, To: "loss"}},
		Nodes: []variate.Node{{
			ID:        "loss",
			Functions: []variate.Function{{Name: "cost", Category: "money", Model: severity}},
		}},
	}
}

func main() {
	m, _, _ := compoundModel().Compile(variate.Config{MinHits: 100, TargetRSE: 0.05, ContribRSE: 0.05, TailP: 0.99, TailHits: 20})
	r, err := m.Simulate(context.Background(), variate.Config{MinHits: 100, TargetRSE: 0.05, ContribRSE: 0.05, TailP: 0.99, TailHits: 20, Seed: 1})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("converged %v  periods > 0: %v\n", r.Converged, r.Periods > 0)
}
Output:
converged true  periods > 0: true

func (*Compiled) SourceIDs

func (m *Compiled) SourceIDs() []string

SourceIDs returns the source names in index order.

func (*Compiled) Spill

func (m *Compiled) Spill() int

Spill returns the window width S.

func (*Compiled) Structure

func (m *Compiled) Structure() Structure

Structure returns the graph's drawing description.

func (*Compiled) TailThresholds

func (m *Compiled) TailThresholds() []float64

TailThresholds are the totals the tail shares are counted against.

func (*Compiled) Transform

func (m *Compiled) Transform(cfg TransformConfig) (*Transformed, error)

Transform computes the distribution of the period total by FFT with a bracket, for models without delays.

Example

The exact distribution of the period total, where the transform applies: a bracket on P(T >= x) and on every quantile.

package main

import (
	"fmt"

	"code.eitanity.com/variate"
	"code.eitanity.com/variate/dist"
)

// compoundModel is the smallest graph: a source with an uncertain rate
// feeding one node that books a value per event.
func compoundModel() variate.Graph {
	rate, _ := dist.NewPERT(2, 5, 12, dist.DefaultPERTShape)
	severity, _ := dist.NewLognormalFromMedianP90(1000, 5000)
	return variate.Graph{
		ID:      "compound",
		Sources: []variate.Source{{ID: "incident", Frequency: rate, To: "loss"}},
		Nodes: []variate.Node{{
			ID:        "loss",
			Functions: []variate.Function{{Name: "cost", Category: "money", Model: severity}},
		}},
	}
}

func main() {
	m, _, _ := compoundModel().Compile(variate.Config{})
	tr, err := m.Transform(variate.TransformConfig{Tol: 1e-2})
	if err != nil {
		fmt.Println(err)
		return
	}
	lo, hi := tr.Total.Quantile(0.99)
	fmt.Printf("applicable %v  grid %d  P99 within [%.0f, %.0f]\n", tr.Applicable, tr.M, lo, hi)
}
Output:
applicable true  grid 65536  P99 within [56382, 56437]

func (*Compiled) TransformEntries

func (m *Compiled) TransformEntries(cfg TransformConfig) (*Counts, error)

TransformEntries computes the distribution of every node's entries per period: Poisson given the period draws, mixed over them.

func (*Compiled) Transformed

func (m *Compiled) Transformed() *Transformed

Transformed returns the transform computed at compile, or nil.

type Config

type Config struct {
	Periods          int64
	AllowUnconverged bool    // run to the caps when the plan exceeds them
	Transform        bool    // compute the transform at compile; the tail criterion then counts periods beyond its quantile
	TransformGrid    int     // largest grid of that transform; 0 = the transform's default
	TransformTol     float64 // its tolerance; 0 = the default
	TransformWork    int64   // its work budget; 0 = the default
	TransformBytes   int64   // the grids a transform pass may hold; 0 = the default
	MinHits          uint64
	ContribRSE       float64
	TargetRSE        float64
	TailP            float64
	TailHits         uint64
	MaxPeriods       int64
	MaxSteps         uint64
	Batch            int
	HistRes          float64

	Seed         uint64
	Workers      int
	BlockPeriods int
	PoolSize     int
	Series       bool
	NoBreakdown  bool
	NodeHist     bool
	Spill        int
	MaxMemory    int64
	Observer     Observer
	Watch        Watch
	Pace         time.Duration
	RoundScratch int
	RecordBuffer int
}

Config holds every run setting; each field's zero value selects the default.

type Counter

type Counter struct {
	ByLeaf []uint64
	Total  uint64
}

Counter counts delivered rounds by leaf.

func NewCounter

func NewCounter(m *Compiled) *Counter

NewCounter sizes the counter for a model.

func (*Counter) Observe

func (c *Counter) Observe(r *Round) error

Observe counts the round.

type Counts

type Counts struct {
	Applicable bool
	Reason     string
	M          int
	Theta      float64
	Passes     int
	QuadNodes  int
	Entries    []Bounds // [node]; H = 1 and no discretisation gap
}

Counts is the distribution of each node's entries per period on the integer lattice, inside a bracket, or the reason the method does not apply.

type ECPoint

type ECPoint struct{ X, P, StdErr float64 }

ECPoint is one point of the exceedance curve: P(T ≥ X) with its binomial standard error.

type Expectation

type Expectation struct {
	Reach               [][]float64 // [source][node]
	EntriesPer          []float64   // [node]
	OutcomeRate         []float64   // [outcome]
	Terminal            [][]float64 // [source][node], 0 for non-leaves
	Mean                float64
	Var                 float64 // +Inf if infinite; NaN with delays or above the pair budget
	DrawsMean, DrawsVar float64
	MeanByCategory      []float64
	MeanBySource        []float64
	Contrib             []float64 // [node]
	VarByCategory       []float64 // NaN with delays or above the pair budget
	VarBySource         []float64
	ContribVar          []float64 // [node]
	StepsPerPeriod      float64
	ArrivalsPerPeriod   float64 // arrivals the renewal and chain sources draw beyond their rounds: the stream's events, the units' failures and repairs
	RoundsPerPeriod     float64 // Σ_k E[λ_k]
	// contains filtered or unexported fields
}

Expectation holds the exact values of the model, indexed like Result.

func (*Expectation) PZero

func (e *Expectation) PZero() float64

PZero is the exact probability of a zero period total.

type Factor

type Factor struct {
	ID    string
	Model dist.Distribution // support in [0, ∞)
}

Factor is a multiplier on rates, drawn once per period and shared by every source naming it: a common shock, which makes the sources' counts dependent and the aggregate tail heavier than independence says.

type Function

type Function struct {
	Name, Category string
	Model          dist.Distribution // value; for PerTime, a rate per period
	Basis          Basis
	Scope          Scope
}

Function is a pdf a node applies on every trigger, booked to a category.

type Graph

type Graph struct {
	ID, Description string
	Sources         []Source
	Nodes           []Node
	Factors         []Factor
	Schedules       []Schedule
	Layers          []Layer // functions of the period total reported beside it
}

Graph is a model: sources feeding a DAG of nodes.

func (Graph) Compile

func (g Graph) Compile(cfg Config) (*Compiled, []Warning, error)

Compile validates the graph and flattens it; the warnings are the non-fatal findings.

Example

Compile validates a graph; Analytic gives the exact mean and variance of the period total without simulating.

package main

import (
	"fmt"

	"code.eitanity.com/variate"
	"code.eitanity.com/variate/dist"
)

// compoundModel is the smallest graph: a source with an uncertain rate
// feeding one node that books a value per event.
func compoundModel() variate.Graph {
	rate, _ := dist.NewPERT(2, 5, 12, dist.DefaultPERTShape)
	severity, _ := dist.NewLognormalFromMedianP90(1000, 5000)
	return variate.Graph{
		ID:      "compound",
		Sources: []variate.Source{{ID: "incident", Frequency: rate, To: "loss"}},
		Nodes: []variate.Node{{
			ID:        "loss",
			Functions: []variate.Function{{Name: "cost", Category: "money", Model: severity}},
		}},
	}
}

func main() {
	m, warnings, err := compoundModel().Compile(variate.Config{})
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, w := range warnings {
		fmt.Println("warning:", w.Code)
	}
	e, _ := m.Analytic()
	fmt.Printf("mean %.0f  sd %.0f  P(T = 0) %.4f\n", e.Mean, sqrt(e.Var), e.PZero())
}

func sqrt(x float64) float64 {
	z := x
	for i := 0; i < 60; i++ {
		z = (z + x/z) / 2
	}
	return z
}
Output:
warning: expected-work
mean 12468  sd 12201  P(T = 0) 0.0118

type Layer

type Layer struct {
	ID         string
	Attachment float64 // the total below which the layer pays nothing
	Limit      float64 // the most the layer pays before the share; 0 = no limit
	Share      float64 // the share of the band the layer pays; 0 = all of it
}

Layer is a function of the period total reported beside it: the part of the total between an attachment and the attachment plus a limit, times a share, as an aggregate deductible, an aggregate limit or a reinsurance layer takes it. A layer is computed from each closed period's total, so it has the statistics, histogram, series and quantity access of any other row; when the transform applies, its mean has exact bounds from the total's bracket.

type Mode

type Mode uint8

Mode is a node's selection mode.

const (
	Absolute Mode = iota
	Sequential
)

type Node

type Node struct {
	ID, Description string
	Functions       []Function
	Mode            Mode
	Outcomes        []Outcome
	Next            string          // continuation without a selection; "" with no Outcomes = leaf
	NextOutage      bool            // the continuation holds for the block's outage (as OutageHolding)
	NextHolding     dist.Continuous // holding time on Next; nil = 0
	NextScope       Scope
}

Node is a state an event passes through.

type Observer

type Observer interface {
	Observe(r *Round) error
}

Observer receives delivered rounds, one at a time, from one goroutine. Returning ErrStop ends the run; any other error fails it.

Example

A Watch narrows the rounds an Observer receives; here to those whose value is at least 10000. The Watch is read at Compile, the Observer at NewWorkspace.

package main

import (
	"context"
	"fmt"

	"code.eitanity.com/variate"
	"code.eitanity.com/variate/dist"
)

// compoundModel is the smallest graph: a source with an uncertain rate
// feeding one node that books a value per event.
func compoundModel() variate.Graph {
	rate, _ := dist.NewPERT(2, 5, 12, dist.DefaultPERTShape)
	severity, _ := dist.NewLognormalFromMedianP90(1000, 5000)
	return variate.Graph{
		ID:      "compound",
		Sources: []variate.Source{{ID: "incident", Frequency: rate, To: "loss"}},
		Nodes: []variate.Node{{
			ID:        "loss",
			Functions: []variate.Function{{Name: "cost", Category: "money", Model: severity}},
		}},
	}
}

// leafCounter is an Observer: it receives every delivered round.
type leafCounter struct{ rounds, steps int }

func (c *leafCounter) Observe(r *variate.Round) error {
	c.rounds++
	c.steps += len(r.Steps)
	return nil
}

func main() {
	cfg := variate.Config{Periods: 200, Watch: variate.Watch{MinValue: 10000}}
	m, _, _ := compoundModel().Compile(cfg)
	obs := &leafCounter{}
	cfg.Observer = obs
	w, _ := m.NewWorkspace(cfg)
	defer w.Close()
	r, _ := w.Run(context.Background(), 3)
	fmt.Printf("events %d, delivered %d, one step each: %v\n", r.Events[0], obs.rounds, obs.steps == obs.rounds)
}
Output:
events 1095, delivered 36, one step each: true

type Outcome

type Outcome struct {
	To            string
	P             dist.Distribution // nil = remainder; Constant for fixed; otherwise drawn per period
	Holding       dist.Continuous   // nil = no delay
	HoldingScope  Scope
	OutageHolding bool // hold for the time the reliability block that fired the round stays down
}

Outcome is one branch of a node's selection.

type PlanRow

type PlanRow struct {
	Criterion        string
	Driver           string
	PlannedPerPeriod float64
	PeriodsNeeded    int64
	Observed         float64
	Met              bool
}

PlanRow is one convergence criterion: planned against observed.

type Prop

type Prop struct{ P, StdErr float64 }

Prop is a proportion with its binomial standard error.

type RecordWriter

type RecordWriter struct {
	// contains filtered or unexported fields
}

RecordWriter writes each delivered round as one fixed-layout little-endian binary record: the 56-byte header and 24 bytes per step.

func NewRecordWriter

func NewRecordWriter(w io.Writer, maxPath int) *RecordWriter

NewRecordWriter returns a writer for rounds of at most maxPath steps; the model's LongestPath gives that.

func (*RecordWriter) Observe

func (rw *RecordWriter) Observe(r *Round) error

Observe writes the round's record.

type Result

type Result struct {
	Seed      uint64
	Periods   int64
	Converged bool
	Stopped   bool
	Binding   string
	Unmet     []string

	Nodes, Outcomes, Categories, Sources []string

	Events       []uint64   // [source]
	Reach        [][]uint64 // [source][node]
	OutcomeCount [][]uint64 // [source][outcome]

	Total      Accum
	ByCategory []Accum
	BySource   []Accum
	EntriesPer []Accum // [node]
	Contrib    []Accum // [node]; zero for nodes without functions
	Layers     []Accum // [layer]: the layer's payout per period

	Steps         uint64
	BeyondHorizon float64
	TailPeriods   int64
	// Per tail threshold (Compiled.TailThresholds), the periods whose
	// total reached it and their total, categories and sources summed,
	// in the row order, for the tail shares.
	TailCounts []int64
	TailSums   [][]float64

	Series *Series // raw per-period rows; fixed runs with Config.Series only
}

Result is the outcome of a run.

type Round

type Round struct {
	Seq     uint64
	Period  int64
	Source  int32
	Arrival float64
	End     float64
	Leaf    int32
	Value   float64
	Steps   []Step
}

Round is one delivered event with its whole path.

type Schedule

type Schedule struct {
	ID     string
	Values []float64 // finite, not negative
}

Schedule is a cycle of multipliers on rates: period p uses the value at p modulo the cycle's length, so a rate can follow a season or a shift pattern. Over whole cycles every value is seen equally often, so the analytics treat the schedule as a multiplier drawn uniformly from its values.

type Scope

type Scope uint8

Scope says how widely one draw is shared: per event, or per period.

const (
	PerEvent Scope = iota
	PerPeriod
)

type Series

type Series struct {
	// contains filtered or unexported fields
}

Series holds every closed period's row of quantities: total, categories, sources, entries per node and contribution per node.

func (*Series) Category

func (s *Series) Category(c int, p int64) float64

Category is category c's value in period p.

func (*Series) CategoryColumn

func (s *Series) CategoryColumn(c int, dst []float64) []float64

CategoryColumn copies category c's values into dst.

func (*Series) Contrib

func (s *Series) Contrib(v int, p int64) float64

Contrib is node v's booked value in period p.

func (*Series) Entries

func (s *Series) Entries(v int, p int64) float64

Entries is the number of entries at node v in period p.

func (*Series) EntriesColumn

func (s *Series) EntriesColumn(v int, dst []float64) []float64

EntriesColumn copies node v's entries into dst.

func (*Series) LayerColumn

func (s *Series) LayerColumn(j int, dst []float64) []float64

LayerColumn copies a layer's payouts into dst.

func (*Series) Periods

func (s *Series) Periods() int64

Periods is the number of periods recorded.

func (*Series) Source

func (s *Series) Source(k int, p int64) float64

Source is source k's value in period p.

func (*Series) Total

func (s *Series) Total(p int64) float64

Total is the period total of period p.

func (*Series) TotalColumn

func (s *Series) TotalColumn(dst []float64) []float64

TotalColumn copies the period totals into dst.

type Source

type Source struct {
	ID, Description string
	Frequency       dist.Distribution // rate per period
	To              string
	Every           int               // fire on every Every-th arrival of the stream; 0 or 1 = every arrival
	Repair          dist.Distribution // holding after each firing, in periods, during which the source is silent; nil = none
	Chains          []Chain           // a reliability diagram the engine simulates in place of Frequency; nil = none
	Factor          string            // a Factor's ID scaling the rate, drawn once per period and shared; "" = none
	Schedule        string            // a Schedule's ID scaling the rate by the period's place in a cycle; "" = none
}

Source is an initiating event flow.

type Stat

type Stat struct {
	N                        int64
	Mean, StdErr, StdDev     float64
	Min, Max                 float64
	P50, P90, P95, P99, P999 float64
	Quantiles                bool // the percentiles exist: the quantity has a histogram
	Clipped                  bool
	Share                    float64
}

Stat summarises one per-period quantity.

type Step

type Step struct {
	Node    int32
	Outcome int32 // −1 at the leaf
	T       float64
	Value   float64
}

Step is one node visit on a round's path.

type Structure

type Structure struct {
	Nodes    []StructureNode
	Outcomes []StructureEdge
	Sources  []StructureSource
}

Structure describes the compiled graph for drawing: the nodes with their functions, the outcomes as edges, and the sources with the node each enters.

type StructureEdge

type StructureEdge struct {
	Name, From, To string
	Holding        bool
}

StructureEdge is an outcome: from a node to its target, named as the report names it, holding when a holding time delays it.

type StructureFunction

type StructureFunction struct {
	Name, Category string
	PerTime        bool
}

StructureFunction is a function's name, category and basis.

type StructureNode

type StructureNode struct {
	ID        string
	Functions []StructureFunction
	Leaf      bool
}

StructureNode is a node and the functions it books.

type StructureSource

type StructureSource struct {
	ID, To string
}

StructureSource is a source and the node it enters.

type Summary

type Summary struct {
	Total      Stat
	Exceedance []ECPoint
	ByCategory map[string]Stat
	BySource   map[string]Stat

	ReachProb  map[string]map[string]Prop
	Terminal   map[string]map[string]Prop
	OutcomeP   map[string]Prop
	EntriesPer map[string]Stat
	ContribPer map[string]Stat // value booked per period at each node
	Layers     map[string]Stat // each layer's payout per period, its share that of the total's mean
	TailShares []TailShare     // who the tail belongs to, at each threshold with a period
	Plan       []PlanRow
}

Summary is the report of a run, with names as keys.

type TailShare

type TailShare struct {
	X          float64
	Periods    int64
	BySource   map[string]float64
	ByCategory map[string]float64
}

TailShare is the share of the total each source and category booked over the periods whose total reached X: who the tail belongs to.

type TransformConfig

type TransformConfig struct {
	MaxGrid  int     // default 1<<22 points
	Tol      float64 // default 1e-3: max of (Upper − Lower)/Upper over x up to x*
	TailP    float64 // default from the compile criteria
	MaxWork  int64   // default 1<<34 grid-point evaluations (a rate quadrature's nodes × points, a function's or closed-form rate's points) over the whole transform
	MaxBytes int64   // default 2<<30: the grids a pass holds at once
}

TransformConfig controls the FFT transform.

type Transformed

type Transformed struct {
	Applicable bool
	Reason     string
	H          float64
	M          int
	Theta      float64
	PZero      float64
	QuadNodes  int
	Passes     int
	Work       int64 // grid-point evaluations spent
	Total      Bounds
	ByCategory []Bounds
	BySource   []Bounds // nil when the model has more than maxSourceBounds sources
}

Transformed is the exact distribution of the period total inside a bracket, or the reason the method does not apply.

type Warning

type Warning struct {
	Code    string
	Subject string
	Message string
}

Warning is a non-fatal finding of Compile.

type Watch

type Watch struct {
	Nodes    []string
	Leaves   []string
	MinValue float64
}

Watch selects which rounds an Observer receives: a round matches every non-empty field, and any entry within a list.

type Workspace

type Workspace struct {
	// contains filtered or unexported fields
}

Workspace holds every buffer a run needs, allocated once, and the persistent worker pool.

func (*Workspace) Bands

func (w *Workspace) Bands(edges, dst []float64) []float64

Bands fills dst[i] with P(edges[i] ≤ T < edges[i+1]) for the period total; dst must have len(edges)−1 entries.

func (*Workspace) BandsOf

func (w *Workspace) BandsOf(row int, edges, dst []float64) []float64

BandsOf fills dst[i] with P(edges[i] ≤ Q < edges[i+1]) for the quantity at row; dst must have len(edges)−1 entries. A row without a histogram leaves dst zero.

func (*Workspace) Close

func (w *Workspace) Close()

Close stops the worker pool. The workspace cannot be used afterwards.

func (*Workspace) ExceedanceOf

func (w *Workspace) ExceedanceOf(row int, dst []ECPoint) []ECPoint

ExceedanceOf returns log-spaced points of P(Q ≥ x) for the quantity at row, as Summary.Exceedance does for the total.

func (*Workspace) Footprint

func (w *Workspace) Footprint() int64

Footprint is the planned size of the workspace's buffers in bytes, the figure checked against MaxMemory.

func (*Workspace) HasHistogram

func (w *Workspace) HasHistogram(row int) bool

HasHistogram reports whether a quantity's row keeps a histogram.

func (*Workspace) Means

func (w *Workspace) Means() []float64

Means returns the analytic means the histogram ranges were sized from, by row quantity; for diagnostics.

func (*Workspace) QuantityRow

func (w *Workspace) QuantityRow(kind, name string) (row int, ok bool)

QuantityRow finds the row of a quantity by kind ("total", "category", "source", "entries", "contrib", "layer") and name; ok is false for a kind or name the model does not have.

func (*Workspace) QuantityStat

func (w *Workspace) QuantityStat(row int) Stat

QuantityStat is the statistics of the quantity at row, with its share of the total for a category or source.

func (*Workspace) Run

func (w *Workspace) Run(ctx context.Context, seed uint64) (*Result, error)

Run simulates a fixed number of periods on the worker pool and returns the workspace's Result, which the next Run overwrites. One Run at a time: a second while one is in progress is refused, and a Close during a Run ends it with an error.

func (*Workspace) Summarize

func (w *Workspace) Summarize(dst *Summary)

Summarize fills a caller-owned Summary from the workspace's result, reusing its slices and maps.

Directories

Path Synopsis
cmd
variate command
Command variate is the generic command-line interface: it loads a model file, sizes or runs it, and reports the results as a table, JSON or CSV, with the rounds streamed on request.
Command variate is the generic command-line interface: it loads a model file, sizes or runs it, and reports the results as a table, JSON or CSV, with the rounds streamed on request.
variate-demo command
Command variate-demo serves the browser demo: the page under web/, the engine compiled to WebAssembly, and the example models.
Command variate-demo serves the browser demo: the page under web/, the engine compiled to WebAssembly, and the example models.
variate-wasm command
Command variate-wasm is the engine for the browser: it exposes run, plan, version, histogram and release to JavaScript through syscall/js, taking a model as YAML text and settings as JSON text, and returning the report as JSON text.
Command variate-wasm is the engine for the browser: it exposes run, plan, version, histogram and release to JavaScript through syscall/js, taking a model as YAML text and settings as JSON text, and returning the report as JSON text.
Package config loads a model file into a variate.Graph and a variate.Config: YAML with one family key per distribution, time units converted to periods through the file's period declaration, several graphs merged under their names, and templates expanded into independent copies.
Package config loads a model file into a variate.Graph and a variate.Config: YAML with one family key per distribution, time units converted to periods through the file's period declaration, several graphs merged under their names, and templates expanded into independent copies.
Package dist holds the distribution families and their exact samplers.
Package dist holds the distribution families and their exact samplers.
examples
gograph command
Command gograph builds a model with the variate API instead of a file: the pattern a domain module follows to compile its own vocabulary into a graph.
Command gograph builds a model with the variate API instead of a file: the pattern a domain module follows to compile its own vocabulary into a graph.
internal
oracle
Package oracle is a deliberately simple reference walker, used only by tests to check the engine's counts and totals on random graphs.
Package oracle is a deliberately simple reference walker, used only by tests to check the engine's counts and totals on random graphs.
Package report writes a run's summary as a table, JSON or CSV from the typed values, by hand.
Package report writes a run's summary as a table, JSON or CSV from the typed values, by hand.
Package stats holds the numerical aggregation behind results: compensated sums, Welford moments with Chan's merge, and the log-bucketed histogram behind quantiles and the exceedance curve.
Package stats holds the numerical aggregation behind results: compensated sums, Welford moments with Chan's merge, and the log-bucketed histogram behind quantiles and the exceedance curve.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL