{-# OPTIONS --safe --cubical-compatible --guardedness --exact-split --double-check #-}
module ALMA.Physics.Quantum.Gaussian where
open import Agda.Builtin.Equality using (_≡_; refl)
open import Data.Product.Base using (_×_; _,_)
open import Data.Rational using (ℚ; 0ℚ; 1ℚ; _+_; _*_; _-_; -_)
open import Data.Rational.Properties using
(+-assoc; +-comm; +-identityʳ; +-inverseˡ; *-distribˡ-+; *-distribʳ-+; neg-distrib-+)
open import Relation.Binary.PropositionalEquality using
(trans; sym; cong; cong₂; module ≡-Reasoning)
open ≡-Reasoning
open import ALMA.Physics.RationalKit using (neg-neg-mul; sq+; sq-; sq-comm; cross-eq)
ℂ : Set
ℂ = ℚ × ℚ
re im : ℂ → ℚ
re (a , _) = a
im (_ , b) = b
infixl 6 _+ᶜ_
infixl 7 _*ᶜ_
_+ᶜ_ : ℂ → ℂ → ℂ
(a , b) +ᶜ (c , d) = (a + c , b + d)
_*ᶜ_ : ℂ → ℂ → ℂ
(a , b) *ᶜ (c , d) = (a * c - b * d , a * d + b * c)
0ᶜ 1ᶜ : ℂ
0ᶜ = (0ℚ , 0ℚ)
1ᶜ = (1ℚ , 0ℚ)
conj : ℂ → ℂ
conj (a , b) = (a , - b)
norm² : ℂ → ℚ
norm² z = re z * re z + im z * im z
norm²-0ᶜ : norm² 0ᶜ ≡ 0ℚ
norm²-0ᶜ = refl
norm²-1ᶜ : norm² 1ᶜ ≡ 1ℚ
norm²-1ᶜ = refl
private
kill : ∀ U V t →
(U - (t + t)) + (V + (t + t)) ≡ U + V
kill U V t = begin
(U - (t + t)) + (V + (t + t))
≡⟨ sym (+-assoc (U - (t + t)) V (t + t)) ⟩
((U - (t + t)) + V) + (t + t)
≡⟨ cong (λ z → z + (t + t)) (+-comm (U - (t + t)) V) ⟩
(V + (U - (t + t))) + (t + t)
≡⟨ +-assoc V (U - (t + t)) (t + t) ⟩
V + ((U - (t + t)) + (t + t))
≡⟨ cong (V +_) (+-assoc U (- (t + t)) (t + t)) ⟩
V + (U + ((- (t + t)) + (t + t)))
≡⟨ cong (λ z → V + (U + z)) (+-inverseˡ (t + t)) ⟩
V + (U + 0ℚ)
≡⟨ cong (V +_) (+-identityʳ U) ⟩
V + U
≡⟨ +-comm V U ⟩
U + V ∎
gather : ∀ w x y z →
(w * y + x * z) + (w * z + x * y)
≡ (w * y + w * z) + (x * y + x * z)
gather w x y z = begin
(w * y + x * z) + (w * z + x * y)
≡⟨ +-assoc (w * y) (x * z) (w * z + x * y) ⟩
w * y + (x * z + (w * z + x * y))
≡⟨ cong (w * y +_) move ⟩
w * y + (w * z + (x * z + x * y))
≡⟨ cong (λ r → w * y + (w * z + r)) (+-comm (x * z) (x * y)) ⟩
w * y + (w * z + (x * y + x * z))
≡⟨ sym (+-assoc (w * y) (w * z) (x * y + x * z)) ⟩
(w * y + w * z) + (x * y + x * z) ∎
where
move : x * z + (w * z + x * y) ≡ w * z + (x * z + x * y)
move = begin
x * z + (w * z + x * y)
≡⟨ sym (+-assoc (x * z) (w * z) (x * y)) ⟩
(x * z + w * z) + x * y
≡⟨ cong (λ r → r + x * y) (+-comm (x * z) (w * z)) ⟩
(w * z + x * z) + x * y
≡⟨ +-assoc (w * z) (x * z) (x * y) ⟩
w * z + (x * z + x * y) ∎
norm²-conj : ∀ (u : ℂ) → norm² (conj u) ≡ norm² u
norm²-conj (a , b) = cong (a * a +_) (neg-neg-mul b b)
norm²-mul : ∀ (u v : ℂ) → norm² (u *ᶜ v) ≡ norm² u * norm² v
norm²-mul (a , b) (c , d) = begin
(ac - bd) * (ac - bd) + (ad + bc) * (ad + bc)
≡⟨ cong₂ _+_ real-part imag-part ⟩
(U - (P + P)) + (V + (Q + Q))
≡⟨ cong ((U - (P + P)) +_) (cong (V +_) (cong₂ _+_ (sym (cross-eq a b c d))
(sym (cross-eq a b c d)))) ⟩
(U - (P + P)) + (V + (P + P))
≡⟨ kill U V P ⟩
U + V
≡⟨ cong₂ _+_ U-eq V-eq ⟩
(a²c² + b²d²) + (a²d² + b²c²)
≡⟨ gather (a * a) (b * b) (c * c) (d * d) ⟩
(a²c² + a²d²) + (b²c² + b²d²)
≡⟨ sym expand ⟩
(a * a + b * b) * (c * c + d * d) ∎
where
ac = a * c ; bd = b * d ; ad = a * d ; bc = b * c
P = ac * bd ; Q = ad * bc
U = ac * ac + bd * bd
V = ad * ad + bc * bc
a²c² = (a * a) * (c * c) ; b²d² = (b * b) * (d * d)
a²d² = (a * a) * (d * d) ; b²c² = (b * b) * (c * c)
real-part : (ac - bd) * (ac - bd) ≡ U - (P + P)
real-part = begin
(ac - bd) * (ac - bd)
≡⟨ sq- ac bd ⟩
ac * ac + (bd * bd + (- (ac * bd) + - (ac * bd)))
≡⟨ cong (ac * ac +_)
(cong (bd * bd +_)
(sym (neg-distrib-+ (ac * bd) (ac * bd)))) ⟩
ac * ac + (bd * bd + - (P + P))
≡⟨ sym (+-assoc (ac * ac) (bd * bd) (- (P + P))) ⟩
(ac * ac + bd * bd) + - (P + P) ∎
imag-part : (ad + bc) * (ad + bc) ≡ V + (Q + Q)
imag-part = trans (sq+ ad bc)
(sym (+-assoc (ad * ad) (bc * bc) (Q + Q)))
U-eq : U ≡ a²c² + b²d²
U-eq = cong₂ _+_ (sq-comm a c) (sq-comm b d)
V-eq : V ≡ a²d² + b²c²
V-eq = cong₂ _+_ (sq-comm a d) (sq-comm b c)
expand : (a * a + b * b) * (c * c + d * d)
≡ (a²c² + a²d²) + (b²c² + b²d²)
expand = begin
(a * a + b * b) * (c * c + d * d)
≡⟨ *-distribʳ-+ (c * c + d * d) (a * a) (b * b) ⟩
a * a * (c * c + d * d) + b * b * (c * c + d * d)
≡⟨ cong₂ _+_ (*-distribˡ-+ (a * a) (c * c) (d * d))
(*-distribˡ-+ (b * b) (c * c) (d * d)) ⟩
(a²c² + a²d²) + (b²c² + b²d²) ∎
Unit : ℂ → Set
Unit z = norm² z ≡ 1ℚ
unit-norm-mul : ∀ u v → Unit u → Unit v → Unit (u *ᶜ v)
unit-norm-mul u v hu hv
rewrite norm²-mul u v | hu | hv = refl