module Revise.Reflection where

Import list


open import Data.Nat using (; _+_; suc; zero; _≤_; s≤s; z≤n; _≟_)
open import Data.Vec using (Vec; []; _∷_; tail; head)
open import Data.Empty using ()
open import Data.Unit using (; tt)
open import Data.Product using (Σ; _×_; _,_; proj₁; proj₂)
open import Data.Sum using (_⊎_; inj₁; inj₂)
open import Function renaming (_∘_ to _∘f_)
open import Relation.Nullary using (Dec; yes; no)
open import Relation.Binary.Core using (Decidable)
open import Relation.Binary.PropositionalEquality using (_≡_; refl; trans; cong)

Syntax for existential quantification


ex : {A : Set}  (A  Set)  Set
ex = Σ _

syntax ex  y  x) = y ∣ x

Permutation relation _∼_


module _ {A : Set} where

  private V = Vec A

  infix 1 _~_
  infixl 3 _∘_

  data _~_ :  {n}  V n  V n  Set where
    zero  : [] ~ []
    suc   :  {n a} {xs ys : V n}    xs ~ ys  a  xs ~ a  ys
    _∘_   :  {n} {xs ys zs : V n}   xs ~ ys  ys ~ zs  xs ~ zs
    exch  :  {n a b} {xs : V n}     a  b  xs ~ b  a  xs

Reflexivity and symmertry of _∼_


  ~-refl :  {n} {xs : V n}  xs ~ xs
  ~-refl {xs = []} = zero
  ~-refl {xs = _  []} = suc zero
  ~-refl {xs = _  _  xs} = exch  exch

  ~-sym :  {n} {xs ys : V n}  xs ~ ys  ys ~ xs
  ~-sym zero = zero
  ~-sym (suc e) = suc (~-sym e)
  ~-sym (e  e₁) = ~-sym e₁  ~-sym e
  ~-sym exch = exch

Smart constructors


  _∘simp_ :  {n} {xs ys zs : V n}   xs ~ ys  ys ~ zs  xs ~ zs
  zero ∘simp a = a
  suc zero ∘simp a = a
  (exch  exch) ∘simp a = a
  a ∘simp (exch  exch) = a
  a ∘simp b = a  b


  sucSimp :  {n x} {xs ys : V n}   xs ~ ys  x  xs ~ x  ys
  sucSimp zero = suc zero
  sucSimp (suc zero) = exch  exch
  sucSimp (exch  exch) = exch  exch
  sucSimp x = suc x

Permutation relation _≈_


  infix 1 _≋_ _≈_
  infixr 3 _↪_

  data Into (n : ) : Set where
    _↪_ : A  V n  Into n

  data _≋_ :  {n}  Into n  V (suc n)  Set where
    zero :  {n x} {xs : V n}  x  xs  x  xs
    suc  :  {n x y} {xs : V n} {ys}  x  xs  ys  x  y  xs  y  ys

  data _≈_ :  {n}  V n  V n  Set where
    [] : []  []
    _∷_  :  {n x} {xs ys : V n} {xxs}  x  xs  xxs  ys  xs  x  ys  xxs

Reflexivity of _≈_


  ≈-refl :  {n} {xs : V n}  xs  xs
  ≈-refl {xs = []} = []
  ≈-refl {xs = _  _} = zero  ≈-refl

_≈__∼_


  ~↪ :  {n x} {xs : V n} {ys}  x  xs  ys  x  xs ~ ys
  ~↪ zero = ~-refl
  ~↪ (suc e) = exch ∘simp sucSimp (~↪ e)

  ≈→~ :  {n} {xs ys : V n}  xs  ys  xs ~ ys
  ≈→~ [] = zero
  ≈→~ (x  e) = sucSimp (≈→~ e) ∘simp ~↪ x

Transitivity of _≈_


  ↪-exch :  {n x y} {xs : V n} {xxs yxxs}  x  xs  xxs  y  xxs  yxxs 
             yxs  (y  xs  yxs) × (x  yxs  yxxs)
  ↪-exch zero zero = _ , zero , suc zero
  ↪-exch zero (suc b) = _ , b , zero
  ↪-exch (suc a) zero = _ , zero , suc (suc a)
  ↪-exch (suc a) (suc b) with ↪-exch a b
  ... | _ , s , t = _ , suc s , suc t

  getOut :  {n x} {xs : V n} {xxs xys}  x  xs  xxs  xxs  xys 
        ys  (x  ys  xys) × (xs  ys)
  getOut zero (x₁  b) = _ , x₁ , b
  getOut (suc a) (x₁  b) with getOut a b
  ... | (l , m , f) with ↪-exch m x₁
  ... | s , k , r = s , r , k  f

  infixl 3 _∘≈_

  _∘≈_ :  {n} {xs ys zs : V n}  xs  ys  ys  zs  xs  zs
  []     ∘≈ f = f
  x₁  e ∘≈ f with getOut x₁ f
  ... | a , b , c = b  (e ∘≈ c)

_∼__≈_


  ~→≈ :  {n} {xs ys : V n}  xs ~ ys  xs  ys
  ~→≈ zero     = []
  ~→≈ (suc e)  = zero  ~→≈ e
  ~→≈ (e  e₁) = ~→≈ e ∘≈ ~→≈ e₁
  ~→≈ exch     = suc zero  zero  ≈-refl

Symmetry of _≈_


  ≈-sym :  {n} {xs ys : V n}  xs  ys  ys  xs
  ≈-sym a = ~→≈ (~-sym (≈→~ a))

Cancellation property of _≈_


  cancel :  {n} {x} {xs ys : V n}  x  xs  x  ys  xs  ys
  cancel (zero  e) = e
  cancel (suc x₁  b  e) = zero  e ∘≈ b  ≈-refl ∘≈ x₁  ≈-refl

Examples


t1 : 1  2  3  4  []  3  2  4  1  []
t1 = suc (suc (suc zero))  suc zero  zero  zero  []


f2 : 1  2  []  1  1  []  
f2 (zero  ()  [])
f2 (suc x  ()  [])

Decidable _≈_


module Dec≈ (A : Set) {{eq : Decidable {A = A} _≡_}} where

  private V = Vec A


  getOut' :  {n} x (xs : V (suc n))  Dec (ys  x  ys  xs)
  getOut'  x  (x₁  xs) with eq x x₁
  getOut' .x₁ (x₁  xs) | yes refl = yes (xs , zero)
  getOut'  x  (x₁  []) | no ¬p = no (¬p ∘f f x refl)  where
    f :  a  x  a  (ys  a  ys  x₁  [])  x  x₁
    f .x₁ k (.[] , zero) = k
  getOut' x (x₁  y  xs) | no ¬p with getOut' x (y  xs)
  ... | yes (a , b) = yes (x₁  a , suc b)
  ... | no ¬q = no (f x refl)  where
    f :  a  x  a  (ys  a  ys  x₁  y  xs)  
    f .x₁ e (.(y  xs) , zero) = ¬p e
    f a e (.x₁  xs , suc q) with a | e
    ... | .x | refl = ¬q (xs , q)


  infix 2 _≈?_

  _≈?_ :  {n}  (xs ys : V n)  Dec (xs  ys)
  []     ≈? [] = yes []
  x  xs ≈? ys with getOut' x ys
  ... | no ¬p = no λ { (h  _)  ¬p (_ , h)}
  ... | yes (zs , p) with xs ≈? zs
  ...  | yes p' = yes (p  p')
  ...  | no ¬p = no λ e  ¬p (cancel (e ∘≈ ≈-sym (p  ≈-refl)))

Examples


open Dec≈  {{_≟_}}  -- TODO: remove this

try = 1  20  3  4  [] ≈? 3  2  4  1  []

Imports for reflection


open import Reflection hiding (_≟_)
open import Data.List using ([]; _∷_)
open import Data.Maybe using (Maybe; just; nothing; maybe′)

Parsing a natural


parseℕ : Term  Maybe 
parseℕ (con c []) with c ≟-Name quote ℕ.zero
... | yes _ = just 0
... | _  = nothing
parseℕ (con c (arg _ x  [])) with c ≟-Name quote ℕ.suc | parseℕ x
... | yes _ | just n = just (suc n)
... | _ | _ = nothing
parseℕ _ = nothing


parseℕ′ : Term  
parseℕ′ t = maybe′ id 0 (parseℕ t)

Representation of one side of a permutation relation


data Side : Set where
  side :  {n}  Vec  n  Side

Parsing of the side


parseSide : Term  Maybe Side
parseSide (con c []) = just (side [])
parseSide (con c (_  arg _ x  arg _ xs  [])) with parseSide xs | parseℕ x
... | just (side s) | just n = just (side (n  s))
... | _ | _ = nothing
parseSide _ = nothing

Solution of a permutation test (with error codes)


data Solution : Set where
   ok :  {n} {xs ys : Vec  n}  Dec (xs  ys)  Solution
   error :   Solution

Computing a solution


computeSolution : Term  Term  Solution
computeSolution l r with parseSide l | parseSide r
... | nothing | _ = error 0
... | _ | nothing = error 1
... | just (side {a} b) | just (side {a'} d)  with a  a'
computeSolution l r | just (side b) | just (side d) | yes refl = ok (b ≈? d)
... | no ¬p = error 2

Negation as a data

This simplifies parsing of a negation.


data Neg (A : Set) : Set where
  neg : (A  )  Neg A

Final steps


err :   Σ Set id
err n = (n  n) , refl


parse : Term  Σ Set id
parse (def c (A  n  arg _ l  arg _ r  [])) with c ≟-Name quote _≈_
... | yes _ =  computeSolution l r   where
  ⟦_⟧ : Solution  Σ Set id 
   ok (yes d)  = _ , d
   error n  = err n
   _  = err 10
... | no _ with c ≟-Name quote _~_ 
... | yes _ =  computeSolution l r   where
  ⟦_⟧ : Solution  Σ Set id 
   ok (yes d)  = _ , ≈→~ d
   error n  = err n
   _  = err 15
... | no _ = err 13
parse (def c' (arg _ (def c (A  n  arg _ l  arg _ r  []))  [])) with c' ≟-Name quote Neg
... | yes _ =  computeSolution l r  where
  ⟦_⟧ : Solution  Σ Set id 
   ok (no d)  = _ , neg d
   error n  = err n
   _  = err 11
... | no _ = err 12
parse _ = err 3


solvePerm : (g : Term)  proj₁ (parse g)
solvePerm g = proj₂ (parse g)

Examples


{- todo
x : 1 ∷ 2 ∷ 2 ∷ 4 ∷ 5 ∷ [] ≈ 2 ∷ 2 ∷ 1 ∷ 4 ∷ 5 ∷ []
x = quoteGoal t in solvePerm t

x1 : 1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ [] ~ 1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ []
x1 = quoteGoal t in solvePerm t

x2 : 1 ∷ 2 ∷ 2 ∷ 4 ∷ 5 ∷ [] ~ 2 ∷ 2 ∷ 1 ∷ 4 ∷ 5 ∷ []
x2 = quoteGoal t in solvePerm t

x3 : 1 ∷ 2 ∷ 2 ∷ 4 ∷ 6 ∷ 7 ∷ 8 ∷ 1 ∷ 5 ∷ [] ~ 2 ∷ 8 ∷ 1 ∷ 6 ∷ 7 ∷ 2 ∷ 1 ∷ 4 ∷ 5 ∷ []
x3 = quoteGoal t in solvePerm t

x' : Neg (1 ∷ 2 ∷ 2 ∷ 4 ∷ 5 ∷ [] ≈ 2 ∷ 12 ∷ 1 ∷ 4 ∷ 5 ∷ [])
x' = quoteGoal t in solvePerm t
-}

x