Verify¶
Requires the verify extra (pip install "longeron[verify]") for the
Hypothesis-driven tiers; cover and prove reach Z3 through the bundled
smt extra, and every tier degrades to recorded gaps where an engine
is missing.
Model-driven requirement-violation hunting: the model fights back.
Everything a property-based tester needs is already declared in the
.sysml text: attribute types give value domains, assert constraint
bodies give minable ranges, assume/require constraints give the
universal property assumptions-hold implies requirements-satisfied,
state machines give the event alphabet, and variation catalogs give the
discrete factors. This module derives all of it, hunts, shrinks, proves,
and materializes every catch as re-checkable M0 individuals.
Four tiers over ONE oracle – the interpreter. Every verdict, in every
tier, comes from instantiate + check + check_requirement (or
simulate for sequences), never from a solver’s arithmetic; solvers
propose, the interpreter decides (the same honesty contract
longeron.analysis.trades keeps):
hunt()– Hypothesis sampling + shrinking: is there a simple violating configuration? Strategies are derived from the model by the domain ladder (types -> direct constraint mining -> Z3 bounds through the reachability fixed point -> declared fallback), and every shrunk catch is paired with an oracle-bisected boundary.sequences()– Hypothesis stateful testing over the realStateMachine: is there a minimal violating event sequence?cover()– in-house IPOG-F t-way covering arrays (longeron.analysis._ipog) with Z3 as the constraint engine: which discrete mixes violate, at t-way coverage? Recall is measured against exhaustive ground truth whenever that stays feasible.prove()– Z3 overlongeron.analysis.smt’s encoding: is violation impossible? Each check is negated one at a time under the assumption set; UNSAT is a proof of absence no sampling can deliver, SAT witnesses are re-checked by the interpreter before they are believed, andOptimizeattributes exact rational feasibility bounds to the constraints that bind them.
verify() is the umbrella: it dispatches by what the scope is (a
state machine runs sequences, an assembly with variation points runs
cover, any other part runs hunt + prove where encodable) and
returns one Report.
Semantics worth pinning (normative): a violated assume constraint
makes a requirement inapplicable – a vacuous pass, never a
failure (exactly
check_requirement()’s existing contract). A configuration is a violation
only when every assumption holds and a require constraint (or an
assert constraint on the subject) is actually false. Vacuous
outcomes are recorded on every report: a hunt that found only vacuous
ground is telling you your assumptions fence off the whole search space
– a finding, not a pass.
Determinism policy (ratified): every Hypothesis run uses
derandomize=True, database=None, and explicit generate/shrink
phases; seeds are accepted and echoed on every report, and reports are
reproducible from their own fields alone.
Requires the verify extra: pip install "longeron[verify]"
(Hypothesis for hunt/sequences; Z3 arrives via the bundled
smt extra for cover/prove and the domain ladder’s third
rung – each is imported lazily, and tiers degrade to recorded gaps
where an engine is missing).
- class longeron.analysis.verify.Boundary(attribute, value, violated)[source]¶
Bases:
objectOne oracle-bisected edge: where
violatedflips alongattribute.
- class longeron.analysis.verify.Counterexample(bindings=<factory>, events=(), violated=(), source='hunt', selection=<factory>, _materializer=None)[source]¶
Bases:
objectOne catch: shrunk bindings, a minimal event sequence, or a bad mix.
- materialize()[source]¶
The catch as an M0
Interpretationof identified individuals, re-checkable with the ordinarycheck/check_requirementmachinery.- Return type:
- longeron.analysis.verify.CounterexampleSource¶
which tier caught a counterexample
alias of
Literal[‘hunt’, ‘sequences’, ‘cover’, ‘prove’]
- class longeron.analysis.verify.Coverage(t, rows=<factory>, recall=None, exhaustive=None, violated_rows=0)[source]¶
Bases:
objectA covering array’s outcome: rows, and measured recall when feasible.
- class longeron.analysis.verify.Domain(name, kind, lo=None, hi=None, mined_from=<factory>, literals=<factory>, unit=None, fallback=False)[source]¶
Bases:
objectThe value domain of one free attribute, as derived from the model.
mined_fromrecords the derivation ladder’s outcome rung by rung (types, mined constraints, Z3-derived assumption bounds, fallbacks), so the report always shows what was derived and what fell back.
- class longeron.analysis.verify.Proof(requirement, status, bound='', binding_constraint='')[source]¶
Bases:
objectOne negated check’s verdict, with exact bounds where asked.
statusis'proven-safe'(UNSAT: no configuration satisfying every other check and every assumption can violate this one),'violation'(a SAT witness the interpreter confirmed), or'unknown'(the solver gave up, or its witness did not survive the interpreter re-check).boundcarries the exact rational supremum of a free attribute over the all-checks-hold region, attached to every proof of the query and attributed tobinding_constraint– the check whose exclusion moves that bound.
- longeron.analysis.verify.ProofStatus¶
one negated check’s verdict: UNSAT (nothing satisfying every other check and assumption can violate it), a SAT witness the interpreter confirmed, or the solver gave up / its witness did not survive the re-check
alias of
Literal[‘proven-safe’, ‘violation’, ‘unknown’]
- class longeron.analysis.verify.Report(scope, status='clean', violations=<factory>, counterexamples=<factory>, proofs=<factory>, vacuous=<factory>, domains=<factory>, gaps=<factory>, boundaries=<factory>, coverage=None, seed=None)[source]¶
Bases:
objectThe one report shape every tier (and the umbrella) returns.
- longeron.analysis.verify.ReportStatus¶
the whole report’s outcome: nothing found, at least one confirmed violation, or every negated check proven safe (
proveonly)alias of
Literal[‘clean’, ‘violated’, ‘proven’]
- class longeron.analysis.verify.Verdict(bindings, violated=<factory>, vacuous=<factory>, error=None)[source]¶
Bases:
objectOne configuration’s outcome under the universal property.
- longeron.analysis.verify.attribute_domains(interp, defn, free, requirements=())[source]¶
Value domains for the named free attributes of
defn.The derivation ladder, most specific source first, every rung recorded in
Domain.mined_from:attribute types (
Real/Integer/Natural/Boolean; enum types become literal lists;Naturaladds a>= 0floor);direct constraint mining –
assert constraintbodies comparing the attribute against a literal (unary-minus literals folded),and-conjunctions folded, and constraints nested in a case’sobjectiveincluded (the spec’s home forassumebounds);Z3-derived bounds through
smt’s reachability fixed point, under the assumption set (bounds that live only on derived attributes are found here);the declared fallback (applied by
strategies_for(), flagged).
A reserved rung (unit-aware ranges from the model’s measurement annotations) records the declared unit informationally only.
- longeron.analysis.verify.bisect_boundary(predicate, lo, hi, tol=1e-09)[source]¶
The threshold where
predicateflips from False (atlo) to True (athi) – refine a shrunk counterexample to the exact edge, against the same oracle that produced it.- Return type:
- longeron.analysis.verify.counterexample_values(counterexample)[source]¶
A
values=dict for the scoreboard from a materialized catch.The trade-study bridge (
longeron.analysis.scoreboard. architecture_values()) generalized to counterexamples: the violator is materialized to M0 and its root individual’s measured scalar slots become scoreboard bindings – the requirement it drives below its ramp floor renders as the red cell.
- longeron.analysis.verify.cover(model, assembly, t=2, assume=(), seed=None, exhaustive_cap=4096)[source]¶
A t-way covering array over the assembly’s variation points, every row evaluated interpreter-exact.
Factors come from
TradeStudy’s variation points (homogeneous selection per point); rows are ordinary selection dicts, evaluated via the same pathTradeStudy.evaluateuses. By default the array ranges over the WHOLE candidate space: the assembly’s constraints are the checks under test, and an array constrained by the checks it hunts could catch nothing by construction.assume=names the constraints that are build rules rather than checks (component compatibility: matching cell counts, prop fit); those are enforced during generation through the Z3 constraint engine, and violations are hunted among the rest – the covering-array reading of the universal property.When the exhaustive space fits under
exhaustive_capcandidate mixes,Coverage.recallmeasures violated-check recall against interpreter-exact ground truth (assumed constraints excluded on both sides); when it does not, the report states the honest guarantee instead – every valid t-tuple covered, violation coverage not guaranteed.- Return type:
- longeron.analysis.verify.events_of(interp, state_machine)[source]¶
Event names accepted anywhere in a state machine definition.
Walks own + inherited members (nested states included) for event triggers – the alphabet a stateful hunt draws its rules from.
- longeron.analysis.verify.hunt(model, part, requirements=(), free=(), max_examples=200, seed=None, fallback=(-1000000.0, 1000000.0))[source]¶
Search for – and shrink to – a simple violating configuration.
Strategies are derived from the model (
attribute_domains()); Hypothesis’sfindlocates and SHRINKS the simplest bindings whoseverdict()reports a violation. The shrunk catch is simplest, not smallest: per free scalar and violated check, the report pairs it with the oracle-bisected edge inReport.boundaries(andprove()supplies the exact algebraic edge where the model encodes). Derandomized;seedis echoed on the report.- Return type:
- longeron.analysis.verify.prove(model, part, requirements=(), free=(), seed=None)[source]¶
Negate each check one at a time under the assumption set.
Every
requireconstraint of the named requirements and everyassert constraintof the part is negated in turn, with the value pins, assumptions, and all other checks held: UNSAT is a proof of absence no sampling can deliver; SAT witnesses are re-checked by the interpreter before they are believed (the solver proposes, the interpreter decides). Per free attribute,Optimizecomputes the exact rational supremum over the all-checks-hold region and attributes it to the check whose exclusion moves it (the binding constraint) – carried on everyProofof the query.Encodability is per-query, not per-model: where a free path reaches nonlinear algebra the encoder refuses honestly, the refusal lands in
Report.gaps, and the signal is to fall back tohunt()over the same scope.- Return type:
- longeron.analysis.verify.sequences(model, state_machine, requirements=(), inputs=None, max_examples=100, max_steps=20, seed=None)[source]¶
Search for – and shrink to – a minimal violating event sequence.
One generic rule sends an arbitrary event from the alphabet read off the model’s transitions (
events_of(); a clock-advance rule is added when the machine declaresafter/attriggers), and one invariant checks therequirementsagainst the live simulation environment.StateMachine.sendrecords non-matching events as ignored, so the rule needs no preconditions and shrinking strips every irrelevant event from the reported sequence.- Return type:
- longeron.analysis.verify.strategies_for(interp, defn, free, requirements=(), fallback=(-1000000.0, 1000000.0), domains=None)[source]¶
Hypothesis strategies for the free attributes (from their domains).
The values are
hypothesis.strategies.SearchStrategyobjects, annotatedAnyat this lazy-import boundary. Sides the ladder could not bound take thefallbackrange and are flagged on the domain (Domain.fallback) – never silent.
- longeron.analysis.verify.verdict(interp, part, requirements, bindings)[source]¶
Instantiate
partunderbindingsand check everything.assert constraintmembers of the part are violations when false; requirementrequireconstraints are violations only when everyassumeconstraint holds (otherwise the requirement is VACUOUS – recorded, never failed). The interpreter is the sole oracle here; configurations its physics cannot evaluate (a sampled negative mass reaching a realsqrt) come back withVerdict.errorset – not a violation, not a pass, and never silently dropped.- Return type:
- longeron.analysis.verify.verify(model, scope, requirements=(), free=(), seed=None, t=2, max_examples=200, max_steps=20)[source]¶
Every applicable tier for one scope, one report.
Dispatch is by what the scope is: a state machine runs
sequences(); an assembly with variation points runscover(); any other part definition/usage runshunt()plusprove()where encodable. Tiers that do not apply are skipped silently; tiers that apply but cannot run (missing extra, no free attributes) are recorded inReport.gaps.- Return type: