Theory Transition_QuasiTerms_Terms
section ‹Transition from Quasi-Terms to Terms›
theory Transition_QuasiTerms_Terms
imports QuasiTerms_Environments_Substitution Equiv_Relation2
begin
text‹This section transits from quasi-terms to terms: defines terms as alpha-equivalence
classes of quasi-terms
(and also abstractions as alpha-equivalence classes of quasi-abstractions),
then defines operators on terms corresponding to those on quasi-terms:
variable injection, binding operation, freshness, swapping, parallel substitution, etc.
Properties previously shown invariant
under alpha-equivalence, including induction principles, are lifted from quasi-terms.
Moreover, a new powerful induction principle, allowing freshness assumptions,
is proved for terms.
As a matter of notation:
Starting from this section, we change the notations for quasi-item meta-variables, prefixing
their names with a "q" -- e.g., qX, qA, qinp, qenv, etc. The old names are now assigned
to the ``real" items: terms, abstractions, inputs, environments.›
subsection ‹Preparation: Integrating quasi-inputs as first-class citizens›
context FixVars
begin
text‹From now on it will be convenient to
also define fresh, swap, good and alpha-equivalence for quasi-inpus.›
definition qSwapInp where
"qSwapInp xs x y qinp == lift (qSwap xs x y) qinp"
definition qSwapBinp where
"qSwapBinp xs x y qbinp == lift (qSwapAbs xs x y) qbinp"
abbreviation qSwapInp_abbrev (‹_ %[[_ ∧ _]]'__› 200) where
"(qinp %[[z1 ∧ z2]]_zs) == qSwapInp zs z1 z2 qinp"
abbreviation qSwapBinp_abbrev (‹_ %%[[_ ∧ _]]'__› 200) where
"(qbinp %%[[z1 ∧ z2]]_zs) == qSwapBinp zs z1 z2 qbinp"
lemma qSwap_qSwapInp:
"((qOp delta qinp qbinp) #[[x ∧ y]]_xs) =
qOp delta (qinp %[[x ∧ y]]_xs) (qbinp %%[[x ∧ y]]_xs)"
unfolding qSwapInp_def qSwapBinp_def by simp
declare qSwap.simps(2) [simp del]
declare qSwap_qSwapInp[simp]
lemmas qSwapAll_simps = qSwap.simps(1) qSwap_qSwapInp
definition qPsubstInp where
"qPsubstInp qrho qinp == lift (qPsubst qrho) qinp"
definition qPsubstBinp where
"qPsubstBinp qrho qbinp == lift (qPsubstAbs qrho) qbinp"
abbreviation qPsubstInp_abbrev (‹_ %[[_]]› 200)
where "(qinp %[[qrho]]) == qPsubstInp qrho qinp"
abbreviation qPsubstBinp_abbrev (‹_ %%[[_]]› 200)
where "(qbinp %%[[qrho]]) == qPsubstBinp qrho qbinp"
lemma qPsubst_qPsubstInp:
"((qOp delta qinp qbinp) #[[rho]]) = qOp delta (qinp %[[rho]]) (qbinp %%[[rho]])"
unfolding qPsubstInp_def qPsubstBinp_def by simp
declare qPsubst.simps(2) [simp del]
declare qPsubst_qPsubstInp[simp]
lemmas qPsubstAll_simps = qPsubst.simps(1) qPsubst_qPsubstInp
definition qSkelInp
where "qSkelInp qinp = lift qSkel qinp"
definition qSkelBinp
where "qSkelBinp qbinp = lift qSkelAbs qbinp"
lemma qSkel_qSkelInp:
"qSkel (qOp delta qinp qbinp) =
Branch (qSkelInp qinp) (qSkelBinp qbinp)"
unfolding qSkelInp_def qSkelBinp_def by simp
declare qSkel.simps(2) [simp del]
declare qSkel_qSkelInp[simp]
lemmas qSkelAll_simps = qSkel.simps(1) qSkel_qSkelInp
definition qFreshInp ::
"'varSort ⇒ 'var ⇒ ('index,('index,'bindex,'varSort,'var,'opSym)qTerm)input ⇒ bool"
where
"qFreshInp xs x qinp == liftAll (qFresh xs x) qinp"
definition qFreshBinp ::
"'varSort ⇒ 'var ⇒ ('bindex,('index,'bindex,'varSort,'var,'opSym)qAbs)input ⇒ bool"
where
"qFreshBinp xs x qbinp == liftAll (qFreshAbs xs x) qbinp"
lemma qFresh_qFreshInp:
"qFresh xs x (qOp delta qinp qbinp) =
(qFreshInp xs x qinp ∧ qFreshBinp xs x qbinp)"
unfolding qFreshInp_def qFreshBinp_def by simp
declare qFresh.simps(2) [simp del]
declare qFresh_qFreshInp[simp]
lemmas qFreshAll_simps = qFresh.simps(1) qFresh_qFreshInp
definition qGoodInp where
"qGoodInp qinp ==
liftAll qGood qinp ∧
|{i. qinp i ≠ None}| <o |UNIV :: 'var set|"
definition qGoodBinp where
"qGoodBinp qbinp ==
liftAll qGoodAbs qbinp ∧
|{i. qbinp i ≠ None}| <o |UNIV :: 'var set|"
lemma qGood_qGoodInp:
"qGood (qOp delta qinp qbinp) = (qGoodInp qinp ∧ qGoodBinp qbinp)"
unfolding qGoodInp_def qGoodBinp_def by auto
declare qGood.simps(2) [simp del]
declare qGood_qGoodInp [simp]
lemmas qGoodAll_simps = qGood.simps(1) qGood_qGoodInp
definition alphaInp where
"alphaInp ==
{(qinp,qinp'). sameDom qinp qinp' ∧ liftAll2 (λqX qX'. qX #= qX') qinp qinp'}"
definition alphaBinp where
"alphaBinp ==
{(qbinp,qbinp'). sameDom qbinp qbinp' ∧ liftAll2 (λqA qA'. qA $= qA') qbinp qbinp'}"
abbreviation alphaInp_abbrev (infix ‹%=› 50) where
"qinp %= qinp' == (qinp,qinp') ∈ alphaInp"
abbreviation alphaBinp_abbrev (infix ‹%%=› 50) where
"qbinp %%= qbinp' == (qbinp,qbinp') ∈ alphaBinp"
lemma alpha_alphaInp:
"(qOp delta qinp qbinp #= qOp delta' qinp' qbinp') =
(delta = delta' ∧ qinp %= qinp' ∧ qbinp %%= qbinp')"
unfolding alphaInp_def alphaBinp_def by auto
declare alpha.simps(2) [simp del]
declare alpha_alphaInp[simp]
lemmas alphaAll_Simps =
alpha.simps(1) alpha_alphaInp
alphaAbs.simps
lemma alphaInp_refl:
"qGoodInp qinp ⟹ qinp %= qinp"
using alpha_refl
unfolding alphaInp_def qGoodInp_def liftAll_def liftAll2_def sameDom_def
by fastforce
lemma alphaBinp_refl:
"qGoodBinp qbinp ⟹ qbinp %%= qbinp"
using alphaAbs_refl
unfolding alphaBinp_def qGoodBinp_def liftAll_def liftAll2_def sameDom_def
by fastforce
lemma alphaInp_sym:
fixes qinp qinp' :: "('index,('index,'bindex,'varSort,'var,'opSym)qTerm)input"
shows "qinp %= qinp' ⟹ qinp' %= qinp"
using alpha_sym unfolding alphaInp_def sameDom_def liftAll2_def by blast
lemma alphaBinp_sym:
fixes qbinp qbinp' :: "('bindex,('index,'bindex,'varSort,'var,'opSym)qAbs)input"
shows "qbinp %%= qbinp' ⟹ qbinp' %%= qbinp"
using alphaAbs_sym unfolding alphaBinp_def sameDom_def liftAll2_def by blast
lemma alphaInp_trans:
assumes good: "qGoodInp qinp" and
alpha1: "qinp %= qinp'" and alpha2: "qinp' %= qinp''"
shows "qinp %= qinp''"
proof-
{fix i qX qX'' assume qinp: "qinp i = Some qX" and qinp'': "qinp'' i = Some qX''"
then obtain qX' where qinp': "qinp' i = Some qX'"
using alpha1 unfolding alphaInp_def sameDom_def liftAll2_def by(cases "qinp' i", force)
hence "qX #= qX'"
using alpha1 qinp unfolding alphaInp_def sameDom_def liftAll2_def by auto
moreover have "qX' #= qX''" using alpha2 qinp' qinp''
unfolding alphaInp_def sameDom_def liftAll2_def by auto
moreover have "qGood qX" using good qinp unfolding qGoodInp_def liftAll_def by auto
ultimately have "qX #= qX''" using alpha_trans by blast
}
thus ?thesis using assms unfolding alphaInp_def sameDom_def liftAll2_def by auto
qed
lemma alphaBinp_trans:
assumes good: "qGoodBinp qbinp" and
alpha1: "qbinp %%= qbinp'" and alpha2: "qbinp' %%= qbinp''"
shows "qbinp %%= qbinp''"
proof-
{fix i qA qA'' assume qbinp: "qbinp i = Some qA" and qbinp'': "qbinp'' i = Some qA''"
then obtain qA' where qbinp': "qbinp' i = Some qA'"
using alpha1 unfolding alphaBinp_def sameDom_def liftAll2_def by(cases "qbinp' i", force)
hence "qA $= qA'"
using alpha1 qbinp unfolding alphaBinp_def sameDom_def liftAll2_def by auto
moreover have "qA' $= qA''" using alpha2 qbinp' qbinp''
unfolding alphaBinp_def sameDom_def liftAll2_def by auto
moreover have "qGoodAbs qA" using good qbinp unfolding qGoodBinp_def liftAll_def by auto
ultimately have "qA $= qA''" using alphaAbs_trans by blast
}
thus ?thesis using assms unfolding alphaBinp_def sameDom_def liftAll2_def by auto
qed
lemma qSwapInp_preserves_qGoodInp:
assumes "qGoodInp qinp"
shows "qGoodInp (qinp %[[x1 ∧ x2]]_xs)"
proof-
{let ?qinp' = "lift (qSwap xs x1 x2) qinp"
fix xsa let ?Left = "{i. ?qinp' i ≠ None}"
have "?Left = {i. qinp i ≠ None}" by(auto simp add: lift_None)
hence "|?Left| <o |UNIV :: 'var set|" using assms unfolding qGoodInp_def by auto
}
thus ?thesis using assms
unfolding qGoodInp_def qSwapInp_def liftAll_lift_comp qGoodInp_def
unfolding comp_def liftAll_def
by (auto simp add: qSwap_preserves_qGood simp del: not_None_eq)
qed
lemma qSwapBinp_preserves_qGoodBinp:
assumes "qGoodBinp qbinp"
shows "qGoodBinp (qbinp %%[[x1 ∧ x2]]_xs)"
proof-
{let ?qbinp' = "lift (qSwapAbs xs x1 x2) qbinp"
fix xsa let ?Left = "{i. ?qbinp' i ≠ None}"
have "?Left = {i. qbinp i ≠ None}" by(auto simp add: lift_None)
hence "|?Left| <o |UNIV :: 'var set|" using assms unfolding qGoodBinp_def by auto
}
thus ?thesis using assms
unfolding qGoodBinp_def qSwapBinp_def liftAll_lift_comp
unfolding qGoodBinp_def unfolding comp_def liftAll_def
by (auto simp add: qSwapAbs_preserves_qGoodAbs simp del: not_None_eq)
qed
lemma qSwapInp_preserves_alphaInp:
assumes "qGoodInp qinp ∨ qGoodInp qinp'" and "qinp %= qinp'"
shows "(qinp %[[x1 ∧ x2]]_xs) %= (qinp' %[[x1 ∧ x2]]_xs)"
using assms unfolding alphaInp_def qSwapInp_def sameDom_def liftAll2_def
by (simp add: lift_None)
(smt (verit) liftAll_def lift_def option.case_eq_if option.exhaust_sel
option.sel qGoodInp_def qSwap_preserves_alpha)
lemma qSwapBinp_preserves_alphaBinp:
assumes "qGoodBinp qbinp ∨ qGoodBinp qbinp'" and "qbinp %%= qbinp'"
shows "(qbinp %%[[x1 ∧ x2]]_xs) %%= (qbinp' %%[[x1 ∧ x2]]_xs)"
using assms unfolding alphaBinp_def qSwapBinp_def sameDom_def liftAll2_def
by (simp add: lift_None)
(smt (verit) liftAll_def lift_def option.case_eq_if option.exhaust_sel option.sel
qGoodBinp_def qSwapAbs_preserves_alphaAbs)
lemma qPsubstInp_preserves_qGoodInp:
assumes "qGoodInp qinp" and "qGoodEnv qrho"
shows "qGoodInp (qinp %[[qrho]])"
using assms unfolding qGoodInp_def qPsubstInp_def liftAll_def
by simp (smt (verit) Collect_cong lift_def option.case_eq_if
option.exhaust_sel option.sel qPsubst_preserves_qGood)
lemma qPsubstBinp_preserves_qGoodBinp:
assumes "qGoodBinp qbinp" and "qGoodEnv qrho"
shows "qGoodBinp (qbinp %%[[qrho]])"
using assms unfolding qGoodBinp_def qPsubstBinp_def liftAll_def
by simp (smt (verit) Collect_cong lift_def option.case_eq_if
option.exhaust_sel option.sel qPsubstAbs_preserves_qGoodAbs)
lemma qPsubstInp_preserves_alphaInp:
assumes "qGoodInp qinp ∨ qGoodInp qinp'" and "qGoodEnv qrho" and "qinp %= qinp'"
shows "(qinp %[[qrho]]) %= (qinp' %[[qrho]])"
using assms unfolding alphaInp_def qPsubstInp_def sameDom_def liftAll2_def
by (simp add: lift_None)
(smt (verit) liftAll_def lift_def option.case_eq_if option.exhaust_sel
option.sel qGoodInp_def qPsubst_preserves_alpha1)
lemma qPsubstBinp_preserves_alphaBinp:
assumes "qGoodBinp qbinp ∨ qGoodBinp qbinp'" and "qGoodEnv qrho" and "qbinp %%= qbinp'"
shows "(qbinp %%[[qrho]]) %%= (qbinp' %%[[qrho]])"
using assms unfolding alphaBinp_def qPsubstBinp_def sameDom_def liftAll2_def
by (simp add: lift_None)
(smt (verit) liftAll_def lift_def option.case_eq_if option.exhaust_sel
option.sel qGoodBinp_def qPsubstAbs_preserves_alphaAbs1)
lemma qFreshInp_preserves_alphaInp_aux:
assumes good: "qGoodInp qinp ∨ qGoodInp qinp'" and alpha: "qinp %= qinp'"
and fresh: "qFreshInp xs x qinp"
shows "qFreshInp xs x qinp'"
using assms unfolding qFreshInp_def liftAll_def proof clarify
fix i qX' assume qinp': "qinp' i = Some qX'"
then obtain qX where qinp: "qinp i = Some qX"
using alpha unfolding alphaInp_def sameDom_def liftAll2_def by (cases "qinp i", auto)
hence "qGood qX ∨ qGood qX'"
using qinp' good unfolding qGoodInp_def liftAll_def by auto
moreover have "qX #= qX'"
using qinp qinp' alpha unfolding alphaInp_def sameDom_def liftAll2_def by auto
moreover have "qFresh xs x qX"
using fresh qinp unfolding qFreshInp_def liftAll_def by simp
ultimately show "qFresh xs x qX'"
using qFresh_preserves_alpha by auto
qed
lemma qFreshBinp_preserves_alphaBinp_aux:
assumes good: "qGoodBinp qbinp ∨ qGoodBinp qbinp'" and alpha: "qbinp %%= qbinp'"
and fresh: "qFreshBinp xs x qbinp"
shows "qFreshBinp xs x qbinp'"
using assms unfolding qFreshBinp_def liftAll_def proof clarify
fix i qA' assume qbinp': "qbinp' i = Some qA'"
then obtain qA where qbinp: "qbinp i = Some qA"
using alpha unfolding alphaBinp_def sameDom_def liftAll2_def by (cases "qbinp i", auto)
hence "qGoodAbs qA ∨ qGoodAbs qA'"
using qbinp' good unfolding qGoodBinp_def liftAll_def by auto
moreover have "qA $= qA'"
using qbinp qbinp' alpha unfolding alphaBinp_def sameDom_def liftAll2_def by auto
moreover have "qFreshAbs xs x qA"
using fresh qbinp unfolding qFreshBinp_def liftAll_def by simp
ultimately show "qFreshAbs xs x qA'"
using qFreshAbs_preserves_alphaAbs by auto
qed
lemma qFreshInp_preserves_alphaInp:
assumes "qGoodInp qinp ∨ qGoodInp qinp'" and "qinp %= qinp'"
shows "qFreshInp xs x qinp ⟷ qFreshInp xs x qinp'"
using alphaInp_sym assms qFreshInp_preserves_alphaInp_aux by blast
lemma qFreshBinp_preserves_alphaBinp:
assumes "qGoodBinp qbinp ∨ qGoodBinp qbinp'" and "qbinp %%= qbinp'"
shows "qFreshBinp xs x qbinp ⟷ qFreshBinp xs x qbinp'"
using alphaBinp_sym assms qFreshBinp_preserves_alphaBinp_aux by blast
lemmas qItem_simps =
qSkelAll_simps qFreshAll_simps qSwapAll_simps qPsubstAll_simps qGoodAll_simps alphaAll_Simps
qSwap_qAFresh_otherSimps qAFresh.simps qGoodItem.simps
end
subsection ‹Definitions of terms and their operators›
type_synonym ('index,'bindex,'varSort,'var,'opSym)"term" =
"('index,'bindex,'varSort,'var,'opSym)qTerm set"
type_synonym ('index,'bindex,'varSort,'var,'opSym)abs =
"('index,'bindex,'varSort,'var,'opSym)qAbs set"
type_synonym ('index,'bindex,'varSort,'var,'opSym)env =
"'varSort ⇒ 'var ⇒ ('index,'bindex,'varSort,'var,'opSym)term option"
text‹A ``parameter" will be something for which
freshness makes sense. Here is the most typical case of a parameter in proofs, putting
together (as lists) finite collections of variables, terms, abstractions and environments:›