(* ========================================================================= *)
(* The Cayley-Hamilton theorem (for real matrices).                          *)
(* ========================================================================= *)
needs "Multivariate/complexes.ml";;
(* ------------------------------------------------------------------------- *)
(* Powers of a square matrix (mpow) and sums of matrices (msum).             *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("mpow",(24,"left"));;
let mpow = define
  `(!A:real^N^N. A mpow 0 = (mat 1 :real^N^N)) /\
   (!A:real^N^N n. A mpow (SUC n) = A ** A mpow n)`;;
 
let MSUM_CLAUSES = prove
 (`(!(f:A->real^N^M). msum {} f = mat 0) /\
   (!x (f:A->real^N^M) s.
        
FINITE(s)
        ==> (msum (x 
INSERT s) f =
             if x 
IN s then msum s f else f(x) + msum s f))`,
 
 
let MSUM_EQ = prove
 (`!f g s. (!x. x 
IN s ==> (f x = g x)) ==> (msum s f = msum s g)`,
 
 
let MSUM_COMPONENT = prove
 (`!f:A->real^N^M i j s.
        1 <= i /\ i <= dimindex(:M) /\
        1 <= j /\ j <= dimindex(:N) /\
        
FINITE s
        ==> (msum s f)$i$j = sum s (\a. f(a)$i$j)`,
 
 
let MSUM_CLAUSES_NUMSEG = prove
 (`(!m. msum(m..0) f = if m = 0 then f(0) else mat 0) /\
   (!m n. msum(m..SUC n) f = if m <= SUC n then msum(m..n) f + f(SUC n)
                             else msum(m..n) f)`,
 
 
(* ------------------------------------------------------------------------- *)
(* The main lemma underlying the proof.                                      *)
(* ------------------------------------------------------------------------- *)
let MATRIC_POLY_LEMMA = prove
 (`!(A:real^N^N) B (C:real^N^N) n.
        (!x. msum (0..n) (\i. (x pow i) %% B i) ** (A - x %% mat 1) = C)
        ==> C = mat 0`,
 
 
(* ------------------------------------------------------------------------- *)
(* Show that cofactor and determinant are n-1 and n degree polynomials.      *)
(* ------------------------------------------------------------------------- *)
let POLYFUN_N_ADD = prove
 (`!f g. (?b. !x. f(x) = sum(0..n) (\i. b i * x pow i)) /\
         (?c. !x. g(x) = sum(0..n) (\i. c i * x pow i))
         ==> ?d. !x. f(x) + g(x) = sum(0..n) (\i. d i * x pow i)`,
 
 
let POLYFUN_N_CMUL = prove
 (`!f c. (?b. !x. f(x) = sum(0..n) (\i. b i * x pow i))
         ==> ?b. !x. c * f(x) = sum(0..n) (\i. b i * x pow i)`,
  REPEAT STRIP_TAC THEN
  EXISTS_TAC `\i. c * (b:num->real) i` THEN
  ASM_REWRITE_TAC[
SUM_LMUL; GSYM REAL_MUL_ASSOC]);;
 
 
let POLYFUN_N_SUM = prove
 (`!f s. 
FINITE s /\
         (!a. a 
IN s ==> ?b. !x. f x a = sum(0..n) (\i. b i * x pow i))
         ==> ?b. !x. sum s (f x) = sum(0..n) (\i. b i * x pow i)`,
 
 
let COFACTOR_ENTRY_AS_POLYFUN = prove
 (`!A:real^N^N x i j.
        1 <= i /\ i <= dimindex(:N) /\
        1 <= j /\ j <= dimindex(:N)
        ==> ?c. !x. cofactor(A - x %% mat 1)$i$j =
                    sum(0..dimindex(:N)-1) (\i. c(i) * x pow i)`,
 
 
(* ------------------------------------------------------------------------- *)
(* Hence define characteristic polynomial coefficients.                      *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Now the Cayley-Hamilton proof.                                            *)
(* ------------------------------------------------------------------------- *)
let MATRIC_POWER_DIFFERENCE = prove
 (`!A:real^N^N x n.
        A mpow (SUC n) - x pow (SUC n) %% mat 1 =
        msum (0..n) (\i. x pow i %% A mpow (n - i)) ** (A - x %% mat 1)`,