Skip to content

Constrained QMC: coupled factor constraints in design generation #103

@jc-macdonald

Description

@jc-macdonald

Problem

There is no built-in way to declare coupled factor constraints at design-generation time — i.e. constraints that say "factor A's allowed values depend on factor B's value". For example:

if active_criteria == "elbo_only" then patience <= 2

Today, users must either (a) generate the full Cartesian / Sobol design and post-filter (which wastes budget and distorts QMC space-filling properties), or (b) split the study into multiple phases with manually pruned grids (which doesn't compose well for >2 coupled factors).

This is distinct from #74 (closed) which addressed observable feasibility filters applied after simulation. This issue is about constraining the input design space before trials are run.

Proposed

  • Add a FactorConstraint (or DesignConstraint) protocol/dataclass that takes a predicate over a candidate config dict and returns bool.
  • Plumb a constraints: Sequence[FactorConstraint] parameter through design.sobol_design, design.full_factorial, and any other generators.
  • For Sobol / QMC: use rejection sampling with oversampling, then trim to the requested n feasible points (document the oversample factor and warn if feasibility ratio is too low).
  • For full factorial: filter the Cartesian product before yielding.
  • Optional sugar: a small DSL or helper for the common "if X == v then Y in S" pattern.

Example

from trade_study.design import sobol_design, FactorConstraint

constraints = [
    FactorConstraint(
        lambda c: c["active_criteria"] != "elbo_only" or c["patience"] <= 2,
        name="elbo_only_short_patience",
    ),
]
design = sobol_design(factors, n=128, constraints=constraints, seed=0)

Notes

  • QMC space-filling properties degrade under rejection; document this and consider exposing the realized discrepancy / coverage diagnostic.
  • Should compose with the existing Phase API so per-phase grids can carry their own constraints.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2-mediumShould fixdesigndesign.py modulefeatureNew feature or enhancement

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions