Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

verified-mbse

Machine-verified V&V matrices for spacecraft systems engineering.

A Lean 4 library that gives SysML v2 / KerML design models a dependent type-theoretic semantics. If your model type-checks, your V&V matrix is complete and your design constraints are proven correct.

lake build passing with zero sorry = every specification verified, every V-matrix cell filled.

The Problem

Systems engineers maintain V&V matrices — tables that map requirements to verification evidence — in spreadsheets, wikis, or DOORS. This creates three failure modes:

  1. Gaps go unnoticed. A cell is empty or says "TBD" but nobody catches it before launch review.
  2. Evidence is disconnected. The proof that "power budget holds across all mode combinations" lives in a separate analysis tool with no formal link to the design model.
  3. Composition is unchecked. Two subsystems are individually correct, but their integration breaks an assumption neither team documented.

verified-mbse eliminates all three by encoding V&V as types:

VVRecord = { spec : Prop, verified : spec, validation : ValidationTrace spec }
 ───────────── ─────────────── ─────────────────────────────────
 requirement machine proof confidence trace (→ trusted)

If a VVRecord exists, the requirement is proven. If a VMatrix.Complete theorem compiles, every cell is filled.

Quick Start

1. Add to your project

-- lakefile.lean
require verifiedMbse from git
 "https://github.com/chantakan/verified-mbse.git"

2. Define components and a state machine

import VerifiedMBSE
open VerifiedMBSE.Core
open VerifiedMBSE.Behavior
open VerifiedMBSE.VV
-- A component with ports and an invariant
def PowerSupply : PartDef :=
 { baseType := { name := some "PowerSupply" }
 ports := [pwrOutPort]
 invariant := True }
-- State machine: invariant preservation is a *type-level contract*
-- (transitions that violate it simply won't compile)
def epsSM : StateMachine EPSMode Nat (fun _ v => v ≤ 1000) where
 initialState := .nominal
 transitions := [nominalToLowPower, lowPowerToFault, ...]

3. Bundle everything into one SubSystemSpec

def epsSpec : SubSystemSpec epsSM :=
 { structural := epsStructural -- System + WellFormed proof
 behavioral := epsBehavioral -- NonEmpty (Kripke-generalized)
 fdir := epsFDIR } -- Safety + Detection + Recovery proofs

This single value proves: the structure is well-formed, the state machine preserves its invariant, and all three FDIR requirements hold.

4. Compose subsystems (N-way nested composition supported)

-- 2 subsystems
def epsAocsPK : ProductKripke epsSM aocsSM := ⟨⟩
def epsAocsSpec : SubSystemSpec epsAocsPK :=
 SubSystemSpec.compose epsSpec aocsSpec epsAocsPK
 epsSM_WellFormed.nonEmpty aocsSM_WellFormed.nonEmpty [] (by intros; contradiction)
-- 3 subsystems (nested) — enabled by B-8 ProductKripke generalization
def epsAocsTcsPK : ProductKripke epsAocsPK tcsSM := ⟨⟩
def epsAocsTcsSpec : SubSystemSpec epsAocsTcsPK :=
 SubSystemSpec.compose epsAocsSpec tcsSpec epsAocsTcsPK
 epsAocsSpec.behavioral.nonEmpty tcsSM_WellFormed.nonEmpty [] (by intros; contradiction)
-- N subsystems via variadic API (B-8d) — List.foldl-based composition
def sats : Option SubSystemPayload :=
 SubSystemPayload.composeMany
 [ SubSystemPayload.ofSpec epsSpec
 , SubSystemPayload.ofSpec aocsSpec
 , SubSystemPayload.ofSpec tcsSpec
 , SubSystemPayload.ofSpec ttcSpec ]

The composed spec auto-derives FDIR safety / detection / recovery for the product. See Variadic Composition Guide for details on the B-8d API.

5. Build the V-Matrix and prove completeness

open VerifiedMBSE.Matrix
def satellite : VMatrix :=
 { columns := [epsColumn, aocsColumn, tcsColumn, ttcColumn] }
-- This theorem IS the verification: no gaps in the V-matrix.
theorem sat_complete : satellite.Complete ["EPS", "AOCS", "TCS", "TTC"] := by
 constructor
 · intro s hs; ... -- every subsystem has a column
 · intro col hcol; ... -- every column covers all layers

6. Generate human-readable outputs

open VerifiedMBSE.Output
#eval IO.println (satellite.toMarkdown "MySatellite")
#eval IO.println (satellite.toTerminal "MySatellite")

Output:

═══════════════════════════════════════════
 V-Matrix: MySatellite
 4 subsystems │ 25 records │ ALL TRUSTED
═══════════════════════════════════════════
 EPS [5] ████████████████████ 100%
 AOCS [6] ████████████████████ 100%
 TCS [8] ████████████████████ 100%
 TTC [6] ████████████████████ 100%
═══════════════════════════════════════════
 Completeness: ✓ All layers covered
═══════════════════════════════════════════

Module Structure

VerifiedMBSE/
├── Core/ # Domain-independent type-theoretic foundations
│ ├── KerML.lean # Element, KerMLType, Feature, Direction
│ ├── Port.lean # PortDef, Conjugation, compatible
│ ├── Specialization.lean # Specialization (preorder), FeatureTyping, Interpretation
│ ├── Component.lean # PartDef, PortRef, Connector, System, WellFormed
│ ├── Compose.lean # System.compose, compose_WellFormed
│ └── Interpretation.lean # PartInstance, ConnectorSemantic, categorical laws
│
├── Behavior/ # Behavioral models (Kripke-generalized LTL)
│ ├── StateMachine.lean # Transition, StateMachine, Reachable, inv_holds
│ ├── Temporal.lean # Always (しろいしかく), Eventually (◇), Next, Until, Leads
│ ├── KripkeStructure.lean # KripkeStructure + ToKripke type class (B-1)
│ ├── StateMachineKripke.lean # StateMachine → KripkeStructure instance
│ ├── StateMachineLTL.lean # Dot-notation for sm.Always / sm.Eventually
│ ├── Product.lean # ProductStateMachine (abbrev of ProductKripke)
│ ├── ProductKripke.lean # ProductKripke (N-way nested, B-8)
│ ├── ProductTemporal.lean # Always_prod / Eventually_prod / Leads_prod lifting
│ └── FDIR.lean # FDIRSpec, StateMachineComponent
│
├── VV/ # Verification & Validation framework
│ ├── Layer.lean # Layer (8-level ECSS-E-ST-10C: mission→part)
│ ├── Evidence.lean # ValidationEvidence, isTrusted, ValidationTrace, VVRecord
│ ├── SubSystemSpec.lean # StructuralSpec, BehavioralSpec, FDIRBundle, SubSystemSpec
│ ├── VVBundle.lean # mkComponentRecord, SubSystemVVBundle, allRecords
│ ├── Power.lean # ModePowerSpec, PowerBudgetOK2
│ ├── Propagation.lean # LayerPropagation, depth-based supports
│ ├── Contract.lean # Contract, ContractedSystem, CouplingConstraint
│ ├── ProductFDIR.lean # FDIRBundle.compose, SubSystemSpec.compose (N-way)
│ └── VariadicCompose.lean # SubSystemPayload, composeMany (B-8d variadic)
│
├── Matrix/ # V-matrix construction
│ ├── VColumn.lean # VColumn, atLayer, Complete, fullyTrusted (struct-discrim)
│ ├── VMatrix.lean # VMatrix, SubSystemComplete, Complete
│ ├── Query.lean # column, cell, allRecords, summary
│ └── ModelBoundary.lean # ModelBoundary (vm : VMatrix) — dependently typed
│
├── Output/ # Human-readable output generation
│ ├── Render.lean # indent, typeName, layerToAbbr (8-layer)
│ ├── SysML.lean # → SysML v2 textual notation
│ ├── StateMachineSysML.lean # → SysML v2 state def
│ ├── Markdown.lean # → Markdown table
│ └── Terminal.lean # → Terminal summary with confidence bars
│
└── Equivalence/ # HoTT-inspired equivalence (advanced)
 ├── ComponentEquiv.lean # PortEquiv, ComponentEquiv, Substitutable
 ├── Refinement.lean # DesignEquiv, RequirementRefinement
 ├── Abstraction.lean # AbstractionLevel, DesignParameter
 └── Univalence.lean # DesignSpace (quotient), ua/ua_inv, Transport, Fiber
Examples/Spacecraft/ # Full satellite case study + acceptance tests
├── EPS.lean # Electric Power Subsystem (+ EPSTypeTag F8 pattern)
├── AOCS.lean # Attitude & Orbit Control
├── TCS.lean # Thermal Control (mode-dependent invariants)
├── TTC.lean # Telemetry, Tracking & Command
├── Satellite.lean # V-Matrix + completeness + ModelBoundary
├── Integration.lean # 2-way and 3-way nested composition sanity tests
├── F1F2Tests.lean # Evidence parameterization + mixed-evidence tests
├── F3F5F6Tests.lean # Specialization preorder, Layer 8-level, ModelBoundary type-binding
├── F8Tests.lean # Interpretation pattern (EPSTypeTag + exhaustive dispatch)
└── VariadicComposeTests.lean # B-8d payload / compose / composeMany sanity tests

Key Types at a Glance

Type What it is Why it matters
PartDef Component with ports + invariant Invariant is a Prop — must be proven at instantiation
Connector Port-to-port connection Carries a compatible proof — incompatible ports won't compile
System.WellFormed All connectors reference valid parts Structural soundness as a theorem
Transition.preserves Invariant preserved across state change Transitions that break invariants are unconstructible
Reachable.inv_holds Safety theorem Every reachable state satisfies the invariant — by induction
ToKripke α S D Type class lifting α to KripkeStructure Unifies LTL over StateMachine / ProductKripke / future continuous-time
ProductKripke x y Heterogeneous product of Kripke structures Enables N-way nested composition (3+ subsystems)
SubSystemSpec Structure + behavior + FDIR One value = complete subsystem verification
SubSystemSpec.compose Parallel composition of two specs Composes FDIR, spawns auto-derived bridge Records
SubSystemPayload Anonymous wrapper bundling α / S / D / ToKripke / x / spec Enables List-based variadic composition across heterogeneous specs (B-8d)
SubSystemPayload.composeMany List.foldl-based N-way composition One-shot composition of N subsystems (B-8d)
SubSystemPayload.composeWithBridge 2-ary payload composition with bridge connectors Inter-subsystem connectors at the payload level (B-8e)
VVRecord Machine proof + validation trace The atomic unit of V&V evidence
ValidationEvidence .trusted / .contract / .confidence 3-level confidence hierarchy; isTrusted by constructor (no Float equality)
VMatrix.Complete No gaps in the V-matrix The main theorem — if it compiles, you're done
Contract Assume-guarantee pair with validity proof Integration obligations become type errors when missing
ContractedSystem Contracts + coupling constraints, all discharged Catches the "individually correct, jointly broken" failure mode
ModelBoundary (vm) Dependently-typed verified/tested/analyzed/unmodeled split verifiedCount auto-derived from vm.totalRecords — no manual sync
Layer 8 levels: mission → part (ECSS-E-ST-10C) depth-based supports relation; new levels added without case explosion
DesignSpace PartDef / ComponentEquiv quotient Univalence: equivalent components are equal in design space
ua / ua_inv Equiv ↔ equality in DesignSpace HoTT univalence via setoid quotient — sorry-free

Design Principles

  1. Declarative. Define a SubSystemSpec; proofs and VVRecords are derived.
  2. Verifiable. lake build = all proofs checked. Zero sorry = zero gaps.
  3. Readable. V-Matrix output in Markdown, terminal, and SysML v2 text.
  4. Composable. N-way nested subsystem composition via ProductKripke, plus variadic composeMany over List SubSystemPayload.
  5. Extensible. Domain-independent core; spacecraft examples are separate.
  6. Typed discipline. ModelBoundary (vm : VMatrix), EPSTypeTag enum for interpretations — structural checks over string matching.

Documentation

Requirements

  • Lean 4 (v4.30.0-rc1)
  • Mathlib

Statistics

Files Lines sorry warnings
Library (VerifiedMBSE/) 37 ~4,450 0 0
Examples (satellite + tests) 11 ~3,630 0 0
Acceptance tests ~100 examples

Build: lake build VerifiedMBSE (177 jobs) + lake build Examples (187 jobs), all passing with zero sorry/warnings.

License

Apache 2.0

About

Formally verified MBSE framework in Lean 4 — dependent type semantics for SysML v2 / KerML with V&V matrix completeness by type checking

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /