Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

proof versus point evaluation

This notebook proves deliveredEnergyBoundedBySupply for every value of its unbound features with verify_holds(), contrasts that with verify_satisfaction()'s point evaluation of the model’s existing assert satisfy claims, shows the checking loop catching a fully broken variant of the lemma as violated and a merely weakened variant as undecided with a real witness, and records the proof as engineering evidence with its own real limits stated plainly.

Notebook 01 stated deliveredEnergyBoundedBySupply and confirmed it is really part of ch08-cumulative.sysml. This notebook runs analysis against that construct and, further down, adds the one new model element this chapter’s own judgment record needs: a ReviewRecordRef tag anchoring AS-C08 to deliveredEnergyBoundedBySupply itself. See Ch8-01 for the construct itself.

The model loaded above already carries both deliveredEnergyBoundedBySupply (notebook 01) and the asC08Tag this notebook introduces further down, so nothing needs building before the analysis runs.

A require constraint referencing an undefined attribute still fails to load, the same language-tier control every chapter carries; this notebook’s own new negative controls, further down, check the model-checking loop itself rather than the language tier.

Negative control ok: bad.ok=False

verify_satisfaction() evaluates every assert satisfy / assert not satisfy declaration the model carries, each at the one set of values its subject happens to have. These are the same three real claims Chapter 3 and Chapter 6 already declared: nothing about them changes in Chapter 8.

  [holds] not satisfy timely by slow
  [FAILS] satisfy timely  (satisfaction satisfy timely: require condition evaluation failed: no value for feature toaster)
  [holds] satisfy heatGenerationReq by rated
  [holds] not satisfy heatGenerationReq by weak

Each of the three claims above is observed at one fixed set of attribute values.

These three claims are not all the same kind of check. timely compares Toaster::cycleTime, still a settable attribute with no relation deriving it from anything: not satisfy timely by slow holding shows the evaluation mechanics working correctly, not a finding about the toaster’s actual timing. heatGenerationReq compares HeatGenerator::power, a chosen physical rating: comparing a rated value against a threshold is a legitimate feasibility check of a design choice, which is why satisfy heatGenerationReq by rated and not satisfy heatGenerationReq by weak are real findings about those two candidates. The fourth verdict above is TimelyToastTest’s own verify timely; objective, not a satisfy claim about a specific subject: it has no subject to evaluate against, which is why it fails here with an evaluation error. conformance.satisfaction_claims_evaluated(), run through conformance.report() below, correctly skips this exact case entirely rather than reporting it as a finding: a verify relationship is not itself a claim about one subject, and the check’s own docstring says so.

Result(check_id='port-type', status='passed', findings=[], applies_from=(5, 3), reason=None, unblock_when=None)
Result(check_id='satisfaction-claims-evaluated', status='passed', findings=[], applies_from=(3, 1), reason=None, unblock_when=None)

satisfaction-claims-evaluated now reports passed on a real, non-vacuous check: every claim this check can evaluate evaluates to what it says it evaluates to.

Every verdict above is verify_satisfaction() evaluating a claim at one fixed set of values, the run engine’s own kind of answer. deliveredEnergyBoundedBySupply asks a different question: does the lemma hold for every value its unbound features could take? toaster.modelcheck.verify_holds() wraps sysml-toolkit’s real verify --solve command (Z3 underneath) to answer exactly that, over a small companion restatement of the construct. Two separate, real limits of this toolchain are why a companion file is used rather than the committed model or the construct’s own original elements directly: toaster.modelcheck’s own text parser cannot yet read a verdict line for a constraint that is also the subject of an assert satisfy declaration, which the committed model has (DEFERRED.md D-029); and, independent of that parser gap, sysml-toolkit’s Z3 backend never actually composes efficiencyBounded and deliveredEnergy into this lemma’s own check at all, whether by same-scope membership, inheritance, or a chained calc call (DEFERRED.md D-030, D-031, both confirmed below). The lemma below is therefore a hand-restated real-arithmetic fact of the same shape as the original relation, not a solver-checked reference to it.

[satisfied] deliveredEnergyBoundedBySupply  (z3: holds for all values of unbound features)

Proved for every value of heatGenCheck.efficiency, heatGenCheck.power and heatGenCheckDuration the antecedent admits, not evaluated at one.

A proof is only worth trusting if the same machinery can also report a real violation, not just agree with whatever is asked of it. The cell below restates the full negation of the lemma: efficiency in range and power, duration non-negative, and delivered energy strictly exceeds supplied energy (A and not B, not A implies not B, which is a different, weaker statement built from the same pieces and genuinely undecided here, since it is vacuously true wherever the antecedent itself fails, e.g. efficiency = 2). A and not B is the one Z3 must actually resolve as unsatisfiable to report violated: given the same bounded hypothesis, delivered energy can never strictly exceed supplied energy, so no assignment can make this conjunction true, and Z3 must reason about a product of three bounded unbound features to see that, not fold a literal constant the way 1 == 2 would.

[violated] deliveredEnergyExceedsSupply  (z3: unsatisfiable -- no assignment can make this hold)

The loop catches a fully broken lemma: violated, not undecided, not silently accepted.

A fully broken lemma is not the only interesting failure mode. A merely weakened variant, loosening the antecedent’s own bound from <= 1.0 to <= 1.2 (the same change Ch8-03 uses to demonstrate staleness), no longer holds for every value or fails for every value: it holds when efficiency <= 1.0 and fails when efficiency is between 1.0 and 1.2. verify_holds() correctly reports this as undecided, with a genuine Z3-found witness satisfying it, not satisfied and not violated; holds() correctly refuses to collapse that into a clean True or False, raising ModelCheckInconclusiveError instead. This is the real, three-way distinction this toolchain draws that a learner should see directly: a property can definitely hold everywhere, definitely fail everywhere, or genuinely not be settled either way by what’s stated, and only the first of those is something to build on without further work.

[undecided] deliveredEnergyBoundedBySupply  (result is indeterminate over unbound features -- z3: satisfiable, e.g. heatGenCheck.efficiency = 0, heatGenCheck.power = 0 [W], heatGenCheckDuration = 1 [s])
holds() correctly refuses to answer: undecided, not proven either way: deliveredEnergyBoundedBySupply (companion-check-scratch/conservation_check_weakened.sysml:15:9)

The proof above is engineering evidence, not a passing test result: it is what would have to be re-checked if HeatGenerator’s bound or deliveredEnergy’s definition ever changed, by hand, since nothing in this toolchain checks that the restated copy stays in sync with either. Recording it as a ReviewRecord states, in a reader’s terms, what makes this evidence appropriate, sufficient and trustworthy (Hawkins et al. 2011, SS3.1-3.4), the same way earlier chapters recorded their own judgment sites.

Before AS-C08 states its claim, the next cells give it a real anchor in the model: a ReviewRecordRef tag naming deliveredEnergyBoundedBySupply as what AS-C08 is about.

metadata asC08Tag : ReviewRecordRef about deliveredEnergyBoundedBySupply {
    identifier = "AS-C08";
}

This fragment is the same text now committed in models/ch08-cumulative.sysml onward, alongside the ReviewRecordRef definition (carried forward since Chapter 2); loading the cumulative model (the model.ok cell above, unchanged) is what makes this a real, checkable tag rather than an assertion the reader has to trust.

AS-C08 states the claim next: what the lemma establishes, and about which model element.

deliveredEnergyBoundedBySupply, a hand-restated real-arithmetic lemma of the same shape as HeatGenerator's efficiencyBounded constraint and deliveredEnergy's own definition, holds for every value of efficiency in [0,1] and every non-negative power and duration a companion restatement admits.

What standard is this claim checked against? verify_holds() reports a single verdict for deliveredEnergyBoundedBySupply, proved by Z3 over the unbound features the companion restatement carries, not merely evaluated at one point.

The lemma governs the companion restatement's own heatGenCheck.efficiency, heatGenCheck.power and heatGenCheckDuration features; it is not a solver-checked reference to HeatGenerator's own efficiencyBounded or deliveredEnergy (DEFERRED.md D-030, D-031), only a hand-restated copy of the same shape.
verify_holds() reports a single satisfied verdict for deliveredEnergyBoundedBySupply, with the reason text naming z3 (not propagation alone), proved for all values of the unbound heatGenCheck.efficiency, heatGenCheck.power and heatGenCheckDuration features.

What is this claim taking as given? The proof rests on the companion file restating deliveredEnergyBoundedBySupply correctly, and on the lemma’s own hypothesis (non-negative power and duration), which the model states here but does not enforce as a standing constraint on HeatGenerator or ApplyHeat elsewhere.

No prior ReviewRecord is assumed; this claim rests on the proof itself.

What supports the claim, and how? The Z3-derived verdict above, cited directly, is the evidence; the rationale states what kind of check produced it and why that is a materially different kind of evidence from a point evaluation, while being explicit about what it does not establish.

['verify_holds: deliveredEnergyBoundedBySupply satisfied (z3: holds for all values of unbound features)']
verify_holds() calls sysml-toolkit's real verify --solve command, which runs Z3 over the unbound features of a companion restatement of this lemma (see the narration above for why a companion file is used) and reports deliveredEnergyBoundedBySupply as satisfied: proved for all values the restatement admits, not read back from one entered value. This is a materially different kind of evidence from an evaluate-only verdict: verify_satisfaction() could only ever check a relation at whichever single power, duration and efficiency a candidate happens to carry. It is also, deliberately, a narrower claim than 'this proves HeatGenerator's own conservation property': see counterevidence.

What could be wrong, and what is still open? A record that hides its own weak points is not more trustworthy, it is less checkable.

This proof is NOT a solver-checked reference to HeatGenerator's own efficiencyBounded constraint or deliveredEnergy calc: this toolchain's Z3 backend does not compose two separately declared assert constraints, whether sibling or inherited (DEFERRED.md D-030), and cannot reason through a chained calc invocation like heatGenCheck.deliveredEnergy(...) (D-031). Confirmed directly: loosening efficiencyBounded's own literal bound to <= 1.5, or doubling deliveredEnergy's own definition by a factor of 2.0, in the real committed model changes neither the original elements' own verdicts nor this lemma's verdict at all, because the lemma restates its own copy of both rather than referencing either. The companion file used by verify_holds also restates the construct rather than checking the committed model directly, because toaster.modelcheck's own text parser does not yet handle the extra annotation the CLI prints for assert satisfy declarations (DEFERRED.md D-029).
Whether efficiency, power and duration ever take values outside the bound in a real candidate is not addressed by this proof; it establishes only that the restated lemma respects conservation wherever its own bound is honored. If HeatGenerator's own efficiencyBounded or deliveredEnergy is ever edited, this record's content_hash (computed from the whole model file) does go stale, which forces a re-review, but nothing automatically re-checks that the restated copy still matches the edited original; that check would be manual. No physical heat generator has been checked against this property; HeatGenerator remains an abstract carrier with no concrete realization of its own.

Assembling the record from the parts above, the same way a construction-zone cell assembles a model fragment from its own named pieces.

Model tag: {'tag': 'ToasterDemo::asC08Tag', 'identifier': 'AS-C08', 'annotated_element': 'ToasterDemo::deliveredEnergyBoundedBySupply'}
Validation errors: []
Record valid: identifier='AS-C08'  engineering_conclusion='supported'

The tag printed above is now part of the loaded model, and validate_record confirms the Python record and the model’s own tag agree about what AS-C08 is actually about. The claim printed above, the proof it points to, and the record’s own counterevidence stating plainly what that proof does and does not establish are three distinct things this notebook watched connect: a written lemma, a real solver’s verdict on it, and a record that never overstates what the verdict actually covers.

Try the chapter exercise in exercises/ch08/exercise.ipynb: it works through the same verify_satisfaction() and stale-detection pattern on its own, separate coffee-maker exercise model.