DecisionCapture

Attaches transition capture to a model that is already built, and takes it back off again (§4.8.2).

The problem it solves

Capture used to be declarable only inside decisionElement { … }, which meant that recording a model's decisions required editing the model. That is the wrong place for the decision: whether this run is being recorded is a property of the run, not of the subsystem being simulated. A user with somebody else's model, a script sweeping ten configurations of which two are worth recording, or a tool layer offering a "record decisions" checkbox all need to attach from outside — and none of them can edit the model element.

The shape is the animation layer's

ksl.animation.AnimationCapture is the house pattern for exactly this: construct it just before a run, its init installs everything and records an undo action per installation, and close runs every undo. This is the same object for decisions, and deliberately smaller — animation has to compose filter sinks and walk every element kind in the model; this has one kind to find and one thing to attach.

val model = Model("Inventory")
val room = StockRoom(model, "Room") // a model that never mentions capture
model.numberOfReplications = 30

DecisionCapture.toDirectory(model, outDir).use { model.simulate() }

What it does not do

It does not close the sinks it attached — unless it made them itself, which is what toDirectory and rolling do. A sink handed to the DecisionCapture constructor by the caller is the caller's, following ksl.observers.ResponseTrace; close detaches it and stops there.

It cannot be constructed or closed while the model is running. attachTransitionSink refuses that, and this does nothing to route around it: a trajectory that begins mid-episode has no predecessor for its first row.

Parameters

model

the model whose decision elements are to be captured

sinkFor

chooses a sink for each decision element; return null to skip that element, which is how a caller records two of a model's five decision elements

Constructors

Link copied to clipboard
constructor(model: Model, sinkFor: (DecisionElement) -> TransitionSink?)

Capture model's decision elements into sinks chosen by sinkFor, which the caller owns.

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard

The elements this capture attached to, in the order it found them.

Link copied to clipboard

The sinks it attached, aligned with capturedElements.

Functions

Link copied to clipboard
open override fun close()

Detaches every sink this capture attached, and closes them if it made them. Idempotent: a second call is a no-op, so use { } around a block that also closes is safe.