Set Warnings "-abstract-large-number".
Ltac invst H := inversion H; subst.
Ltac ctor := constructor.
Ltac ector := econstructor.
Ltac fext := apply functional_extensionality; intro.
Ltac gd x := generalize dependent x.
Ltac cg := try congruence.
Ltac clr_eqrefl:=
repeat match goal with
| H: ?A = ?A |- _ => clear H
end.
Ltac clr_dup:=
repeat match goal with
| H:?A, H':?A |- _ => clear H'
end.
Ltac clrs:=
clr_eqrefl; clr_dup.
Definition is_inj{T1 T2}(f:T1->T2):=
forall a b, f a = f b -> a = b.
Ltac ff_inj RR H := pose proof (ffx_eq_x_inj _ RR _ _ H); subst.
Fixpoint positive_len(x:positive):nat :=
match x with
| xH => O
| xI x0 => S (positive_len x0)
| xO x0 => S (positive_len x0)
end.
Fixpoint enc_v1(x:positive):positive :=
match x with
| xH => xH
| xI x0 => xI (xI (enc_v1 x0))
| xO x0 => xI (xO (enc_v1 x0))
end.
Definition enc_pair(x:positive*positive):positive :=
let (x1,x2):=x in
append (enc_v1 (Pos.of_succ_nat (positive_len x1))) (xO (append x1 x2)).
Fixpoint enc_list(x:list positive):positive :=
match x with
| nil => xH
| h::t => enc_pair (h,enc_list t)
end.
Notation "x &&& y" := (if x then y else false) (at level 80, right associativity).
Notation "x ||| y" := (if x then true else y) (at level 85, right associativity).
Definition set_ins{T}(enc:T->positive)(s:list T * PositiveMap.tree unit)(x:T):(list T * PositiveMap.tree unit)*bool :=
let enc := (enc x) in
match PositiveMap.find enc (snd s) with
| None => ((x::fst s, PositiveMap.add enc tt (snd s)),false)
| Some _ => (s,true)
end.
Definition set_in{T}(enc:T->positive)(s:list T * PositiveMap.tree unit)(x:T):Prop :=
PositiveMap.find (enc x) (snd s) = Some tt.
Definition set_WF{T}(enc:T->positive)(s:list T * PositiveMap.tree unit):Prop :=
forall (x:T),
set_in enc s x <->
In x (fst s).
Fixpoint pop_back{T}(x:T)(ls:list T):(list T) :=
match ls with
| h::t =>
x::(pop_back h t)
| nil => nil
end.
Fixpoint pop_back'{T}(x:T)(ls:list T):(list T)*T :=
match ls with
| nil => (nil,x)
| h :: t => let (a,b):=pop_back' h t in (x::a,b)
end.
Inductive St:Set :=
| St0
| St1
| St2
| St3.
Definition St_enc(x:St):positive :=
match x with
| St0 => xH
| St1 => xO xH
| St2 => xI xH
| St3 => xO (xO xH)
end.
intros x1 x2.
destruct x1,x2; cbn; cg.
Qed.
Definition St_eqb(s1 s2:St) :=
match s1,s2 with
| St0,St0 | St1,St1 | St2,St2 | St3,St3 => true
| _,_ => false
end.
Ltac eq_dec eqb_spec eqb s1 s2 :=
pose proof (eqb_spec s1 s2);
destruct (eqb s1 s2).
Ltac St_eq_dec s1 s2 :=
eq_dec St_eqb_spec St_eqb s1 s2.
Inductive Σ:Set :=
| Σ0
| Σ1.
Definition Σ_eqb(i1 i2:Σ) :=
match i1,i2 with
| Σ0,Σ0 | Σ1,Σ1 => true
| _,_ => false
end.
Definition Σ_enc(x:Σ):positive :=
match x with
| Σ0 => xH
| Σ1 => xO xH
end.
intros x1 x2.
destruct x1,x2; cbn; cg.
Qed.
Fixpoint listΣ_enc(x:list Σ):positive :=
match x with
| nil => xH
| Σ0::t => xO (listΣ_enc t)
| Σ1::t => xI (listΣ_enc t)
end.
Definition listT_enc{T}(f:T->positive)(x:list T):positive :=
enc_list (map f x).
Inductive Dir:Set :=
| Dneg
| Dpos.
Definition Dir_to_Z(x:Dir) :=
match x with
| Dneg => Zneg 1
| Dpos => Zpos 1
end.
Definition Dir_rev(d:Dir) :=
match d with
| Dneg => Dpos
| Dpos => Dneg
end.
Definition Dir_eqb(d1 d2:Dir):bool :=
match d1,d2 with
| Dpos,Dpos | Dneg,Dneg => true
| _,_ => false
end.

Lemma Dir_eqb_spec d1 d2:
if Dir_eqb d1 d2 then d1=d2 else d1<>d2.