{-# OPTIONS --without-K --exact-split --rewriting --overlapping-instances #-}
open import HoTT hiding (_<_ ; ltS ; ltSR ; _+_ ; _×_)
import lib.types.Nat as N
import lib.types.Sigma as S
open import Pi.UFin.BAut
open import Pi.Common.Misc
open import Pi.Common.Extra
open import Pi.Syntax.Pi+.Indexed as Pi+
open import Pi.Syntax.Pi^ as Pi^
open import Pi.Syntax.Pi^Helpers as Pi^
open import Pi.Syntax.Pi as Pi
open import Pi.Equiv.Translation2
import Pi.Equiv.Equiv1 as Pi+
import Pi.Equiv.Equiv0Hat as Pi^
import Pi.Equiv.Equiv1Hat as Pi^
import Pi.Equiv.Equiv0Norm as Pi^
import Pi.Equiv.Equiv1Norm as Pi^
open import Pi.UFin.UFin
open import Pi.UFin.Monoidal
open import Pi.Common.FinHelpers
open import Pi.Lehmer.FinExcept
module Pi.Examples.Toffoli where
open import Pi.Examples.Base
swap2 : 𝔹 2 Pi.⟷₁ 𝔹 2
swap2 = swap⋆
_ : (–> (interp' swap2) (inr tt , inr tt) == inr tt , inr tt) S.×
(–> (interp' swap2) (inr tt , inl tt) == inl tt , inr tt) S.×
(–> (interp' swap2) (inl tt , inr tt) == inr tt , inl tt) S.×
(–> (interp' swap2) (inl tt , inl tt) == inl tt , inl tt)
_ = idp , idp , idp , idp
controlled : {t : Pi.U} → (c : t Pi.⟷₁ t) → (𝟚 Pi.× t Pi.⟷₁ 𝟚 Pi.× t)
controlled c = dist ◎ ((id⟷₁ ⊗ c) ⊕ id⟷₁) ◎ factor
controlled^ : {t : Pi.U} → (c : t Pi.⟷₁ t) → _
controlled^ c = eval₁ (controlled c)
cif : {t : Pi.U} → (c₁ c₂ : t Pi.⟷₁ t) → (𝟚 Pi.× t Pi.⟷₁ 𝟚 Pi.× t)
cif c₁ c₂ = dist ◎ ((id⟷₁ ⊗ c₁) ⊕ (id⟷₁ ⊗ c₂)) ◎ factor
cif^ : {t : Pi.U} → (c₁ c₂ : t Pi.⟷₁ t) → _
cif^ c₁ c₂ = eval₁ (cif c₁ c₂)
not : 𝟚 Pi.⟷₁ 𝟚
not = swap₊
not^ : 2 Pi^.⟷₁^ 2
not^ = eval₁ not
not^p : Fin 2 → Fin 2
not^p = –> (Pi^.evalNorm₁ not^)
_ : (not^p 0 == 1) S.× (not^p 1 == 0)
_ = fin= idp , fin= idp
cnot : 𝟚 Pi.× 𝟚 Pi.⟷₁ 𝟚 Pi.× 𝟚
cnot = controlled not
cnot^ : 4 ⟷₁^ 4
cnot^ = eval₁ cnot
cnot^p : Fin 4 → Fin 4
cnot^p = –> (Pi^.evalNorm₁ cnot^)
_ : (cnot^p 0 == 1) S.× (cnot^p 1 == 0) S.× (cnot^p 2 == 2) S.× (cnot^p 3 == 3)
_ = fin= idp , fin= idp , fin= idp , fin= idp
toffoli₃ : 𝟚 Pi.× (𝟚 Pi.× 𝟚) Pi.⟷₁ 𝟚 Pi.× (𝟚 Pi.× 𝟚)
toffoli₃ = controlled cnot
toffoli₃^ : 8 ⟷₁^ 8
toffoli₃^ = eval₁ toffoli₃
toffoli : ∀ n → 𝔹 n Pi.⟷₁ 𝔹 n
toffoli O = id⟷₁
toffoli (S O) = swap₊
toffoli (S (S n)) = cif (toffoli (S n)) id⟷₁
toffoli^ : ∀ n → _
toffoli^ = eval₁ ∘ toffoli
toffoli+ : ∀ n → _
toffoli+ = Pi^.quote^₁ ∘ Pi^.quoteNorm₁ idp ∘ Pi^.evalNorm₁ ∘ toffoli^
toffoli^2-perm : Aut (Fin 4)
toffoli^2-perm = Pi^.evalNorm₁ (toffoli^ 2)
swap23 : Aut (Fin 4)
swap23 = equiv f f f-f f-f
where f : Fin 4 → Fin 4
f (O , ϕ) = 1
f (1 , ϕ) = 0
f (2 , ϕ) = 2
f (3 , ϕ) = 3
f (n , N.ltSR (N.ltSR (N.ltSR (N.ltSR ()))))
f-f : (x : Fin 4) → f (f x) == x
f-f (O , ϕ) = fin= idp
f-f (1 , ϕ) = fin= idp
f-f (2 , ϕ) = fin= idp
f-f (3 , ϕ) = fin= idp
f-f (n , N.ltSR (N.ltSR (N.ltSR (N.ltSR ()))))
toffoli^2perm=swap23 : toffoli^2-perm == swap23
toffoli^2perm=swap23 = e= ϕ
where ϕ : (f : Fin 4) → –> toffoli^2-perm f == –> swap23 f
ϕ (O , ϕ) = fin= idp
ϕ (1 , ϕ) = fin= idp
ϕ (2 , ϕ) = fin= idp
ϕ (3 , ϕ) = fin= idp
ϕ (n , N.ltSR (N.ltSR (N.ltSR (N.ltSR ()))))
swap23^ : 4 Pi^.⟷₁^ 4
swap23^ = Pi^.quoteNorm₁ idp swap23
swap23+ : 𝟜+ Pi+.⟷₁ 𝟜+
swap23+ = Pi+.quote₁ idp swap23
toffoli2+ : 𝟜+ Pi+.⟷₁ 𝟜+
toffoli2+ = Pi^.quote^₁ swap23^
swap67 : Aut (Fin 8)
swap67 = equiv f f f-f f-f
where f : Fin 8 → Fin 8
f (O , ϕ) = 1
f (1 , ϕ) = 0
f (2 , ϕ) = 2
f (3 , ϕ) = 3
f (4 , ϕ) = 4
f (5 , ϕ) = 5
f (6 , ϕ) = 6
f (7 , ϕ) = 7
f (n , N.ltSR (N.ltSR (N.ltSR (N.ltSR (N.ltSR (N.ltSR (N.ltSR (N.ltSR ()))))))))
f-f : (x : Fin 8) → f (f x) == x
f-f (O , ϕ) = fin= idp
f-f (1 , ϕ) = fin= idp
f-f (2 , ϕ) = fin= idp
f-f (3 , ϕ) = fin= idp
f-f (4 , ϕ) = fin= idp
f-f (5 , ϕ) = fin= idp
f-f (6 , ϕ) = fin= idp
f-f (7 , ϕ) = fin= idp
f-f (n , N.ltSR (N.ltSR (N.ltSR (N.ltSR (N.ltSR (N.ltSR (N.ltSR (N.ltSR ()))))))))
swap67+ : _ Pi+.⟷₁ _
swap67+ = Pi^.quote^₁ (Pi^.quoteNorm₁ idp swap67)