CompositeArm
Composite Arm built from N independent sub-arms. Each observation is routed through every sub-arm's CompositeSubArm.valueExpr / CompositeSubArm.weightExpr / CompositeSubArm.filter AST before being fed to the corresponding per-sub-arm accumulator. The composite result is a ResultList of the sub-snapshots; pair with CompositePosterior to combine sub-arm draws into a single score.
Plumbing is AST-driven (no lambdas) so the whole spec is wire-serializable. Per-sub-arm encode is still applied after valueExpr; e.g. with LogNormalArm
valueExpr = Xthe lognormal's ownencode = lnruns, so don't double-log viavalueExpr = Log(X).
Example; zero-inflated lognormal revenue:
val ziln = CompositeArm(listOf(
CompositeSubArm(BernoulliArm(), valueExpr = IfExpr(X gt 0.0, Const(1.0), Const(0.0))),
CompositeSubArm(LogNormalArm(), filter = X gt 0.0),
))
val score = CompositePosterior(
subPosteriors = listOf(BetaPosterior, LogNormalGammaPosterior),
combine = V(0) * V(1),
)
val bandit = MultiArmedBandit(nbrArms = 4, policy = ThompsonSampling(ziln, score))Constructors
CompositeArm
Properties
subArms
Sub-arms whose stats receive routed observations.
Functions
createStat
Allocate a fresh per-arm accumulator already seeded with this arm's prior pseudo-counts.
Map a raw observation onto the scale the stat accumulates. Identity by default; LogNormalArm overrides with ln so the underlying stat tracks the log-reward and the Normal-Gamma posterior fits the log-normal generative model.