name: op-synth-set-bernoulli
description: Multi-select set_* bitmask generation — independent per-option Bernoulli draws, or a joint-structure resample when a paired field is declared.
kind: operator
category: SYNTH
operator: set_bernoulli
type: reference
applies_to: inspect, predict, manifest
examples_tags: [synth, distribution-shape]
Synth distributions emit per-row values; no Response.Components.
Use when
Fills a multi-select answer: each option is ticked on its own at its own rate, such as 40% picking email and 25% SMS.
Questions it answers:
- How do I simulate a tick-all-that-apply question?
- How do I generate which channels each customer has opted into?
Use something else:
weighted_categoricalwhen each row picks exactly one answer.bernoulliwhen there is only one yes/no flag.
Params
options— list[string], required. Dictionary entries in bit order (biti↔options[i]). Pre-registers the field’s dictionary at schema-build time — never lazily by first touch, so bit assignment is deterministic.frequencies— list[float], default0.5each. Per-optionP(bit set)in[0, 1]; length must matchoptions.
An option draws independently unless Spec.SetCategoricalPairs / SetNumericPairs / SetSetPairs names it as a captured joint pair’s target — then its bit is resampled from the pair’s conditional probability instead of frequencies[i].
Inputs
Field type: — any set rung, set_u8/u16/u32/u64/u128/u256; options length must not exceed the type’s MaxSetEntries() (8/16/32/64/128/256). The draw is width-agnostic — a member above bit 64 gets the same independent Bernoulli as one below it.
Output
Per-row map[string]bool (every declared option; true = selected), assembled into the bitmask at write time from each selected option’s pre-registered dictionary ID, never by first-encounter order.
Gotchas
- Empty
options,frequencieslength mismatch, or a frequency outside[0, 1]→SERVICE_VALIDATION. optionscount overMaxSetEntries()→PULSE_IMPORT_SET_OVERFLOWat schema build.SpecFromProfilefills this fromFieldProfile.Set.Optionsand wiresSetCategoricalPairs/SetNumericPairs/SetSetPairsfromConditional.Set*Pairsonly when the paired field also reconstructed to its expected distribution (weighted_categorical/normal/set_bernoulli).- A profile captured without
--conditionalhas no joint sections — every option draws its own marginal, byte-for-byte the pre-joint behaviour. SpecFromProfilecarries EVERY captured member, at every rung —FieldProfile.Set.Optionsis bit-ordered and uncapped belowMaxSetEntries(), so a 206-memberset_u256round-trips member-for-member. A translation that stopped at 64 would generate a plausible cohort whose high members are simply never selected.- Go map iteration order is never used for bit assignment (dictionary pre-populated in
optionsorder), so the seeded stream stays byte-identical.
See
pulse_examples_search tags=[synth]- Skills:
synth-set-fields,type-set-u8,op-synth-weighted-categorical,op-synth-bernoulli