module Atoms where

{-
This file defines Atoms and develops some basic lemmas about Atoms.
-}


open import Basics

------------------------------------------------------------------------------------------------------------------
--Definition of Atom     
-----------------------------------------------------------------------------------------------------------------

data Atom : Set where
  root : Atom
  next : Atom  Atom

---------------------------------------------------------------------------------------------------------------
--= and ≠ are injective wrt next
---------------------------------------------------------------------------------------------------------------

nextInj : (a b : Atom)  (next a  next b)  a  b
nextInj a .a refl = refl

a≠b⇒na≠nb : {a b : Atom}  (a  b  )  ((next a  next b)  )
a≠b⇒na≠nb {a}{b} a≡b⊥ na≡nb = a≡b⊥ (nextInj a b na≡nb)

----------------------------------------------------------------------------------------------------------------
--Decidable equality of atoms
----------------------------------------------------------------------------------------------------------------

AtEqDec : (a b : Atom)  Dec(a  b)
AtEqDec root root = yes refl
AtEqDec root (next b) = no  ())
AtEqDec (next a) root = no  ())
AtEqDec (next a) (next b) with AtEqDec a b
AtEqDec (next a) (next .a) | yes refl = yes refl
AtEqDec (next a) (next b) | no x = no  p  x (nextInj a b p))

---------------------------------------------------------------------------------------------------------------
--Swapping operation on atoms
---------------------------------------------------------------------------------------------------------------

swap : Atom × Atom  Atom  Atom
swap (a , b) c with AtEqDec c a | AtEqDec c b
swap (a , b) .a | yes refl | _ = b
swap (a , b) .b | no _ | yes refl = a
swap (a , b) c | no _ | no _ = c

swapaba≡b : (a b : Atom)  swap (a , b) a  b
swapaba≡b a b with AtEqDec a a
swapaba≡b a b | yes refl = refl
swapaba≡b a b | no x with x refl
swapaba≡b a b | no _ | ()

swapabb≡a : (a b : Atom)  swap (a , b) b  a
swapabb≡a a b with AtEqDec b a
swapabb≡a b .b | yes refl = refl
swapabb≡a a b | no _ with AtEqDec b b
swapabb≡a a b | no _ | yes refl = refl
swapabb≡a a b | no _ | no x with x refl
swapabb≡a a b | no _ | no _ | ()

swapabc≡c : (a b c : Atom) (f : c  a  ) (g : c  b  )  swap (a , b) c  c
swapabc≡c a b c f g with AtEqDec c a
swapabc≡c a b .a f g | yes refl with f refl
swapabc≡c a b .a f g | yes refl | ()
swapabc≡c a b c f g | no _ with AtEqDec c b
swapabc≡c a c .c f g | no _ | yes refl with g refl
swapabc≡c a c .c f g | no _ | yes refl | ()
swapabc≡c a b c f g | no _ | no x = refl

--------------------------------------------------------------------------------------------------------------
--Swapping is idempotent
-------------------------------------------------------------------------------------------------------------

swap∘swap≡swap : (a b c : Atom)  swap (a , b) (swap (a , b) c)  c
swap∘swap≡swap a b c with AtEqDec c a
swap∘swap≡swap a b .a | yes refl = swapabb≡a a b
swap∘swap≡swap a b c | no _ with AtEqDec c b
swap∘swap≡swap a c .c | no _ | yes refl = swapaba≡b a c
swap∘swap≡swap a b c | no f | no g = swapabc≡c a b c f g

------------------------------------------------------------------------------------------------------------
--Support of an atom
-----------------------------------------------------------------------------------------------------------

supp : Atom  List Atom
supp a = [ a ]

-----------------------------------------------------------------------------------------------------------
--Finding an atom that is not in a list of atoms
----------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------
--Meaning of _∉_
------------------------------------------------------------------------------------------------------

data _∉_ (a : Atom) : List Atom  Set where
  a∉[] : a  []
  a∉as :  {b as}  a  as   ( b  a )  a  (b :: as)

----------------------------------------------------------------------------------------------------
--an ordering relation on atoms
----------------------------------------------------------------------------------------------------

data _<'_  : Atom  Atom  Set where
 r<n :  {a}  root <' next a
 n₁<n₂ :  {a b}  a <' b  next a <' next b

----------------------------------------------------------------------------------------------------
--order extended to lists of atoms
---------------------------------------------------------------------------------------------------

data _<_ : List Atom  Atom  Set where
 []< :  {a}  [] < a
 as< :  {a b as}  as < b  a <' b  (a :: as) < b

---------------------------------------------------------------------------------------------------
--The greater of two atoms
--------------------------------------------------------------------------------------------------

greater : Atom  Atom  Atom
greater root root = next (root)
greater (next a) root = next (next a)
greater root (next a) = next (next a)
greater (next a) (next b) = next(greater a b)

-----------------------------------------------------------------------------------------------
--Outside a list of atoms
----------------------------------------------------------------------------------------------

outside : List Atom  Atom
outside [] = root
outside (a :: as) = greater a (outside as) 

----------------------------------------------------------------------------------------
--Proving that outside is truly outside
---------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------
--Next is greater than previous
----------------------------------------------------------------------------------------

b<nb : (b : Atom)  b <' next b
b<nb root = r<n 
b<nb (next b) = n₁<n₂ (b<nb b)

------------------------------------------------------------------------------------------
--Greater is greater than both
-----------------------------------------------------------------------------------------

a>bc⇒a>b : (b c : Atom)  b <' greater b c  
a>bc⇒a>b root root = r<n 
a>bc⇒a>b root (next c) = r<n 
a>bc⇒a>b (next b) root  = b<nb (next b)
a>bc⇒a>b (next b) (next c)  = n₁<n₂ (a>bc⇒a>b b c)

a>bc⇒a>c : (b c : Atom)  c <' greater b c  
a>bc⇒a>c root root = r<n 
a>bc⇒a>c root (next c) = b<nb (next c)
a>bc⇒a>c (next b) root  = r<n
a>bc⇒a>c (next b) (next c)  = n₁<n₂ (a>bc⇒a>c b c)

---------------------------------------------------------------------------------------------
--Greater than is transitive
--------------------------------------------------------------------------------------------

a<'b<'c : (a b c : Atom)  a <' b  b <' c  a <' c
a<'b<'c _ _ root a<'b = \ ()
a<'b<'c _ root (next _) = λ ()
a<'b<'c root (next b) (next c) _ _ = r<n
a<'b<'c (next a) (next b) (next c) (n₁<n₂ a<'b) (n₁<n₂ b<'c) = n₁<n₂ (a<'b<'c a b c a<'b b<'c)

----------------------------------------------------------------------------------------------
--Greater than a list of atoms
---------------------------------------------------------------------------------------------

as<a<'b : (a b : Atom)  (as : List Atom)  as < a  a <' b  as < b
as<a<'b a b [] as<a a<'b = []<
as<a<'b a b (x :: xs) (as< xs<a x<'a) a<'b = as< (as<a<'b a b xs xs<a a<'b) (a<'b<'c x a b x<'a a<'b) 

----------------------------------------------------------------------------------------------
--Outside is greater than
---------------------------------------------------------------------------------------------

outside< : (xs : List Atom)  xs < (outside xs)
outside< [] = []< 
outside< (a :: as) = as< (as<a<'b (outside as) (greater a (outside as)) as (outside< as) (a>bc⇒a>c a (outside as)))  (a>bc⇒a>b a (outside as))

----------------------------------------------------------------------------------------------
--Greater than is not equal to
---------------------------------------------------------------------------------------------

<≠ : {a b : Atom}  a <' b  a  b  
<≠ r<n = λ ()
<≠ (n₁<n₂ a<'b) = a≠b⇒na≠nb (<≠ a<'b)

------------------------------------------------------------------------------------------
--Greater than does not belong to
-----------------------------------------------------------------------------------------

<∉ :  {a as}  as < a  a  as
<∉ []< = a∉[]
<∉ (as< as<b a<'b) = a∉as (<∉ as<b) (<≠ a<'b)

--------------------------------------------------------------------------------------------
--Hence outside is not equal to
--------------------------------------------------------------------------------------------
 
outside∉ : (xs : List Atom)  (outside xs)  xs
outside∉ xs = <∉ (outside< xs)

--------------------------------------------------------------------------------------------