module Cubical.Algebra.Determinant.RingSum where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Data.Nat renaming ( _+_ to _+ℕ_ ; _·_ to _·ℕ_
                                       ; +-comm to +ℕ-comm
                                       ; +-assoc to +ℕ-assoc
                                       ; ·-assoc to ·ℕ-assoc)
open import Cubical.Data.Vec.Base using (_∷_; [])
open import Cubical.Foundations.Structure using (⟨_⟩)
open import Cubical.Data.FinData
open import Cubical.Algebra.Ring
open import Cubical.Algebra.Ring.Base
open import Cubical.Algebra.Ring.BigOps
open import Cubical.Algebra.Monoid.BigOp
open import Cubical.Algebra.CommRing
open import Cubical.Algebra.CommRing.Base
open import Cubical.Data.Nat.Order
open import Cubical.Tactics.CommRingSolver

module RingSum ( : Level) (P' : CommRing ) where

  R' = CommRing→Ring P'

  open RingStr (snd (CommRing→Ring P')) renaming ( is-set to isSetR)

   = Sum.∑ (CommRing→Ring P')

  R : Type 
  R =  P' 

  open  MonoidBigOp  (Ring→AddMonoid R')



  -- Compatability theorems
  ∑Compat : {n : }  (U V : FinVec R n) 
            ((i : Fin n)   U i  V i)   U   V
  ∑Compat U V f = bigOpExt f

  ∑∑Compat : {n m : }  (U V : FinVec (FinVec R m) n) 
             ((i : Fin n)  (j : Fin m)   U i j  V i j) 
               i    j  U i j))    i     j  V i j))
  ∑∑Compat U V Eq =
     i   (U i))
   ≡⟨
     ∑Compat
        i   (U i))
        i   (V i))
        i  ∑Compat (U i) (V i) (Eq i))
    
     i   (V i))
   

  -- Spliting a sum in the sum:
  ∑Split = Sum.∑Split R'

  ∑∑Split : {n m : }  (U V : Fin n  Fin m  R) 
      i    j  U i j + V i j))
    
      i    j  U i j)) +
      i    j  V i j))
  ∑∑Split U V =
      i    j  U i j + V i j))
    ≡⟨
      ∑Compat
        i    j  U i j + V i j))
        i    j  U i j) +  ( λ j   V i j))
        i  ∑Split  j  U i j) ( λ j   V i j))
     
      i    j  U i j) +   j  V i j))
    ≡⟨ ∑Split  i    j  U i j))  i    j  V i j)) 
    (  i   (U i)) +   i   (V i)))
    

  -- Distributivity of the sum
  ∑DistR = Sum.∑Mulrdist (CommRing→Ring P')

  ∑DistL = Sum.∑Mulldist (CommRing→Ring P')

  -- Sum of Zeros is Zero
  ∑Zero : {n : }  (U : FinVec R n)  ((i : Fin n)  U i  0r)   U  0r
  ∑Zero {zero} U f = refl
  ∑Zero {suc n} U f =
     U
    ≡⟨ refl 
    (U zero +   i  U (suc i)) )
    ≡⟨ cong  a  a +    i  U (suc i))) (f zero) 
    (0r +   i  U (suc i)))
    ≡⟨ +Comm 0r (  i  U (suc i))) 
      i  U (suc i)) + 0r
    ≡⟨ +IdR (  i  U (suc i))) 
      i  U (suc i))
    ≡⟨ ∑Zero {n} ((λ i  U (suc i)))  i  f (suc i))  
    0r 

  -- Summs are commutative
  ∑Comm : {n m : }  (U : FinVec (FinVec R m) n) 
      i    j  U i j ))    j    i  U i j))
  ∑Comm {zero} {zero} U = refl
  ∑Comm {zero} {m} U =
    0r
    ≡⟨ sym (∑Zero  (j : Fin m)  0r)  (j : Fin m)  refl)) 
      (j : Fin m)  0r)
    ≡⟨ ∑Compat  j  0r)  j    i  U i j ))  j  refl)  
    ( ( λ j    i  U i j )))
    
  ∑Comm {n} {zero} U =
      (i : Fin n)  0r)
    ≡⟨ ∑Zero (  (i : Fin n)  0r)) (  i  refl)) 
    0r
    
  ∑Comm {suc n} {suc m} U =
      i   (U i))
    ≡⟨ refl 
    (   i  (U i zero  +  λ j  (U i (suc j)))) )
    ≡⟨ bigOpSplit +Comm  i  U i zero)  i   λ j  (U i (suc j))) 
    (  i  (U i zero)) +  λ i  ( λ j  (U i (suc j))))
    ≡⟨ cong  a    i  (U i zero)) + a) (∑Comm λ i  ( λ j  (U i (suc j) ))) 
    (  i  U i zero) +   j    i  U i (suc j))))
    ≡⟨ refl 
      j    i  U i j))
    

  -- Indikator function:  ind> i j = 1r if i>j and ind> i j = 0r else
  ind> : (i j : )  R
  ind> zero j = 0r
  ind> (suc i) zero = 1r
  ind> (suc i) (suc j) = ind> i j

  ind>prop : {n m : }  (A B : FinVec (FinVec R m) n) 
             ((i : Fin n)  (j : Fin m)  (toℕ j) <' (toℕ i)  A i j  B i j) 
             (i : Fin n)  (j : Fin m) 
             (ind> (toℕ i) (toℕ j) · A i j)  (ind> (toℕ i) (toℕ j) · B i j)
  ind>prop {m = suc m} A B f zero j = solve! P'
  ind>prop {m = suc m} A B f (suc i) zero =
    cong
       a  1r · a)
      (f (suc i) zero (s≤s z≤))
  ind>prop {m = suc m} A B f (suc i) (suc j) =
    ind>prop
       i j  A (suc i) (suc j))
       i j  B (suc i) (suc j))
       i₁ j₁ le  f (suc i₁) (suc j₁)
      (s≤s le))
      i
      j

  ind>anti :  {n m : }  (A B : FinVec (FinVec R m) n) 
              ((i : Fin n) (j : Fin m)  (toℕ i) ≤' (toℕ j)  A i j  B i j) 
              (i : Fin n)  (j : Fin m) 
              (1r + (- ind> (toℕ i) (toℕ j))) · A i j  (1r + - (ind> (toℕ i) (toℕ j))) · B i j
  ind>anti {m = suc m} A B f zero j =
    cong
     a  (1r + - 0r) · a)
    (f zero j z≤)
  ind>anti {m = suc m} A B f (suc i) zero = solve! P'
  ind>anti {m = suc m} A B f (suc i) (suc j) =
    ind>anti
       i j  A (suc i) (suc j))
       i j  B (suc i) (suc j))
       i₁ j₁ le  f (suc i₁) (suc j₁) (s≤s le)) i j

  ind>Neg : (i j : )  (1r + - ind> (suc i) j)  ind> j i
  ind>Neg i zero = +InvR 1r
  ind>Neg zero (suc j) = solve! P'
  ind>Neg (suc i) (suc j) = ind>Neg i j

  ind>Suc : (i j : )  ind> (suc i) j  (1r + - ind> j i)
  ind>Suc i zero = solve! P'
  ind>Suc zero (suc j) = solve! P'
  ind>Suc (suc i) (suc j) = ind>Suc i j

  --Index Shift--
  ∑∑ShiftSuc : {n : }  (A : Fin (suc n)  Fin n  R) 
      (i : Fin (suc n))    ( λ j  ind> (toℕ i) (toℕ j)       · A i j))
    
      (i : Fin n)          ( λ j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j))
  ∑∑ShiftSuc {zero} A = ∑Zero {one}  j  0r)  j  refl)
  ∑∑ShiftSuc {suc n} A =
     {suc (suc n)}
       i 
          j  ind> (toℕ i) (toℕ j) · A i j))
    ≡⟨ refl 
     {suc n}
       j  ind> zero (toℕ j) · A zero j)
    +   i 
          j 
          ind> (toℕ (suc i)) (toℕ j) · A (suc i) j))
    ≡⟨
      cong
        a  a +   i 
                      j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j)))
       (∑Compat
          j  ind> zero (toℕ j) · A zero j)
          j  0r)
          j  solve! P'))
     
     {suc n}  j  0r) +
      i    j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j))
    ≡⟨
      cong
       a  a +   i    j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j)))
      (∑Zero {suc n}  j  0r)  j  refl)) 
    0r +   i    j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j))
    ≡⟨
      +Comm
       0r
       (  i    j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j)))
     
      i    j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j)) + 0r
    ≡⟨
      +IdR
        (  i    j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j)))
     
      i    j  ind> (toℕ (suc i)) (toℕ j) · A (suc i) j))
    

  ∑∑ShiftWeak : {n : }  (A : Fin (suc n)  Fin n  R) 
      (i : Fin (suc n))   ( λ j  (1r + - ind> (toℕ i) (toℕ j)) · A i j))
    
      (i : Fin n) 
          ( λ j 
             (1r + - ind> (toℕ (weakenFin i)) (toℕ j)) · A (weakenFin i) j))
  ∑∑ShiftWeak {zero} A =
    ∑Zero {one}
       i   ( λ j  (1r + - ind> (toℕ i) (toℕ j)) · A i j))
       i  refl)
  ∑∑ShiftWeak {suc n} A =
    (  j  (1r + - ind> zero (toℕ j)) · A zero j) +
      
       i    j  (1r + - ind> (toℕ (suc i)) (toℕ j)) · A (suc i) j)))
    ≡⟨
      cong
         a     j  (1r + - ind> zero (toℕ j)) · A zero j) + a)
        (∑Compat
           i    j  (1r + - ind> (toℕ (suc i)) (toℕ j)) · A (suc i) j))
           i 
            (1r + - ind> (toℕ (suc i)) zero) · A (suc i) zero +
              j  (1r + - ind> (toℕ (suc i)) (toℕ (suc j))) · A (suc i) (suc j)))
           i  refl))
      
      j  (1r + - ind> zero (toℕ j)) · A zero j) +
      i 
         (1r + - ind> (toℕ (suc i)) zero) · A (suc i) zero +
             j 
             (1r + - ind> (toℕ (suc i)) (toℕ (suc j))) · A (suc i) (suc j)))
    ≡⟨
      cong
       a     j  (1r + - ind> zero (toℕ j)) · A zero j) + a)
      (∑Split
         i 
          (1r + - ind> (toℕ (suc i)) zero) · A (suc i) zero)
           i 
              j 
                 (1r + - ind> (toℕ (suc i)) (toℕ (suc j)))
                 · A (suc i) (suc j))))
     
    (  j  (1r + - ind> zero (toℕ j)) · A zero j) +
      (  i  (1r + - ind> (toℕ (suc i)) zero) · A (suc i) zero) +
       
        i 
            j  (1r + - ind> (toℕ i) (toℕ j)) · A (suc i) (suc j)))))
    ≡⟨
      cong
        a 
           j  (1r + - ind> zero (toℕ j)) · A zero j) +
         (  i 
           (1r + - ind> (toℕ (suc i)) zero) ·
           A (suc i) zero) + a))
       (∑∑ShiftWeak  i j   A (suc i) (suc j)))
     
    (  j  (1r + - ind> zero (toℕ j)) · A zero j) +
      (  i  (1r + - ind> (toℕ (suc i)) zero) · A (suc i) zero) +
       
        i 
          
           j 
             (1r + - ind> (toℕ (suc (weakenFin i))) (toℕ (suc j)))
             · A (suc (weakenFin i)) (suc j)))))
    ≡⟨
      cong
       a 
        (  j  (1r + - ind> zero (toℕ j)) · A zero j) +
        (a +
           i 
             j 
             (1r + - ind> (toℕ (suc (weakenFin i))) (toℕ (suc j)))
             · A (suc (weakenFin i)) (suc j))))))
      (
          i  (1r + - ind> (toℕ (suc i)) zero) · A (suc i) zero)
        ≡⟨ refl 
          i 
          (1r + - 1r) · A (suc i) zero)
        ≡⟨ ∑Compat (
           λ i  (1r + - 1r) · A (suc i) zero)
            i  0r)
            i  solve! P')
         
          (i : Fin (suc n))  0r)
        ≡⟨
          ∑Zero
             (i : Fin (suc n))  0r)
             i  refl)
         
        0r
        ≡⟨ sym (∑Zero  (i : Fin n)  0r)  i  refl)) 
          (i : Fin  n)  0r)
        ≡⟨ ∑Compat
            (i : Fin  n)  0r)
            i  (1r + - 1r) · A (suc (weakenFin i)) zero)
            i  solve! P')
         
          i  (1r + - 1r) · A (suc (weakenFin i)) zero)
      )
    (  j  (1r + - ind> zero (toℕ j)) · A zero j) +
      (
        i 
          (1r + - ind> (toℕ (suc (weakenFin i))) zero) ·
          A (suc (weakenFin i)) zero)
       +
       
        i 
          
           j 
             (1r + - ind> (toℕ (suc (weakenFin i))) (toℕ (suc j))) ·
             A (suc (weakenFin i)) (suc j)))))
    ≡⟨
      cong
       a    j  (1r + - ind> zero (toℕ j)) · A zero j) + a)
      (sym
        (∑Split
         i 
          (1r + - ind> (toℕ (suc (weakenFin i))) zero) ·
          A (suc (weakenFin i)) zero)
         i    j 
                 (1r + - ind> (toℕ (suc (weakenFin i))) (toℕ (suc j))) ·
                 A (suc (weakenFin i)) (suc j)))))
     
      j  (1r + - ind> zero (toℕ j)) · A zero j) +
       
        i 
          
           j 
             (1r + - ind> (toℕ (suc (weakenFin i))) (toℕ j)) ·
             A (suc (weakenFin i)) j))