kumulant

CompositeArm

@Serializable
@SerialName(value = "CompositeArm")
data class CompositeArm(val subArms: List<CompositeSubArm>) : Arm<ResultList<Result>> (source)

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 = X the lognormal's own encode = ln runs, so don't double-log via valueExpr = 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

constructor(subArms: List<CompositeSubArm>)(source)

Types

Link copied to clipboard
object Companion

Companion host for factory helpers.

Properties

subArms

Sub-arms whose stats receive routed observations.

Functions

createStat

open override fun createStat(): SeriesStat<ResultList<Result>>(source)

Allocate a fresh per-arm accumulator already seeded with this arm's prior pseudo-counts.

Link copied to clipboard
open fun encode(value: Double): Double

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.