Introduce the bearer: the particular system a quantity is about. The context has two black-box oscillators, A and B, each a body on a wall spring. An IndividualQuantity o k ℝ is a real magnitude of kind k about the object o, so the oscillator a quantity is about is part of its type. Dividing oscillator A's spring constant by oscillator A's mass type-checks and gives an IndividualQuantity of kind omegaSquaredK about A. Supplying oscillator B's mass where a mass about A is expected fails to type-check with a type mismatch. A Designated instance gives A and B distinct nominal names, so they remain two systems even when their parameter values are equal.
Oscillators A and B have the same sort, harmonic oscillator (theorem) HCP.L1_TwoBodies#oscillator_context_and_sort.
The designations of A and B are different, and a designation that gives every oscillator the same name is not injective, so it cannot be a Designated instance (theorem) HCP.L1_TwoBodies#designation.
For each oscillator o, omegaSqOf divides o's spring constant by o's mass with IndividualQuantity.div and type-checks as an IndividualQuantity of kind omegaSquaredK about o, whose magnitude is o's k/m (type-checked) HCP.L1_TwoBodies#oscillator_indexed_quantities.
Oscillator B's mass, supplied where a mass about A is expected, fails with a type mismatch: as a value, as an argument of IndividualQuantity.add or IndividualQuantity.div, and when oscillator A of rig R₁ is mixed with oscillator A of rig R₂ (refused) HCP.L1_TwoBodies#refused_cross_oscillator.
Subtracting an earlier record of A's mass from a later one, both on rig R₁, type-checks as an IndividualQuantity of kind massK about A, using DifferenceKind.ofScale; its magnitude is the later mass minus the earlier mass (type-checked) HCP.L1_TwoBodies#same_rig_estimate_difference.
Dedicating a kind to an object whose type has no Sorted instance fails to type-check (refused) HCP.L1_TwoBodies#refused_unsorted_object.
Cross-system contamination: oscillator B's mass used in oscillator A's k/m. Bare reals and Quantity values without a bearer accept it; IndividualQuantity rejects it with a type mismatch (HCP.L1_TwoBodies#bare_real_cross_oscillators, HCP.L1_TwoBodies#kinded_bearer_free_cross_oscillators, HCP.L1_TwoBodies#refused_cross_oscillator).
False identity: one name used for both oscillators, so A and B are reported as one system. The designation_inj proof that every Designated instance needs rules this out (HCP.L1_TwoBodies#designation).
Unsorted bearer: a quantity about an object of no stated sort. It fails to type-check because no Sorted instance exists for the object's type (HCP.L1_TwoBodies#refused_unsorted_object).
You are a PhysLib contributor: a physicist who writes Lean in PhysLib. You know Lean and
PhysLib and trust Dimension and WithDim; L0 has already shown what those dimensions
can and cannot distinguish.
Two bodies are now in view, one inside each black-box oscillator: whose mass is this? Bare reals and bearer-free kinded values let one oscillator's mass enter another's formula. L1 indexes mass and stiffness by an oscillator bearer scoped to a nominal Rig, so its own k/m is accepted and cross-oscillator operations are refused. Each oscillator is the whole characterized by ω₀, which is why k and m share its index. One name is one system: records under that name are its states at different times, configurations, or rival estimates of it; comparing them is the point. Different names, R₁ and R₂, are distinct systems even when their parameters match. L2 opens each box into body and spring(s), revisits which component bears mass and stiffness, and considers the pair as a whole.
Cross-system contamination. Oscillators A and B have the same kinds, so B's mass can enter A's frequency if the bearer is omitted; the cross-oscillator refusal is pinned at HCP.L1_TwoBodies#refused_cross_oscillator.
False identity. Giving A and B one name makes two oscillators look like one system; the injective designation and its constant-name counterexample are pinned at HCP.L1_TwoBodies#designation.
Two particulars, Oscillator A and B, of one sort (harmonic oscillator); each black box contains one point-like body and its own wall spring. The oscillators do not interact. One name is one system; its records are states, configurations, or rival estimates to compare. R₁ and R₂ are distinct names even when parameters match. L2 opens each box into body and spring(s), and introduces their whole/part relations.
No new kinds: mass and stiffness share a rig-indexed oscillator bearer, allowing its k/m quotient.
B's mass can enter A's formula when only the kind is checked; one constant designation would collapse A and B into one system.
Stage 2: the kinded form carries its bearer.
Under L0's assumptions, each oscillator is a homogeneous, rigid, point-like body on one
ideal, massless spring attached to a fixed, infinitely massive wall, along a line. The
oscillator's mass is its body's mass, and its stiffness is its spring's. The oscillator
is the whole characterized by ω₀, so k and m must carry the same oscillator index.
The two oscillators do not interact in L1. L2 revisits that assumption as it opens each
box into body and spring(s) and considers the pair as a whole.
Cross-oscillator operations and cross-rig addition are refused; the same-rig time states admit a typed mass difference whose magnitude reads the real fields. Total mass is meaningful, but whose total requires a whole; that is L2.
7
Ask for the mass kind dedicated to a nominal object with no sort.
HCP.L1_TwoBodies#refused_unsorted_object
A nominal Object cannot supply the Sorted instance required by dedicatedFor.
1. Bare reals. Put oscillator B's mass in oscillator A's frequency radicand. The
upstream oscillator accepts the cross-oscillator expression as a real:
-- Bare reals: √(S₁.k / S₂.m) accepts oscillator A's stiffness and oscillator B's mass as a real; bare values cannot catch this cross-system radicand.example(S₁S₂:ClassicalMechanics.HarmonicOscillator):ℝ:=√(S₁.k/S₂.m)
2. Kinded, but bearer-free. The spring-constant/mass quotient also accepts values from
different oscillators. It is still a Quantity, with no oscillator index:
-- Bearer safety: A bearer-free Quantity omegaSquaredK accepts oscillator A's stiffness divided by oscillator B's mass; erasing the bearer leaves only the kind.example(S₁S₂:ClassicalMechanics.HarmonicOscillator):QuantityForPhysLib.ClassicalMechanics.omegaSquaredKℝ:=ForPhysLib.ClassicalMechanics.springQS₁/ForPhysLib.ClassicalMechanics.massQS₂
3. Declare the context. Oscillators A and B are distinct particulars of one sort.
Each contains one body and one wall spring; neither component is separately indexed yet:
inductiveOscillator|A|BderivingDecidableEq,ReprdefoscillatorS:SortOfSystem:=⟨"harmonic oscillator"⟩instance:SortedOscillator:=⟨fun_=>oscillatorS⟩-- Same sort, distinct systems: Proves that sortOf assigns oscillator A and oscillator B the same sort, so sort alone does not identify either system.example:Sorted.sortOfOscillator.A=Sorted.sortOfOscillator.B:=rfl
4. Designate without collapsing. A designation gives each oscillator a nominal name.
Designated requires a proof, designation_inj, that the designation is injective: two
different oscillators never get the same name. Without that proof, anything keyed by name,
such as a report or a SysML export, could merge A and B into one system. This is the
false-identity risk. The instance below names A "oscillator A" and B "oscillator B" and
proves injectivity by cases. The theorem constant_designation_not_injective shows why a
lazy designation fails: the function that names every oscillator "oscillator" sends A and
B to the same name, so it is not injective, and no Designated instance can use it:
5. Carry the bearer. The oscillator is the whole characterized by ω₀; mass and
stiffness therefore share its index. One Rig name is one system: two TwoOscillators r
records are its states at different times, configurations, or rival estimates, and
comparing their quantities is the point. OscillatorOf r keeps those records' oscillator
bearers shared; different rig names are distinct systems regardless of matching parameters.
Under L0's
massless-spring, fixed-wall assumptions, these magnitudes read the body's mass and
spring's stiffness. The existing kind table supplies the quotient law; the magnitude
theorem reads the real fields. The catalogue entry remains shared because both oscillators
have the same sort:
/--
One rig name is one system; its records are states, configurations, or rival estimates to
compare. Different names denote distinct systems.
-/inductiveRig|R₁|R₂derivingDecidableEq,ReprstructureTwoOscillators(r:Rig)whereosc:Oscillator→ClassicalMechanics.HarmonicOscillatorstructureOscillatorOf(r:Rig)whereosc:OscillatordefmassOf{r:Rig}(sys:TwoOscillatorsr)(o:OscillatorOfr):IndividualQuantityoForPhysLib.ClassicalMechanics.massKℝ:=⟨(sys.osco.osc).m⟩defstiffnessOf{r:Rig}(sys:TwoOscillatorsr)(o:OscillatorOfr):IndividualQuantityoForPhysLib.ClassicalMechanics.springConstantKℝ:=⟨(sys.osco.osc).k⟩defomegaSqOf{r:Rig}(sys:TwoOscillatorsr)(o:OscillatorOfr):IndividualQuantityoForPhysLib.ClassicalMechanics.omegaSquaredKℝ:=IndividualQuantity.div(KindDiv.law(k₁:=ForPhysLib.ClassicalMechanics.springConstantK)(k₂:=ForPhysLib.ClassicalMechanics.massK)(k:=ForPhysLib.ClassicalMechanics.omegaSquaredK))(stiffnessOfsyso)(massOfsyso)/-- Bearer safety: Proves that oscillator O's indexed omegaSquaredK magnitude equals O.k / O.m; the bearer index keeps stiffness and mass on the same oscillator. -/theoremomegaSqOf_magnitude{r:Rig}(sys:TwoOscillatorsr)(o:OscillatorOfr):(omegaSqOfsyso).magnitude=(sys.osco.osc).k/(sys.osco.osc).m:=r:Rigsys:TwoOscillatorsro:OscillatorOfr⊢ (omegaSqOfsyso).magnitude=(sys.osco.osc).k/(sys.osco.osc).mAll goals completed! 🐙defwhole:Component:=⟨"whole"⟩/-- Kind vs bearer: Proves that the mass kind dedicated to oscillator A's whole equals the kind dedicated to oscillator B's whole; only the bearer index distinguishes their masses. -/theoremmass_kind_shared_by_oscillators:ForPhysLib.ClassicalMechanics.massK.dedicatedForOscillator.Awhole=ForPhysLib.ClassicalMechanics.massK.dedicatedForOscillator.Bwhole:=KindOfProperty.dedicatedFor_congrrflwhole
The sort-level catalogue comparison uses Sorted Oscillator; the rig-scoped wrapper
needs no additional Sorted or Designated instance.
6. Compare states; refuse cross-system substitution. Two weighings of oscillator A at
different times on rig R₁ have a typed mass difference whose magnitude reads the later
and earlier real fields. B's mass cannot fill A's slot, A's stiffness cannot be divided by
B's mass, and the two different oscillators' quantities cannot be added at this layer. Nor
can same-named oscillator A masses be added across R₁ and R₂: those names identify
distinct systems. Total mass is physically meaningful, but whose total requires a whole;
that is L2's question:
-- Bearer safety: Refused: type mismatch between oscillator B's mass bearer and the required oscillator A bearer; this prevents substituting B's mass into an A-specific quantity./--
error: Type mismatch
massOf sys { osc := Oscillator.B }
has type
IndividualQuantity { osc := Oscillator.B } ForPhysLib.ClassicalMechanics.massK ℝ
but is expected to have type
IndividualQuantity { osc := Oscillator.A } ForPhysLib.ClassicalMechanics.massK ℝ
-/#guard_msgsinexample{r:Rig}(sys:TwoOscillatorsr):IndividualQuantity(⟨.A⟩:OscillatorOfr)ForPhysLib.ClassicalMechanics.massKℝ:=massOfsys⟨.B⟩-- Bearer safety: Refused: type mismatch between oscillator A's and oscillator B's mass bearers; this prevents adding across systems before introducing an assembly whole./--
error: Application type mismatch: The argument
massOf sys { osc := Oscillator.B }
has type
IndividualQuantity { osc := Oscillator.B } ForPhysLib.ClassicalMechanics.massK ℝ
but is expected to have type
IndividualQuantity { osc := Oscillator.A } ForPhysLib.ClassicalMechanics.massK ℝ
in the application
IndividualQuantity.add ⋯ (massOf sys { osc := Oscillator.A }) (massOf sys { osc := Oscillator.B })
-/#guard_msgsinexample{r:Rig}(sys:TwoOscillatorsr):=IndividualQuantity.addDifferenceKind.ofScale(massOfsys⟨.A⟩)(massOfsys⟨.B⟩)-- Bearer safety: Refused: type mismatch between oscillator A's stiffness bearer and oscillator B's mass bearer; this prevents a cross-oscillator k/m quotient./--
error: Application type mismatch: The argument
massOf sys { osc := Oscillator.B }
has type
IndividualQuantity { osc := Oscillator.B } ForPhysLib.ClassicalMechanics.massK ℝ
but is expected to have type
IndividualQuantity { osc := Oscillator.A } ForPhysLib.ClassicalMechanics.massK ℝ
in the application
IndividualQuantity.div h (stiffnessOf sys { osc := Oscillator.A }) (massOf sys { osc := Oscillator.B })
-/#guard_msgsinexample{r:Rig}(sys:TwoOscillatorsr):=leth:=KindDiv.law(k₁:=ForPhysLib.ClassicalMechanics.springConstantK)(k₂:=ForPhysLib.ClassicalMechanics.massK)(k:=ForPhysLib.ClassicalMechanics.omegaSquaredK)IndividualQuantity.divh(stiffnessOfsys⟨.A⟩)(massOfsys⟨.B⟩)-- Bearer safety: Refused: type mismatch between oscillator A on R₁ and oscillator A on R₂; this prevents conflating distinct rigs even when values match./--
error: Application type mismatch: The argument
massOf { osc := o } { osc := Oscillator.A }
has type
IndividualQuantity (@OscillatorOf.mk Rig.R₂ Oscillator.A) ForPhysLib.ClassicalMechanics.massK ℝ
but is expected to have type
IndividualQuantity (@OscillatorOf.mk Rig.R₁ Oscillator.A) ForPhysLib.ClassicalMechanics.massK ℝ
in the application
IndividualQuantity.add ⋯ (massOf { osc := o } { osc := Oscillator.A }) (massOf { osc := o } { osc := Oscillator.A })
-/#guard_msgsinexample(o:Oscillator→ClassicalMechanics.HarmonicOscillator):=IndividualQuantity.addDifferenceKind.ofScale(massOf(⟨o⟩:TwoOscillators.R₁)⟨.A⟩)(massOf(⟨o⟩:TwoOscillators.R₂)⟨.A⟩)defoscillatorAMassDifference(earlierlater:TwoOscillators.R₁):IndividualQuantity(⟨.A⟩:OscillatorOf.R₁)ForPhysLib.ClassicalMechanics.massKℝ:=IndividualQuantity.addDifferenceKind.ofScale(massOflater⟨.A⟩)(-(massOfearlier⟨.A⟩))-- Same-name records: Constructs a massK IndividualQuantity about oscillator A on R₁, so earlier and later records of that rig can be compared.#guard_msgsinexample(earlierlater:TwoOscillators.R₁):IndividualQuantity(⟨.A⟩:OscillatorOf.R₁)ForPhysLib.ClassicalMechanics.massKℝ:=oscillatorAMassDifferenceearlierlater/-- Same-name records: Proves that oscillator A's R₁ mass-difference magnitude is later mass minus earlier mass. -/theoremoscillatorAMassDifference_magnitude(earlierlater:TwoOscillators.R₁):(oscillatorAMassDifferenceearlierlater).magnitude=(later.osc.A).m-(earlier.osc.A).m:=byearlier:TwoOscillatorsRig.R₁later:TwoOscillatorsRig.R₁⊢ (oscillatorAMassDifferenceearlierlater).magnitude=(later.oscOscillator.A).m-(earlier.oscOscillator.A).msimp[oscillatorAMassDifference,IndividualQuantity.add_magnitude,IndividualQuantity.neg_magnitude,massOf]earlier:TwoOscillatorsRig.R₁later:TwoOscillatorsRig.R₁⊢ Carrier.add(later.oscOscillator.A).m(-(earlier.oscOscillator.A).m)=(later.oscOscillator.A).m-(earlier.oscOscillator.A).mchange(later.osc.A).m+(-(earlier.osc.A).m)=(later.osc.A).m-(earlier.osc.A).mearlier:TwoOscillatorsRig.R₁later:TwoOscillatorsRig.R₁⊢ (later.oscOscillator.A).m+-(earlier.oscOscillator.A).m=(later.oscOscillator.A).m-(earlier.oscOscillator.A).mringAll goals completed! 🐙
7. A name is not a sort. A nominal Object does not supply Sorted System, so the
catalogue cannot be dedicated through that name:
-- Bearer safety: Refused: no Sorted System instance lets Lean dedicate a mass kind to this nominal object; a name alone cannot supply a system sort./--
error: failed to synthesize instance of type class
Sorted System
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/#guard_msgsinexample:=ForPhysLib.ClassicalMechanics.massK.dedicatedFor(⟨"oscillator A"⟩:Object)whole
Keep the contributor's vocabulary: oscillator, body, mass, spring, and bearer.
Quote each Lean check from its anchored L1 region; do not redefine PhysLib or PKC declarations.
Distinguish a bearer-free Quantity from an IndividualQuantity indexed by an oscillator.
Distinguish the oscillator label from its OscillatorOf r bearer, which is scoped to a nominal rig identity.
Treat one Rig name as one system: its records are states at different times, configurations, or rival estimates to compare; distinct rig names denote distinct systems.
Treat each oscillator as the whole at L1; body and spring become separate bearers when L2 opens the box.
Treat the guarded elaboration messages as evidence only for the refusals they actually show.
Black box: one homogeneous, rigid, point-like body on one ideal, massless wall spring; mass mA and stiffness kA.
System
Oscillator B
One particular of sort harmonic oscillator
Same L0 assumptions; mass mB and stiffness kB.
Relation
A and B
Distinct, designated oscillators
The oscillators do not interact; L2 revisits this assumption.
Inside each box
Body and spring
Not separately indexed in L1
The oscillator's mass is the body's mass; its stiffness is the spring's. L2 opens these components.
Outside
Walls
Fixed, infinitely massive walls
Each ideal spring has its own fixed-wall boundary.
Outside
Lines
One-dimensional lines of motion
Each oscillator's body remains constrained to its line.
The Lean model takes each complete oscillator as its bearer, scoped to a nominal Rig:
massOf, stiffnessOf, and omegaSqOf share an OscillatorOf r index. One name is one
system; records under it are states at different times, configurations, or rival estimates
whose quantities are meant to be compared. R₁ and R₂ are distinct systems even when their
oscillator parameters match. The box opens into body and spring(s) at L2, where the question
of which component bears mass or stiffness becomes explicit.