open import Algebra.Apartness
open import Relation.Binary
open import Algebra.DecidableField
module MatrixFuncNormalization.normBef {c ℓ₁ ℓ₂} (dField : DecidableField c ℓ₁ ℓ₂) where
open import Level hiding (suc)
open import Function
open import Data.Empty
open import Data.Bool using (true; false)
open import Data.Maybe using (Maybe)
open import Data.Maybe.Relation.Unary.All
open import Data.Product
open import Data.Fin.Base as F hiding (lift; _-_; _+_)
open import Data.Fin.Properties as F hiding (_≟_)
open import Data.Fin.Patterns
open import Data.Sum
open import Data.Nat hiding (_⊔_; <-cmp; _≟_; _<_; _*_; _+_; _<′_)
open import Data.List using (List)
open import Data.Vec.Functional
open import Data.Vec.Functional.Properties
open import Relation.Nullary.Construct.Add.Supremum
import Relation.Binary.Construct.Add.Supremum.Strict as AddSupMod
open import Relation.Binary.PropositionalEquality as ≡ hiding (setoid; refl)
import Relation.Binary.Construct.Add.Point.Equality as Equality
open import Relation.Nullary
open import Relation.Nullary.Decidable
import Relation.Binary.Reasoning.Setoid as ReasonSetoid
open import Algebra
import Algebra.Properties.Ring as RingProps
open import Algebra.Matrix.Properties
open import Algebra.Matrix.Structures
import Algebra.Module.Instances.FunctionalVector as AMIF
import MatrixFuncNormalization.MatrixProps as MatrixProps
import Algebra.Module.VecSpace as VecSpace
open import Vector.Base using (_[_]≔_)
open import MatrixFuncNormalization.FinInduction
open import Algebra.MatrixData renaming (Matrix to MatrixData)
open import lbry
open DecidableField dField renaming (Carrier to F; heytingField to hField)
open HeytingField hField using (heytingCommutativeRing)
open hFieldProps hField
open MRing rawRing
open MRingProps ring
open RingProps ring
open FuncNormAllLines
open FuncNormAndZeros
open import Algebra.Module.Base ring
open module AddSup {n} = AddSupMod (_<_ {n})
open module M = AMIF ring hiding (_+ᴹ_)
module ≈-Reasoning = ReasonSetoid setoid
open module PNorm {n} = MatrixProps (<-strictTotalOrder n)
open module PVec {n} = VecSpace (leftModule n)
open module Equality′ {a} {A} = Equality {a} {A = A} _≡_ renaming (≈∙-refl to ≈∙-refl′)
private variable
ℓ₃ : Level
ASet : Set ℓ₃
m n : ℕ
p px py : Fin n ⁺
xs ys : Vector F n
private
≈∙-refl : Reflexive (_≈∙_ {A = ASet})
≈∙-refl = ≈∙-refl′ ≡.refl
private
PivValue : Vector F n → Fin n ⁺ → Set ℓ₂
PivValue xs = All $ λ i → xs i # 0#
Lookup≢0 : (xs : Vector F n) (p : Fin n) → Set _
Lookup≢0 xs p = xs p # 0# × ∀ i → i < p → xs i ≈ 0#
AllZeros : (xs : Vector F n) → Set _
AllZeros xs = ∀ p → xs p ≈ 0#
0ⱽ : Vector F n
0ⱽ _ = 0#
VecPivots' : (xs : Vector F n) → Set _
VecPivots' xs = (Σ[ p ∈ Fin _ ] Lookup≢0 xs p) ⊎ AllZeros xs
vecPivots'→⁺ : {xs : Vector F n} → VecPivots' xs → Fin n ⁺
vecPivots'→⁺ (inj₁ (p , _)) = [ p ]
vecPivots'→⁺ (inj₂ _) = ⊤⁺
VecPivotPos : (xs : Vector F n) (p : Fin n ⁺) → Set (ℓ₁ ⊔ ℓ₂)
VecPivotPos xs ⊤⁺ = Lift ℓ₂ (AllZeros xs)
VecPivotPos xs [ p ] = Lookup≢0 xs p
sameVecPiv : {xs ys : Vector F n} (xs≡ys : ∀ i → xs i ≡ ys i) {p : Fin n ⁺} → VecPivotPos xs p → VecPivotPos ys p
lower (sameVecPiv xs≡ys {⊤⁺} (lift vPiv)) i rewrite ≡.sym (xs≡ys i) = vPiv i
proj₁ (sameVecPiv xs≡ys {[ p ]} (xsp#0 , ineq)) rewrite ≡.sym (xs≡ys p) = xsp#0
proj₂ (sameVecPiv xs≡ys {[ p ]} (xsp#0 , ineq)) i rewrite ≡.sym (xs≡ys i) = ineq i
alwaysSamePivot' : ∀ (xs : Vector F n) p₁ p₂ → Lookup≢0 xs p₁ → Lookup≢0 xs p₂ → p₁ ≡ p₂
alwaysSamePivot' xs p₁ p₂ (vpiv₁≢0 , vpiv₁≡0) (vpiv₂≢0 , vpiv₂≡0) with <-cmp p₁ p₂
... | tri< p₁<p₂ _ _ = ⊥-elim (tightʳ vpiv₁≢0 (vpiv₂≡0 p₁ p₁<p₂))
... | tri> _ _ p₁>p₂ = ⊥-elim (tightʳ vpiv₂≢0 (vpiv₁≡0 p₂ p₁>p₂))
... | tri≈ _ p₁≡p₂ _ = p₁≡p₂
alwaysSamePivot : ∀ (xs : Vector F n) p₁ p₂ → VecPivotPos xs p₁ → VecPivotPos xs p₂ → p₁ ≡ p₂
alwaysSamePivot xs [ x ] ⊤⁺ (xsx≢0 , _) (lift vpiv₂) = ⊥-elim (tightʳ xsx≢0 (vpiv₂ _))
alwaysSamePivot xs ⊤⁺ [ x ] (lift vpiv₁) (xsx≢0 , _) = ⊥-elim (tightʳ xsx≢0 (vpiv₁ _))
alwaysSamePivot xs ⊤⁺ ⊤⁺ vpiv₁ vpiv₂ = ≡.refl
alwaysSamePivot xs [ _ ] [ _ ] vpiv₁ vpiv₂ = cong [_] (alwaysSamePivot' xs _ _ vpiv₁ vpiv₂)
VecPiv : Vector F n → Set _
VecPiv xs = Σ[ p ∈ _ ] Lookup≢0 xs p
VecPivots : Vector F n → Set _
VecPivots xs = Σ[ p ∈ _ ] VecPivotPos xs p
VecPivotsΣ : ∀ n → Set _
VecPivotsΣ n = Σ[ xs ∈ Vector F n ] Σ[ p ∈ Fin n ⁺ ] PivValue xs p × VecPivotPos xs p
findNonZero : (xs : Vector F n) → VecPivots xs
proj₁ (findNonZero {zero} xs) = ⊤⁺
proj₂ (findNonZero {zero} xs) = lift $ λ ()
findNonZero {suc n} xs with xs F.zero ≟ 0# | findNonZero (tail xs)
... | yes xs0#0 | fn = [ F.zero ] , xs0#0 , λ _ ()
... | no xs0≈0 | [ i ] , xsI#0 , xs<I≈0 = [ suc i ] , xsI#0 ,
λ where zero j<si → tight _ _ .proj₁ xs0≈0 ; (suc j) sj<si → xs<I≈0 j (≤-pred sj<si)
... | no xs0≈0 | ⊤⁺ , (lift allZeros) = ⊤⁺ ,
lift (λ where zero → tight _ _ .proj₁ xs0≈0 ; (suc i) → allZeros i)
findNonZeroPos : Vector F n → Fin _ ⁺
findNonZeroPos = proj₁ ∘ findNonZero
_-v_ : Op₂ $ Vector F n
xs -v ys = xs M.+ᴹ (-ᴹ ys)
moreZeros≥Piv : ∀ {xs ys : Vector F n}
{px : Fin n} {py : Fin n ⁺} →
Lookup≢0 xs px → VecPivotPos ys py
→ (∀ x → x < px → ys x ≈ 0#)
→ ys px ≈ 0#
→ [ px ] <′ py
moreZeros≥Piv {py = ⊤⁺} lx vPivy ys<X≡0 ysX≡0 = _ ≤⊤⁺
moreZeros≥Piv {px = px} {[ py ]} lx (pivYs , vPivy) ys<X≡0 ysX≡0 with <-cmp px py
... | tri< px<py _ _ = inj₁ [ px<py ]
... | tri≈ _ ≡.refl _ = tightBoth pivYs ysX≡0
... | tri> _ _ py<px = tightBoth pivYs $ ys<X≡0 py py<px
reduceVector : ∀ {xs ys : Vector F n} {piv}
(fxs : VecPivotPos xs piv) (fys : VecPivotPos ys piv)
→ Σ[ res ∈ Vector F n ] Σ[ pivRes ∈ Fin n ⁺ ]
(VecPivotPos res pivRes × piv <′ pivRes × ([ xs ,, ys ] ≈ⱽ [ xs ,, res ]))
reduceVector {xs = xs} {ys} {⊤⁺} (lift fxs) (lift fys) = _ , ⊤⁺ , lift fys , (⊤⁺ ≤⊤⁺) , idR ≈ᴹ-refl
reduceVector {xs = xs} {ys} piv@{[ pxs ]} pivXs@(fxs#0 , fxs) (_ , fys) =
_ , helper (findNonZero ysn .proj₂)
where
open ≈-Reasoning
vx = xs pxs
vx⁻¹ = #⇒invertible fxs#0 .proj₁
vy = ys pxs
-vx⁻¹vy = - (vy * vx⁻¹)
xsn = -vx⁻¹vy *ₗ xs
ysn = ys M.+ᴹ xsn
ysnXs<≈0 : ∀ i → i < pxs → ysn i ≈ 0#
ysnXs<≈0 i i<pxs = begin
ys i + -vx⁻¹vy * xs i ≈⟨ +-cong (fys i i<pxs) (*-congˡ (fxs i i<pxs)) ⟩
0# + -vx⁻¹vy * 0# ≈⟨ +-congˡ (zeroʳ _) ⟩
0# + 0# ≈⟨ +-identityʳ 0# ⟩
0# ∎
α = begin
vy * vx⁻¹ * vx ≈⟨ *-assoc _ _ _ ⟩
vy * (vx⁻¹ * vx) ≈⟨ *-congˡ (x#0→x⁻¹*x≈1 fxs#0) ⟩
vy * 1# ≈⟨ *-identityʳ _ ⟩
vy ∎
vyvx⁻¹vx≈vy = begin
- (vy * vx⁻¹) * vx ≈˘⟨ -‿distribˡ-* _ _ ⟩
- (vy * vx⁻¹ * vx) ≈⟨ -‿cong α ⟩
- vy ∎
ysnXs≈0 : ysn pxs ≈ 0#
ysnXs≈0 = begin
vy + - (vy * vx⁻¹) * vx ≈⟨ +-congˡ vyvx⁻¹vx≈vy ⟩
vy + - vy ≈⟨ -‿inverseʳ _ ⟩
0# ∎
helper : ∀ {pivYs'} → VecPivotPos ysn pivYs' → Σ[ pivRes ∈ Fin _ ⁺ ]
(VecPivotPos ysn pivRes × piv <′ pivRes × ([ xs ,, ys ] ≈ⱽ [ xs ,, ysn ]))
helper pivYs' = _ , pivYs' , pxs≤pysn' , normed where
pxs≤pysn' = moreZeros≥Piv pivXs pivYs' ysnXs<≈0 ysnXs≈0
normed = rec (addCons 0F 1F (from-no (0F F.≟ 1F)) -vx⁻¹vy) (idR ≈ᴹ-refl)
λ where 0F _ → refl ; 1F _ → refl ; (suc (suc ()))
normTwoRows : {xs ys : Vector F n} {px py : Fin n ⁺}
(fxs : VecPivotPos xs px) (fys : VecPivotPos ys py)
→ Σ[ xs′ ∈ Vector F n ] Σ[ ys′ ∈ Vector F n ] Σ[ px′ ∈ Fin n ⁺ ] Σ[ py′ ∈ Fin n ⁺ ]
(VecPivotPos xs′ px′ × VecPivotPos ys′ py′
× [ xs ,, ys ] ≈ⱽ [ xs′ ,, ys′ ] × NormedTwoBeforeAfter px py px′ py′)
normTwoRows {xs = xs} {ys} {px} {py} fxs fys with compare⊤⁺ px py
... | tri< _ _ _ = xs , ys , px , py , fxs , fys , idR (λ where 0F _ → refl; (suc _) _ → refl) , lift (≈∙-refl , ≈∙-refl)
... | tri> _ _ _ = ys , xs , py , px , fys , fxs ,
rec {ys = [ xs ,, ys ]} (swapOp 0F 1F (from-no (0F F.≟ 1F))) (idR (λ where 0F _ → refl; (suc _) _ → refl)) (λ where 0F _ → refl; 1F _ → refl) ,
lift (≈∙-refl , ≈∙-refl)
... | tri≈ _ ∙≈∙ _ = let vecRed@(ys′ , py′ , pys′ , px<pys , vecSpacePreserverd) = reduceVector fxs fys in
xs , ys′ , px , py′ , fxs , pys′ , vecSpacePreserverd , ≈∙-refl , px<pys
... | tri≈ _ [ ≡.refl ] _ = let vecRed@(ys′ , py′ , pys′ , px<pys , vecSpacePreserverd) = reduceVector fxs fys in
xs , ys′ , px , py′ , fxs , pys′ , vecSpacePreserverd , ≈∙-refl , px<pys
MatrixPivots : Matrix F n m → Vector (Fin m ⁺) n → Set _
MatrixPivots xs pivsXs = ∀ i → VecPivotPos (xs i) (pivsXs i)
getMatrixPivots : (xs : Matrix F n m) → Σ[ pivs ∈ Vector (Fin m ⁺) n ] MatrixPivots xs pivs
proj₁ (getMatrixPivots xs) = _
proj₂ (getMatrixPivots xs) i = proj₂ (findNonZero (xs i))
MatrixWithPivots : (n m : ℕ) → Set _
MatrixWithPivots n m = Σ[ xs ∈ Matrix F n m ] Σ[ pivs ∈ Vector (Fin m ⁺) n ] MatrixPivots xs pivs
matrixPivs : MatrixWithPivots n m → Vector (Fin m ⁺) n
matrixPivs (_ , pivs , _) = pivs
matrix→matPivs : Matrix F n m → MatrixWithPivots n m
matrix→matPivs xs = _ , _ , getMatrixPivots xs .proj₂
normMatrixTwoRows : ∀ (xs : Matrix F n m) (pivsXs : Vector (Fin m ⁺) n)
(mXsPivs : MatrixPivots xs pivsXs) i j i≢j →
Σ[ ys ∈ Matrix F n m ] Σ[ pivsYs ∈ Vector (Fin m ⁺) n ]
(MatrixPivots ys pivsYs × xs ≈ⱽ ys × BothRowsAreNormalize i j i≢j pivsXs pivsYs)
normMatrixTwoRows {n = n@(suc ℕ.zero)} {m} xs pivsXs mXsPivs 0F 0F i≢j = contradiction ≡.refl i≢j
normMatrixTwoRows {n = n@(suc (suc _))} {m} xs pivsXs mXsPivs i j i≢j = helper (normTwoRows (mXsPivs i) (mXsPivs j))
where
helper : Σ[ xs′ ∈ Vector F m ] Σ[ ys′ ∈ Vector F m ] Σ[ px′ ∈ Fin m ⁺ ] Σ[ py′ ∈ Fin m ⁺ ]
Σ[ fxs′ ∈ VecPivotPos xs′ px′ ] Σ[ fys′ ∈ VecPivotPos ys′ py′ ]
([ xs i ,, xs j ] ≈ⱽ [ xs′ ,, ys′ ] × NormedTwoBeforeAfter _ _ px′ py′)
→ Σ[ ys ∈ Matrix F n m ] Σ[ pivsYs ∈ Vector (Fin m ⁺) n ]
(MatrixPivots ys pivsYs × xs ≈ⱽ ys × BothRowsAreNormalize i j i≢j pivsXs pivsYs)
helper (xs′ , ys′ , px′ , py′ , fxs′ , fys′ , sameVecSpace , normedBef) =
_ , pivsYs , mPivots , sameVecSpaceAfter , differentialAreEqual , normedAfter
where
sameVecSpaceAfter : xs ≈ⱽ _
sameVecSpaceAfter = stepVecSpace xs [ xs′ ,, ys′ ] i j i≢j sameVecSpace
pivsYs : Vector (Fin m ⁺) n
pivsYs k with does (k F.≟ i) | does (k F.≟ j)
... | true | _ = px′
... | false | true = py′
... | false | false = pivsXs k
mPivots : MatrixPivots _ pivsYs
mPivots k with k F.≟ i | k F.≟ j
... | yes ≡.refl | yes ≡.refl = contradiction ≡.refl i≢j
... | no k≢i | no k≢j = subst (λ x → VecPivotPos x (pivsXs k)) (≡.sym
(≡.trans (updateAt-minimal _ _ _ k≢j) (updateAt-minimal _ _ _ k≢i))) (mXsPivs k)
... | no k≢i | yes ≡.refl = subst (λ x → VecPivotPos x py′) (≡.sym (updateAt-updates k _)) fys′
... | yes ≡.refl | no k≢j = subst (λ x → VecPivotPos x px′) (≡.sym
(≡.trans (updateAt-minimal _ _ _ k≢j) (updateAt-updates i _))) fxs′
differentialAreEqual : ∀ k → k ≢ i → k ≢ j → pivsXs k ≈∙ pivsYs k
differentialAreEqual k k≢i k≢j rewrite dec-false (k F.≟ i) k≢i | dec-false (k F.≟ j) k≢j = ≈∙-refl
pivsYsI≡px′ : pivsYs i ≡ px′
pivsYsI≡px′ rewrite dec-true (i F.≟ i) ≡.refl = ≡.refl
pivsYsJ≡py′ : pivsYs j ≡ py′
pivsYsJ≡py′ rewrite dec-false (j F.≟ i) (i≢j ∘ ≡.sym) | dec-true (j F.≟ j) ≡.refl = ≡.refl
normedAfter : NormedTwoBeforeAfter (pivsXs i) (pivsXs j) (pivsYs i) (pivsYs j)
normedAfter = subst (λ x → NormedTwoBeforeAfter (pivsXs i) (pivsXs j) x (pivsYs j)) (≡.sym pivsYsI≡px′)
(subst (NormedTwoBeforeAfter (pivsXs i) (pivsXs j) px′) (≡.sym pivsYsJ≡py′) normedBef)
funcNorm : FuncNormAllLines m n (MatrixWithPivots (suc n) m)
numberZeros funcNorm = matrixPivs
normProps funcNorm = finProps
f (fNormLines funcNorm i j i≢j) (xs , pivs , proof) = let
ys , pivs , pivRes , _ = normMatrixTwoRows xs pivs proof i j i≢j
in ys , pivs , pivRes
nZerosProp (fNormLines funcNorm i j i≢j) (xs , pivs , proof) = let
ys , pivs , pivRes , vecSpace , normalized = normMatrixTwoRows xs pivs proof i j i≢j
in normalized
usingNorm : MatrixWithPivots (suc n) m → Σ[ ys ∈ MatrixWithPivots (suc n) m ] AllRowsNormalized (matrixPivs ys)
usingNorm = normalizeA funcNorm
MatrixStart : MatrixWithPivots n m → Set _
MatrixStart xs@(xs′ , _) = Σ[ ys@(ys′ , _) ∈ MatrixWithPivots _ _ ] xs′ ≈ⱽ ys′
matrixPivsStart : (xs : MatrixWithPivots n m) → MatrixStart xs → Vector (Fin m ⁺) n
matrixPivsStart _ = matrixPivs ∘ proj₁
getMatrixStart : (xs : MatrixWithPivots n m) → MatrixStart xs
getMatrixStart xs = xs , ≈ⱽ-refl
funcNormSpaceVec : (xs : MatrixWithPivots (suc n) m) → FuncNormAllLines m n (MatrixStart xs)
numberZeros (funcNormSpaceVec xs) = matrixPivsStart xs
normProps (funcNormSpaceVec xs) = finProps
f (fNormLines (funcNormSpaceVec xs) i j i≢j) ((ys , pivs , proof) , xs≈ⱽys) = let
(ys , pivs , pivRes , ys≈ⱽzs , _) = normMatrixTwoRows _ pivs proof i j i≢j
in (ys , pivs , pivRes) , ≈ⱽ-trans xs≈ⱽys ys≈ⱽzs
nZerosProp (fNormLines (funcNormSpaceVec xs) i j i≢j) ((ys , pivs , proof) , xs≈ⱽys) = let
(_ , _ , _ , _ , prop) = normMatrixTwoRows _ pivs proof i j i≢j in prop
usingNormVecSpace : (xs : MatrixWithPivots (suc n) m) (xs′ : MatrixStart xs)
→ Σ[ ys ∈ MatrixStart xs ] AllRowsNormalized (matrixPivsStart xs ys)
usingNormVecSpace = normalizeA ∘ funcNormSpaceVec
normalizeMatrix : (xs : Matrix F n m) → Σ[ (ys , pivs , _) ∈ MatrixWithPivots n m ]
(AllRowsNormalized pivs × xs ≈ⱽ ys)
proj₁ (proj₁ (normalizeMatrix {ℕ.zero} xs)) () _
proj₁ (proj₂ (proj₁ (normalizeMatrix {ℕ.zero} xs))) ()
proj₂ (proj₂ (proj₁ (normalizeMatrix {ℕ.zero} xs))) ()
proj₁ (proj₂ (normalizeMatrix {ℕ.zero} xs)) () j x
proj₂ (proj₂ (normalizeMatrix {ℕ.zero} xs)) = idR (λ ())
normalizeMatrix {suc n} xs = let
mPivs = matrix→matPivs xs
res@((ys , xs≈ⱽys) , normed) = usingNormVecSpace mPivs (getMatrixStart mPivs)
in ys , normed , xs≈ⱽys
normalizeData : Op₁ $ MatrixData F n m
normalizeData = matrixFunc→Data ∘ proj₁ ∘ proj₁ ∘ normalizeMatrix ∘ matrixData→Fun
getCoeff : MatrixData F n m → List _
getCoeff xs = let
xsFunc = matrixData→Fun xs
res@(_ , _ , xs≈ⱽys) = normalizeMatrix xsFunc
in ≈ⱽ⇒listVops xs≈ⱽys