RIS.transducer: definition and properties of the binding transducer.
Set Implicit Arguments.
Require Export stacks words.
Section s.
Context {atom : Set}{π : Atom atom}.
Context {X : Set} {π : Alphabet π X}.
Require Export stacks words.
Section s.
Context {atom : Set}{π : Atom atom}.
Context {X : Set} {π : Alphabet π X}.
Transducer
Definition
The predicate s β£ l1 | l2 β¦ s' encodes the transition function of the transducer. It holds when there exists a transition in the transducer from state s to state s' labelled with letters l1|l2.
Definition step (s : stack) (l1 l2 : letter) (s' : stack) :=
match (l1,l2) with
| (β¨a,β¨b) β s' = (a,b)::s
| (aβ©,bβ©) β (s β¨ a β¦ b) β§ s' = s β (a,b)
| (var x,var y) β s' = s β§ β p, y = pβx β§ β a, a β βxβ β s β¨ a β¦ pβa
| _ β False
end.
Notation " s β£ l1 | l2 β¦ s' " := (step s l1 l2 s') (at level 80).
match (l1,l2) with
| (β¨a,β¨b) β s' = (a,b)::s
| (aβ©,bβ©) β (s β¨ a β¦ b) β§ s' = s β (a,b)
| (var x,var y) β s' = s β§ β p, y = pβx β§ β a, a β βxβ β s β¨ a β¦ pβa
| _ β False
end.
Notation " s β£ l1 | l2 β¦ s' " := (step s l1 l2 s') (at level 80).
The predicate s β£ u | v β€
s' encodes paths in the transducer. It holds when there exists a path in the transducer from state s to state s' labelled with the words u|v.
Reserved Notation " s β£ u | v β€
s' " (at level 80).
Inductive path : word β word β stack β stack β Prop :=
| pathΟ΅ s : s β£ [] | [] β€ s
| pathl s2 u v l1 l2 s1 s3 :
s1 β£ l1 | l2 β¦ s2 β s2 β£ u | v β€ s3 β s1 β£ l1::u | l2::v β€ s3
where " s β£ u | v β€ s' " := (path u v s s').
Hint Constructors path.
Inductive path : word β word β stack β stack β Prop :=
| pathΟ΅ s : s β£ [] | [] β€ s
| pathl s2 u v l1 l2 s1 s3 :
s1 β£ l1 | l2 β¦ s2 β s2 β£ u | v β€ s3 β s1 β£ l1::u | l2::v β€ s3
where " s β£ u | v β€ s' " := (path u v s s').
Hint Constructors path.
The function Ξ΄t: computing a path in the transducer
Fixpoint compatible s u v :=
match (u,v) with
| ([],[]) β true
| ([],_) | (_,[]) β false
| (β¨a::u,β¨b::v)β compatible ((a,b)::s) u v
| (aβ©::u,bβ©::v)β
if (pairedb s a b)
then compatible (sβ(a,b)) u v
else false
| (var x::u,var y::v)β
match var_perm' βxβ s with
| None β false
| Some p β (pβx =?= y)&&(compatible s u v)
end
| (_::_,_::_) β false
end.
match (u,v) with
| ([],[]) β true
| ([],_) | (_,[]) β false
| (β¨a::u,β¨b::v)β compatible ((a,b)::s) u v
| (aβ©::u,bβ©::v)β
if (pairedb s a b)
then compatible (sβ(a,b)) u v
else false
| (var x::u,var y::v)β
match var_perm' βxβ s with
| None β false
| Some p β (pβx =?= y)&&(compatible s u v)
end
| (_::_,_::_) β false
end.
If sβ£u|vβ€
s', then Ξ΄t s u v returns s'. Otherwise, Ξ΄t s u v returns []. This implies that there is at most one path from s labelled with u|v.
Fixpoint Ξ΄t s u v :=
match (u,v) with
| ([],[]) β s
| ([],_) | (_,[]) β []
| (β¨a::u,β¨b::v)β Ξ΄t ((a,b)::s) u v
| (aβ©::u,bβ©::v)β
if (pairedb s a b)
then Ξ΄t (sβ(a,b)) u v
else []
| (var x::u,var y::v)β
match var_perm' βxβ s with
| None β []
| Some p β
if (pβx =?= y)
then Ξ΄t s u v
else []
end
| (_::_,_::_) β []
end.
Ltac case_var s x y :=
let p := fresh "p" in
let e := fresh "e" in
case_eq (var_perm' βxβ s);
[intros p e;destruct_eqX (pβx) y|intros e].
match (u,v) with
| ([],[]) β s
| ([],_) | (_,[]) β []
| (β¨a::u,β¨b::v)β Ξ΄t ((a,b)::s) u v
| (aβ©::u,bβ©::v)β
if (pairedb s a b)
then Ξ΄t (sβ(a,b)) u v
else []
| (var x::u,var y::v)β
match var_perm' βxβ s with
| None β []
| Some p β
if (pβx =?= y)
then Ξ΄t s u v
else []
end
| (_::_,_::_) β []
end.
Ltac case_var s x y :=
let p := fresh "p" in
let e := fresh "e" in
case_eq (var_perm' βxβ s);
[intros p e;destruct_eqX (pβx) y|intros e].
There is a path from s1 to s2 labelled with u|v if and only if u,v is compatible with s1 and s2 is Ξ΄t s1 u v.
Theorem Ξ΄t_compatible_spec s1 u v s2 :
Ξ΄t s1 u v = s2 β§ compatible s1 u v = true β s1 β£ u|v β€ s2.
Corollary Ξ΄t_path s u v : compatible s u v = true β s β£ u|v β€ Ξ΄t s u v.
Ξ΄t s1 u v = s2 β§ compatible s1 u v = true β s1 β£ u|v β€ s2.
Corollary Ξ΄t_path s u v : compatible s u v = true β s β£ u|v β€ Ξ΄t s u v.
When u,v is not compatible with s, we set Ξ΄t s u v to be the empty list. This choice of a default value is arbitrary.
The transition predicate commutes with permutation actions.
Fact nom_step p s1 s2 l1 l2 :
s1 β£ l1 | l2 β¦ s2 β p β s1 β£ pβl1 | pβl2 β¦ pβs2.
Corollary nom_path p s1 s2 u v :
s1 β£ u | v β€ s2 β p β s1 β£ pβu | pβv β€ pβs2.
Corollary nom_compatible p s u v :
compatible s u v = compatible (pβs) (pβu) (pβv).
Corollary nom_Ξ΄t p s u v :
pβ(Ξ΄t s u v) = Ξ΄t (pβs) (pβu) (pβv).
s1 β£ l1 | l2 β¦ s2 β p β s1 β£ pβl1 | pβl2 β¦ pβs2.
Corollary nom_path p s1 s2 u v :
s1 β£ u | v β€ s2 β p β s1 β£ pβu | pβv β€ pβs2.
Corollary nom_compatible p s u v :
compatible s u v = compatible (pβs) (pβu) (pβv).
Corollary nom_Ξ΄t p s u v :
pβ(Ξ΄t s u v) = Ξ΄t (pβs) (pβu) (pβv).
If s is accepting, then for any word u there is an accepting stack s' such that s β£ u | u β€
s'.
Lemma path_id_Accepting u : β s, s β β (Ξ΄t s u u) β.
Lemma path_id_compatible u : β s, s β β compatible s u u = true.
Corollary path_id s u : s β β β s', s'β β§ s β£ u | u β€ s'.
Lemma path_id_compatible u : β s, s β β compatible s u u = true.
Corollary path_id s u : s β β β s', s'β β§ s β£ u | u β€ s'.
If there is a path from labelled with u|v, then u and v have the same length.
If u1 and v1 have the same length, then u1++u2,v1++v2 is compatible with s if and only if u1,v1 is compatible with s and u2,v2 is compatible with Ξ΄t s u1 v1.
Proposition compatible_app u1 u2 v1 v2 s :
β’u1β₯ = β’v1β₯ β
compatible s (u1++u2) (v1++v2) = (compatible s u1 v1)
&& compatible (Ξ΄t s u1 v1) u2 v2.
β’u1β₯ = β’v1β₯ β
compatible s (u1++u2) (v1++v2) = (compatible s u1 v1)
&& compatible (Ξ΄t s u1 v1) u2 v2.
If u1,v1 is compatible with s then Ξ΄t s (u1++u2) (v1++v2) may be computed as Ξ΄t (Ξ΄t s u1 v1) u2 v2.
Proposition Ξ΄t_app u1 u2 v1 v2 s :
compatible s u1 v1 = true β Ξ΄t s (u1++u2) (v1++v2) = Ξ΄t (Ξ΄t s u1 v1) u2 v2.
compatible s u1 v1 = true β Ξ΄t s (u1++u2) (v1++v2) = Ξ΄t (Ξ΄t s u1 v1) u2 v2.
If there is a path labelled with u1++u2|v1++v2, and if u1 and v1 have the same length, then it can be factored as a path labelled with u1|v1 followed by one with label u2|v2.
Corollary path_decompose_app u1 u2 v1 v2 s1 s2 :
(s1 β£ u1++u2 | v1++v2 β€ s2) β β’u1β₯ = β’v1β₯ β
β s3, s1 β£ u1 | v1 β€ s3 β§ s3 β£ u2 | v2 β€ s2.
Corollary path_letter u l v s1 s2 :
(s1 β£ u++[l] | v β€ s2) β
β v' l' s3, v = v' ++ [l'] β§ s1 β£ u | v' β€ s3 β§ s3 β£ l | l' β¦ s2.
(s1 β£ u1++u2 | v1++v2 β€ s2) β β’u1β₯ = β’v1β₯ β
β s3, s1 β£ u1 | v1 β€ s3 β§ s3 β£ u2 | v2 β€ s2.
Corollary path_letter u l v s1 s2 :
(s1 β£ u++[l] | v β€ s2) β
β v' l' s3, v = v' ++ [l'] β§ s1 β£ u | v' β€ s3 β§ s3 β£ l | l' β¦ s2.
If we know s2 to be accepting, we may simplify image (s1++s2) a, var_perm x (s1++s2), pairedb (s1++s2) a b, compatible (s1++s2) u v. Also, Ξ΄t (s1++s2) u v is accepting if and only if Ξ΄t s1 u v is.
Proposition image_app_Accepting s1 s2 :
s2 β β β a, image (s1++s2) a = image s1 a.
Corollary var_perm_app_Accepting s1 s2 x :
s2 β β var_perm x (s1++s2) = var_perm x s1 .
Lemma pairedb_app_Accepting s1 s2 :
s2 β β β a b, pairedb (s1++s2) a b = pairedb s1 a b.
Proposition compatible_app_Accepting s1 s2 u v :
s2 β β compatible (s1++s2) u v = compatible s1 u v.
Proposition Ξ΄t_app_Accepting s1 s2 u v :
s2 β β Ξ΄t (s1++s2) u v β β Ξ΄t s1 u v β.
Corollary path_app_Accepting s1 s2 u v s3 :
s2 β β s1 β£ u | v β€ s3 β β s4, s1++s2 β£ u | v β€ s4 β§ (s3 β β s4 β).
s2 β β β a, image (s1++s2) a = image s1 a.
Corollary var_perm_app_Accepting s1 s2 x :
s2 β β var_perm x (s1++s2) = var_perm x s1 .
Lemma pairedb_app_Accepting s1 s2 :
s2 β β β a b, pairedb (s1++s2) a b = pairedb s1 a b.
Proposition compatible_app_Accepting s1 s2 u v :
s2 β β compatible (s1++s2) u v = compatible s1 u v.
Proposition Ξ΄t_app_Accepting s1 s2 u v :
s2 β β Ξ΄t (s1++s2) u v β β Ξ΄t s1 u v β.
Corollary path_app_Accepting s1 s2 u v s3 :
s2 β β s1 β£ u | v β€ s3 β β s4, s1++s2 β£ u | v β€ s4 β§ (s3 β β s4 β).
We can flip a path with label u|v into a path with label v|u.
Lemma step_sym a b s1 s2 : s1 β£ a | b β¦ s2 β s1` β£ b | a β¦ s2`.
Corollary path_sym s u v s' : s β£ u | v β€ s' β (s`) β£ v | u β€ (s'`).
Corollary compatible_flip s u v : compatible (s`) u v = compatible s v u.
Corollary Ξ΄t_flip s u v : Ξ΄t (s`) u v = (Ξ΄t s v u)`.
Corollary path_sym s u v s' : s β£ u | v β€ s' β (s`) β£ v | u β€ (s'`).
Corollary compatible_flip s u v : compatible (s`) u v = compatible s v u.
Corollary Ξ΄t_flip s u v : Ξ΄t (s`) u v = (Ξ΄t s v u)`.
We can compose a path with label u|v with a path with label v|w to get a path with label u|w, if their starting points are compatible.
Lemma step_mix l1 l2 l3 s1 s2 s3 s4 :
prj2 s1 = prj1 s3 β s1 β£ l1 | l2 β¦ s2 β s3 β£ l2 | l3 β¦ s4 β
(s1 β s3) β£ l1 | l3 β¦ (s2 β s4) β§ prj2 s2 = prj1 s4.
Corollary path_mix u v w s1 s2 s3 s4 :
prj2 s1 = prj1 s3 β (s1 β£ u | v β€ s2) β (s3 β£ v | w β€ s4) β
prj2 s2 = prj1 s4 β§ (s1 β s3) β£ u | w β€ (s2 β s4).
prj2 s1 = prj1 s3 β s1 β£ l1 | l2 β¦ s2 β s3 β£ l2 | l3 β¦ s4 β
(s1 β s3) β£ l1 | l3 β¦ (s2 β s4) β§ prj2 s2 = prj1 s4.
Corollary path_mix u v w s1 s2 s3 s4 :
prj2 s1 = prj1 s3 β (s1 β£ u | v β€ s2) β (s3 β£ v | w β€ s4) β
prj2 s2 = prj1 s4 β§ (s1 β s3) β£ u | w β€ (s2 β s4).
Notice that paths are deterministic, in the sense that given a starting point s and a label u|v, there is at most one stack s' such that sβ£ u | v β€
s'.
Remark step_det a b s s1 s2 : s β£ a | b β¦ s1 β s β£ a | b β¦ s2 β s1 = s2.
Remark path_det u v s s1 s2 : s β£ u | v β€ s1 β s β£ u | v β€ s2 β s1 = s2.
Remark path_det u v s s1 s2 : s β£ u | v β€ s1 β s β£ u | v β€ s2 β s1 = s2.
We can compose a path from s1 to s2 and one from s2 to s3 to get a path from s1 to s3.
Lemma path_app u1 u2 v1 v2 s1 s2 s3 :
s1 β£ u1 | v1 β€ s2 β s2 β£ u2 | v2 β€ s3 β s1 β£ u1++u2 | v1++v2 β€ s3.
s1 β£ u1 | v1 β€ s2 β s2 β£ u2 | v2 β€ s3 β s1 β£ u1++u2 | v1++v2 β€ s3.
Binding power
If s β£ u | v β€ s', we can relate the number of occurrences of atoms in s and s' with the binding power of u and v with respect to a.
Proposition stack_binding a u s s' :
(s β£ u | u β€ s') β
nb a (prj1 s') = (nb a (prj1 s) - d_binding (π a u)) + c_binding (π a u).
Corollary stack_binding_both u v s s' :
(s β£ u | v β€ s') β
β a,
nb a (prj1 s') = (nb a (prj1 s) - d_binding (π a u)) + c_binding (π a u)
β§
nb a (prj2 s') = (nb a (prj2 s) - d_binding (π a v)) + c_binding (π a v).
(s β£ u | u β€ s') β
nb a (prj1 s') = (nb a (prj1 s) - d_binding (π a u)) + c_binding (π a u).
Corollary stack_binding_both u v s s' :
(s β£ u | v β€ s') β
β a,
nb a (prj1 s') = (nb a (prj1 s) - d_binding (π a u)) + c_binding (π a u)
β§
nb a (prj2 s') = (nb a (prj2 s) - d_binding (π a v)) + c_binding (π a v).
Using these, we can compute the size of the target stack from the c-binding power of u.
Lemma size_stack u v s :
[] β£ u | v β€ s β β’sβ₯ = sum (fun a β c_binding (π a u)) {{βuβ}}.
[] β£ u | v β€ s β β’sβ₯ = sum (fun a β c_binding (π a u)) {{βuβ}}.
Applying permutations on one component
We introduce a new operation. p β§ s is the stack obtained by replacing every pair (a,b) in s with (a,pβb).
Definition mixp p s : stack:= (prj1 s) β (pβprj2 s).
Infix "β§" := mixp (at level 50).
Remark mixp_fst p l : prj1 (p β§ l) = prj1 l.
Remark mixp_snd p l : prj2 (p β§ l) = prj2 (pβl).
Remark mixp_snd_bis p l : prj2 (p β§ l) = pβprj2 l.
Remark mixp_cons p a b l : p β§ ((a,b)::l) = (a,pβb)::p β§ l.
Remark mixp_app p l m : p β§ (l++m) = p β§ l ++ p β§ m.
Remark mixp_absent p l a b : absent (pβ§l) a b β absent l a (pββb).
Infix "β§" := mixp (at level 50).
Remark mixp_fst p l : prj1 (p β§ l) = prj1 l.
Remark mixp_snd p l : prj2 (p β§ l) = prj2 (pβl).
Remark mixp_snd_bis p l : prj2 (p β§ l) = pβprj2 l.
Remark mixp_cons p a b l : p β§ ((a,b)::l) = (a,pβb)::p β§ l.
Remark mixp_app p l m : p β§ (l++m) = p β§ l ++ p β§ m.
Remark mixp_absent p l a b : absent (pβ§l) a b β absent l a (pββb).
min_occ a u is equal to d_binding (π a u) if the boolean component of π a u is false, and d_binding (π a u)+1 otherwise.
Definition min_occ a v :=
match π a v with (m,true,_) β S m | (m,_,_) β m end.
Remark min_occ_app a u v : min_occ a u β€ min_occ a (u++v).
match π a v with (m,true,_) β S m | (m,_,_) β m end.
Remark min_occ_app a u v : min_occ a u β€ min_occ a (u++v).
This is the technical lemma needed to prove that the law Ξ±Ξ± holds for stacks. More precisely, we want to show that if b #Ξ± u and a #Ξ± u then there is a path from the empty stack to some accepting stack labelled with u | [(a,b)]βu. We generalise the statement by changing a,b #Ξ± u with a permutation p such that β a, Β¬ a #Ξ± u β p β a = a.
Intuitively, one might think that the following holds: s β£ u | v β€
s' β p β§ s β£ u | pβv β€
pβ§s'. Unfortunately, this is not true in general, consider for instance [] β£ aβ© | aβ© β€
[].
For this reason we need to require that β a, Β¬ a #Ξ± v β p β a = a. However, while the statement becomes true in this case, it is not suitable for induction. Thus we assume the stronger condition
β a, p β a β a β min_occ a v β€ nb a (prj2 s).
Lemma perm_path_mixp p u v s s' :
(β a, p β a β a β min_occ a v β€ nb a (prj2 s)) β (s β£ u | v β€ s') β
p β§ s β£ u | pβv β€ pβ§s'.
Corollary Ξ±fresh_perm_path p u v s s' :
(β a, Β¬ a #Ξ± v β p β a = a) β s β£ u | v β€ s' β p β§ s β£ u | pβv β€ p β§ s'.
Corollary Ξ±fresh_perm_path_nil p u :
(β a, Β¬ a #Ξ± u β p β a = a) β β s, [] β£ u | pβu β€ s β§ s β.
(β a, p β a β a β min_occ a v β€ nb a (prj2 s)) β (s β£ u | v β€ s') β
p β§ s β£ u | pβv β€ pβ§s'.
Corollary Ξ±fresh_perm_path p u v s s' :
(β a, Β¬ a #Ξ± v β p β a = a) β s β£ u | v β€ s' β p β§ s β£ u | pβv β€ p β§ s'.
Corollary Ξ±fresh_perm_path_nil p u :
(β a, Β¬ a #Ξ± u β p β a = a) β β s, [] β£ u | pβu β€ s β§ s β.
Main result
Completeness
It is now fairly routine to check that whenever u and v are alpha-equivalent, there is a path labelled with u|v from the empty stack to some accepting stack.Soundness
To prove completeness, we will proceed by induction on the length of the path, focusing on the last step:- if []β£[]|[]β€ [], then []β‘[];
- if [] β£ u|v β€
s β£ l|l' β¦ s' and s' is accepting, then the letters l,l' can be:
- β¨a,β¨b, but because s' is accepting we deduce that a=b and s' is accepting;
- var x,var y, with s=s', and because s' is accepting we deduce that var x=var y;
- aβ©,bβ©.
- u=u1++β¨a::u2 and v=v1++β¨b::v2, where u1 and v1 have the same length;
- a β u2 and b β v2.
Lemma path_stack_decompose_aux u v a b t1 t2 :
([] β£ u | v β€ t1++(a,b)::t2) β
β u1 u2 v1 v2, u=u1++β¨a::u2
β§ v=v1++β¨b::v2
β§ β’u1β₯ = β’v1β₯
β§ nb a (prj1 t1) = c_binding (π a u2)
β§ nb b (prj2 t1) = c_binding (π b v2)
β§ nb a (prj1 t2) = c_binding (π a u1)
β§ nb b (prj2 t2) = c_binding (π b v1).
Corollary path_stack_decompose u v a b s :
([] β£ u | v β€ s) β
aβ b β
(s β¨ a β¦ b) β
β u1 u2 v1 v2, u=u1++β¨a::u2
β§ v=v1++β¨b::v2
β§ β’u1β₯ = β’v1β₯
β§ a β u2
β§ b β v2.
([] β£ u | v β€ t1++(a,b)::t2) β
β u1 u2 v1 v2, u=u1++β¨a::u2
β§ v=v1++β¨b::v2
β§ β’u1β₯ = β’v1β₯
β§ nb a (prj1 t1) = c_binding (π a u2)
β§ nb b (prj2 t1) = c_binding (π b v2)
β§ nb a (prj1 t2) = c_binding (π a u1)
β§ nb b (prj2 t2) = c_binding (π b v1).
Corollary path_stack_decompose u v a b s :
([] β£ u | v β€ s) β
aβ b β
(s β¨ a β¦ b) β
β u1 u2 v1 v2, u=u1++β¨a::u2
β§ v=v1++β¨b::v2
β§ β’u1β₯ = β’v1β₯
β§ a β u2
β§ b β v2.
We may now prove the second direction of our main theorem: whenever we have an accepting path labelled with u|v, u and v are alpha-equivalent.
Note that this proof relies on the fact that Atom is infinite. This is in fact the only place in the proof where we use this fact. Indeed, to prove that β¨a;β¨b;aβ©;bβ© is equivalent to β¨b;β¨a;bβ©;aβ©, the transducer only uses names a and b, but the derivation of β‘ will need to use a Ξ±-fresh name.
Theorem path_Ξ±equiv u v s : s β β [] β£ u | v β€
s β u β‘ v.
Theorem completeness u v : u β‘ v β (β s, [] β£ u | v β€ s β§ s β).
Theorem completeness u v : u β‘ v β (β s, [] β£ u | v β€ s β§ s β).
Using the equivalence between paths and alpha-equivalence, and lemma Ξ±fresh_perm_path_nil, we can prove that the following rule is admissible.