prodigy.analysis.loop_strategies¶
Loop strategies (registry)¶
A loop strategy tells the forward analysis how to deal with one while loop:
unroll it a fixed number of times, check a user-provided invariant, synthesise an
EVT invariant, and so on. Up to now the strategy and its parameters were asked for
interactively inside WhileHandler.
This module makes strategies explicit data:
ParamSpecdescribes one parameter (type, label, legacy CLI prompt, default).LoopStrategydescribes one strategy (stable name, menu text, parameters, nominal soundness) and points to the function that runs it.LoopTaskis what a strategy receives: the loop, the incoming distribution and a way to read its parameters (from the session’s decisions, or interactively).LoopOutcomeis what a strategy returns: the outgoing distribution plus what is known about it (exact, lower bound with residual mass, upper bound, unknown) and a certificate that a front end can display or re-check.
Strategies are registered by name, so additional strategies (for example from the
lower-bounds work) appear in the CLI menu, the JSON API and the web GUI without touching
those front ends: call register_loop_strategy() at import time.
- class Bound[source]¶
Bases:
objectWhat is known about a distribution computed by (part of) an analysis.
The values are compared to the exact semantics of the program:
EXACT: equal to the exact semantics (certified).LOWER: coefficient-wise below the exact semantics; the mass that is not accounted for is at most the recorded residual mass. No termination assumption.UPPER: coefficient-wise above the exact semantics (Park’s lemma).UNKNOWN: an approximation without a guaranteed direction, or a result whose side conditions could not be checked.
- EXACT = 'exact'¶
- LOWER = 'lower'¶
- UPPER = 'upper'¶
- UNKNOWN = 'unknown'¶
- ALL = ('exact', 'lower', 'upper', 'unknown')¶
- class ParamSpec(name, kind, label, prompt='', default=None, help='', minimum=None, choices=(), alias_of=None, optional=False)[source]¶
Bases:
objectOne parameter of a loop strategy.
- Parameters:
- kind: str¶
One of
int,probability,pgcl(program source),expression(generating-function expression),file(path, CLI only),choice.
- alias_of: str | None = None¶
If set, this parameter is an alternative way to provide
alias_of(e.g. an invariant file instead of the invariant source).
- class LoopOutcome(distribution, error_prob, kind='unknown', residual=0, certificate=dict(), messages=list(), query_bounds=dict())[source]¶
Bases:
objectResult of running a loop strategy once.
- Parameters:
- distribution: Distribution¶
- error_prob: Distribution¶
- residual: Any = 0¶
upper bound on the mass that is not accounted for, in the units of the incoming distribution (i.e. before any later normalisation).
- Type:
For
LOWER
- query_bounds: Dict[Tuple[str, str], Tuple[Any, Any]]¶
Bounds that the strategy computed itself for the queries directly after the loop, as
(kind, expression) -> (lower, upper)with kind"?Pr"or"?Ex"andNonefor an unknown side. They refer to the incoming distribution of the loop and tighten the intervals of exactly these queries (e.g. the upper bounds of an EVT super-invariant).
- class LoopTask(instruction, prog_info, distribution, error_prob, config, analyzer, session, loop, decision, strategy, record=None)[source]¶
Bases:
objectEverything a strategy needs to analyse one occurrence of a loop.
- Parameters:
instruction (
WhileInstr)prog_info (
ProgramInfo)distribution (
Distribution)error_prob (
Distribution)config (
ForwardAnalysisConfig)analyzer (
Callable[[SkipInstr|AbortInstr|WhileInstr|IfInstr|AsgnInstr|ChoiceInstr|LoopInstr|TickInstr|ObserveInstr|QueryInstr|ProbabilityQueryInstr|ExpectationInstr|PlotInstr|PrintInstr|OptimizationQuery|Sequence[SkipInstr|AbortInstr|WhileInstr|IfInstr|AsgnInstr|ChoiceInstr|LoopInstr|TickInstr|ObserveInstr|QueryInstr|ProbabilityQueryInstr|ExpectationInstr|PlotInstr|PrintInstr|OptimizationQuery],ProgramInfo,Distribution,Distribution,ForwardAnalysisConfig],Tuple[Distribution,Distribution]])session (
AnalysisSession)decision (
LoopDecision)strategy (
LoopStrategy)record (
Any)
- instruction: WhileInstr¶
- prog_info: ProgramInfo¶
- distribution: Distribution¶
- error_prob: Distribution¶
- config: ForwardAnalysisConfig¶
- analyzer: Callable[[SkipInstr | AbortInstr | WhileInstr | IfInstr | AsgnInstr | ChoiceInstr | LoopInstr | TickInstr | ObserveInstr | QueryInstr | ProbabilityQueryInstr | ExpectationInstr | PlotInstr | PrintInstr | OptimizationQuery | Sequence[SkipInstr | AbortInstr | WhileInstr | IfInstr | AsgnInstr | ChoiceInstr | LoopInstr | TickInstr | ObserveInstr | QueryInstr | ProbabilityQueryInstr | ExpectationInstr | PlotInstr | PrintInstr | OptimizationQuery], ProgramInfo, Distribution, Distribution, ForwardAnalysisConfig], Tuple[Distribution, Distribution]]¶
- session: AnalysisSession¶
- decision: LoopDecision¶
- strategy: LoopStrategy¶
- record: Any = None¶
The session’s
LoopRecordfor this loop.
- param(name)[source]¶
Value of parameter
name: from the decision if present, otherwise from the session’s decision provider (asks on the terminal in the interactive CLI, uses the default or reports a missing decision elsewhere).
- class LoopStrategy(name, title, menu_text, soundness, description, run, params=(), legacy_key=None, requires_unconditioned=False)[source]¶
Bases:
objectA registered way of analysing a while loop.
- Parameters:
Text of the entry in the interactive CLI menu.
- soundness: str¶
Nominal guarantee (see
Bound); the actual outcome may be weaker, e.g. when a side condition cannot be checked.
- run: Callable[[LoopTask], LoopOutcome]¶
- register_loop_strategy(strategy, *, replace=False)[source]¶
Makes
strategyavailable to the CLI menu, the JSON API and the web GUI.- Parameters:
strategy (
LoopStrategy)replace (
bool)
- Return type:
- loop_strategies()[source]¶
All registered strategies; the six historic ones first, in menu order.
- Return type: