pyfcstm.verify.algorithms.lifecycle
Lifecycle-focused SMT-local verification algorithms.
This module checks first-cycle relationships between lifecycle actions. The
current raw algorithm focuses on the entry path into a leaf state and the first
during chain that can run immediately after entry. Public callers should
normally import the algorithm from pyfcstm.verify.
Algorithm map:
Function |
Formula shape |
Diagnostic |
|---|---|---|
Branch-condition determinacy after root initial entry and concrete
|
|
Example:
>>> from pyfcstm.verify import enter_postcondition_implies_during_precondition
>>> callable(enter_postcondition_implies_during_precondition)
True
__all__
- pyfcstm.verify.algorithms.lifecycle.__all__ = ['enter_postcondition_implies_during_precondition']
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.
enter_postcondition_implies_during_precondition
- pyfcstm.verify.algorithms.lifecycle.enter_postcondition_implies_during_precondition(state: State, variables: Sequence[VarDefine], *, smt_timeout_ms: int | None = None) AlgorithmResult[source]
Detect first-cycle during conditions determined by enter-time values.
This algorithm detects first-cycle
duringbranch conditions whose truth value is already fixed by declaration initializers, root initial-transition effects, and concreteenteractions along every feasible root initial entry path into the leaf state. It is a local first-cycle check: it does not unroll repeated cycles and it skips pseudo states, composite states, abstract lifecycle actions, and leaves without concreteduringlogic.Let
Cbe the set of feasible initial-entry contexts for leaf states. Each contextcproduces a post-entry symbolic storeV_c. For a first-cycle branch conditionp, the algorithm asks whether each context proves one branch direction:\[\forall c \in C.\quad \operatorname{unsat}(A_c \land \lnot p(V_c)) \;\lor\; \operatorname{unsat}(A_c \land p(V_c))\]The implementation reports only conditions whose descriptor is common to all feasible contexts, so a diagnostic means the same condition is determined regardless of which root initial branch reached the state.
Result semantics:
kind == "unsat"means at least one first-cycle condition has a fixed branch direction after entry and diagnostics carryI_ENTER_DURING_CONTRADICT.kind == "sat"means no common first-cycle condition is proven fixed, or the state is outside the algorithm scope.kind == "unknown"or"timeout"means a solver query was inconclusive and no deterministic diagnostic was emitted.kind == "undecidable_skip"means entry-path or operation translation could not provide sound first-cycle evidence.
- Parameters:
- Returns:
Algorithm result.
- Return type:
Example:
>>> from textwrap import dedent >>> from pyfcstm.dsl import parse_with_grammar_entry >>> from pyfcstm.model import parse_dsl_node_to_state_machine >>> from pyfcstm.verify import enter_postcondition_implies_during_precondition >>> def parse_machine(source): ... ast = parse_with_grammar_entry(dedent(source), "state_machine_dsl") ... return parse_dsl_node_to_state_machine(ast) >>> def variables(machine): ... return tuple(machine.defines.values()) >>> # A.enter sets x = 1, so the first-cycle during condition is true. >>> machine = parse_machine(''' ... def int x = 0; ... state System { ... state A { ... enter { x = 1; } ... during { ... if [x > 0] { x = x + 1; } else { x = x - 1; } ... } ... } ... [*] -> A; ... } ... ''') >>> state_a = machine.root_state.substates["A"] >>> result = enter_postcondition_implies_during_precondition( ... state_a, ... variables(machine), ... ) >>> result.kind 'unsat' >>> result.diagnostics[0]["code"] 'I_ENTER_DURING_CONTRADICT' >>> result.diagnostics[0]["data"]["branch_taken"] 'true' >>> # A leaf without concrete during operations is outside the scope. >>> machine = parse_machine(''' ... def int x = 0; ... state System { ... state A { ... enter { x = 1; } ... } ... [*] -> A; ... } ... ''') >>> enter_postcondition_implies_during_precondition( ... machine.root_state.substates["A"], ... variables(machine), ... ).kind 'sat'