forked from Isabelle_DOF/Isabelle_DOF
Varous little changes, and attemps to improve example sections and proof support.
This commit is contained in:
parent
85af8bc3ed
commit
1172f0f30a
520
src/SI/Units.thy
520
src/SI/Units.thy
|
@ -21,14 +21,29 @@ text\<open> This is an attempt to model the system and its derived entities (cf.
|
||||||
\<^url>\<open>https://www.quora.com/What-are-examples-of-SI-units\<close>) in Isabelle/HOL.
|
\<^url>\<open>https://www.quora.com/What-are-examples-of-SI-units\<close>) in Isabelle/HOL.
|
||||||
The design objective are twofold (and for the case of Isabelle somewhat
|
The design objective are twofold (and for the case of Isabelle somewhat
|
||||||
contradictory, see below)
|
contradictory, see below)
|
||||||
|
|
||||||
|
The construction proceeds in three phases:
|
||||||
|
\<^enum> We construct a generic type \<^theory_text>\<open>SI_domain\<close> which is basically an "inner representation" or
|
||||||
|
"semantic domain" of all SI types. Since SI-types have an interpretation in this domain,
|
||||||
|
it serves to give semantics to type-constructors by operations on this domain, too.
|
||||||
|
We construct a multiplicative group on it.
|
||||||
|
\<^enum> From \<^theory_text>\<open>SI_domain\<close> we build a \<^theory_text>\<open>'a SI_tagged_domain\<close> types, i.e. a polymorphic family of values
|
||||||
|
tagged with values from \<^theory_text>\<open>SI_domain\<close>. We construct multiplicative and additive
|
||||||
|
groups over it.
|
||||||
|
\<^enum> We construct a type-class characterizing SI - type expressions
|
||||||
|
and types tagged with SI - type expressions; this construction paves the
|
||||||
|
way to overloaded interpretation functions from SI type-expressions to
|
||||||
|
|
||||||
\<close>
|
\<close>
|
||||||
|
|
||||||
subsection \<open> Data-level Units \<close>
|
section\<open>The Domains of SI types and SI-tagged types\<close>
|
||||||
|
|
||||||
|
subsection \<open> The \<^theory_text>\<open>SI_domain\<close>-type and its operations \<close>
|
||||||
|
|
||||||
text \<open> An SI unit associates with each of the seven base unit an integer that denotes the power
|
text \<open> An SI unit associates with each of the seven base unit an integer that denotes the power
|
||||||
to which it is raised. We use a record to represent this 7-tuple, to enable code generation. \<close>
|
to which it is raised. We use a record to represent this 7-tuple, to enable code generation. \<close>
|
||||||
|
|
||||||
record SIUnit =
|
record SI_domain =
|
||||||
Seconds :: int
|
Seconds :: int
|
||||||
Meters :: int
|
Meters :: int
|
||||||
Kilograms :: int
|
Kilograms :: int
|
||||||
|
@ -39,21 +54,20 @@ record SIUnit =
|
||||||
|
|
||||||
text \<open> We define a commutative monoid for SI units. \<close>
|
text \<open> We define a commutative monoid for SI units. \<close>
|
||||||
|
|
||||||
instantiation SIUnit_ext :: (one) one
|
instantiation SI_domain_ext :: (one) one
|
||||||
begin
|
begin
|
||||||
\<comment> \<open> Here, $1$ is the dimensionless unit \<close>
|
\<comment> \<open> Here, $1$ is the dimensionless unit \<close>
|
||||||
definition one_SIUnit_ext :: "'a SIUnit_ext" where
|
definition one_SI_domain_ext :: "'a SI_domain_ext"
|
||||||
[code_unfold]:
|
where [code_unfold]: "1 = \<lparr> Seconds = 0, Meters = 0, Kilograms = 0, Amperes = 0
|
||||||
"1 = \<lparr> Seconds = 0, Meters = 0, Kilograms = 0, Amperes = 0
|
, Kelvins = 0, Moles = 0, Candelas = 0, \<dots> = 1 \<rparr>"
|
||||||
, Kelvins = 0, Moles = 0, Candelas = 0, \<dots> = 1 \<rparr>"
|
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation SIUnit_ext :: (times) times
|
instantiation SI_domain_ext :: (times) times
|
||||||
begin
|
begin
|
||||||
\<comment> \<open> Multiplication is defined by adding together the powers \<close>
|
\<comment> \<open> Multiplication is defined by adding together the powers \<close>
|
||||||
definition times_SIUnit_ext :: "'a SIUnit_ext \<Rightarrow> 'a SIUnit_ext \<Rightarrow> 'a SIUnit_ext" where
|
definition times_SI_domain_ext :: "'a SI_domain_ext \<Rightarrow> 'a SI_domain_ext \<Rightarrow> 'a SI_domain_ext"
|
||||||
[code_unfold]:
|
where [code_unfold]:
|
||||||
"x * y = \<lparr> Seconds = Seconds x + Seconds y, Meters = Meters x + Meters y
|
"x * y = \<lparr> Seconds = Seconds x + Seconds y, Meters = Meters x + Meters y
|
||||||
, Kilograms = Kilograms x + Kilograms y, Amperes = Amperes x + Amperes y
|
, Kilograms = Kilograms x + Kilograms y, Amperes = Amperes x + Amperes y
|
||||||
, Kelvins = Kelvins x + Kelvins y, Moles = Moles x + Moles y
|
, Kelvins = Kelvins x + Kelvins y, Moles = Moles x + Moles y
|
||||||
|
@ -61,45 +75,49 @@ begin
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instance SIUnit_ext :: (comm_monoid_mult) comm_monoid_mult
|
instance SI_domain_ext :: (comm_monoid_mult) comm_monoid_mult
|
||||||
proof
|
proof
|
||||||
fix a b c :: "'a SIUnit_ext"
|
fix a b c :: "'a SI_domain_ext"
|
||||||
show "a * b * c = a * (b * c)"
|
show "a * b * c = a * (b * c)"
|
||||||
by (simp add: times_SIUnit_ext_def mult.assoc)
|
by (simp add: times_SI_domain_ext_def mult.assoc)
|
||||||
show "a * b = b * a"
|
show "a * b = b * a"
|
||||||
by (simp add: times_SIUnit_ext_def mult.commute)
|
by (simp add: times_SI_domain_ext_def mult.commute)
|
||||||
show "1 * a = a"
|
show "1 * a = a"
|
||||||
by (simp add: times_SIUnit_ext_def one_SIUnit_ext_def)
|
by (simp add: times_SI_domain_ext_def one_SI_domain_ext_def)
|
||||||
qed
|
qed
|
||||||
|
|
||||||
text \<open> We also define the inverse and division operations, and an abelian group. \<close>
|
text \<open> We also define the inverse and division operations, and an abelian group. \<close>
|
||||||
|
|
||||||
instantiation SIUnit_ext :: ("{times,inverse}") inverse
|
instantiation SI_domain_ext :: ("{times,inverse}") inverse
|
||||||
begin
|
begin
|
||||||
definition inverse_SIUnit_ext :: "'a SIUnit_ext \<Rightarrow> 'a SIUnit_ext" where
|
definition inverse_SI_domain_ext :: "'a SI_domain_ext \<Rightarrow> 'a SI_domain_ext"
|
||||||
[code_unfold]:
|
where [code_unfold]:
|
||||||
"inverse x = \<lparr> Seconds = - Seconds x , Meters = - Meters x
|
"inverse x = \<lparr> Seconds = - Seconds x , Meters = - Meters x
|
||||||
, Kilograms = - Kilograms x, Amperes = - Amperes x
|
, Kilograms = - Kilograms x, Amperes = - Amperes x
|
||||||
, Kelvins = - Kelvins x, Moles = - Moles x
|
, Kelvins = - Kelvins x, Moles = - Moles x
|
||||||
, Candelas = - Candelas x, \<dots> = inverse (more x) \<rparr>"
|
, Candelas = - Candelas x, \<dots> = inverse (more x) \<rparr>"
|
||||||
|
|
||||||
definition divide_SIUnit_ext :: "'a SIUnit_ext \<Rightarrow> 'a SIUnit_ext \<Rightarrow> 'a SIUnit_ext" where
|
definition divide_SI_domain_ext :: "'a SI_domain_ext \<Rightarrow> 'a SI_domain_ext \<Rightarrow> 'a SI_domain_ext"
|
||||||
[code_unfold]: "divide_SIUnit_ext x y = x * (inverse y)"
|
where [code_unfold]:
|
||||||
|
"divide_SI_domain_ext x y = x * (inverse y)"
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instance SIUnit_ext :: (ab_group_mult) ab_group_mult
|
instance SI_domain_ext :: (ab_group_mult) ab_group_mult
|
||||||
proof
|
proof
|
||||||
fix a b :: "'a SIUnit_ext"
|
fix a b :: "'a SI_domain_ext"
|
||||||
show "inverse a \<cdot> a = 1"
|
show "inverse a \<cdot> a = 1"
|
||||||
by (simp add: inverse_SIUnit_ext_def times_SIUnit_ext_def one_SIUnit_ext_def)
|
by (simp add: inverse_SI_domain_ext_def times_SI_domain_ext_def one_SI_domain_ext_def)
|
||||||
show "a \<cdot> inverse b = a div b"
|
show "a \<cdot> inverse b = a div b"
|
||||||
by (simp add: divide_SIUnit_ext_def)
|
by (simp add: divide_SI_domain_ext_def)
|
||||||
qed
|
qed
|
||||||
|
|
||||||
record 'a SI =
|
|
||||||
|
subsection \<open> The \<^theory_text>\<open>SI_tagged_domain\<close>-type and its operations \<close>
|
||||||
|
|
||||||
|
record 'a SI_tagged_domain =
|
||||||
factor :: 'a
|
factor :: 'a
|
||||||
unit :: SIUnit
|
unit :: SI_domain
|
||||||
|
|
||||||
instantiation unit :: comm_monoid_add
|
instantiation unit :: comm_monoid_add
|
||||||
begin
|
begin
|
||||||
|
@ -122,90 +140,175 @@ begin
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation SI_ext :: (times, times) times
|
instantiation SI_tagged_domain_ext :: (times, times) times
|
||||||
begin
|
begin
|
||||||
definition "times_SI_ext x y = \<lparr> factor = factor x \<cdot> factor y, unit = unit x \<cdot> unit y, \<dots> = more x \<cdot> more y \<rparr>"
|
definition "times_SI_tagged_domain_ext x y = \<lparr> factor = factor x \<cdot> factor y, unit = unit x \<cdot> unit y, \<dots> = more x \<cdot> more y \<rparr>"
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation SI_ext :: (zero, zero) zero
|
instantiation SI_tagged_domain_ext :: (zero, zero) zero
|
||||||
begin
|
begin
|
||||||
definition "zero_SI_ext = \<lparr> factor = 0, unit = 1, \<dots> = 0 \<rparr>"
|
definition "zero_SI_tagged_domain_ext = \<lparr> factor = 0, unit = 1, \<dots> = 0 \<rparr>"
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation SI_ext :: (one, one) one
|
instantiation SI_tagged_domain_ext :: (one, one) one
|
||||||
begin
|
begin
|
||||||
definition "one_SI_ext = \<lparr> factor = 1, unit = 1, \<dots> = 1 \<rparr>"
|
definition "one_SI_tagged_domain_ext = \<lparr> factor = 1, unit = 1, \<dots> = 1 \<rparr>"
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation SI_ext :: (inverse, inverse) inverse
|
instantiation SI_tagged_domain_ext :: (inverse, inverse) inverse
|
||||||
begin
|
begin
|
||||||
definition "inverse_SI_ext x = \<lparr> factor = inverse (factor x), unit = inverse (unit x), \<dots> = inverse (more x) \<rparr>"
|
definition "inverse_SI_tagged_domain_ext x = \<lparr> factor = inverse (factor x), unit = inverse (unit x), \<dots> = inverse (more x) \<rparr>"
|
||||||
definition "divide_SI_ext x y = \<lparr> factor = factor x / factor y, unit = unit x / unit y, \<dots> = more x / more y \<rparr>"
|
definition "divide_SI_tagged_domain_ext x y = \<lparr> factor = factor x / factor y, unit = unit x / unit y, \<dots> = more x / more y \<rparr>"
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instance SI_ext :: (comm_monoid_mult, comm_monoid_mult) comm_monoid_mult
|
instance SI_tagged_domain_ext :: (comm_monoid_mult, comm_monoid_mult) comm_monoid_mult
|
||||||
by (intro_classes, simp_all add: one_SI_ext_def times_SI_ext_def mult.assoc, simp add: mult.commute)
|
by (intro_classes, simp_all add: one_SI_tagged_domain_ext_def
|
||||||
|
times_SI_tagged_domain_ext_def mult.assoc, simp add: mult.commute)
|
||||||
|
|
||||||
text \<open> A base unit is an SI unit here precisely one unit has power 1. \<close>
|
text \<open> A base unit is an SI_tagged_domain unit here precisely one unit has power 1. \<close>
|
||||||
|
|
||||||
definition is_BaseUnit :: "SIUnit \<Rightarrow> bool" where
|
definition is_BaseUnit :: "SI_domain \<Rightarrow> bool" where
|
||||||
"is_BaseUnit u = (\<exists> n. u = 1\<lparr>Meters := n\<rparr> \<or> u = 1\<lparr>Kilograms := n\<rparr> \<or> u = 1\<lparr>Seconds := n\<rparr>
|
"is_BaseUnit u = (\<exists> n. u = 1\<lparr>Meters := n\<rparr> \<or> u = 1\<lparr>Kilograms := n\<rparr> \<or> u = 1\<lparr>Seconds := n\<rparr>
|
||||||
\<or> u = 1\<lparr>Amperes := n\<rparr> \<or> u = 1\<lparr>Kelvins := n\<rparr> \<or> u = 1\<lparr>Moles := n\<rparr>
|
\<or> u = 1\<lparr>Amperes := n\<rparr> \<or> u = 1\<lparr>Kelvins := n\<rparr> \<or> u = 1\<lparr>Moles := n\<rparr>
|
||||||
\<or> u = 1\<lparr>Candelas := n\<rparr>)"
|
\<or> u = 1\<lparr>Candelas := n\<rparr>)"
|
||||||
|
|
||||||
subsection \<open> Type-level Units \<close>
|
|
||||||
|
|
||||||
subsubsection \<open> Classes \<close>
|
section\<open>The Syntax and Semantics of SI types and SI-tagged types\<close>
|
||||||
|
|
||||||
text \<open> A type class for unit denoting types. A type-level unit is a singleton type that associates
|
subsection \<open> Basic SI-types \<close>
|
||||||
with an value-level SI unit. \<close>
|
|
||||||
|
|
||||||
class siunit = finite +
|
text \<open> We provide a syntax for type-expressions; The definition of
|
||||||
fixes siunit_of :: "'a itself \<Rightarrow> SIUnit"
|
the basic type constructors is straight-forward via a one-elementary set. \<close>
|
||||||
|
|
||||||
|
typedef meter = "UNIV :: unit set" .. setup_lifting type_definition_meter
|
||||||
|
typedef kilogram = "UNIV :: unit set" .. setup_lifting type_definition_kilogram
|
||||||
|
typedef second = "UNIV :: unit set" .. setup_lifting type_definition_second
|
||||||
|
typedef ampere = "UNIV :: unit set" .. setup_lifting type_definition_ampere
|
||||||
|
typedef kelvin = "UNIV :: unit set" .. setup_lifting type_definition_kelvin
|
||||||
|
typedef mole = "UNIV :: unit set" .. setup_lifting type_definition_mole
|
||||||
|
typedef candela = "UNIV :: unit set" .. setup_lifting type_definition_candela
|
||||||
|
|
||||||
|
|
||||||
|
subsection \<open> SI-type expressions and SI-type interpretation \<close>
|
||||||
|
|
||||||
|
text \<open> The case for the construction of the multiplicative and inverse operators requires ---
|
||||||
|
thus, the unary and binary operators on our SI type language --- require that their arguments
|
||||||
|
are restricted to the set of SI-type expressions.
|
||||||
|
|
||||||
|
The mechanism in Isabelle to characterize a certain sub-class of Isabelle-type expressions
|
||||||
|
are \<^emph>\<open>type classes\<close>. We therefore need such a sub-class; for reasons of convenience,
|
||||||
|
we combine its construction also with the "semantics" of SI types in terms of
|
||||||
|
@{typ SI_domain}. \<close>
|
||||||
|
|
||||||
|
subsubsection \<open> SI-type expression definition as type-class \<close>
|
||||||
|
|
||||||
|
class si_type = finite +
|
||||||
|
fixes si_sem :: "'a itself \<Rightarrow> SI_domain"
|
||||||
assumes unitary_unit_pres: "card (UNIV::'a set) = 1"
|
assumes unitary_unit_pres: "card (UNIV::'a set) = 1"
|
||||||
|
|
||||||
syntax
|
syntax
|
||||||
"_SI" :: "type \<Rightarrow> logic" ("SI'(_')")
|
"_SI" :: "type \<Rightarrow> logic" ("SI'(_')")
|
||||||
|
|
||||||
translations
|
translations
|
||||||
"SI('a)" == "CONST siunit_of TYPE('a)"
|
"SI('a)" == "CONST si_sem TYPE('a)"
|
||||||
|
|
||||||
text \<open> An SI base unit type has a value-level base unit. \<close>
|
text \<open> The sub-set of basic SI type expressions can be characterized by the following
|
||||||
|
operation: \<close>
|
||||||
|
|
||||||
class sibaseunit = siunit +
|
class si_baseunit = si_type +
|
||||||
assumes is_BaseUnit: "is_BaseUnit SI('a)"
|
assumes is_BaseUnit: "is_BaseUnit SI('a)"
|
||||||
|
|
||||||
subsubsection \<open> Arithmetic \<close>
|
subsubsection \<open> SI base type constructors \<close>
|
||||||
|
|
||||||
text \<open> We define multiplication at the SI type level \<close>
|
text\<open>We embed the basic SI types into the SI type expressions: \<close>
|
||||||
|
declare [[show_sorts]]
|
||||||
|
|
||||||
typedef ('a::siunit, 'b::siunit) UnitTimes (infixl "\<cdot>" 69) = "UNIV :: unit set" ..
|
instantiation meter :: si_baseunit
|
||||||
|
begin
|
||||||
|
definition si_sem_meter :: "meter itself \<Rightarrow> SI_domain" where "si_sem_meter x = 1\<lparr>Meters := 1\<rparr>"
|
||||||
|
instance by (intro_classes, auto simp add: si_sem_meter_def is_BaseUnit_def, (transfer, simp)+)
|
||||||
|
end
|
||||||
|
|
||||||
|
instantiation kilogram :: si_baseunit
|
||||||
|
begin
|
||||||
|
definition si_sem_kilogram :: "kilogram itself \<Rightarrow> SI_domain" where "si_sem_kilogram x = 1\<lparr>Kilograms := 1\<rparr>"
|
||||||
|
instance by (intro_classes, auto simp add: si_sem_kilogram_def is_BaseUnit_def, (transfer, simp)+)
|
||||||
|
end
|
||||||
|
|
||||||
|
instantiation second :: si_baseunit
|
||||||
|
begin
|
||||||
|
definition si_sem_second :: "second itself \<Rightarrow> SI_domain" where "si_sem_second x = 1\<lparr>Seconds := 1\<rparr>"
|
||||||
|
instance by (intro_classes, auto simp add: si_sem_second_def is_BaseUnit_def, (transfer, simp)+)
|
||||||
|
end
|
||||||
|
|
||||||
|
instantiation ampere :: si_baseunit
|
||||||
|
begin
|
||||||
|
definition si_sem_ampere :: "ampere itself \<Rightarrow> SI_domain" where "si_sem_ampere x = 1\<lparr>Amperes := 1\<rparr>"
|
||||||
|
instance by (intro_classes, auto simp add: si_sem_ampere_def is_BaseUnit_def, (transfer, simp)+)
|
||||||
|
end
|
||||||
|
|
||||||
|
instantiation kelvin :: si_baseunit
|
||||||
|
begin
|
||||||
|
definition si_sem_kelvin :: "kelvin itself \<Rightarrow> SI_domain" where "si_sem_kelvin x = 1\<lparr>Kelvins := 1\<rparr>"
|
||||||
|
instance by (intro_classes, auto simp add: si_sem_kelvin_def is_BaseUnit_def, (transfer, simp)+)
|
||||||
|
end
|
||||||
|
|
||||||
|
instantiation mole :: si_baseunit
|
||||||
|
begin
|
||||||
|
definition si_sem_mole :: "mole itself \<Rightarrow> SI_domain" where "si_sem_mole x = 1\<lparr>Moles := 1\<rparr>"
|
||||||
|
instance by (intro_classes, auto simp add: si_sem_mole_def is_BaseUnit_def, (transfer, simp)+)
|
||||||
|
end
|
||||||
|
|
||||||
|
instantiation candela :: si_baseunit
|
||||||
|
begin
|
||||||
|
definition si_sem_candela :: "candela itself \<Rightarrow> SI_domain" where "si_sem_candela x = 1\<lparr>Candelas := 1\<rparr>"
|
||||||
|
instance by (intro_classes, auto simp add: si_sem_candela_def is_BaseUnit_def, (transfer, simp)+)
|
||||||
|
end
|
||||||
|
|
||||||
|
lemma [simp] : "is_BaseUnit SI(meter)" by(simp add: Units.si_baseunit_class.is_BaseUnit)
|
||||||
|
lemma [simp] : "is_BaseUnit SI(kilogram)" by(simp add: Units.si_baseunit_class.is_BaseUnit)
|
||||||
|
lemma [simp] : "is_BaseUnit SI(second)" by(simp add: Units.si_baseunit_class.is_BaseUnit)
|
||||||
|
lemma [simp] : "is_BaseUnit SI(ampere)" by(simp add: Units.si_baseunit_class.is_BaseUnit)
|
||||||
|
lemma [simp] : "is_BaseUnit SI(kelvin)" by(simp add: Units.si_baseunit_class.is_BaseUnit)
|
||||||
|
lemma [simp] : "is_BaseUnit SI(mole)" by(simp add: Units.si_baseunit_class.is_BaseUnit)
|
||||||
|
lemma [simp] : "is_BaseUnit SI(candela)" by(simp add: Units.si_baseunit_class.is_BaseUnit)
|
||||||
|
|
||||||
|
|
||||||
|
subsubsection \<open> Higher SI Type Constructors: Inner Product and Inverse \<close>
|
||||||
|
text\<open>On the class of SI-types (in which we have already inserted the base SI types),
|
||||||
|
the definitions of the type constructors for inner product and inverse is straight) forward.\<close>
|
||||||
|
|
||||||
|
typedef ('a::si_type, 'b::si_type) UnitTimes (infixl "\<cdot>" 69) = "UNIV :: unit set" ..
|
||||||
setup_lifting type_definition_UnitTimes
|
setup_lifting type_definition_UnitTimes
|
||||||
|
|
||||||
text \<open> We can prove that multiplication of two SI types yields an SI type. \<close>
|
text \<open> We can prove that multiplication of two SI types yields an SI type. \<close>
|
||||||
|
|
||||||
instantiation UnitTimes :: (siunit, siunit) siunit
|
instantiation UnitTimes :: (si_type, si_type) si_type
|
||||||
begin
|
begin
|
||||||
definition siunit_of_UnitTimes :: "('a \<cdot> 'b) itself \<Rightarrow> SIUnit" where
|
definition si_sem_UnitTimes :: "('a \<cdot> 'b) itself \<Rightarrow> SI_domain" where
|
||||||
"siunit_of_UnitTimes x = SI('a) * SI('b)"
|
"si_sem_UnitTimes x = SI('a) * SI('b)"
|
||||||
instance by (intro_classes, simp_all add: siunit_of_UnitTimes_def, (transfer, simp)+)
|
instance by (intro_classes, simp_all add: si_sem_UnitTimes_def, (transfer, simp)+)
|
||||||
end
|
end
|
||||||
|
|
||||||
text \<open> Similarly, we define division of two SI types and prove that SI types are closed under this. \<close>
|
text \<open> Similarly, we define division of two SI types and prove that SI types are closed under this. \<close>
|
||||||
|
|
||||||
typedef 'a UnitInv ("(_\<^sup>-\<^sup>1)" [999] 999) = "UNIV :: unit set" ..
|
typedef 'a UnitInv ("(_\<^sup>-\<^sup>1)" [999] 999) = "UNIV :: unit set" ..
|
||||||
setup_lifting type_definition_UnitInv
|
setup_lifting type_definition_UnitInv
|
||||||
instantiation UnitInv :: (siunit) siunit
|
instantiation UnitInv :: (si_type) si_type
|
||||||
begin
|
begin
|
||||||
definition siunit_of_UnitInv :: "('a\<^sup>-\<^sup>1) itself \<Rightarrow> SIUnit" where
|
definition si_sem_UnitInv :: "('a\<^sup>-\<^sup>1) itself \<Rightarrow> SI_domain" where
|
||||||
"siunit_of_UnitInv x = inverse SI('a)"
|
"si_sem_UnitInv x = inverse SI('a)"
|
||||||
instance by (intro_classes, simp_all add: siunit_of_UnitInv_def, (transfer, simp)+)
|
instance by (intro_classes, simp_all add: si_sem_UnitInv_def, (transfer, simp)+)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
subsubsection \<open> Syntactic Support for SI type expressions. \<close>
|
||||||
|
|
||||||
|
text\<open>A number of type-synonyms allow for more compact notation: \<close>
|
||||||
type_synonym ('a, 'b) UnitDiv = "'a \<cdot> ('b\<^sup>-\<^sup>1)" (infixl "'/" 69)
|
type_synonym ('a, 'b) UnitDiv = "'a \<cdot> ('b\<^sup>-\<^sup>1)" (infixl "'/" 69)
|
||||||
|
|
||||||
type_synonym 'a UnitSquare = "'a \<cdot> 'a" ("(_)\<^sup>2" [999] 999)
|
type_synonym 'a UnitSquare = "'a \<cdot> 'a" ("(_)\<^sup>2" [999] 999)
|
||||||
|
@ -213,6 +316,8 @@ type_synonym 'a UnitCube = "'a \<cdot> 'a \<cdot> 'a" ("(_)\<^sup>3" [999] 999)
|
||||||
type_synonym 'a UnitInvSquare = "('a\<^sup>2)\<^sup>-\<^sup>1" ("(_)\<^sup>-\<^sup>2" [999] 999)
|
type_synonym 'a UnitInvSquare = "('a\<^sup>2)\<^sup>-\<^sup>1" ("(_)\<^sup>-\<^sup>2" [999] 999)
|
||||||
type_synonym 'a UnitInvCube = "('a\<^sup>3)\<^sup>-\<^sup>1" ("(_)\<^sup>-\<^sup>3" [999] 999)
|
type_synonym 'a UnitInvCube = "('a\<^sup>3)\<^sup>-\<^sup>1" ("(_)\<^sup>-\<^sup>3" [999] 999)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
translations (type) "'a\<^sup>-\<^sup>2" <= (type) "('a\<^sup>2)\<^sup>-\<^sup>1"
|
translations (type) "'a\<^sup>-\<^sup>2" <= (type) "('a\<^sup>2)\<^sup>-\<^sup>1"
|
||||||
translations (type) "'a\<^sup>-\<^sup>3" <= (type) "('a\<^sup>3)\<^sup>-\<^sup>1"
|
translations (type) "'a\<^sup>-\<^sup>3" <= (type) "('a\<^sup>3)\<^sup>-\<^sup>1"
|
||||||
|
|
||||||
|
@ -233,74 +338,32 @@ print_translation \<open>
|
||||||
_ => raise Match)]
|
_ => raise Match)]
|
||||||
\<close>
|
\<close>
|
||||||
|
|
||||||
subsubsection \<open> SI base type constructors \<close>
|
|
||||||
|
|
||||||
declare [[show_sorts]]
|
|
||||||
|
|
||||||
typedef meter = "UNIV :: unit set" .. setup_lifting type_definition_meter
|
subsection \<open> SI Tagged Types \<close>
|
||||||
instantiation meter :: sibaseunit
|
text\<open>We 'lift' SI type expressions to SI tagged type expressions as follows:\<close>
|
||||||
begin
|
|
||||||
definition siunit_of_meter :: "meter itself \<Rightarrow> SIUnit" where "siunit_of_meter x = 1\<lparr>Meters := 1\<rparr>"
|
|
||||||
instance by (intro_classes, auto simp add: siunit_of_meter_def is_BaseUnit_def, (transfer, simp)+)
|
|
||||||
end
|
|
||||||
|
|
||||||
typedef kilogram = "UNIV :: unit set" .. setup_lifting type_definition_kilogram
|
typedef (overloaded) ('n, 'u::si_type) Unit ("_[_]" [999,0] 999)
|
||||||
instantiation kilogram :: sibaseunit
|
= "{x :: 'n SI_tagged_domain. unit x = SI('u)}"
|
||||||
begin
|
|
||||||
definition siunit_of_kilogram :: "kilogram itself \<Rightarrow> SIUnit" where "siunit_of_kilogram x = 1\<lparr>Kilograms := 1\<rparr>"
|
|
||||||
instance by (intro_classes, auto simp add: siunit_of_kilogram_def is_BaseUnit_def, (transfer, simp)+)
|
|
||||||
end
|
|
||||||
|
|
||||||
typedef second = "UNIV :: unit set" .. setup_lifting type_definition_second
|
|
||||||
instantiation second :: sibaseunit
|
|
||||||
begin
|
|
||||||
definition siunit_of_second :: "second itself \<Rightarrow> SIUnit" where "siunit_of_second x = 1\<lparr>Seconds := 1\<rparr>"
|
|
||||||
instance by (intro_classes, auto simp add: siunit_of_second_def is_BaseUnit_def, (transfer, simp)+)
|
|
||||||
end
|
|
||||||
|
|
||||||
typedef ampere = "UNIV :: unit set" .. setup_lifting type_definition_ampere
|
|
||||||
instantiation ampere :: sibaseunit
|
|
||||||
begin
|
|
||||||
definition siunit_of_ampere :: "ampere itself \<Rightarrow> SIUnit" where "siunit_of_ampere x = 1\<lparr>Amperes := 1\<rparr>"
|
|
||||||
instance by (intro_classes, auto simp add: siunit_of_ampere_def is_BaseUnit_def, (transfer, simp)+)
|
|
||||||
end
|
|
||||||
|
|
||||||
typedef kelvin = "UNIV :: unit set" .. setup_lifting type_definition_kelvin
|
|
||||||
instantiation kelvin :: sibaseunit
|
|
||||||
begin
|
|
||||||
definition siunit_of_kelvin :: "kelvin itself \<Rightarrow> SIUnit" where "siunit_of_kelvin x = 1\<lparr>Kelvins := 1\<rparr>"
|
|
||||||
instance by (intro_classes, auto simp add: siunit_of_kelvin_def is_BaseUnit_def, (transfer, simp)+)
|
|
||||||
end
|
|
||||||
|
|
||||||
typedef mole = "UNIV :: unit set" .. setup_lifting type_definition_mole
|
|
||||||
instantiation mole :: sibaseunit
|
|
||||||
begin
|
|
||||||
definition siunit_of_mole :: "mole itself \<Rightarrow> SIUnit" where "siunit_of_mole x = 1\<lparr>Moles := 1\<rparr>"
|
|
||||||
instance by (intro_classes, auto simp add: siunit_of_mole_def is_BaseUnit_def, (transfer, simp)+)
|
|
||||||
end
|
|
||||||
|
|
||||||
typedef candela = "UNIV :: unit set" .. setup_lifting type_definition_candela
|
|
||||||
instantiation candela :: sibaseunit
|
|
||||||
begin
|
|
||||||
definition siunit_of_candela :: "candela itself \<Rightarrow> SIUnit" where "siunit_of_candela x = 1\<lparr>Candelas := 1\<rparr>"
|
|
||||||
instance by (intro_classes, auto simp add: siunit_of_candela_def is_BaseUnit_def, (transfer, simp)+)
|
|
||||||
end
|
|
||||||
|
|
||||||
subsection \<open> SI tagged types \<close>
|
|
||||||
|
|
||||||
typedef (overloaded) ('n, 'u::siunit) Unit ("_[_]" [999,0] 999) = "{x :: 'n SI. unit x = SI('u)}"
|
|
||||||
morphisms fromUnit toUnit by (rule_tac x="\<lparr> factor = undefined, unit = SI('u) \<rparr>" in exI, simp)
|
morphisms fromUnit toUnit by (rule_tac x="\<lparr> factor = undefined, unit = SI('u) \<rparr>" in exI, simp)
|
||||||
|
|
||||||
text \<open> Coerce values when their units are equivalent \<close>
|
text \<open> Coerce values when their units are equivalent \<close>
|
||||||
|
|
||||||
definition coerceUnit :: "'u\<^sub>2 itself \<Rightarrow> 'a['u\<^sub>1::siunit] \<Rightarrow> 'a['u\<^sub>2::siunit]" where
|
definition coerceUnit :: "'u\<^sub>2 itself \<Rightarrow> 'a['u\<^sub>1::si_type] \<Rightarrow> 'a['u\<^sub>2::si_type]" where
|
||||||
"coerceUnit t x = (if SI('u\<^sub>1) = SI('u\<^sub>2) then toUnit (fromUnit x) else undefined)"
|
"SI('u\<^sub>1) = SI('u\<^sub>2) \<Longrightarrow> coerceUnit t x = (toUnit (fromUnit x))"
|
||||||
|
|
||||||
|
|
||||||
|
section\<open>Operations SI-tagged types via their Semantic Domains\<close>
|
||||||
|
|
||||||
|
subsection\<open>Predicates on SI-tagged types\<close>
|
||||||
|
|
||||||
text \<open> Two SI types are equivalent if they have the same value-level units. \<close>
|
text \<open> Two SI types are equivalent if they have the same value-level units. \<close>
|
||||||
|
|
||||||
definition Unit_equiv :: "'n['a::siunit] \<Rightarrow> 'n['b::siunit] \<Rightarrow> bool" (infix "\<approx>\<^sub>U" 50) where
|
definition Unit_equiv :: "'n['a::si_type] \<Rightarrow> 'n['b::si_type] \<Rightarrow> bool" (infix "\<approx>\<^sub>U" 50) where
|
||||||
"a \<approx>\<^sub>U b \<longleftrightarrow> fromUnit a = fromUnit b"
|
"a \<approx>\<^sub>U b \<longleftrightarrow> fromUnit a = fromUnit b"
|
||||||
|
|
||||||
|
text\<open>This gives us an equivalence, but, unfortunately, not a congruence.\<close>
|
||||||
|
|
||||||
lemma Unit_equiv_refl [simp]: "a \<approx>\<^sub>U a"
|
lemma Unit_equiv_refl [simp]: "a \<approx>\<^sub>U a"
|
||||||
by (simp add: Unit_equiv_def)
|
by (simp add: Unit_equiv_def)
|
||||||
|
|
||||||
|
@ -310,24 +373,54 @@ lemma Unit_equiv_sym: "a \<approx>\<^sub>U b \<Longrightarrow> b \<approx>\<^sub
|
||||||
lemma Unit_equiv_trans: "\<lbrakk> a \<approx>\<^sub>U b; b \<approx>\<^sub>U c \<rbrakk> \<Longrightarrow> a \<approx>\<^sub>U c"
|
lemma Unit_equiv_trans: "\<lbrakk> a \<approx>\<^sub>U b; b \<approx>\<^sub>U c \<rbrakk> \<Longrightarrow> a \<approx>\<^sub>U c"
|
||||||
by (simp add: Unit_equiv_def)
|
by (simp add: Unit_equiv_def)
|
||||||
|
|
||||||
|
(* the following series of equivalent statements ... *)
|
||||||
|
|
||||||
lemma coerceUnit_eq_iff:
|
lemma coerceUnit_eq_iff:
|
||||||
fixes x :: "'a['u\<^sub>1::siunit]"
|
fixes x :: "'a['u\<^sub>1::si_type]"
|
||||||
assumes "SI('u\<^sub>1) = SI('u\<^sub>2::siunit)"
|
assumes "SI('u\<^sub>1) = SI('u\<^sub>2::si_type)"
|
||||||
shows "(coerceUnit TYPE('u\<^sub>2) x) \<approx>\<^sub>U x"
|
shows "(coerceUnit TYPE('u\<^sub>2) x) \<approx>\<^sub>U x"
|
||||||
by (metis Unit_equiv_def assms coerceUnit_def fromUnit toUnit_inverse)
|
by (metis Unit_equiv_def assms coerceUnit_def fromUnit toUnit_inverse)
|
||||||
|
|
||||||
|
(* or equivalently *)
|
||||||
|
|
||||||
|
lemma coerceUnit_eq_iff2:
|
||||||
|
fixes x :: "'a['u\<^sub>1::si_type]"
|
||||||
|
assumes "SI('u\<^sub>1) = SI('u\<^sub>2::si_type)" and "y = (coerceUnit TYPE('u\<^sub>2) x)"
|
||||||
|
shows "x \<approx>\<^sub>U y"
|
||||||
|
by (metis Unit_equiv_def assms coerceUnit_def fromUnit toUnit_inverse)
|
||||||
|
|
||||||
|
lemma updown_eq_iff:
|
||||||
|
fixes x :: "'a['u\<^sub>1::si_type]" fixes y :: "'a['u\<^sub>2::si_type]"
|
||||||
|
assumes "SI('u\<^sub>1) = SI('u\<^sub>2::si_type)" and "y = (toUnit (fromUnit x))"
|
||||||
|
shows "x \<approx>\<^sub>U y"
|
||||||
|
by (metis Unit_equiv_def assms fromUnit toUnit_inverse)
|
||||||
|
|
||||||
|
text\<open>This is more general that \<open>y = x \<Longrightarrow> x \<approx>\<^sub>U y\<close>, since x and y may have different type.\<close>
|
||||||
|
|
||||||
|
find_theorems "(toUnit (fromUnit _))"
|
||||||
|
|
||||||
|
|
||||||
|
lemma eq_ :
|
||||||
|
fixes x :: "'a['u\<^sub>1::si_type]" fixes y :: "'a['u\<^sub>2::si_type]"
|
||||||
|
assumes "x \<approx>\<^sub>U y"
|
||||||
|
shows "SI('u\<^sub>1) = SI('u\<^sub>2::si_type)"
|
||||||
|
by (metis (full_types) Unit_equiv_def assms fromUnit mem_Collect_eq)
|
||||||
|
|
||||||
|
|
||||||
|
subsection\<open>Operations on SI-tagged types\<close>
|
||||||
|
|
||||||
setup_lifting type_definition_Unit
|
setup_lifting type_definition_Unit
|
||||||
|
|
||||||
lift_definition
|
lift_definition
|
||||||
Unit_times :: "('n::times)['a::siunit] \<Rightarrow> 'n['b::siunit] \<Rightarrow> 'n['a\<cdot>'b]" (infixl "*\<^sub>U" 69) is "(*)"
|
Unit_times :: "('n::times)['a::si_type] \<Rightarrow> 'n['b::si_type] \<Rightarrow> 'n['a \<cdot>'b]" (infixl "*\<^sub>U" 69) is "(*)"
|
||||||
by (simp add: siunit_of_UnitTimes_def times_SI_ext_def)
|
by (simp add: si_sem_UnitTimes_def times_SI_tagged_domain_ext_def)
|
||||||
|
|
||||||
lift_definition
|
lift_definition
|
||||||
Unit_inverse :: "('n::inverse)['a::siunit] \<Rightarrow> 'n['a\<^sup>-\<^sup>1]" ("(_\<^sup>-\<^sup>\<one>)" [999] 999) is "inverse"
|
Unit_inverse :: "('n::inverse)['a::si_type] \<Rightarrow> 'n['a\<^sup>-\<^sup>1]" ("(_\<^sup>-\<^sup>\<one>)" [999] 999) is "inverse"
|
||||||
by (simp add: inverse_SI_ext_def siunit_of_UnitInv_def)
|
by (simp add: inverse_SI_tagged_domain_ext_def si_sem_UnitInv_def)
|
||||||
|
|
||||||
abbreviation
|
abbreviation
|
||||||
Unit_divide :: "('n::{times,inverse})['a::siunit] \<Rightarrow> 'n['b::siunit] \<Rightarrow> 'n['a/'b]" (infixl "'/\<^sub>U" 70) where
|
Unit_divide :: "('n::{times,inverse})['a::si_type] \<Rightarrow> 'n['b::si_type] \<Rightarrow> 'n['a/'b]" (infixl "'/\<^sub>U" 70) where
|
||||||
"Unit_divide x y \<equiv> x *\<^sub>U y\<^sup>-\<^sup>\<one>"
|
"Unit_divide x y \<equiv> x *\<^sub>U y\<^sup>-\<^sup>\<one>"
|
||||||
|
|
||||||
abbreviation Unit_sq ("(_)\<^sup>\<two>" [999] 999) where "u\<^sup>\<two> \<equiv> u *\<^sub>U u"
|
abbreviation Unit_sq ("(_)\<^sup>\<two>" [999] 999) where "u\<^sup>\<two> \<equiv> u *\<^sub>U u"
|
||||||
|
@ -336,21 +429,21 @@ abbreviation Unit_cube ("(_)\<^sup>\<three>" [999] 999) where "u\<^sup>\<three>
|
||||||
abbreviation Unit_neq_sq ("(_)\<^sup>-\<^sup>\<two>" [999] 999) where "u\<^sup>-\<^sup>\<two> \<equiv> (u\<^sup>\<two>)\<^sup>-\<^sup>\<one>"
|
abbreviation Unit_neq_sq ("(_)\<^sup>-\<^sup>\<two>" [999] 999) where "u\<^sup>-\<^sup>\<two> \<equiv> (u\<^sup>\<two>)\<^sup>-\<^sup>\<one>"
|
||||||
abbreviation Unit_neq_cube ("(_)\<^sup>-\<^sup>\<three>" [999] 999) where "u\<^sup>-\<^sup>\<three> \<equiv> (u\<^sup>\<three>)\<^sup>-\<^sup>\<one>"
|
abbreviation Unit_neq_cube ("(_)\<^sup>-\<^sup>\<three>" [999] 999) where "u\<^sup>-\<^sup>\<three> \<equiv> (u\<^sup>\<three>)\<^sup>-\<^sup>\<one>"
|
||||||
|
|
||||||
instantiation Unit :: (zero,siunit) zero
|
instantiation Unit :: (zero,si_type) zero
|
||||||
begin
|
begin
|
||||||
lift_definition zero_Unit :: "('a, 'b) Unit" is "\<lparr> factor = 0, unit = SI('b) \<rparr>"
|
lift_definition zero_Unit :: "('a, 'b) Unit" is "\<lparr> factor = 0, unit = SI('b) \<rparr>"
|
||||||
by simp
|
by simp
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation Unit :: (one,siunit) one
|
instantiation Unit :: (one,si_type) one
|
||||||
begin
|
begin
|
||||||
lift_definition one_Unit :: "('a, 'b) Unit" is "\<lparr> factor = 1, unit = SI('b) \<rparr>"
|
lift_definition one_Unit :: "('a, 'b) Unit" is "\<lparr> factor = 1, unit = SI('b) \<rparr>"
|
||||||
by simp
|
by simp
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation Unit :: (plus,siunit) plus
|
instantiation Unit :: (plus,si_type) plus
|
||||||
begin
|
begin
|
||||||
lift_definition plus_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
lift_definition plus_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
||||||
is "\<lambda> x y. \<lparr> factor = factor x + factor y, unit = SI('b) \<rparr>"
|
is "\<lambda> x y. \<lparr> factor = factor x + factor y, unit = SI('b) \<rparr>"
|
||||||
|
@ -358,26 +451,26 @@ lift_definition plus_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instance Unit :: (semigroup_add,siunit) semigroup_add
|
instance Unit :: (semigroup_add,si_type) semigroup_add
|
||||||
by (intro_classes, transfer, simp add: add.assoc)
|
by (intro_classes, transfer, simp add: add.assoc)
|
||||||
|
|
||||||
instance Unit :: (ab_semigroup_add,siunit) ab_semigroup_add
|
instance Unit :: (ab_semigroup_add,si_type) ab_semigroup_add
|
||||||
by (intro_classes, transfer, simp add: add.commute)
|
by (intro_classes, transfer, simp add: add.commute)
|
||||||
|
|
||||||
instance Unit :: (monoid_add,siunit) monoid_add
|
instance Unit :: (monoid_add,si_type) monoid_add
|
||||||
by (intro_classes; (transfer, simp))
|
by (intro_classes; (transfer, simp))
|
||||||
|
|
||||||
instance Unit :: (comm_monoid_add,siunit) comm_monoid_add
|
instance Unit :: (comm_monoid_add,si_type) comm_monoid_add
|
||||||
by (intro_classes; transfer, simp)
|
by (intro_classes; transfer, simp)
|
||||||
|
|
||||||
instantiation Unit :: (uminus,siunit) uminus
|
instantiation Unit :: (uminus,si_type) uminus
|
||||||
begin
|
begin
|
||||||
lift_definition uminus_Unit :: "'a['b] \<Rightarrow> 'a['b]"
|
lift_definition uminus_Unit :: "'a['b] \<Rightarrow> 'a['b]"
|
||||||
is "\<lambda> x. \<lparr> factor = - factor x, unit = unit x \<rparr>" by (simp)
|
is "\<lambda> x. \<lparr> factor = - factor x, unit = unit x \<rparr>" by (simp)
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation Unit :: (minus,siunit) minus
|
instantiation Unit :: (minus,si_type) minus
|
||||||
begin
|
begin
|
||||||
lift_definition minus_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
lift_definition minus_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
||||||
is "\<lambda> x y. \<lparr> factor = factor x - factor y, unit = unit x \<rparr>" by (simp)
|
is "\<lambda> x y. \<lparr> factor = factor x - factor y, unit = unit x \<rparr>" by (simp)
|
||||||
|
@ -385,9 +478,9 @@ lift_definition minus_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instance Unit :: (numeral,siunit) numeral ..
|
instance Unit :: (numeral,si_type) numeral ..
|
||||||
|
|
||||||
instantiation Unit :: (times,siunit) times
|
instantiation Unit :: (times,si_type) times
|
||||||
begin
|
begin
|
||||||
lift_definition times_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
lift_definition times_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
||||||
is "\<lambda> x y. \<lparr> factor = factor x * factor y, unit = SI('b) \<rparr>"
|
is "\<lambda> x y. \<lparr> factor = factor x * factor y, unit = SI('b) \<rparr>"
|
||||||
|
@ -395,66 +488,73 @@ lift_definition times_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instance Unit :: (power,siunit) power ..
|
instance Unit :: (power,si_type) power ..
|
||||||
|
|
||||||
instance Unit :: (semigroup_mult,siunit) semigroup_mult
|
instance Unit :: (semigroup_mult,si_type) semigroup_mult
|
||||||
by (intro_classes, transfer, simp add: mult.assoc)
|
by (intro_classes, transfer, simp add: mult.assoc)
|
||||||
|
|
||||||
instance Unit :: (ab_semigroup_mult,siunit) ab_semigroup_mult
|
instance Unit :: (ab_semigroup_mult,si_type) ab_semigroup_mult
|
||||||
by (intro_classes, (transfer, simp add: mult.commute))
|
by (intro_classes, (transfer, simp add: mult.commute))
|
||||||
|
|
||||||
instance Unit :: (comm_semiring,siunit) comm_semiring
|
instance Unit :: (comm_semiring,si_type) comm_semiring
|
||||||
by (intro_classes, transfer, simp add: linordered_field_class.sign_simps(18) mult.commute)
|
by (intro_classes, transfer, simp add: linordered_field_class.sign_simps(18) mult.commute)
|
||||||
|
|
||||||
instance Unit :: (comm_semiring_0,siunit) comm_semiring_0
|
instance Unit :: (comm_semiring_0,si_type) comm_semiring_0
|
||||||
by (intro_classes, (transfer, simp)+)
|
by (intro_classes, (transfer, simp)+)
|
||||||
|
|
||||||
instance Unit :: (comm_monoid_mult,siunit) comm_monoid_mult
|
instance Unit :: (comm_monoid_mult,si_type) comm_monoid_mult
|
||||||
by (intro_classes, (transfer, simp add: mult.commute)+)
|
by (intro_classes, (transfer, simp add: mult.commute)+)
|
||||||
|
|
||||||
instance Unit :: (comm_semiring_1,siunit) comm_semiring_1
|
instance Unit :: (comm_semiring_1,si_type) comm_semiring_1
|
||||||
by (intro_classes; (transfer, simp add: semiring_normalization_rules(1-8,24)))
|
by (intro_classes; (transfer, simp add: semiring_normalization_rules(1-8,24)))
|
||||||
|
|
||||||
instantiation Unit :: (divide,siunit) divide
|
instantiation Unit :: (divide,si_type) divide
|
||||||
begin
|
begin
|
||||||
lift_definition divide_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
lift_definition divide_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> 'a['b]"
|
||||||
is "\<lambda> x y. \<lparr> factor = factor x div factor y, unit = SI('b) \<rparr>" by simp
|
is "\<lambda> x y. \<lparr> factor = factor x div factor y, unit = SI('b) \<rparr>" by simp
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation Unit :: (inverse,siunit) inverse
|
instantiation Unit :: (inverse,si_type) inverse
|
||||||
begin
|
begin
|
||||||
lift_definition inverse_Unit :: "'a['b] \<Rightarrow> 'a['b]"
|
lift_definition inverse_Unit :: "'a['b] \<Rightarrow> 'a['b]"
|
||||||
is "\<lambda> x. \<lparr> factor = inverse (factor x), unit = SI('b) \<rparr>" by simp
|
is "\<lambda> x. \<lparr> factor = inverse (factor x), unit = SI('b) \<rparr>" by simp
|
||||||
instance ..
|
instance ..
|
||||||
end
|
end
|
||||||
|
|
||||||
instantiation Unit :: (order,siunit) order
|
instantiation Unit :: (order,si_type) order
|
||||||
begin
|
begin
|
||||||
lift_definition less_eq_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> bool" is "\<lambda> x y. factor x \<le> factor y" .
|
lift_definition less_eq_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> bool" is "\<lambda> x y. factor x \<le> factor y" .
|
||||||
lift_definition less_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> bool" is "\<lambda> x y. factor x < factor y" .
|
lift_definition less_Unit :: "'a['b] \<Rightarrow> 'a['b] \<Rightarrow> bool" is "\<lambda> x y. factor x < factor y" .
|
||||||
instance by (intro_classes, (transfer, simp add: less_le_not_le)+)
|
instance by (intro_classes, (transfer, simp add: less_le_not_le)+)
|
||||||
end
|
end
|
||||||
|
|
||||||
lift_definition mk_unit :: "'a \<Rightarrow> 'u itself \<Rightarrow> ('a::one)['u::siunit]"
|
lift_definition mk_unit :: "'a \<Rightarrow> 'u itself \<Rightarrow> ('a::one)['u::si_type]"
|
||||||
is "\<lambda> n u. \<lparr> factor = n, unit = SI('u) \<rparr>" by simp
|
is "\<lambda> n u. \<lparr> factor = n, unit = SI('u) \<rparr>" by simp
|
||||||
|
|
||||||
syntax "_mk_unit" :: "logic \<Rightarrow> type \<Rightarrow> logic" ("UNIT'(_, _')")
|
syntax "_mk_unit" :: "logic \<Rightarrow> type \<Rightarrow> logic" ("UNIT'(_, _')")
|
||||||
translations "UNIT(n, 'a)" == "CONST mk_unit n TYPE('a)"
|
translations "UNIT(n, 'a)" == "CONST mk_unit n TYPE('a)"
|
||||||
|
|
||||||
|
subsection \<open>Polymorphic Operations for Elementary SI Units \<close>
|
||||||
|
|
||||||
named_theorems si_def
|
named_theorems si_def
|
||||||
|
|
||||||
definition [si_def]: "meter = UNIT(1, meter)"
|
definition [si_def]: "meter = UNIT(1, meter)"
|
||||||
definition [si_def]: "second = UNIT(1, second)"
|
definition [si_def]: "second = UNIT(1, second)"
|
||||||
definition [si_def]: "kilogram = UNIT(1, kilogram)"
|
definition [si_def]: "kilogram = UNIT(1, kilogram)"
|
||||||
definition [si_def]: "ampere = UNIT(1, ampere)"
|
definition [si_def]: "ampere = UNIT(1, ampere)"
|
||||||
definition [si_def]: "kelvin = UNIT(1, kelvin)"
|
definition [si_def]: "kelvin = UNIT(1, kelvin)"
|
||||||
definition [si_def]: "mole = UNIT(1, mole)"
|
definition [si_def]: "mole = UNIT(1, mole)"
|
||||||
definition [si_def]: "candela = UNIT(1, candela)"
|
definition [si_def]: "candela = UNIT(1, candela)"
|
||||||
|
|
||||||
definition factorUnit :: "'a['u::siunit] \<Rightarrow> 'a" ("\<lbrakk>_\<rbrakk>\<^sub>U") where
|
subsubsection \<open>The Projection: Stripping the SI-Tags \<close>
|
||||||
|
|
||||||
|
definition factorUnit :: "'a['u::si_type] \<Rightarrow> 'a" ("\<lbrakk>_\<rbrakk>\<^sub>U") where
|
||||||
"factorUnit x = factor (fromUnit x)"
|
"factorUnit x = factor (fromUnit x)"
|
||||||
|
|
||||||
|
|
||||||
|
subsubsection \<open>More Operations \<close>
|
||||||
|
|
||||||
lemma unit_eq_iff_factor_eq:
|
lemma unit_eq_iff_factor_eq:
|
||||||
"x = y \<longleftrightarrow> \<lbrakk>x\<rbrakk>\<^sub>U = \<lbrakk>y\<rbrakk>\<^sub>U"
|
"x = y \<longleftrightarrow> \<lbrakk>x\<rbrakk>\<^sub>U = \<lbrakk>y\<rbrakk>\<^sub>U"
|
||||||
by (auto simp add: factorUnit_def, transfer, simp)
|
by (auto simp add: factorUnit_def, transfer, simp)
|
||||||
|
@ -484,15 +584,15 @@ lemma factorUnit_numeral [si_def]: "\<lbrakk>numeral n\<rbrakk>\<^sub>U = numera
|
||||||
apply (metis factorUnit_one factorUnit_plus numeral_code(3))
|
apply (metis factorUnit_one factorUnit_plus numeral_code(3))
|
||||||
done
|
done
|
||||||
|
|
||||||
lemma factorUnit_mk [si_def]: "\<lbrakk>UNIT(n, 'u::siunit)\<rbrakk>\<^sub>U = n"
|
lemma factorUnit_mk [si_def]: "\<lbrakk>UNIT(n, 'u::si_type)\<rbrakk>\<^sub>U = n"
|
||||||
by (simp add: factorUnit_def, transfer, simp)
|
by (simp add: factorUnit_def, transfer, simp)
|
||||||
|
|
||||||
method si_calc =
|
method si_calc =
|
||||||
(simp add: unit_eq_iff_factor_eq unit_le_iff_factor_le si_def)
|
(simp add: unit_eq_iff_factor_eq unit_le_iff_factor_le si_def)
|
||||||
|
|
||||||
subsubsection \<open> Derived Units \<close>
|
section \<open> Some Derived Units \<close>
|
||||||
|
|
||||||
definition "radian = 1 \<cdot> (meter *\<^sub>U meter\<^sup>-\<^sup>\<one>)"
|
definition "radian = 1 \<cdot> (meter *\<^sub>U meter\<^sup>-\<^sup>\<one>)"
|
||||||
|
|
||||||
definition degree :: "real[meter / meter]" where
|
definition degree :: "real[meter / meter]" where
|
||||||
[si_def]: "degree = (2\<cdot>(UNIT(pi,_)) / 180)\<cdot>radian"
|
[si_def]: "degree = (2\<cdot>(UNIT(pi,_)) / 180)\<cdot>radian"
|
||||||
|
@ -505,14 +605,122 @@ definition [si_def]: "pint = 0.56826125 \<cdot> litre"
|
||||||
|
|
||||||
definition [si_def]: "milli = UNIT(0.001, _)"
|
definition [si_def]: "milli = UNIT(0.001, _)"
|
||||||
|
|
||||||
definition [si_def]: "centi = UNIT(0.01, _)"
|
|
||||||
|
|
||||||
definition [si_def]: "kilo = UNIT(1000, _)"
|
definition [si_def]: "kilo = UNIT(1000, _)"
|
||||||
|
|
||||||
|
definition [si_def]: "hour = 3600 \<cdot> second"
|
||||||
|
|
||||||
abbreviation "tonne \<equiv> kilo\<cdot>kilogram"
|
abbreviation "tonne \<equiv> kilo\<cdot>kilogram"
|
||||||
|
|
||||||
abbreviation "newton \<equiv> (kilogram *\<^sub>U meter) /\<^sub>U second\<^sup>\<two>"
|
abbreviation "newton \<equiv> (kilogram *\<^sub>U meter) /\<^sub>U second\<^sup>\<two>"
|
||||||
|
|
||||||
abbreviation "volt \<equiv> kilogram *\<^sub>U meter\<^sup>\<two> *\<^sub>U second\<^sup>-\<^sup>\<three> *\<^sub>U ampere\<^sup>-\<^sup>\<one>"
|
abbreviation "volt \<equiv> kilogram *\<^sub>U meter\<^sup>\<two> *\<^sub>U second\<^sup>-\<^sup>\<three> *\<^sub>U ampere\<^sup>-\<^sup>\<one>"
|
||||||
|
|
||||||
|
abbreviation "watt \<equiv> kilogram *\<^sub>U meter\<^sup>\<two> *\<^sub>U second\<^sup>-\<^sup>\<three>"
|
||||||
|
|
||||||
|
abbreviation "joule \<equiv> kilogram *\<^sub>U meter\<^sup>\<two> *\<^sub>U second\<^sup>\<two>"
|
||||||
|
|
||||||
|
text\<open>The full beauty of the approach is perhaps revealed here, with the type of a classical
|
||||||
|
three-dimensional gravitation field:\<close>
|
||||||
|
type_synonym gravitation_field = "(real\<^sup>3 \<Rightarrow> real\<^sup>3)[meter \<cdot> (second)\<^sup>-\<^sup>2]"
|
||||||
|
|
||||||
|
section \<open> Tactic Support for SI type expressions. \<close>
|
||||||
|
|
||||||
|
lemmas [si_def] = Units.si_sem_meter_def Units.si_sem_kilogram_def Units.si_sem_second_def
|
||||||
|
Units.si_sem_ampere_def Units.si_sem_kelvin_def Units.si_sem_mole_def
|
||||||
|
Units.si_sem_candela_def
|
||||||
|
|
||||||
|
si_sem_UnitTimes_def si_sem_UnitInv_def
|
||||||
|
times_SI_domain_ext_def one_SI_domain_ext_def
|
||||||
|
|
||||||
|
(* renaming and putting defs into the rewrite set (which is usually not a good idea) *)
|
||||||
|
lemma "SI(meter) = 1\<lparr>Meters := 1\<rparr>" by(simp add: si_def)
|
||||||
|
lemma "SI(kilogram)= 1\<lparr>Kilograms := 1\<rparr>" by(simp add: si_def)
|
||||||
|
lemma "SI(second) = 1\<lparr>Seconds := 1\<rparr> " by(simp add: si_def)
|
||||||
|
lemma "SI(ampere) = 1\<lparr>Amperes := 1\<rparr>" by(simp add: si_def)
|
||||||
|
lemma "SI(kelvin) = 1\<lparr>Kelvins := 1\<rparr> " by(simp add: si_def)
|
||||||
|
lemma "SI(mole) = 1\<lparr>Moles := 1\<rparr>" by(simp add: si_def)
|
||||||
|
lemma "SI(candela) = 1\<lparr>Candelas := 1\<rparr>" by(simp add: si_def)
|
||||||
|
|
||||||
|
lemma "SI(mole \<cdot> kelvin \<cdot> mole) = SI(kelvin \<cdot> (mole)\<^sup>2)" by(simp add: si_def)
|
||||||
|
|
||||||
|
lemma [si_def]:"fromUnit UNIT(x::'a::one, second) =
|
||||||
|
\<lparr>factor = x,
|
||||||
|
unit = \<lparr>Seconds = 1, Meters = 0, Kilograms = 0, Amperes = 0,
|
||||||
|
Kelvins = 0, Moles = 0, Candelas = 0\<rparr>\<rparr>"
|
||||||
|
by (simp add: mk_unit.rep_eq one_SI_domain_ext_def si_sem_second_def)
|
||||||
|
|
||||||
|
lemma [si_def]:"fromUnit UNIT(x::'a::one, meter) =
|
||||||
|
\<lparr>factor = x,
|
||||||
|
unit = \<lparr>Seconds = 0, Meters = 1, Kilograms = 0, Amperes = 0,
|
||||||
|
Kelvins = 0, Moles = 0, Candelas = 0\<rparr>\<rparr>"
|
||||||
|
by (simp add: mk_unit.rep_eq one_SI_domain_ext_def si_sem_meter_def)
|
||||||
|
|
||||||
|
lemma [si_def]:"fromUnit UNIT(x::'a::one, kilogram) =
|
||||||
|
\<lparr>factor = x,
|
||||||
|
unit = \<lparr>Seconds = 0, Meters = 0, Kilograms = 1, Amperes = 0,
|
||||||
|
Kelvins = 0, Moles = 0, Candelas = 0\<rparr>\<rparr>"
|
||||||
|
by (simp add: mk_unit.rep_eq one_SI_domain_ext_def si_sem_kilogram_def)
|
||||||
|
|
||||||
|
lemma [si_def]:"fromUnit UNIT(x::'a::one, ampere) =
|
||||||
|
\<lparr>factor = x,
|
||||||
|
unit = \<lparr>Seconds = 0, Meters = 0, Kilograms = 0, Amperes = 1,
|
||||||
|
Kelvins = 0, Moles = 0, Candelas = 0\<rparr>\<rparr>"
|
||||||
|
by (simp add: mk_unit.rep_eq one_SI_domain_ext_def si_sem_ampere_def)
|
||||||
|
|
||||||
|
lemma [si_def]:"fromUnit UNIT(x::'a::one, kelvin) =
|
||||||
|
\<lparr>factor = x,
|
||||||
|
unit = \<lparr>Seconds = 0, Meters = 0, Kilograms = 0, Amperes = 0,
|
||||||
|
Kelvins = 1, Moles = 0, Candelas = 0\<rparr>\<rparr>"
|
||||||
|
by (simp add: mk_unit.rep_eq one_SI_domain_ext_def si_sem_kelvin_def)
|
||||||
|
|
||||||
|
lemma [si_def]:"fromUnit UNIT(x::'a::one, mole) =
|
||||||
|
\<lparr>factor = x,
|
||||||
|
unit = \<lparr>Seconds = 0, Meters = 0, Kilograms = 0, Amperes = 0,
|
||||||
|
Kelvins = 0, Moles = 1, Candelas = 0\<rparr>\<rparr>"
|
||||||
|
by (simp add: mk_unit.rep_eq one_SI_domain_ext_def si_sem_mole_def)
|
||||||
|
|
||||||
|
lemma [si_def]:"fromUnit UNIT(x::'a::one, candela) =
|
||||||
|
\<lparr>factor = x,
|
||||||
|
unit = \<lparr>Seconds = 0, Meters = 0, Kilograms = 0, Amperes = 0,
|
||||||
|
Kelvins = 0, Moles = 0, Candelas = 1\<rparr>\<rparr>"
|
||||||
|
by (simp add: mk_unit.rep_eq one_SI_domain_ext_def si_sem_candela_def)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lemma Unit_times_commute:
|
||||||
|
"((X::'a::{one,ab_semigroup_mult}['b::si_type]) *\<^sub>U (Y::'a['c::si_type])) \<approx>\<^sub>U (Y *\<^sub>U X)"
|
||||||
|
unfolding Unit_equiv_def
|
||||||
|
by (simp add: Unit_times.rep_eq linordered_field_class.sign_simps(5) times_SI_tagged_domain_ext_def)
|
||||||
|
|
||||||
|
|
||||||
|
(* just a check that instantiation works for special cases ... *)
|
||||||
|
lemma " (UNIT(x, candela) *\<^sub>U UNIT(y::'a::{one,ab_semigroup_mult}, mole))
|
||||||
|
\<approx>\<^sub>U (UNIT(y, mole) *\<^sub>U UNIT(x, candela)) "
|
||||||
|
by(simp add: Unit_times_commute)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lemma "watt *\<^sub>U hour \<approx>\<^sub>U 3600 *\<^sub>U joule"
|
||||||
|
unfolding Unit_equiv_def
|
||||||
|
apply(simp add: Units.Unit_times.rep_eq si_def
|
||||||
|
zero_SI_tagged_domain_ext_def times_SI_tagged_domain_ext_def
|
||||||
|
inverse_SI_tagged_domain_ext_def
|
||||||
|
Unit_inverse_def Unit_times_def)
|
||||||
|
find_theorems fromUnit
|
||||||
|
oops
|
||||||
|
|
||||||
|
thm Units.Unit.toUnit_inverse
|
||||||
|
|
||||||
|
lemma "factor(fromUnit(toUnit\<lparr>factor = X:: 'a :: {inverse,times,numeral},
|
||||||
|
unit = SI('b::si_type) \<rparr>)) = X"
|
||||||
|
apply(subst Units.Unit.toUnit_inverse,auto)
|
||||||
|
oops
|
||||||
|
|
||||||
|
lemma "watt *\<^sub>U hour \<approx>\<^sub>U 3.6 *\<^sub>U kilo *\<^sub>U joule"
|
||||||
|
oops
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Reference in New Issue