2-2 Matrices on nat

We define the monoid of 2-2 matrices, the coefficient of which are natural numbers. The operation is matrix multiplication, and the unity is the diagonal matrix Id2=(1,0,0,1). The construction of the monoid matrix is done as usual:
Record Mat2:Set :=
  mat2{
      M11:nat;
      M12:nat;
      M21:nat;
      M22:nat}.

Definition Id2:=(mat2 (S O) O O (S O)).   
Definition Mat_mult:=[M,M':Mat2]
                      (mat2 (plus (mult (M11 M) (M11 M'))
                                  (mult (M12 M) (M21 M'))  )
                       etc.

Lemma matrix:(monoid Mat2).
Proof.
 Realizer (mkmonoid Mat2 Id2 Mat_mult).
 Program_all.
 ...
In this release, we choosed to skip the demonstration of associativity of matrix multiplication, proceeding by intimidation:
Well_Known Mat_assoc: (M,M',M'':Mat2)
                       (Mat_mult M (Mat_mult M' M''))=
                       (Mat_mult (Mat_mult M M') M'').

Fibonacci numbers

We present a well-known application of computing with 2-2 matrices: If we define Fibonacci numbers as usual:
Fixpoint Fib[n:nat]:nat :=
    <nat>Case n of
      (* O *) (S O)
      (* S p *) [p:nat]
           <nat>Case p of
               (* O *) (S O)
               (* S q *)
                  [q:nat](plus (Fib q) (Fib p))
           end
     end.
Let us define some matrix:
Definition fib_mat:=(mat2 (S O) (S O) (S O) O).
We have to prove that the (1,1) coefficient of the n-th power of fib_mat is (Fib n), i.e.
Lemma fib_computation:(n:nat)(lt O n)->
         (Fib n)=
         (M11 (power Mat2 matrix fib_mat n)).

An auxiliary function

The natural way to prove fib_computation seems to use a lemma:
Lemma fib_n:(n:nat) (lt O n)->
                    (power Mat2 matrix fib_mat n)=
                    (mat2 (Fib n)
                          (Fib (pred n))
                          (Fib (pred n))
                          (Fib (pred (pred n)))).
The problem comes from the fact that, for n=1, the first power of fib_mat should contain a zero, which is not a Fibonacci number. Since we cannot extend the definition by some equality:
(Fib -1)=O
we build an auxiliary function such that
(shift_Fib O)
(shift_Fib (S n))=(Fib n)
and prove:
Lemma fib_n:(n:nat)
             (power Mat2 matrix fib_mat (S n))=
                   (mat2 (shift_Fib (S (S n)))
                         (shift_Fib (S n))
                         (shift_Fib (S n))
                         (shift_Fib n)).

A demo in CaML

In the file main, we derive a program for computing fibonaci numbers:
Lemma fibonacci:(n:nat){q:nat | q=(Fib n)}.


Realizer [n:nat]
    <nat>if (zerop n)
            then (S O)
            else (M11 
                  (addchains dic n Mat2 matrix fib_mat)).
Program_all.
...
We can test it as usual:
#load "Demo.ml";;
##open "Demo";;

#fibonacci;;
- : int -> int = <fun>

#fibonacci 20;;
- : int = 10946

#fibonacci 0;;
- : int = 1

#fibonacci 10;;
- : int = 89