# TheoryBodies

body:
  top: THEORY

  BEGIN

   IMPORTING
      matrices,
      matrix_inv,
      matrix_det,
      query_coeff,
      matrix_props,
      matrix_diag,
      tensor_product,
      matrix_upper_triang

  END top


body:
  matrices: THEORY


  BEGIN

    IMPORTING structures@listn,reals@sigma_nat,
  	    structures@array2list,
  	    reals@sigma_swap[nat]
  	    


    % This does now force a matrix to have the same
    % number of entries in each row. It just assumes that
    % the longest row is the total number of columns
    % and that any rows of less length have all
    % entries zero after their lengths.

    Matrix: TYPE = list[list[real]]

    MatrixMN(m,n:nat): TYPE = {M:Matrix |
      length(M)=m AND FORALL (i:below(length(M))):
        length(nth(M,i)) = n}

    FullMatrix: TYPE = {M:Matrix |
      null?(M) OR
      FORALL (i,j:below(length(M))):
        length(nth(M,i)) = length(nth(M,j))}

    SM,SM1,SM2: VAR FullMatrix

    Vector: TYPE = list[real]

    r: VAR real

    VectorN(n:nat): TYPE = listn[real](n)

    zero(n:nat): VectorN(n) =
      array2list[real](n)(LAMBDA (p:nat): 0)

    M,N,A,B: VAR Matrix

    v,v1,v2: VAR Vector

    i,j : VAR nat

    m,n : VAR nat

    pn,pm : VAR posnat

    F,G: VAR [[nat,nat]->real]

    MEx: Matrix = (: (:1,2:),(:3,4,5:),(:6:) :)

    % equivalence of nth and lenth functions

    length_matrix_eq: LEMMA 
      FORALL (nn: nat, LL: list[listn[real](nn)]):
        length[list[real]](LL) = length[listn[real](nn)](LL)

    nth_matrix_eq : LEMMA
     FORALL (nn: nat, LL: list[listn[real](nn)],i:below[length[list[real]](LL)]):
       nth[listn[real](nn)](LL, i) = nth[list[real]](LL, i)

    length_matrix_equiv: LEMMA 
      FORALL (nn: nat, LL: list[listn[real](nn)]):
        length[list[real]](LL) = length[listn[real](nn)](LL)

    length_matrix_nth: LEMMA 
      FORALL (nn: nat, LL: list[listn[real](nn)],i:below[length[list[real]](LL)]):
        length[real](nth[list[real]](LL,i)) = nn

    matrix_listn_nth: LEMMA
      FORALL (nn: nat, LL: list[listn[real](nn)],i:below[length[list[real]](LL)],
      	   j:below[length[real](nth[listn[real](nn)](LL,i))]):
        nth[real](nth[listn[real](nn)](LL,i),j)=
        nth[real](nth[list[real]](LL,i),j)

    access(v1)(i): real =
      IF i<length(v1) THEN nth(v1,i)
      ELSE 0 ENDIF

    rows(M): nat = length(M)

    length_rows: LEMMA length(M) = rows(M)

    columns(M): RECURSIVE {c:nat|
      (FORALL (i:below(length(M))):
        length(nth(M,i))<=c) AND 
      (null?(M) AND c=0 OR EXISTS (i:below(length(M))):
        length(nth(M,i))=c)} =
      IF null?(M) THEN 0
      ELSE max(length(car(M)),columns(cdr(M))) ENDIF
      MEASURE length(M)

    row(M)(i): Vector =
      IF i>=length(M) THEN null[real]
      ELSE nth(M,i) ENDIF

    col(M)(i): RECURSIVE VectorN(rows(M)) =
      IF null?(M) THEN null[real]
      ELSE cons(access(car(M))(i),col(cdr(M))(i)) ENDIF
      MEASURE length(M)

    col_def: LEMMA
      length(col(M)(i)) = rows(M) AND
      FORALL (j:below(rows(M))):
        nth(col(M)(i),j) = 
          IF i < length(nth(M,j)) THEN nth(nth(M,j),i)
  	ELSE 0 ENDIF

    col_zero: LEMMA i>=columns(M) IMPLIES
      col(M)(i) = zero(rows(M))

    access_zero: LEMMA access(zero(n))(i)=0

    nonempty?(M): bool =
      rows(M)>0 AND columns(M)>0

    Mp,Np: VAR (nonempty?)

    entry(M)(i,j):real =
      access(row(M)(i))(j)

    entry_test: LEMMA
      entry((: (: 1, 2, 0 :), (: 3, 4, 5 :), (: 6, 0, 0 :) :))(1,1)=4

    access_row: LEMMA access(row(M)(i))(j) = entry(M)(i,j)

    access_col: LEMMA access(col(M)(j))(i) = entry(M)(i,j)

    coltest: LEMMA col(MEx)(1) = (: 2,4,0 :)

    full_matrix_columns: LEMMA (null?(SM) AND columns(SM)=0) OR
      columns(SM) = length(car(SM))

    rows_mn: LEMMA FORALL (M:MatrixMN(m,n)): rows(M)=m

    columns_mn: LEMMA FORALL (pm:posnat,n:nat,M:MatrixMN(pm,n)): columns(M)=n

    length_row: LEMMA i<length(SM) IMPLIES length(row(SM)(i))=columns(SM)

    length_col: LEMMA length(col(SM)(i))=rows(SM)

    PosFullMatrix: TYPE = {SM|rows(SM)>0 AND columns(SM)>0}

    Square: TYPE = {D:PosFullMatrix | rows(D) = columns(D)}

    SQ,IQ,GQ: VAR Square

    SquareMatrix(pn): TYPE = {SQ | rows(SQ)=pn}

    PFM,D1,D2: VAR PosFullMatrix

    columns_0_entry: LEMMA columns(M)=0 IMPLIES entry(M)(i,j)=0

    rows_0_entry: LEMMA rows(M)=0 IMPLIES entry(M)(i,j)=0

    entry_eq_0: LEMMA i>=rows(M) OR j>=columns(M) IMPLIES entry(M)(i,j)=0

    % full_matrix_size: JUDGEMENT
    %   SM HAS_TYPE MatrixMN(rows(SM),columns(SM))
    
    % Similarly for matrices, by assuming anything
    % greater than the length is zero, we can do
    % operations on vectors of different lengths

    add(v1,v2): RECURSIVE VectorN(max(length(v1),length(v2))) =
      IF null?(v1) THEN v2
      ELSIF null?(v2) THEN v1
      ELSE cons(car(v1)+car(v2),add(cdr(v1),cdr(v2))) ENDIF
      MEASURE length(v1)+length(v2)

    scal(r,v2): RECURSIVE VectorN(length(v2)) =
      IF null?(v2) THEN v2
      ELSE cons(r*car(v2),scal(r,cdr(v2))) ENDIF
      MEASURE length(v2)

    sub(v1,v2): VectorN(max(length(v1),length(v2))) =
      add(v1,scal(-1,v2))

    dot(v1,v2): RECURSIVE real =
      IF null?(v1) OR null?(v2) THEN 0
      ELSE car(v1)*car(v2)+dot(cdr(v1),cdr(v2)) ENDIF
      MEASURE length(v1)+length(v2);

    super_dot(v1,v2): RECURSIVE {rr:real|rr=dot(v1,v2)} =
      IF null?(v1) OR null?(v2) THEN 0
      ELSIF car(v1)=0 THEN dot(cdr(v1),cdr(v2))
      ELSE car(v1)*car(v2)+dot(cdr(v1),cdr(v2)) ENDIF
      MEASURE length(v1)+length(v2);

    super_duper_dot(FF,GG:[nat->real],kz:nat): RECURSIVE real =
      IF kz = 0 THEN (IF FF(0)=0 THEN 0 ELSE FF(0)*GG(0) ENDIF) 
      ELSE super_duper_dot(FF,GG,kz-1)+(IF FF(kz)=0 THEN 0 ELSE FF(kz)*GG(kz) ENDIF)
      ENDIF MEASURE kz;

    +(v1,v2): VectorN(max(length(v1),length(v2))) = add(v1,v2);

    *(r,v2): VectorN(length(v2)) = scal(r,v2);

    -(v1,v2): VectorN(max(length(v1),length(v2))) = sub(v1,v2);

    *(v1,v2): real = dot(v1,v2);

    access_sum: LEMMA access(v1+v2)(i)=access(v1)(i)+access(v2)(i)

    access_scal: LEMMA access(r*v)(i)=r*access(v)(i)

    vect_scal_1: LEMMA 1*v = v

    dot_eq_sigma: LEMMA
      dot(v1,v2) = sigma(0,min(length(v1)-1,length(v2)-1),LAMBDA (k:nat):
        access(v1)(k)*access(v2)(k))

    dot_zero_right: LEMMA
      v*zero(n)=0

    dot_commutes: LEMMA v1*v2 = v2*v1

    dot_zero_left: LEMMA
      zero(n)*v=0

    length_add_vect: LEMMA length(v1+v2)=max(length(v1),length(v2))

    length_add_vect_same: LEMMA length(v1)=length(v2) IMPLIES
      length(v1+v2) = length(v1)

    length_scal_vect: LEMMA length(r*v1)=length(v1)


    % Form a matrix from an array F:[[nat,nat]->real]

    form_matrix(F:[[nat,nat]->real],m,n:nat):
      {M:MatrixMN(m,n)| FORALL (i:below(m),j:below(n)):
        nth(row(M)(i),j) = F(i,j)} =
      array2list[listn[real](n)](m)(LAMBDA (k:nat): 
        array2list[real](n)(LAMBDA (p:nat): F(k,p)))

    columns_form_matrix: LEMMA FORALL (F:[[nat,nat]->real]):
      m=0 OR columns(form_matrix(F,m,n)) = n

    rows_form_matrix: LEMMA FORALL (F:[[nat,nat]->real]):
      rows(form_matrix(F,m,n)) = m

    form_matrix_empty: LEMMA FORALL (m, n: nat, F:[[nat, nat]->real]):
          m=0  IMPLIES null?(form_matrix(F, m, n)) 

    FEx(i,j:nat): real =
    		IF i=0 THEN (IF j=0 THEN 1 ELSIF j=1 THEN 2 ELSE 0 ENDIF)
    		ELSIF i=1 THEN IF j=0 THEN 3 ELSIF j=1 THEN 4 ELSE 5 ENDIF
    		ELSIF i=2 AND j=0 THEN 6 ELSE 0 ENDIF

    form_matrix_test1: LEMMA form_matrix(FEx,3,3) =  
      (: (: 1, 2, 0 :), (: 3, 4, 5 :), (: 6, 0, 0 :) :)

    full_matrix_eq: LEMMA
      SM1=SM2 IFF (rows(SM1)=rows(SM2) AND columns(SM1)=columns(SM2)
        AND FORALL (i:below(rows(SM1)),j:below(columns(SM1))):
        	    entry(SM1)(i,j)=entry(SM2)(i,j))

    matrix2array: LEMMA
      SM = form_matrix(entry(SM),rows(SM),columns(SM))

    entry_form_matrix: LEMMA
      entry(form_matrix(F,m,n))(i,j) = 
        IF i<m AND j<n THEN F(i,j) ELSE 0 ENDIF

    entry_form_matrix2: LEMMA
      i<m AND j<n IMPLIES
      entry(form_matrix(F,m,n))(i,j) = F(i,j)

    form_matrix_eq: LEMMA
      form_matrix(F,m,n)=form_matrix(G,m,n) IFF
      FORALL (i,j): i<m AND j<n IMPLIES F(i,j)=G(i,j)

    matrix_reduce_prop: LEMMA FORALL (P:[Matrix->bool]):
      (FORALL (F): P(form_matrix(F,m,n))) IMPLIES
      (FORALL (M:MatrixMN(m,n)): P(M))

    % matrix_reduce_prop2: LEMMA FORALL (P:[[Matrix,Matrix]->bool]):
    %   (FORALL (F,G): P(form_matrix(F,m,n),form_matrix(G,k,n))) IMPLIES
    %   (FORALL (M:MatrixMN(m,n)): P(M))

    % Matrix Multiplication

    mult(M,N): {A: MatrixMN(rows(M),columns(N))|
      FORALL (i,j): entry(A)(i,j) = row(M)(i)*col(N)(j)}  =
      form_matrix(LAMBDA (i,j:nat): dot(row(M)(i),col(N)(j)),rows(M),columns(N));

    *(M,N): {A: MatrixMN(rows(M),columns(N))|
      FORALL (i,j): entry(A)(i,j) = row(M)(i)*col(N)(j)} = mult(M,N);

    mult_full: JUDGEMENT
      *(M,N) HAS_TYPE FullMatrix

    mult_null_left: LEMMA
      null[list[real]]*M = null[list[real]]

    mult_null_right: LEMMA
      LET N = M*null[list[real]] IN
        length(N) = length(M) AND
         FORALL (i:below(length(N))): nth(N,i)=null[real]

    columns_mult: LEMMA (NOT null?(M)) IMPLIES
      columns(M*N) = columns(N)

    rows_mult: LEMMA
      rows(M*N) = rows(M)

    columns_append: LEMMA
      columns(append(M,N)) = max(columns(M),columns(N))

    append_mult: LEMMA (NOT null?(M)) IMPLIES
      append(M,N)*A=append(M*A,N*A)

    matrix_mult_assoc: LEMMA (NOT null?(N)) IMPLIES
      (M*N)*A = M*(N*A)

    entry_mult: LEMMA
      entry(M*N)(i,j) = IF i<rows(M) AND j<columns(N) THEN
        row(M)(i)*col(N)(j) ELSE 0 ENDIF

    form_matrix_mult: LEMMA 
      FORALL (F,G:[[nat,nat]->real],k,m,n:nat):
        m>0 AND k>0 IMPLIES
        form_matrix(F,k,m)*form_matrix(G,m,n) =
        form_matrix(LAMBDA (i,j:nat): IF i>k OR j>n THEN 0
        			 ELSE sigma(0,m-1,LAMBDA (d:nat): F(i,d)*G(d,j)) ENDIF,k,n)

    % Matrix Addition

    add(M,N): {A: MatrixMN(max(rows(M),rows(N)),max(columns(M),columns(N)))|
      FORALL (i,j): entry(A)(i,j) = entry(M)(i,j)+entry(N)(i,j)}  =
      form_matrix(LAMBDA (i,j:nat): entry(M)(i,j)+entry(N)(i,j),
        max(rows(M),rows(N)),max(columns(M),columns(N)));

    +(M,N): {A: MatrixMN(max(rows(M),rows(N)),max(columns(M),columns(N)))|
      FORALL (i,j): entry(A)(i,j) = entry(M)(i,j)+entry(N)(i,j)} =
        add(M,N);

    columns_add: LEMMA
      columns(M+N) = max(columns(M),columns(N))

    rows_add: LEMMA
      rows(M+N) = max(rows(M),rows(N))

    matrix_add_assoc: LEMMA
      (M+N)+A = M+(N+A)

    matrix_add_comm: LEMMA 
       M+N = N+M

    scal(r,M): {A: MatrixMN(rows(M),columns(M))|
      FORALL (i,j): entry(A)(i,j) = r*entry(M)(i,j)}  =
      form_matrix(LAMBDA (i,j:nat): r*entry(M)(i,j),
        rows(M),columns(M));

    *(r,M): {A: MatrixMN(rows(M),columns(M))|
      FORALL (i,j): entry(A)(i,j) = r*entry(M)(i,j)}  =
      scal(r,M);

    columns_scal: LEMMA columns(r*M)=columns(M)

    rows_scal: LEMMA rows(r*M)=rows(M)

    sub(M,N): {A: MatrixMN(max(rows(M),rows(N)),max(columns(M),columns(N)))|
      FORALL (i,j): entry(A)(i,j) = entry(M)(i,j)-entry(N)(i,j)}  =
      M+(-1)*N;

    -(M,N): {A: MatrixMN(max(rows(M),rows(N)),max(columns(M),columns(N)))|
      FORALL (i,j): entry(A)(i,j) = entry(M)(i,j)-entry(N)(i,j)}  =
      sub(M,N);
        
    rows_sub: LEMMA rows(M-N)=max(rows(M),rows(N))

    columns_sub: LEMMA columns(M-N)=max(columns(M),columns(N))

    matrix_sub_test: LEMMA
      (: (: 1,2,3 :), (: 4,5,6 :), (: 7,8,9 :) :)-
      (: (: 9,8,7 :), (: 6,5,4 :), (: 3,2,1 :) :) =
      (: (: -8,-6,-4 :), (: -2,0,2 :), (: 4,6,8 :) :)

    % Identity Matrix

    Id(pm): {M: SquareMatrix(pm) |
      (FORALL (i,j): entry(M)(i,j) =
        IF i<pm AND i=j THEN 1 ELSE 0 ENDIF) AND
      (FORALL (pn:posnat,N:MatrixMN(pm,pn)): M*N = N) AND
      (FORALL (pn:posnat,N:MatrixMN(pn,pm)): N*M = N)} =
      form_matrix(LAMBDA (i,j:nat): IF i=j THEN 1 ELSE 0 ENDIF,pm,pm)

    mult_Id_left: LEMMA rows(D1) = pm IMPLIES Id(pm)*D1 = D1

    mult_Id_right: LEMMA columns(D1) = pm IMPLIES D1*Id(pm) = D1

    rows_Id: LEMMA rows(Id(pm)) = pm

    columns_Id: LEMMA columns(Id(pm)) = pm

    entry_Id: LEMMA entry(Id(pm))(i,j) =
      IF i>=pm OR j>=pm OR i/=j THEN 0 ELSE 1 ENDIF

    transpose(PFM): PosFullMatrix =
      form_matrix(LAMBDA (i,j:nat): entry(PFM)(j,i),columns(PFM),rows(PFM))

    rows_transpose: LEMMA rows(transpose(PFM))=columns(PFM)

    columns_transpose: LEMMA columns(transpose(PFM))=rows(PFM)

    entry_transpose: LEMMA entry(transpose(PFM))(i,j)=entry(PFM)(j,i)

    transpose_transpose: LEMMA transpose(transpose(PFM))=PFM

    transpose_mult: LEMMA columns(D1)=rows(D2) IMPLIES
      transpose(D1*D2)=transpose(D2)*transpose(D1)

    form_matrix_square: JUDGEMENT
      form_matrix(F,i,j) HAS_TYPE FullMatrix

    transpose_Id: LEMMA transpose(Id(pm))=Id(pm)

    vect2matrix(v|length(v)>0): {PFM | rows(PFM)=1 AND columns(PFM)=length(v)} =
      form_matrix(LAMBDA (i,j): IF i=0 THEN access(v)(j) ELSE 0 ENDIF,1,length(v))

    vect2matrix_eq: LEMMA length(v1)>0 AND length(v2)>0 AND
      vect2matrix(v1)=vect2matrix(v2) IMPLIES
      v1=v2

  END matrices

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 8, column 5) for  reals@sigma_swap[nat]
      % generated from assumption sigma_swap.connected_domain
  IMP_sigma_swap_TCC1: OBLIGATION
    (FORALL (x, y: nat), (z: integer): x <= z AND z <= y IMPLIES z >= 0);

  % Subtype TCC generated (at line 62, column 30) for  i
      % expected type  below[length[listn[real](nn)](LL)]
  nth_matrix_eq_TCC1: OBLIGATION
    FORALL (nn: nat, LL: list[listn[real](nn)],
            i: below[length[list[real]](LL)]):
      i < length[listn[real](nn)](LL);

  % Subtype TCC generated (at line 76, column 38) for  j
      % expected type  below[length(nth[list[real]](LL, i))]
  matrix_listn_nth_TCC1: OBLIGATION
    FORALL (nn: nat, LL: list[listn[real](nn)],
            i: below[length[list[real]](LL)],
            j: below[length[real](nth[listn[real](nn)](LL, i))]):
      j < length[real](nth[list[real]](LL, i));

  % Subtype TCC generated (at line 91, column 21) for  0
      % expected type  {c: nat |
                     %          (FORALL (i: below(length(M))):
                     %             length(nth(M, i)) <= c)
                     %           AND
                     %           (null?(M) AND c = 0 OR
                     %             (EXISTS (i: below(length(M))):
                     %                length(nth(M, i)) = c))}
  columns_TCC1: OBLIGATION
    FORALL (M: Matrix):
      null?(M) IMPLIES
       (FORALL (i: below(length[list[real]](M))):
          length[real](nth[list[real]](M, i)) <= 0)
        AND
        (null?[list[real]](M) OR
          (EXISTS (i: below(length[list[real]](M))):
             length[real](nth[list[real]](M, i)) = 0));

  % Subtype TCC generated (at line 92, column 24) for  M
      % expected type  (cons?[list[real]])
  columns_TCC2: OBLIGATION
    FORALL (M: Matrix): NOT null?(M) IMPLIES cons?[list[real]](M);

  % Termination TCC generated (at line 92, column 28) for  columns(cdr(M))
  columns_TCC3: OBLIGATION
    FORALL (M: Matrix):
      NOT null?(M) IMPLIES
       length[list[real]](cdr[list[real]](M)) < length[list[real]](M);

  % Subtype TCC generated (at line 92, column 9) for
      % max(length(car(M)), columns(cdr(M)))
      % expected type  {c: nat |
                     %          (FORALL (i: below(length(M))):
                     %             length(nth(M, i)) <= c)
                     %           AND
                     %           (null?(M) AND c = 0 OR
                     %             (EXISTS (i: below(length(M))):
                     %                length(nth(M, i)) = c))}
  columns_TCC4: OBLIGATION
    FORALL (M: Matrix,
            v:
              [M1: {z: Matrix | length(z) < length(M)} ->
                 {c: nat |
                          (FORALL (i: below(length(M1))):
                             length(nth(M1, i)) <= c)
                           AND
                           (null?(M1) AND c = 0 OR
                             (EXISTS (i: below(length(M1))):
                                length(nth(M1, i)) = c))}]):
      NOT null?(M) IMPLIES
       (FORALL (i: below(length[list[real]](M))):
          length[real](nth[list[real]](M, i)) <=
           max(length[real](car[list[real]](M)), v(cdr[list[real]](M))))
        AND
        (null?[list[real]](M) AND
          max(length[real](car[list[real]](M)), v(cdr[list[real]](M))) = 0
          OR
          (EXISTS (i: below(length[list[real]](M))):
             length[real](nth[list[real]](M, i)) =
              max(length[real](car[list[real]](M)), v(cdr[list[real]](M)))));

  % Subtype TCC generated (at line 97, column 15) for  i
      % expected type  below[length[list[real]](M)]
  row_TCC1: OBLIGATION
    FORALL (M: Matrix, i: nat):
      NOT i >= length(M) IMPLIES i < length[list[real]](M);

  % Subtype TCC generated (at line 100, column 21) for  null[real]
      % expected type  VectorN(rows(M))
  col_TCC1: OBLIGATION
    FORALL (M: Matrix): null?(M) IMPLIES length[real](null[real]) = rows(M);

  % Subtype TCC generated (at line 101, column 9) for
      % cons(access(car(M))(i), col(cdr(M))(i))
      % expected type  VectorN(rows(M))
  col_TCC2: OBLIGATION
    FORALL (M: Matrix,
            v:
              [M1: {z: Matrix | length(z) < length(M)} ->
                 [nat -> VectorN(rows(M1))]],
            i: nat):
      NOT null?(M) IMPLIES
       length[real]
           (cons[real]
                (access(car[list[real]](M))(i), v(cdr[list[real]](M))(i)))
        = rows(M);

  % Subtype TCC generated (at line 107, column 20) for  j
      % expected type  below[length(col(M)(i))]
  col_def_TCC1: OBLIGATION
    FORALL (M: Matrix, i: nat):
      length(col(M)(i)) = rows(M) IMPLIES
       (FORALL (j: below(rows(M))): j < length[real](col(M)(i)));

  % Subtype TCC generated (at line 108, column 28) for  j
      % expected type  below[length[list[real]](M)]
  col_def_TCC2: OBLIGATION
    FORALL (M: Matrix, i: nat):
      length(col(M)(i)) = rows(M) IMPLIES
       (FORALL (j: below(rows(M))): j < length[list[real]](M));

  % Subtype TCC generated (at line 134, column 29) for  SM
      % expected type  (cons?[list[real]])
  full_matrix_columns_TCC1: OBLIGATION
    FORALL (SM: FullMatrix):
      NOT (null?(SM) AND columns(SM) = 0) IMPLIES cons?[list[real]](SM);

  % Subtype TCC generated (at line 168, column 22) for  v2
      % expected type  VectorN(max(length(v1), length(v2)))
  add_TCC1: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      null?(v1) IMPLIES
       length[real](v2) = max(length[real](v1), length[real](v2));

  % Subtype TCC generated (at line 169, column 25) for  v1
      % expected type  VectorN(max(length(v1), length(v2)))
  add_TCC2: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      null?(v2) AND NOT null?(v1) IMPLIES
       length[real](v1) = max(length[real](v1), length[real](v2));

  % Subtype TCC generated (at line 170, column 18) for  v1
      % expected type  (cons?[real])
  add_TCC3: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      NOT null?(v2) AND NOT null?(v1) IMPLIES cons?[real](v1);

  % Subtype TCC generated (at line 170, column 26) for  v2
      % expected type  (cons?[real])
  add_TCC4: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      NOT null?(v2) AND NOT null?(v1) IMPLIES cons?[real](v2);

  % Termination TCC generated (at line 170, column 30) for
      % add(cdr(v1), cdr(v2))
  add_TCC5: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      NOT null?(v2) AND NOT null?(v1) IMPLIES
       length[real](cdr[real](v1)) + length[real](cdr[real](v2)) <
        length[real](v1) + length[real](v2);

  % Subtype TCC generated (at line 170, column 9) for
      % cons(car(v1) + car(v2), add(cdr(v1), cdr(v2)))
      % expected type  VectorN(max(length(v1), length(v2)))
  add_TCC6: OBLIGATION
    FORALL (v1: Vector, v2: Vector,
            v:
              [d1:
                 {z: [Vector, Vector] |
                          length(z`1) + length(z`2) <
                           length(v1) + length(v2)} ->
                 VectorN(max(length(d1`1), length(d1`2)))]):
      NOT null?(v2) AND NOT null?(v1) IMPLIES
       length[real]
           (cons[real]
                (car[real](v1) + car[real](v2),
                 v(cdr[real](v1), cdr[real](v2))))
        = max(length[real](v1), length[real](v2));

  % Subtype TCC generated (at line 175, column 20) for  v2
      % expected type  (cons?[real])
  scal_TCC1: OBLIGATION
    FORALL (v2: Vector): NOT null?(v2) IMPLIES cons?[real](v2);

  % Termination TCC generated (at line 175, column 24) for  scal(r, cdr(v2))
  scal_TCC2: OBLIGATION
    FORALL (v2: Vector):
      NOT null?(v2) IMPLIES length[real](cdr[real](v2)) < length[real](v2);

  % Subtype TCC generated (at line 175, column 9) for
      % cons(r * car(v2), scal(r, cdr(v2)))
      % expected type  VectorN(length(v2))
  scal_TCC3: OBLIGATION
    FORALL (r: real, v2: Vector,
            v:
              [d1: {z: [real, Vector] | length(z`2) < length(v2)} ->
                 VectorN(length(d1`2))]):
      NOT null?(v2) IMPLIES
       length[real](cons[real](r * car[real](v2), v(r, cdr[real](v2)))) =
        length[real](v2);

  % Subtype TCC generated (at line 179, column 4) for  add(v1, scal(-1, v2))
      % expected type  VectorN(max(length(v1), length(v2)))
  sub_TCC1: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      length[real](add(v1, scal(-1, v2))) =
       max(length[real](v1), length[real](v2));

  % Subtype TCC generated (at line 187, column 35) for  0
      % expected type  {rr: real | rr = dot(v1, v2)}
  super_dot_TCC1: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      null?(v1) OR null?(v2) IMPLIES 0 = dot(v1, v2);

  % Subtype TCC generated (at line 188, column 25) for  dot(cdr(v1), cdr(v2))
      % expected type  {rr: real | rr = dot(v1, v2)}
  super_dot_TCC2: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      car(v1) = 0 AND NOT null?(v1) AND NOT null?(v2) IMPLIES
       dot(cdr[real](v1), cdr[real](v2)) = dot(v1, v2);

  % Subtype TCC generated (at line 189, column 9) for
      % car(v1) * car(v2) + dot(cdr(v1), cdr(v2))
      % expected type  {rr: real | rr = dot(v1, v2)}
  super_dot_TCC3: OBLIGATION
    FORALL (v1: Vector, v2: Vector):
      NOT car(v1) = 0 AND NOT null?(v1) AND NOT null?(v2) IMPLIES
       car[real](v1) * car[real](v2) + dot(cdr[real](v1), cdr[real](v2)) =
        dot(v1, v2);

  % Subtype TCC generated (at line 194, column 31) for  kz - 1
      % expected type  nat
  super_duper_dot_TCC1: OBLIGATION
    FORALL (kz: nat): NOT kz = 0 IMPLIES kz - 1 >= 0;

  % Termination TCC generated (at line 194, column 9) for
      % super_duper_dot(FF, GG, kz - 1)
  super_duper_dot_TCC2: OBLIGATION
    FORALL (kz: nat): NOT kz = 0 IMPLIES kz - 1 < kz;

  % Subtype TCC generated (at line 212, column 25) for
      % min(length(v1) - 1, length(v2) - 1)
      % expected type  T_high[nat]
  dot_eq_sigma_TCC1: OBLIGATION
    FORALL (v1, v2: Vector):
      min(length[real](v1) - 1, length[real](v2) - 1) >= 0 OR
       (EXISTS (j: nat):
          min(length[real](v1) - 1, length[real](v2) - 1) <= j);

  % Subtype TCC generated (at line 235, column 20) for  j
      % expected type  below[length(row(M)(i))]
  form_matrix_TCC1: OBLIGATION
    FORALL (m, n: nat, M: MatrixMN(m, n), i: below(m), j: below(n)):
      j < length[real](row(M)(i));

  % Existence TCC generated (at line 236, column 4) for
      % array2list[listn[real](n)]
  form_matrix_TCC2: OBLIGATION
    FORALL (n: nat): EXISTS (x: listn[real](n)): TRUE;

  % Subtype TCC generated (at line 236, column 4) for
      % array2list[listn[real](n)]
      %     (m)
      %     (LAMBDA (k: nat): array2list[real](n)(LAMBDA (p: nat): F(k, p)))
      % expected type  {M: MatrixMN(m, n) |
                     %          FORALL (i: below(m), j: below(n)):
                     %            nth(row(M)(i), j) = F(i, j)}
  form_matrix_TCC3: OBLIGATION
    FORALL (F: [[nat, nat] -> real], m, n: nat):
      (length[list[real]]
           (array2list[listn[real](n)]
                (m)
                (LAMBDA (k: nat):
                   array2list[real](n)(LAMBDA (p: nat): F(k, p))))
        = m
        AND
        (FORALL (i:
                   below(length[list[real]]
                             (array2list[listn[real](n)]
                                  (m)
                                  (LAMBDA (k: nat):
                                     array2list[real]
                                         (n)(LAMBDA (p: nat): F(k, p)))))):
           length[real]
               (nth[list[real]]
                    (array2list[listn[real](n)]
                         (m)
                         (LAMBDA (k: nat):
                            array2list[real](n)(LAMBDA (p: nat): F(k, p))),
                     i))
            = n))
       AND
       (FORALL (i: below(m), j: below(n)):
          nth[real]
              (row(array2list[listn[real](n)]
                       (m)
                       (LAMBDA (k: nat):
                          array2list[real](n)(LAMBDA (p: nat): F(k, p))))
                  (i),
               j)
           = F(i, j));

  % Subtype TCC generated (at line 288, column 4) for
      % form_matrix(LAMBDA (i, j: nat): dot(row(M)(i), col(N)(j)), rows(M),
      %             columns(N))
      % expected type  {A: MatrixMN(rows(M), columns(N)) |
                     %          FORALL (i, j):
                     %            entry(A)(i, j) = row(M)(i) * col(N)(j)}
  mult_TCC1: OBLIGATION
    FORALL (M: Matrix, N: Matrix):
      FORALL (i_1: nat, j_1: nat):
        entry(form_matrix(LAMBDA (i, j: nat): dot(row(M)(i), col(N)(j)),
                          rows(M), columns(N)))
             (i_1, j_1)
         = row(M)(i_1) * col(N)(j_1);

  % Judgement subtype TCC generated (at line 294, column 4) for  M * N
      % expected type  FullMatrix
  mult_full: OBLIGATION
    FORALL (M, N):
      null?[list[real]](M * N) OR
       (FORALL (i, j: below(length[list[real]](M * N))):
          length[real](nth[list[real]](M * N, i)) =
           length[real](nth[list[real]](M * N, j)));

  % Subtype TCC generated (at line 328, column 23) for  m - 1
      % expected type  T_high[nat]
  form_matrix_mult_TCC1: OBLIGATION
    FORALL (k, m, n: nat):
      m > 0 AND k > 0 IMPLIES
       (FORALL (i, j: nat):
          NOT i > k AND NOT j > n IMPLIES
           m - 1 >= 0 OR (EXISTS (j: nat): m - 1 <= j));

  % Subtype TCC generated (at line 334, column 4) for
      % form_matrix(LAMBDA (i, j: nat): entry(M)(i, j) + entry(N)(i, j),
      %             max(rows(M), rows(N)), max(columns(M), columns(N)))
      % expected type  {A:
                     %    MatrixMN(max(rows(M), rows(N)),
                     %             max(columns(M), columns(N))) |
                     %          FORALL (i, j):
                     %            entry(A)(i, j) =
                     %             entry(M)(i, j) + entry(N)(i, j)}
  add_TCC7: OBLIGATION
    FORALL (M: Matrix, N: Matrix):
      FORALL (i_1: nat, j_1: nat):
        entry(form_matrix(LAMBDA (i, j: nat):
                            entry(M)(i, j) + entry(N)(i, j),
                          max(rows(M), rows(N)), max(columns(M), columns(N))))
             (i_1, j_1)
         = entry(M)(i_1, j_1) + entry(N)(i_1, j_1);

  % Subtype TCC generated (at line 355, column 4) for
      % form_matrix(LAMBDA (i, j: nat): r * entry(M)(i, j), rows(M),
      %             columns(M))
      % expected type  {A: MatrixMN(rows(M), columns(M)) |
                     %          FORALL (i, j):
                     %            entry(A)(i, j) = r * entry(M)(i, j)}
  scal_TCC4: OBLIGATION
    FORALL (r: real, M: Matrix):
      FORALL (i_1: nat, j_1: nat):
        entry(form_matrix(LAMBDA (i, j: nat): r * entry(M)(i, j), rows(M),
                          columns(M)))
             (i_1, j_1)
         = r * entry(M)(i_1, j_1);

  % Subtype TCC generated (at line 368, column 4) for  M + (-1) * N
      % expected type  {A:
                     %    MatrixMN(max(rows(M), rows(N)),
                     %             max(columns(M), columns(N))) |
                     %          FORALL (i, j):
                     %            entry(A)(i, j) =
                     %             entry(M)(i, j) - entry(N)(i, j)}
  sub_TCC2: OBLIGATION
    FORALL (M: Matrix, N: Matrix):
      (length[list[real]](M + (-1) * N) = max(rows(M), rows(N)) AND
        (FORALL (i: below(length[list[real]](M + (-1) * N))):
           length[real](nth[list[real]](M + (-1) * N, i)) =
            max(columns(M), columns(N))))
       AND
       (FORALL (i, j):
          entry(M + (-1) * N)(i, j) = entry(M)(i, j) - entry(N)(i, j));

  % Subtype TCC generated (at line 390, column 4) for
      % form_matrix(LAMBDA (i, j: nat): IF i = j THEN 1 ELSE 0 ENDIF, pm, pm)
      % expected type  {M: SquareMatrix(pm) |
                     %          (FORALL (i, j):
                     %             entry(M)(i, j) =
                     %              IF i < pm AND i = j THEN 1 ELSE 0 ENDIF)
                     %           AND
                     %           (FORALL (pn: posnat, N: MatrixMN(pm, pn)):
                     %              M * N = N)
                     %            AND
                     %            (FORALL (pn: posnat, N: MatrixMN(pn, pm)):
                     %               N * M = N)}
  Id_TCC1: OBLIGATION
    FORALL (pm: posnat):
           null?[list[real]]
               (form_matrix(LAMBDA (i, j: nat): IF i = j THEN 1 ELSE 0 ENDIF,
                            pm, pm))
            OR
            (FORALL (i_1,
                     j_1:
                       below(length[list[real]]
                                 (form_matrix(LAMBDA
                                              (i, j: nat):
                                              IF i = j THEN 1 ELSE 0 ENDIF,
                                              pm,
                                              pm)))):
               length[real]
                   (nth[list[real]]
                        (form_matrix(LAMBDA (i, j: nat):
                                       IF i = j THEN 1 ELSE 0 ENDIF,
                                     pm, pm),
                         i_1))
                =
                length[real]
                    (nth[list[real]]
                         (form_matrix(LAMBDA
                                      (i, j: nat):
                                      IF i = j THEN 1 ELSE 0 ENDIF,
                                      pm,
                                      pm),
                          j_1)))
       AND rows(form_matrix(LAMBDA (i, j: nat): IF i = j THEN 1 ELSE 0 ENDIF,
                            pm, pm))
            > 0
       AND columns(form_matrix(LAMBDA (i, j: nat):
                                 IF i = j THEN 1 ELSE 0 ENDIF,
                               pm, pm))
            > 0
       AND rows(form_matrix(LAMBDA (i, j: nat): IF i = j THEN 1 ELSE 0 ENDIF,
                            pm, pm))
            =
            columns(form_matrix(LAMBDA (i, j: nat):
                                  IF i = j THEN 1 ELSE 0 ENDIF,
                                pm, pm))
       AND rows(form_matrix(LAMBDA (i, j: nat): IF i = j THEN 1 ELSE 0 ENDIF,
                            pm, pm))
            = pm
       AND FORALL (i_1: nat, j_1: nat):
             entry(form_matrix(LAMBDA (i, j: nat):
                                 IF i = j THEN 1 ELSE 0 ENDIF,
                               pm, pm))
                  (i_1, j_1)
              = IF i_1 < pm AND i_1 = j_1 THEN 1 ELSE 0 ENDIF
       AND FORALL (pn: posnat, N: MatrixMN(pm, pn)):
             form_matrix(LAMBDA (i, j: nat): IF i = j THEN 1 ELSE 0 ENDIF,
                         pm, pm)
              * N
              = N
       AND FORALL (pn: posnat, N: MatrixMN(pn, pm)):
             N *
              form_matrix(LAMBDA (i, j: nat): IF i = j THEN 1 ELSE 0 ENDIF,
                          pm, pm)
              = N;

  % Subtype TCC generated (at line 404, column 4) for
      % form_matrix(LAMBDA (i, j: nat): entry(PFM)(j, i), columns(PFM),
      %             rows(PFM))
      % expected type  PosFullMatrix
  transpose_TCC1: OBLIGATION
    FORALL (PFM: PosFullMatrix):
      (null?[list[real]]
           (form_matrix(LAMBDA (i, j: nat): entry(PFM)(j, i), columns(PFM),
                        rows(PFM)))
        OR
        (FORALL (i_1,
                 j_1:
                   below(length[list[real]]
                             (form_matrix(LAMBDA
                                          (i, j: nat):
                                          entry(PFM)(j, i),
                                          columns(PFM),
                                          rows(PFM))))):
           length[real]
               (nth[list[real]]
                    (form_matrix(LAMBDA (i, j: nat): entry(PFM)(j, i),
                                 columns(PFM), rows(PFM)),
                     i_1))
            =
            length[real]
                (nth[list[real]]
                     (form_matrix(LAMBDA (i, j: nat): entry(PFM)(j, i),
                                  columns(PFM), rows(PFM)),
                      j_1))))
       AND
       rows(form_matrix(LAMBDA (i, j: nat): entry(PFM)(j, i), columns(PFM),
                        rows(PFM)))
        > 0
        AND
        columns(form_matrix(LAMBDA (i, j: nat): entry(PFM)(j, i),
                            columns(PFM), rows(PFM)))
         > 0;

  % Subtype TCC generated (at line 415, column 14) for  D1 * D2
      % expected type  PosFullMatrix
  transpose_mult_TCC1: OBLIGATION
    FORALL (D1, D2: PosFullMatrix):
      columns(D1) = rows(D2) IMPLIES
       rows(D1 * D2) > 0 AND columns(D1 * D2) > 0;

  % Judgement subtype TCC generated (at line 418, column 4) for
      % form_matrix(F, i, j)
      % expected type  FullMatrix
  form_matrix_square: OBLIGATION
    FORALL (F, i, j):
      null?[list[real]](form_matrix(F, i, j)) OR
       (FORALL (i_1, j_1: below(length[list[real]](form_matrix(F, i, j)))):
          length[real](nth[list[real]](form_matrix(F, i, j), i_1)) =
           length[real](nth[list[real]](form_matrix(F, i, j), j_1)));

  % Subtype TCC generated (at line 423, column 4) for
      % form_matrix(LAMBDA (i, j): IF i = 0 THEN access(v)(j) ELSE 0 ENDIF,
      %             1, length(v))
      % expected type  {PFM | rows(PFM) = 1 AND columns(PFM) = length(v)}
  vect2matrix_TCC1: OBLIGATION
    FORALL (v: Vector | length[real](v) > 0):
      (rows(form_matrix(LAMBDA (i, j):
                          IF i = 0 THEN access(v)(j) ELSE 0 ENDIF,
                        1, length[real](v)))
        = 1
        AND
        columns(form_matrix(LAMBDA (i, j):
                              IF i = 0 THEN access(v)(j) ELSE 0 ENDIF,
                            1, length[real](v)))
         = length[real](v))
       AND
       rows(form_matrix(LAMBDA (i, j):
                          IF i = 0 THEN access(v)(j) ELSE 0 ENDIF,
                        1, length[real](v)))
        > 0
        AND
        columns(form_matrix(LAMBDA (i, j):
                              IF i = 0 THEN access(v)(j) ELSE 0 ENDIF,
                            1, length[real](v)))
         > 0;


body:
  matrix_props: THEORY


  BEGIN

    IMPORTING matrices,reals@real_fun_ops


    SM,SM1,SM2: VAR FullMatrix

    r: VAR real

    nzr: VAR nzreal

    M,N,A,B: VAR Matrix

    v,v1,v2: VAR Vector

    i,j,k,p : VAR nat

    m,n : VAR nat

    pn,pm : VAR posnat

    F,G: VAR [[nat,nat]->real]

    Mp,Np: VAR (nonempty?)

    PFM,D1,D2,D: VAR PosFullMatrix

    matrix_2x2: LEMMA
      rows(D)=2 AND columns(D)=2 IMPLIES
      D = (:(:entry(D)(0,0),entry(D)(0,1):),
        	  (:entry(D)(1,0),entry(D)(1,1):):)

    SQ,IQ,GQ: VAR Square

    length_row: LEMMA length(row(SM)(i)) = IF i>=rows(SM) THEN 0 ELSE columns(SM) ENDIF

    length_nth_row: LEMMA i<length(SM) IMPLIES length(nth(SM,i)) = columns(SM)

    columns_cdr: LEMMA rows(D)>1 IMPLIES columns(cdr(D)) = columns(D)

    columns_cons: LEMMA columns(cons(v,M)) = max(length(v),columns(M))

    access_col: LEMMA access(col(SM)(i))(j) = access(row(SM)(j))(i)

    % Determinant %

    remove(M,i,j): {N |
      (rows(M)>1 AND columns(M)>1  IMPLIES
      (rows(N)=rows(M)-1 AND columns(N)=columns(M)-1)) AND
      (FORALL (m,n):
        LET newm= IF m>=i OR i>=rows(M) THEN m+1 ELSE m ENDIF,
        	  newn= IF n>=j OR j>=columns(M) THEN n+1 ELSE n ENDIF IN
        entry(N)(m,n)=entry(M)(newm,newn))} =
      IF rows(M)=0 OR columns(M)=0 THEN null[list[real]] ELSE
       form_matrix(LAMBDA (m,n): 
        LET newm= IF m>=i OR i>=rows(M) THEN m+1 ELSE m ENDIF,
        	  newn= IF n>=j OR j>=columns(M) THEN n+1 ELSE n ENDIF IN entry(M)(newm,newn),rows(M)-1,columns(M)-1) ENDIF

    remove_posfullmatrix: JUDGEMENT
      remove(D,i,j) HAS_TYPE FullMatrix

    rows_remove: LEMMA
      rows(remove(M,i,j)) = IF rows(M)=0 or columns(M)=0 THEN 0 ELSE rows(M)-1 ENDIF

    columns_remove: LEMMA
      columns(remove(M,i,j)) = IF rows(M)<=1 OR columns(M)=0 THEN 0
      			     ELSE columns(M)-1 ENDIF

    remove_remove_1_0: LEMMA rows(D)>2 AND
      columns(D)>2 AND m<=n 
      AND n<columns(D)-1 AND m<columns(D)-1 IMPLIES
      remove(remove(D, 1, n+1), 0, m) = 
      remove(remove(D, 0, m), 0, n)

    remove_remove_1_0_0: LEMMA rows(D)>2 AND
      columns(D)>2 
      AND n<columns(D)-1 IMPLIES
      remove(remove(D, 1, 0), 0, n)=remove(remove(D, 0, 1 + n), 0, 0)

    remove_remove_1_n: LEMMA rows(D)>2 AND
      columns(D)>2 
      AND n+m<columns(D)-1 IMPLIES
      remove(remove(D, 1, n), 0, m + n)
         =remove(remove(D, 0, 1 + m + n), 0, n)

    entry_remove: LEMMA 
      entry(remove(M,i,j))(m,n) =
        LET newm= IF m>=i OR i>=rows(M) THEN m+1 ELSE m ENDIF,
        	  newn= IF n>=j OR j>=columns(M) THEN n+1 ELSE n ENDIF IN
        entry(M)(newm,newn)
    
    remove_Id_0_0: LEMMA pm>1 IMPLIES remove(Id(pm),0,0) = Id(pm-1)

    % remove_remove: LEMMA
    %   remove(remove(M,i,j),k,p)=
    %     LET newi = IF k<i THEN k ELSE k 

    remove_test: LEMMA remove((:(:1,2:),(:3,4:):),1,1)=(:(:1:):)

    det(M): RECURSIVE real =
      IF null?(M) OR rows(M)/=columns(M) THEN 0
      ELSIF rows(M)=1 THEN entry(M)(0,0)
      ELSE sigma(0,columns(M)-1,LAMBDA (k): 
           (-1)^k*entry(M)(0,k)*det(remove(M,0,k))) ENDIF
      MEASURE length(M)

    det_test: LEMMA FORALL (a,b,c,d:real):
      det((:(:a,b:),(:c,d:):))=a*d-b*c

    det_size_noteq: LEMMA rows(M)/=columns(M) IMPLIES det(M)=0

    % Elementary matrix operations

    % Swapping two rows

    swap(i,j)(F)(k,p): real = IF k=i THEN F(j,p)
    		     	  ELSIF k=j THEN F(i,p)
  			  ELSE F(k,p) ENDIF

    swap_fun_test: LEMMA
      LET FF = (LAMBDA (i,j:nat): 0) IN
        swap(0,1)(FF)(1,1)=0

    swap(i,j)(D): {PFM|rows(PFM)=rows(D) AND columns(PFM)=columns(D) AND
      FORALL (k,p): i<rows(D) AND j<rows(D) IMPLIES entry(PFM)(k,p)=(IF k=i 
      		       	       THEN entry(D)(j,p) ELSIF k=j THEN entry(D)(i,p)
  			  ELSE entry(D)(k,p) ENDIF)} =
     form_matrix(swap(i,j)(entry(D)),rows(D),columns(D))

    entry_swap: LEMMA
      entry(swap(i,j)(D))(k,p) = IF k<rows(D) AND p<columns(D)
        THEN swap(i,j)(entry(D))(k,p) ELSE 0 ENDIF

    swap_test: LEMMA swap(0,1)((:(:1,2:),(:3,4:):)) = (:(:3,4:),(:1,2:):)

    remove_swap_1: LEMMA rows(D)>=2 AND columns(D)>=2 IMPLIES
      remove(swap(0, 1)(D), 0, n) =
      remove(D,1,n)

    remove_swap_2: LEMMA i/=0 AND j/=0 AND i<rows(D) AND j<rows(D)
      AND rows(D)=columns(D)
      IMPLIES
       remove(swap(i,j)(D),0,n)=swap(i-1,j-1)(remove(D,0,n))

    swap_sym: LEMMA swap(i,j)(D) = swap(j,i)(D)

    det_swap_0_1: LEMMA rows(D)>1 IMPLIES det(swap(0,1)(D))=-det(D)

    swap_swap_matrix: LEMMA i<rows(D) AND j<rows(D) IMPLIES
      swap(i,j)(swap(i,j)(D))=D

    swap_similar: LEMMA i<rows(D) AND j<rows(D) AND k<rows(D) AND
    i/=j AND j/=k AND k/=i IMPLIES
      swap(k,j)(D) = swap(i,j)(swap(k,i)(swap(i,j)(D)))

    det_swap: LEMMA i/=j AND i<rows(D) AND j<rows(D) IMPLIES
      det(swap(i,j)(D))=-det(D)

    row_swap: LEMMA i<rows(D) AND j<rows(D) IMPLIES
      row(swap(i,j)(D))(k) =
      row(D)(IF k=i THEN j ELSIF k=j THEN i ELSE k ENDIF)

    rows_swap: LEMMA rows(swap(i,j)(D)) = rows(D)

    columns_swap: LEMMA columns(swap(i,j)(D)) = columns(D)

    swap_id: LEMMA swap(i,i)(D)=D

    swap_eq: LEMMA row(D)(i) = row(D)(j) IMPLIES
      swap(i,j)(D) = D

    det_rows_eq_0: LEMMA i<rows(D) AND j<rows(D) AND
      row(D)(i) = row(D)(j) AND i/=j IMPLIES
      det(D) = 0

    % Multiplying a row by a scalar

    replace_row(i,v)(D|columns(D)=length(v)): RECURSIVE 
      {PFM|rows(PFM)=rows(D) AND columns(PFM)=columns(D) AND
        (FORALL (j): row(PFM)(j) = IF j<rows(D) AND j=i THEN v ELSE row(D)(j) ENDIF) AND
        (FORALL (j,k): entry(PFM)(j,k)=IF j<rows(D) AND j=i THEN access(v)(k) ELSE entry(D)(j,k) ENDIF)} =
      IF i>=rows(D) THEN D
      ELSIF rows(D)=1 THEN cons(v,null[list[real]])
      ELSIF i=0 THEN cons(v,cdr(D))
      ELSE cons(car(D),replace_row(i-1,v)(cdr(D))) ENDIF MEASURE rows(D)

    entry_replace_row: LEMMA columns(D)=length(v) IMPLIES
      entry(replace_row(i,v)(D))(j,k) = (IF j<rows(D) AND j=i THEN access(v)(k) ELSE entry(D)(j,k) ENDIF)

    rows_replace_row: LEMMA columns(D) = length(v) IMPLIES
      rows(replace_row(i,v)(D)) = rows(D)

    columns_replace_row: LEMMA columns(D) = length(v) IMPLIES
      columns(replace_row(i,v)(D)) = columns(D)

    remove_replace_row: LEMMA columns(D) = length(v) AND rows(D)>1 AND columns(D)>1 IMPLIES
      remove(replace_row(k,v)(D),k,j) = remove(D,k,j)

    swap_replace_row: LEMMA columns(D)=length(v) AND i<rows(D) AND 
      j<rows(D) AND k<rows(D) IMPLIES
      swap(i,j)(replace_row(k,v)(D)) = (IF i = k THEN replace_row(j,v)(swap(i,j)(D))
      				     ELSIF j = k THEN replace_row(i,v)(swap(i,j)(D))
  				     ELSE replace_row(k,v)(swap(i,j)(D)) ENDIF)

    row_replace_row: LEMMA columns(D) = length(v) IMPLIES
      row(replace_row(i,v)(D))(j) = IF j<rows(D) AND j=i THEN v ELSE row(D)(j) ENDIF

    remove_replace_row_eq: LEMMA columns(D) = length(v) IMPLIES
      remove(replace_row(i,v)(D),i,j) = remove(D,i,j)

    det_replace_row_sum: LEMMA length(v1)=length(v2) AND columns(D)=length(v1) AND i<rows(D) IMPLIES
      det(replace_row(i,v1+v2)(D)) = det(replace_row(i,v1)(D)) + det(replace_row(i,v2)(D))

    det_replace_row_scal: LEMMA columns(D) = length(v) AND i<rows(D) IMPLIES
      det(replace_row(i,r*v)(D)) = r*det(replace_row(i,v)(D))

    replace_row_id: LEMMA i<rows(D) IMPLIES
      replace_row(i,row(D)(i))(D) = D

    det_replace_row_sum_scal: LEMMA i<rows(D) AND j<rows(D) AND i/=j IMPLIES
      det(replace_row(i,row(D)(i)+r*row(D)(j))(D)) = det(D)

    replace_row_sum_to_scal: LEMMA i<rows(D) AND j<rows(D) IMPLIES
      replace_row(i,row(D)(i)+row(D)(j))(D)=replace_row(i,row(D)(i)+1*row(D)(j))(D)

    det_Id: LEMMA det(Id(pn))=1

    det_first_column_zero: LEMMA
      (FORALL (i): i<rows(D) IMPLIES entry(D)(i,0)=0) IMPLIES
      det(D)=0

    remove_transpose: LEMMA 
      rows(D)>1 AND columns(D)>1 IMPLIES
      remove(transpose(D),i,j) =
      transpose(remove(D,j,i))



  END matrix_props

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 42, column 51) for  D
      % expected type  (cons?[list[real]])
  columns_cdr_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix): rows(D) > 1 IMPLIES cons?[list[real]](D);

  % Subtype TCC generated (at line 57, column 38) for  null[list[real]]
      % expected type  {N |
                     %          (rows(M) > 1 AND columns(M) > 1 IMPLIES
                     %            (rows(N) = rows(M) - 1 AND
                     %              columns(N) = columns(M) - 1))
                     %           AND
                     %           (FORALL (m, n):
                     %              entry(N)(m, n) =
                     %               entry(M)
                     %                    (IF m >= i OR i >= rows(M)
                     %                     THEN 1 + m
                     %                     ELSE m
                     %                     ENDIF,
                     %                     IF n >= j OR j >= columns(M)
                     %                     THEN 1 + n
                     %                     ELSE n
                     %                     ENDIF))}
  remove_TCC1: OBLIGATION
    FORALL (M: Matrix, i: nat, j: nat):
      rows(M) = 0 OR columns(M) = 0 IMPLIES
       (rows(M) > 1 AND columns(M) > 1 IMPLIES
         (rows(null[list[real]]) = rows(M) - 1 AND
           columns(null[list[real]]) = columns(M) - 1))
        AND
        (FORALL (m, n):
           entry(null[list[real]])(m, n) =
            entry(M)
                 (IF m >= i OR i >= rows(M) THEN 1 + m ELSE m ENDIF,
                  IF n >= j OR j >= columns(M) THEN 1 + n ELSE n ENDIF));

  % Subtype TCC generated (at line 60, column 85) for  rows(M) - 1
      % expected type  nat
  remove_TCC2: OBLIGATION
    FORALL (M: Matrix):
      NOT rows(M) = 0 AND NOT columns(M) = 0 IMPLIES rows(M) - 1 >= 0;

  % Subtype TCC generated (at line 60, column 95) for  columns(M) - 1
      % expected type  nat
  remove_TCC3: OBLIGATION
    FORALL (M: Matrix):
      NOT rows(M) = 0 AND NOT columns(M) = 0 IMPLIES columns(M) - 1 >= 0;

  % Subtype TCC generated (at line 58, column 5) for
      % form_matrix(LAMBDA (m, n):
      %               LET newm =
      %                     IF m >= i OR i >= rows(M) THEN m + 1
      %                     ELSE m
      %                     ENDIF,
      %                   newn =
      %                     IF n >= j OR j >= columns(M) THEN n + 1
      %                     ELSE n
      %                     ENDIF
      %                 IN entry(M)(newm, newn),
      %             rows(M) - 1, columns(M) - 1)
      % expected type  {N |
                     %          (rows(M) > 1 AND columns(M) > 1 IMPLIES
                     %            (rows(N) = rows(M) - 1 AND
                     %              columns(N) = columns(M) - 1))
                     %           AND
                     %           (FORALL (m, n):
                     %              entry(N)(m, n) =
                     %               entry(M)
                     %                    (IF m >= i OR i >= rows(M)
                     %                     THEN 1 + m
                     %                     ELSE m
                     %                     ENDIF,
                     %                     IF n >= j OR j >= columns(M)
                     %                     THEN 1 + n
                     %                     ELSE n
                     %                     ENDIF))}
  remove_TCC4: OBLIGATION
    FORALL (M: Matrix, i: nat, j: nat):
      NOT rows(M) = 0 AND NOT columns(M) = 0 IMPLIES
       (rows(M) > 1 AND columns(M) > 1 IMPLIES
         (rows(form_matrix(LAMBDA (m, n):
                             LET newm =
                                   IF m >= i OR i >= rows(M) THEN m + 1
                                   ELSE m
                                   ENDIF,
                                 newn =
                                   IF n >= j OR j >= columns(M) THEN n + 1
                                   ELSE n
                                   ENDIF
                               IN entry(M)(newm, newn),
                           rows(M) - 1, columns(M) - 1))
           = rows(M) - 1
           AND
           columns(form_matrix(LAMBDA (m, n):
                                 LET newm =
                                       IF m >= i OR i >= rows(M)
                                       THEN m + 1
                                       ELSE m
                                       ENDIF,
                                     newn =
                                       IF n >= j OR j >= columns(M)
                                       THEN n + 1
                                       ELSE n
                                       ENDIF
                                   IN entry(M)(newm, newn),
                               rows(M) - 1, columns(M) - 1))
            = columns(M) - 1))
        AND
        (FORALL (m_1: nat, n_1: nat):
           entry(form_matrix(LAMBDA (m, n):
                               LET newm =
                                     IF m >= i OR i >= rows(M) THEN m + 1
                                     ELSE m
                                     ENDIF,
                                   newn =
                                     IF n >= j OR j >= columns(M) THEN n + 1
                                     ELSE n
                                     ENDIF
                                 IN entry(M)(newm, newn),
                             rows(M) - 1, columns(M) - 1))
                (m_1, n_1)
            =
            entry(M)
                 (IF m_1 >= i OR i >= rows(M) THEN 1 + m_1 ELSE m_1 ENDIF,
                  IF n_1 >= j OR j >= columns(M) THEN 1 + n_1
                  ELSE n_1
                  ENDIF));

  % Judgement subtype TCC generated (at line 63, column 4) for  remove(D, i, j)
      % expected type  FullMatrix
  remove_posfullmatrix: OBLIGATION
    FORALL (D, i, j):
      null?[list[real]](remove(D, i, j)) OR
       (FORALL (i_1, j_1: below(length[list[real]](remove(D, i, j)))):
          length[real](nth[list[real]](remove(D, i, j), i_1)) =
           length[real](nth[list[real]](remove(D, i, j), j_1)));

  % Subtype TCC generated (at line 95, column 60) for  pm - 1
      % expected type  pm: posnat
  remove_Id_0_0_TCC1: OBLIGATION
    FORALL (pm: posnat): pm > 1 IMPLIES pm - 1 >= 0 AND pm - 1 > 0;

  % Subtype TCC generated (at line 106, column 17) for  columns(M) - 1
      % expected type  T_high[nat]
  det_TCC1: OBLIGATION
    FORALL (M: Matrix):
      NOT rows(M) = 1 AND NOT null?(M) AND NOT rows(M) /= columns(M) IMPLIES
       columns(M) - 1 >= 0 OR (EXISTS (j: nat): columns(M) - 1 <= j);

  % Termination TCC generated (at line 107, column 30) for
      % det(remove(M, 0, k))
  det_TCC2: OBLIGATION
    FORALL (M: Matrix):
      NOT rows(M) = 1 AND NOT null?(M) AND NOT rows(M) /= columns(M) IMPLIES
       (FORALL (k: nat):
          length[list[real]](remove(M, 0, k)) < length[list[real]](M));

  % Subtype TCC generated (at line 131, column 3) for
      % form_matrix(swap(i, j)(entry(D)), rows(D), columns(D))
      % expected type  {PFM |
                     %          rows(PFM) = rows(D) AND
                     %           columns(PFM) = columns(D) AND
                     %            (FORALL (k, p):
                     %               i < rows(D) AND j < rows(D) IMPLIES
                     %                entry(PFM)(k, p)
                     %                =
                     %                (IF k = i
                     %                 THEN entry(D)(j, p)
                     %                 ELSIF k = j
                     %                 THEN entry(D)(i, p)
                     %                 ELSE entry(D)(k, p)
                     %                 ENDIF))}
  swap_TCC1: OBLIGATION
    FORALL (i: nat, j: nat, D: PosFullMatrix):
           rows(form_matrix(swap(i, j)(entry(D)), rows(D), columns(D))) =
            rows(D)
       AND columns(form_matrix(swap(i, j)(entry(D)), rows(D), columns(D))) =
            columns(D)
       AND FORALL (k, p):
             i < rows(D) AND j < rows(D) IMPLIES
              entry(form_matrix(swap(i, j)(entry(D)), rows(D), columns(D)))
                   (k, p)
               =
               (IF k = i THEN entry(D)(j, p)
                ELSIF k = j THEN entry(D)(i, p)
                ELSE entry(D)(k, p)
                ENDIF)
       AND rows(form_matrix(swap(i, j)(entry(D)), rows(D), columns(D))) > 0
       AND columns(form_matrix(swap(i, j)(entry(D)), rows(D), columns(D))) >
            0;

  % Subtype TCC generated (at line 137, column 29) for
      % (: (: 1, 2 :), (: 3, 4 :) :)
      % expected type  D: PosFullMatrix
  swap_test_TCC1: OBLIGATION
    (null?[list[real]]((: (: 1, 2 :), (: 3, 4 :) :)) OR
      (FORALL (i,
               j: below(length[list[real]]((: (: 1, 2 :), (: 3, 4 :) :)))):
         length[real](nth[list[real]]((: (: 1, 2 :), (: 3, 4 :) :), i)) =
          length[real](nth[list[real]]((: (: 1, 2 :), (: 3, 4 :) :), j))))
     AND
     rows((: (: 1, 2 :), (: 3, 4 :) :)) > 0 AND
      columns((: (: 1, 2 :), (: 3, 4 :) :)) > 0;

  % Subtype TCC generated (at line 146, column 44) for  remove(D, 0, n)
      % expected type  D: PosFullMatrix
  remove_swap_2_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i, j, n: nat):
           rows(D) = columns(D) AND j < rows(D) AND i < rows(D) AND j /= 0
       AND i /= 0
       IMPLIES rows(remove(D, 0, n)) > 0 AND columns(remove(D, 0, n)) > 0;

  % Subtype TCC generated (at line 146, column 35) for  i - 1
      % expected type  nat
  remove_swap_2_TCC2: OBLIGATION
    FORALL (D: PosFullMatrix, i, j: nat):
           rows(D) = columns(D) AND j < rows(D) AND i < rows(D) AND j /= 0
       AND i /= 0
       IMPLIES i - 1 >= 0;

  % Subtype TCC generated (at line 146, column 39) for  j - 1
      % expected type  nat
  remove_swap_2_TCC3: OBLIGATION
    FORALL (D: PosFullMatrix, i, j: nat):
           rows(D) = columns(D) AND j < rows(D) AND i < rows(D) AND j /= 0
       AND i /= 0
       IMPLIES j - 1 >= 0;

  % Subtype TCC generated (at line 185, column 23) for  D
      % expected type  {PFM |
                     %          rows(PFM) = rows(D) AND
                     %           columns(PFM) = columns(D) AND
                     %            (FORALL (j):
                     %               row(PFM)(j) =
                     %                IF j < rows(D) AND j = i
                     %                THEN v
                     %                ELSE row(D)(j)
                     %                ENDIF)
                     %             AND
                     %             (FORALL (j, k):
                     %                entry(PFM)(j, k)
                     %                =
                     %                IF j < rows(D) AND j = i
                     %                THEN access(v)(k)
                     %                ELSE entry(D)(j, k)
                     %                ENDIF)}
  replace_row_TCC1: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v)):
      i >= rows(D) IMPLIES
       (FORALL (j):
          row(D)(j) = IF j < rows(D) AND j = i THEN v ELSE row(D)(j) ENDIF)
        AND
        (FORALL (j, k):
           entry(D)(j, k) =
            IF j < rows(D) AND j = i THEN access(v)(k)
            ELSE entry(D)(j, k)
            ENDIF);

  % Subtype TCC generated (at line 186, column 25) for
      % cons(v, null[list[real]])
      % expected type  {PFM |
                     %          rows(PFM) = rows(D) AND
                     %           columns(PFM) = columns(D) AND
                     %            (FORALL (j):
                     %               row(PFM)(j) =
                     %                IF j < rows(D) AND j = i
                     %                THEN v
                     %                ELSE row(D)(j)
                     %                ENDIF)
                     %             AND
                     %             (FORALL (j, k):
                     %                entry(PFM)(j, k)
                     %                =
                     %                IF j < rows(D) AND j = i
                     %                THEN access(v)(k)
                     %                ELSE entry(D)(j, k)
                     %                ENDIF)}
  replace_row_TCC2: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v)):
      rows(D) = 1 AND NOT i >= rows(D) IMPLIES
            null?[list[real]](cons[Vector](v, null[list[real]])) OR
             (FORALL (i_1,
                      j:
                        below(length[list[real]]
                                  (cons[Vector](v, null[list[real]])))):
                length[real]
                    (nth[list[real]](cons[Vector](v, null[list[real]]), i_1))
                 =
                 length[real]
                     (nth[list[real]](cons[Vector](v, null[list[real]]), j)))
        AND rows(cons[Vector](v, null[list[real]])) > 0
        AND columns(cons[Vector](v, null[list[real]])) > 0
        AND rows(cons[Vector](v, null[list[real]])) = rows(D)
        AND columns(cons[Vector](v, null[list[real]])) = columns(D)
        AND FORALL (j):
              row(cons[Vector](v, null[list[real]]))(j) =
               IF j < rows(D) AND j = i THEN v ELSE row(D)(j) ENDIF
        AND FORALL (j, k):
              entry(cons[Vector](v, null[list[real]]))(j, k) =
               IF j < rows(D) AND j = i THEN access(v)(k)
               ELSE entry(D)(j, k)
               ENDIF;

  % Subtype TCC generated (at line 187, column 30) for  D
      % expected type  (cons?[list[real]])
  replace_row_TCC3: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v)):
      i = 0 AND NOT rows(D) = 1 AND NOT i >= rows(D) IMPLIES
       cons?[list[real]](D);

  % Subtype TCC generated (at line 187, column 19) for  cons(v, cdr(D))
      % expected type  {PFM |
                     %          rows(PFM) = rows(D) AND
                     %           columns(PFM) = columns(D) AND
                     %            (FORALL (j):
                     %               row(PFM)(j) =
                     %                IF j < rows(D) AND j = i
                     %                THEN v
                     %                ELSE row(D)(j)
                     %                ENDIF)
                     %             AND
                     %             (FORALL (j, k):
                     %                entry(PFM)(j, k)
                     %                =
                     %                IF j < rows(D) AND j = i
                     %                THEN access(v)(k)
                     %                ELSE entry(D)(j, k)
                     %                ENDIF)}
  replace_row_TCC4: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v)):
      i = 0 AND NOT rows(D) = 1 AND NOT i >= rows(D) IMPLIES
            null?[list[real]](cons[Vector](v, cdr[list[real]](D))) OR
             (FORALL (i_1,
                      j:
                        below(length[list[real]]
                                  (cons[Vector](v, cdr[list[real]](D))))):
                length[real]
                    (nth[list[real]]
                         (cons[Vector](v, cdr[list[real]](D)), i_1))
                 =
                 length[real]
                     (nth[list[real]]
                          (cons[Vector](v, cdr[list[real]](D)), j)))
        AND rows(cons[Vector](v, cdr[list[real]](D))) > 0
        AND columns(cons[Vector](v, cdr[list[real]](D))) > 0
        AND rows(cons[Vector](v, cdr[list[real]](D))) = rows(D)
        AND columns(cons[Vector](v, cdr[list[real]](D))) = columns(D)
        AND FORALL (j):
              row(cons[Vector](v, cdr[list[real]](D)))(j) =
               IF j < rows(D) AND j = i THEN v ELSE row(D)(j) ENDIF
        AND FORALL (j, k):
              entry(cons[Vector](v, cdr[list[real]](D)))(j, k) =
               IF j < rows(D) AND j = i THEN access(v)(k)
               ELSE entry(D)(j, k)
               ENDIF;

  % Subtype TCC generated (at line 188, column 18) for  D
      % expected type  (cons?[list[real]])
  replace_row_TCC5: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v)):
      NOT i = 0 AND NOT rows(D) = 1 AND NOT i >= rows(D) IMPLIES
       cons?[list[real]](D);

  % Subtype TCC generated (at line 188, column 40) for  cdr(D)
      % expected type  D: {D | columns(D) = length(v)}
  replace_row_TCC6: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v)):
      NOT i = 0 AND NOT rows(D) = 1 AND NOT i >= rows(D) IMPLIES
       (null?[list[real]](cdr[list[real]](D)) OR
         (FORALL (i_1, j: below(length[list[real]](cdr[list[real]](D)))):
            length[real](nth[list[real]](cdr[list[real]](D), i_1)) =
             length[real](nth[list[real]](cdr[list[real]](D), j))))
        AND
        (rows(cdr[list[real]](D)) > 0 AND columns(cdr[list[real]](D)) > 0)
         AND columns(cdr[list[real]](D)) = length[real](v);

  % Subtype TCC generated (at line 188, column 33) for  i - 1
      % expected type  nat
  replace_row_TCC7: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v)):
      NOT i = 0 AND NOT rows(D) = 1 AND NOT i >= rows(D) IMPLIES i - 1 >= 0;

  % Termination TCC generated (at line 188, column 21) for
      % replace_row(i - 1, v)(cdr(D))
  replace_row_TCC8: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v)):
      NOT i = 0 AND NOT rows(D) = 1 AND NOT i >= rows(D) IMPLIES
       rows(cdr[list[real]](D)) < rows(D);

  % Subtype TCC generated (at line 188, column 9) for
      % cons(car(D), replace_row(i - 1, v)(cdr(D)))
      % expected type  {PFM |
                     %          rows(PFM) = rows(D) AND
                     %           columns(PFM) = columns(D) AND
                     %            (FORALL (j):
                     %               row(PFM)(j) =
                     %                IF j < rows(D) AND j = i
                     %                THEN v
                     %                ELSE row(D)(j)
                     %                ENDIF)
                     %             AND
                     %             (FORALL (j, k):
                     %                entry(PFM)(j, k)
                     %                =
                     %                IF j < rows(D) AND j = i
                     %                THEN access(v)(k)
                     %                ELSE entry(D)(j, k)
                     %                ENDIF)}
  replace_row_TCC9: OBLIGATION
    FORALL (i: nat, v: Vector,
            D: PosFullMatrix | columns(D) = length[real](v),
            v1:
              [d1: [nat, Vector] ->
                 [D1:
                    {z: {D | columns(D) = length(d1`2)} |
                             rows(z) < rows(D)} ->
                    {PFM |
                             rows(PFM) = rows(D1) AND
                              columns(PFM) = columns(D1) AND
                               (FORALL (j):
                                  row(PFM)(j) =
                                   IF j < rows(D1) AND j = d1`1 THEN d1`2
                                   ELSE row(D1)(j)
                                   ENDIF)
                                AND
                                (FORALL (j, k):
                                   entry(PFM)(j, k) =
                                    IF j < rows(D1) AND j = d1`1
                                      THEN access(d1`2)(k)
                                    ELSE entry(D1)(j, k)
                                    ENDIF)}]]):
      NOT i = 0 AND NOT rows(D) = 1 AND NOT i >= rows(D) IMPLIES
            null?[list[real]]
                (cons[list[real]]
                     (car[list[real]](D), v1(i - 1, v)(cdr[list[real]](D))))
             OR
             (FORALL (i_1,
                      j:
                        below(length[list[real]]
                                  (cons[list[real]]
                                       (car[list[real]](D),
                                        v1(i - 1, v)(cdr[list[real]](D)))))):
                length[real]
                    (nth[list[real]]
                         (cons[list[real]]
                              (car[list[real]](D),
                               v1(i - 1, v)(cdr[list[real]](D))),
                          i_1))
                 =
                 length[real]
                     (nth[list[real]]
                          (cons[list[real]]
                               (car[list[real]](D),
                                v1(i - 1, v)(cdr[list[real]](D))),
                           j)))
        AND rows(cons[list[real]]
                     (car[list[real]](D), v1(i - 1, v)(cdr[list[real]](D))))
             > 0
        AND columns(cons[list[real]]
                        (car[list[real]](D),
                         v1(i - 1, v)(cdr[list[real]](D))))
             > 0
        AND rows(cons[list[real]]
                     (car[list[real]](D), v1(i - 1, v)(cdr[list[real]](D))))
             = rows(D)
        AND columns(cons[list[real]]
                        (car[list[real]](D),
                         v1(i - 1, v)(cdr[list[real]](D))))
             = columns(D)
        AND FORALL (j):
              row(cons[list[real]]
                      (car[list[real]](D), v1(i - 1, v)(cdr[list[real]](D))))
                 (j)
               = IF j < rows(D) AND j = i THEN v ELSE row(D)(j) ENDIF
        AND FORALL (j, k):
              entry(cons[list[real]]
                        (car[list[real]](D),
                         v1(i - 1, v)(cdr[list[real]](D))))
                   (j, k)
               =
               IF j < rows(D) AND j = i THEN access(v)(k)
               ELSE entry(D)(j, k)
               ENDIF;

  % Subtype TCC generated (at line 204, column 69) for  swap(i, j)(D)
      % expected type  D: {D | columns(D) = length(v)}
  swap_replace_row_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i, j, k: nat, v: Vector):
           k < rows(D) AND j < rows(D) AND i < rows(D)
       AND columns(D) = length(v) AND i = k
       IMPLIES columns(swap(i, j)(D)) = length[real](v);

  % Subtype TCC generated (at line 205, column 47) for  swap(i, j)(D)
      % expected type  D: {D | columns(D) = length(v)}
  swap_replace_row_TCC2: OBLIGATION
    FORALL (D: PosFullMatrix, i, j, k: nat, v: Vector):
           k < rows(D) AND j < rows(D) AND i < rows(D)
       AND columns(D) = length(v) AND NOT i = k AND j = k
       IMPLIES columns(swap(i, j)(D)) = length[real](v);

  % Subtype TCC generated (at line 206, column 31) for  swap(i, j)(D)
      % expected type  D: {D | columns(D) = length(v)}
  swap_replace_row_TCC3: OBLIGATION
    FORALL (D: PosFullMatrix, i, j, k: nat, v: Vector):
           k < rows(D) AND j < rows(D) AND i < rows(D)
       AND columns(D) = length(v) AND NOT i = k AND NOT j = k
       IMPLIES columns(swap(i, j)(D)) = length[real](v);

  % Subtype TCC generated (at line 215, column 29) for  D
      % expected type  D: {D | columns(D) = length(v1 + v2)}
  det_replace_row_sum_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i: nat, v1, v2: Vector):
      i < rows(D) AND columns(D) = length(v1) AND length(v1) = length(v2)
       IMPLIES columns(D) = length[real](v1 + v2);

  % Subtype TCC generated (at line 215, column 85) for  D
      % expected type  D: {D | columns(D) = length(v2)}
  det_replace_row_sum_TCC2: OBLIGATION
    FORALL (D: PosFullMatrix, i: nat, v1, v2: Vector):
      i < rows(D) AND columns(D) = length(v1) AND length(v1) = length(v2)
       IMPLIES columns(D) = length[real](v2);

  % Subtype TCC generated (at line 218, column 27) for  D
      % expected type  D: {D | columns(D) = length(r * v)}
  det_replace_row_scal_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i: nat, r: real, v: Vector):
      i < rows(D) AND columns(D) = length(v) IMPLIES
       columns(D) = length[real](r * v);

  % Subtype TCC generated (at line 221, column 29) for  D
      % expected type  D: {D_1 | columns(D_1) = length(row(D)(i))}
  replace_row_id_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i: nat):
      i < rows(D) IMPLIES columns(D) = length[real](row(D)(i));

  % Subtype TCC generated (at line 224, column 45) for  D
      % expected type  D:
                     %   {D_1 |
                     %            columns(D_1) =
                     %             length(row(D)(i) + r * row(D)(j))}
  det_replace_row_sum_scal_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i, j: nat, r: real):
      i /= j AND j < rows(D) AND i < rows(D) IMPLIES
       columns(D) = length[real](row(D)(i) + r * row(D)(j));

  % Subtype TCC generated (at line 227, column 39) for  D
      % expected type  D: {D_1 | columns(D_1) = length(row(D)(i) + row(D)(j))}
  replace_row_sum_to_scal_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i, j: nat):
      j < rows(D) AND i < rows(D) IMPLIES
       columns(D) = length[real](row(D)(i) + row(D)(j));

  % Subtype TCC generated (at line 227, column 79) for  D
      % expected type  D:
                     %   {D_1 |
                     %            columns(D_1) =
                     %             length(row(D)(i) + 1 * row(D)(j))}
  replace_row_sum_to_scal_TCC2: OBLIGATION
    FORALL (D: PosFullMatrix, i, j: nat):
      j < rows(D) AND i < rows(D) IMPLIES
       columns(D) = length[real](row(D)(i) + 1 * row(D)(j));

  % Subtype TCC generated (at line 238, column 14) for  remove(D, j, i)
      % expected type  PosFullMatrix
  remove_transpose_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i, j: nat):
      columns(D) > 1 AND rows(D) > 1 IMPLIES
       rows(remove(D, j, i)) > 0 AND columns(remove(D, j, i)) > 0;


body:
  matrix_det: THEORY


  BEGIN

    IMPORTING matrix_props,orders@lex3


    SM,SM1,SM2: VAR FullMatrix

    r: VAR real

    nzr: VAR nzreal

    M,N,A,B: VAR Matrix

    v,v1,v2: VAR Vector

    i,j,k,p : VAR nat

    m,n : VAR nat

    pn,pm : VAR posnat

    F,G: VAR [[nat,nat]->real]

    Mp,Np: VAR (nonempty?)

    PFM,D1,D2,D: VAR PosFullMatrix

    SQ,IQ,GQ,
    SQ2,IQ2,GQ2,DQ,DQ2,
    Q,R,S,T,
    Q2,R2,S2,T2: VAR Square

    % Elementary Matrices

    Esr(pn)(i,r): SquareMatrix(pn) =
      form_matrix(LAMBDA (k,j:nat): IF k/=j THEN 0 ELSIF k/=i THEN 1 ELSE r ENDIF,pn,pn)

    entry_Esr: LEMMA entry(Esr(pn)(i,r))(k,j) =
      IF k/=j OR k>=pn OR j>=pn THEN 0 ELSIF k/=i THEN 1 ELSE r ENDIF

    rows_Esr: LEMMA rows(Esr(pn)(i,r)) = pn

    columns_Esr: LEMMA columns(Esr(pn)(i,r)) = pn

    det_Esr: LEMMA i<pn IMPLIES det(Esr(pn)(i,r)) = r

    transpose_Esr: LEMMA transpose(Esr(pn)(i,r)) = Esr(pn)(i,r)

    mult_Esr_left: LEMMA rows(D)=pn AND i<pn IMPLIES Esr(pn)(i,r)*D = replace_row(i,r*row(D)(i))(D)

    mult_Esr_Esr_inv: LEMMA r/=0 AND i<pn IMPLIES Esr(pn)(i,r)*Esr(pn)(i,1/r)=Id(pn)


    Ers(pn)(i,j): {M:SquareMatrix(pn)|M=swap(i,j)(Id(pn))} =
      form_matrix(LAMBDA (k,p:nat): IF k=i AND p=j THEN 1
      		       		  ELSIF k=j AND p=i THEN 1
  				  ELSIF k/=i AND k/=j AND k=p THEN 1
  				  ELSE 0 ENDIF,pn,pn)

    entry_Ers: LEMMA entry(Ers(pn)(i,j))(k,p) =
      IF k>=pn OR p>=pn THEN 0 ELSIF k=i AND p=j THEN 1 ELSIF k=j AND p=i THEN 1
      ELSIF k/=i AND k/=j AND k=p THEN 1 ELSE 0 ENDIF

    rows_Ers: LEMMA rows(Ers(pn)(i,j)) = pn

    columns_Ers: LEMMA columns(Ers(pn)(i,j)) = pn

    mult_Ers_left: LEMMA rows(D)=pn AND i<pn AND j<pn IMPLIES
      Ers(pn)(i,j)*D = swap(i,j)(D)

    transpose_Ers: LEMMA transpose(Ers(pn)(i,j)) = Ers(pn)(j,i)

    det_Ers: LEMMA i<pn AND j<pn IMPLIES
      det(Ers(pn)(i,j)) = IF i = j THEN 1 ELSE -1 ENDIF

    mult_Ers_Ers_inv: LEMMA i<pn AND j<pn IMPLIES
      Ers(pn)(i,j)*Ers(pn)(i,j) = Id(pn)

    Easr(pn)(i,j,r): SquareMatrix(pn) =
      form_matrix(LAMBDA (k,p:nat): IF k=i THEN (IF j=i AND p=i THEN 1+r
      		       		     	       ELSIF p=i THEN 1 ELSIF p=j THEN r
  					       ELSE 0 ENDIF)
  				  ELSIF k=p THEN 1 ELSE 0 ENDIF,pn,pn)

    entry_Easr: LEMMA entry(Easr(pn)(i,j,r))(k,p) =
      IF k>=pn OR p>=pn THEN 0 ELSIF k=i THEN (IF j=i AND p=i THEN 1+r
      	ELSIF p=i THEN 1 ELSIF p=j THEN r ELSE 0 ENDIF)
  	ELSIF k=p THEN 1 ELSE 0 ENDIF

    rows_Easr: LEMMA rows(Easr(pn)(i,j,r)) = pn

    columns_Easr: LEMMA columns(Easr(pn)(i,j,r)) = pn

    mult_Easr_left: LEMMA rows(D)=pn AND i<pn AND j<pn IMPLIES
      Easr(pn)(i,j,r)*D = replace_row(i,row(D)(i)+r*row(D)(j))(D)

    transpose_Easr: LEMMA transpose(Easr(pn)(i,j,r)) = Easr(pn)(j,i,r)

    det_Easr: LEMMA i<pn AND j<pn IMPLIES
      det(Easr(pn)(i,j,r)) = IF i = j THEN 1+r ELSE 1 ENDIF

    mult_Easr_Easr_inv: LEMMA i<pn AND j<pn AND i/=j IMPLIES
      Easr(pn)(i,j,r)*Easr(pn)(i,j,-r) = Id(pn)

    % Zero

    ZERO(pn): SquareMatrix(pn) = form_matrix(LAMBDA (i,j): 0,pn,pn)

    % Upper triangulation

    upper_triangular?(M): bool =
      FORALL (i,j): i>j AND i<rows(M) IMPLIES entry(M)(i,j)=0

    prod_diag((M|rows(M)>0),i): RECURSIVE real =
      IF i >=rows(M)-1 THEN entry(M)(rows(M)-1,rows(M)-1) 
      ELSE entry(M)(i,i)*prod_diag(M,i+1) ENDIF MEASURE max(rows(M)-i,0)

    prod_diag_remove_0_0: LEMMA k+1<rows(S) IMPLIES
      prod_diag(remove(S, 0, 0), k) = prod_diag(S,k+1)

    diagonal?(M): bool = FORALL (i,j): i/=j IMPLIES entry(M)(i,j)=0

    diagonal_upper_triangular: LEMMA
      diagonal?(M) IMPLIES upper_triangular?(M)

    det_upper_triangular: LEMMA
      upper_triangular?(S) IMPLIES
      det(S) = prod_diag(S,0)
    
    det_upper_triangular_zero: LEMMA
      upper_triangular?(S) IMPLIES
      (det(S)=0 IFF (EXISTS (i): i<rows(S) AND entry(S)(i,i)=0))

    upper_triangular_mult: LEMMA
      upper_triangular?(S) AND upper_triangular?(R) IMPLIES
      upper_triangular?(S*R)

    lower_triangular?(M): bool =
      FORALL (i,j): i<j AND i<rows(M) IMPLIES entry(M)(i,j)=0

    lower_triangular_mult: LEMMA
      lower_triangular?(S) AND lower_triangular?(R) IMPLIES
      lower_triangular?(S*R)

    upper_triangular_Id: LEMMA upper_triangular?(Id(pn))

    lower_triangular_Id: LEMMA lower_triangular?(Id(pn))

    upper_triangular_Easr: LEMMA i<j IMPLIES
      upper_triangular?(Easr(pn)(i,j,r))

    lower_triangular_Easr: LEMMA i>j IMPLIES
      lower_triangular?(Easr(pn)(i,j,r))

    % Products elementary matrices

    include_scals,
    include_swaps: VAR bool % allow scalar multiple row elementary matrices in
    		      % the products or not

    prod_mat(pn)(FM:[nat->SquareMatrix(pn)],k): RECURSIVE SquareMatrix(pn) =
      IF k=0 THEN FM(0) ELSE prod_mat(pn)(FM,k-1)*FM(k) ENDIF MEASURE k

    prod_mat_eq: LEMMA FORALL (FM,GM:[nat->SquareMatrix(pn)]):
      (FORALL (i):i<=k IMPLIES FM(i)=GM(i)) IMPLIES prod_mat(pn)(FM,k)=prod_mat(pn)(GM,k)

    mult_prod_mat: LEMMA FORALL (FM,GM:[nat->SquareMatrix(pn)]):
      prod_mat(pn)(FM,k)*prod_mat(pn)(GM,p) =
      prod_mat(pn)(LAMBDA (i:nat): IF i<=k THEN FM(i) ELSE GM(i-k-1) ENDIF,k+p+1)

    prod_mat_expand_left: LEMMA FORALL (FM:[nat->SquareMatrix(pn)]): k>0 IMPLIES
      prod_mat(pn)(FM,k) = FM(0)*prod_mat(pn)(LAMBDA (i): FM(i+1),k-1)

    transpose_prod_mat: LEMMA FORALL (FM:[nat->SquareMatrix(pn)]):
      transpose(prod_mat(pn)(FM,k)) = prod_mat(pn)(LAMBDA (i): IF i<=k THEN 
      				  transpose(FM(k-i)) ELSE FM(i) ENDIF,k)

    is_simple_seq?(pn)(FM:[nat->SquareMatrix(pn)],k,include_scals,include_swaps):bool =
      FORALL (p): FM(p)=Id(pn) OR 
        (include_swaps AND EXISTS (i,j): i<pn AND j<pn AND FM(p)=Ers(pn)(i,j)) OR
        (EXISTS (i,j,r): i<pn AND j<pn AND i/=j AND FM(p) = Easr(pn)(i,j,r)) OR
        (include_scals AND EXISTS (i,r): i<pn AND FM(p) = Esr(pn)(i,r))

    is_simple_prod?(pn,include_scals,include_swaps)(SQ:SquareMatrix(pn)): bool = 
      EXISTS (FM:[nat->SquareMatrix(pn)],k): is_simple_seq?(pn)(FM,k,include_scals,include_swaps)
        AND SQ = prod_mat(pn)(FM,k)

    mult_simple_prod: LEMMA FORALL (R,S:SquareMatrix(pn)):
      is_simple_prod?(pn,include_scals,include_swaps)(R) AND
      is_simple_prod?(pn,include_scals,include_swaps)(S) IMPLIES
      is_simple_prod?(pn,include_scals,include_swaps)(R*S)

    Id_simple_prod: LEMMA is_simple_prod?(pn,include_scals,include_swaps)(Id(pn))

    Esr_simple_prod: LEMMA i<pn AND include_scals  IMPLIES
      is_simple_prod?(pn,include_scals,include_swaps)(Esr(pn)(i,r))

    Ers_simple_prod: LEMMA i<pn AND j<pn AND include_swaps IMPLIES
      is_simple_prod?(pn,include_scals,include_swaps)(Ers(pn)(i,j))

    Easr_simple_prod: LEMMA i<pn AND j<pn AND i/=j IMPLIES
      is_simple_prod?(pn,include_scals,include_swaps)(Easr(pn)(i,j,r))

    det_simple_prod_1: LEMMA FORALL (S:SquareMatrix(pn)):
      is_simple_prod?(pn,false,false)(S) IMPLIES
      det(S)=1

    det_mult_simple_prod_left: LEMMA FORALL (S,R:SquareMatrix(pn)):
      is_simple_prod?(pn,false,false)(S) IMPLIES
      det(S*R)=det(R)

    Easr_null: LEMMA NOT null?(Easr(pn)(i,j,r))

    transpose_simple_prod: LEMMA FORALL (S:SquareMatrix(pn)):
      is_simple_prod?(pn,include_scals,include_swaps)(S) IFF 
      is_simple_prod?(pn,include_scals,include_swaps)(transpose(S))

    diagonal_simple_prod: LEMMA FORALL (S:SquareMatrix(pn)):
    			diagonal?(S) IMPLIES is_simple_prod?(pn,true,include_swaps)(S)

    is_simple_prod_implic: LEMMA
      FORALL (S:SquareMatrix(pn),include_scals2,include_swaps2:bool):
      (include_scals IMPLIES include_scals2) AND
      (include_swaps IMPLIES include_swaps2) AND
      is_simple_prod?(pn,include_scals,include_swaps)(S) IMPLIES
      is_simple_prod?(pn,include_scals2,include_swaps2)(S)





  END matrix_det

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 39, column 4) for
      % form_matrix(LAMBDA (k, j: nat):
      %               IF k /= j THEN 0 ELSIF k /= i THEN 1 ELSE r ENDIF,
      %             pn, pn)
      % expected type  SquareMatrix(pn)
  Esr_TCC1: OBLIGATION
    FORALL (pn: posnat, i: nat, r: real):
      rows(form_matrix(LAMBDA (k, j: nat):
                         IF k /= j THEN 0 ELSIF k /= i THEN 1 ELSE r ENDIF,
                       pn, pn))
       = pn
       AND
       rows(form_matrix(LAMBDA (k, j: nat):
                          IF k /= j THEN 0 ELSIF k /= i THEN 1 ELSE r ENDIF,
                        pn, pn))
        =
        columns(form_matrix(LAMBDA (k, j: nat):
                              IF k /= j THEN 0
                              ELSIF k /= i THEN 1
                              ELSE r
                              ENDIF,
                            pn, pn))
        AND
        rows(form_matrix(LAMBDA (k, j: nat):
                           IF k /= j THEN 0 ELSIF k /= i THEN 1 ELSE r ENDIF,
                         pn, pn))
         > 0
         AND
         columns(form_matrix(LAMBDA (k, j: nat):
                               IF k /= j THEN 0
                               ELSIF k /= i THEN 1
                               ELSE r
                               ENDIF,
                             pn, pn))
          > 0;

  % Subtype TCC generated (at line 52, column 95) for  D
      % expected type  D: {D_1 | columns(D_1) = length(r * row(D)(i))}
  mult_Esr_left_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i: nat, pn: posnat, r: real):
      i < pn AND rows(D) = pn IMPLIES
       columns(D) = length[real](r * row(D)(i));

  % Subtype TCC generated (at line 58, column 4) for
      % form_matrix(LAMBDA (k, p: nat):
      %               IF k = i AND p = j THEN 1
      %               ELSIF k = j AND p = i THEN 1
      %               ELSIF k /= i AND k /= j AND k = p THEN 1
      %               ELSE 0
      %               ENDIF,
      %             pn, pn)
      % expected type  {M: SquareMatrix(pn) | M = swap(i, j)(Id(pn))}
  Ers_TCC1: OBLIGATION
    FORALL (pn: posnat, i: nat, j: nat):
           form_matrix(LAMBDA (k, p: nat):
                         IF k = i AND p = j THEN 1
                         ELSIF k = j AND p = i THEN 1
                         ELSIF k /= i AND k /= j AND k = p THEN 1
                         ELSE 0
                         ENDIF,
                       pn, pn)
            = swap(i, j)(Id(pn))
       AND rows(form_matrix(LAMBDA (k, p: nat):
                              IF k = i AND p = j THEN 1
                              ELSIF k = j AND p = i THEN 1
                              ELSIF k /= i AND k /= j AND k = p THEN 1
                              ELSE 0
                              ENDIF,
                            pn, pn))
            = pn
       AND rows(form_matrix(LAMBDA (k, p: nat):
                              IF k = i AND p = j THEN 1
                              ELSIF k = j AND p = i THEN 1
                              ELSIF k /= i AND k /= j AND k = p THEN 1
                              ELSE 0
                              ENDIF,
                            pn, pn))
            =
            columns(form_matrix(LAMBDA (k, p: nat):
                                  IF k = i AND p = j THEN 1
                                  ELSIF k = j AND p = i THEN 1
                                  ELSIF k /= i AND k /= j AND k = p THEN 1
                                  ELSE 0
                                  ENDIF,
                                pn, pn))
       AND rows(form_matrix(LAMBDA (k, p: nat):
                              IF k = i AND p = j THEN 1
                              ELSIF k = j AND p = i THEN 1
                              ELSIF k /= i AND k /= j AND k = p THEN 1
                              ELSE 0
                              ENDIF,
                            pn, pn))
            > 0
       AND columns(form_matrix(LAMBDA (k, p: nat):
                                 IF k = i AND p = j THEN 1
                                 ELSIF k = j AND p = i THEN 1
                                 ELSIF k /= i AND k /= j AND k = p THEN 1
                                 ELSE 0
                                 ENDIF,
                               pn, pn))
            > 0;

  % Subtype TCC generated (at line 83, column 4) for
      % form_matrix(LAMBDA (k, p: nat):
      %               IF k = i
      %                 THEN (IF j = i AND p = i THEN 1 + r
      %                       ELSIF p = i THEN 1
      %                       ELSIF p = j THEN r
      %                       ELSE 0
      %                       ENDIF)
      %               ELSIF k = p THEN 1
      %               ELSE 0
      %               ENDIF,
      %             pn, pn)
      % expected type  SquareMatrix(pn)
  Easr_TCC1: OBLIGATION
    FORALL (pn: posnat, i: nat, j: nat, r: real):
      rows(form_matrix(LAMBDA (k, p: nat):
                         IF k = i
                           THEN (IF j = i AND p = i THEN 1 + r
                                 ELSIF p = i THEN 1
                                 ELSIF p = j THEN r
                                 ELSE 0
                                 ENDIF)
                         ELSIF k = p THEN 1
                         ELSE 0
                         ENDIF,
                       pn, pn))
       = pn
       AND
       rows(form_matrix(LAMBDA (k, p: nat):
                          IF k = i
                            THEN (IF j = i AND p = i THEN 1 + r
                                  ELSIF p = i THEN 1
                                  ELSIF p = j THEN r
                                  ELSE 0
                                  ENDIF)
                          ELSIF k = p THEN 1
                          ELSE 0
                          ENDIF,
                        pn, pn))
        =
        columns(form_matrix(LAMBDA (k, p: nat):
                              IF k = i
                                THEN (IF j = i AND p = i
                                      THEN 1 + r
                                      ELSIF p = i
                                      THEN 1
                                      ELSIF p = j
                                      THEN r
                                      ELSE 0
                                      ENDIF)
                              ELSIF k = p THEN 1
                              ELSE 0
                              ENDIF,
                            pn, pn))
        AND
        rows(form_matrix(LAMBDA (k, p: nat):
                           IF k = i
                             THEN (IF j = i AND p = i THEN 1 + r
                                   ELSIF p = i THEN 1
                                   ELSIF p = j THEN r
                                   ELSE 0
                                   ENDIF)
                           ELSIF k = p THEN 1
                           ELSE 0
                           ENDIF,
                         pn, pn))
         > 0
         AND
         columns(form_matrix(LAMBDA (k, p: nat):
                               IF k = i
                                 THEN (IF j = i AND p = i
                                       THEN 1 + r
                                       ELSIF p = i
                                       THEN 1
                                       ELSIF p = j
                                       THEN r
                                       ELSE 0
                                       ENDIF)
                               ELSIF k = p THEN 1
                               ELSE 0
                               ENDIF,
                             pn, pn))
          > 0;

  % Subtype TCC generated (at line 98, column 61) for  D
      % expected type  D:
                     %   {D_1 |
                     %            columns(D_1) =
                     %             length(row(D)(i) + r * row(D)(j))}
  mult_Easr_left_TCC1: OBLIGATION
    FORALL (D: PosFullMatrix, i, j: nat, pn: posnat, r: real):
      j < pn AND i < pn AND rows(D) = pn IMPLIES
       columns(D) = length[real](row(D)(i) + r * row(D)(j));

  % Subtype TCC generated (at line 110, column 31) for
      % form_matrix(LAMBDA (i, j): 0, pn, pn)
      % expected type  SquareMatrix(pn)
  ZERO_TCC1: OBLIGATION
    FORALL (pn: posnat):
      rows(form_matrix(LAMBDA (i, j): 0, pn, pn)) = pn AND
       rows(form_matrix(LAMBDA (i, j): 0, pn, pn)) =
        columns(form_matrix(LAMBDA (i, j): 0, pn, pn))
        AND
        rows(form_matrix(LAMBDA (i, j): 0, pn, pn)) > 0 AND
         columns(form_matrix(LAMBDA (i, j): 0, pn, pn)) > 0;

  % Subtype TCC generated (at line 119, column 54) for  max(rows(M) - i, 0)
      % expected type  naturalnumber
  prod_diag_TCC1: OBLIGATION
    FORALL ((M: Matrix | rows(M) > 0), i: nat): max(rows(M) - i, 0) >= 0;

  % Subtype TCC generated (at line 118, column 35) for  rows(M) - 1
      % expected type  nat
  prod_diag_TCC2: OBLIGATION
    FORALL ((M: Matrix | rows(M) > 0), i: nat):
      i >= rows(M) - 1 IMPLIES rows(M) - 1 >= 0;

  % Termination TCC generated (at line 119, column 23) for
      % prod_diag(M, i + 1)
  prod_diag_TCC3: OBLIGATION
    FORALL ((M: Matrix | rows(M) > 0), i: nat):
      NOT i >= rows(M) - 1 IMPLIES
       max(rows(M) - (i + 1), 0) < max(rows(M) - i, 0);

  % Subtype TCC generated (at line 122, column 14) for  remove(S, 0, 0)
      % expected type  {M | rows(M) > 0}
  prod_diag_remove_0_0_TCC1: OBLIGATION
    FORALL (S: Square, k: nat):
      k + 1 < rows(S) IMPLIES rows(remove(S, 0, 0)) > 0;

  % Subtype TCC generated (at line 165, column 43) for  k - 1
      % expected type  nat
  prod_mat_TCC1: OBLIGATION
    FORALL (pn: posnat, FM: [nat -> SquareMatrix(pn)], k: nat):
      NOT k = 0 IMPLIES k - 1 >= 0;

  % Termination TCC generated (at line 165, column 27) for
      % prod_mat(pn)(FM, k - 1)
  prod_mat_TCC2: OBLIGATION
    FORALL (pn: posnat, FM: [nat -> SquareMatrix(pn)], k: nat):
      NOT k = 0 IMPLIES k - 1 < k;

  % Subtype TCC generated (at line 165, column 27) for
      % prod_mat(pn)(FM, k - 1) * FM(k)
      % expected type  SquareMatrix(pn)
  prod_mat_TCC3: OBLIGATION
    FORALL (pn: posnat, FM: [nat -> SquareMatrix(pn)], k: nat,
            v:
              [pn1: posnat ->
                 [{z: [[nat -> SquareMatrix(pn1)], nat] | z`2 < k} ->
                    SquareMatrix(pn1)]]):
      NOT k = 0 IMPLIES
       rows(v(pn)(FM, k - 1) * FM(k)) = pn AND
        rows(v(pn)(FM, k - 1) * FM(k)) = columns(v(pn)(FM, k - 1) * FM(k))
         AND
         rows(v(pn)(FM, k - 1) * FM(k)) > 0 AND
          columns(v(pn)(FM, k - 1) * FM(k)) > 0;

  % Subtype TCC generated (at line 172, column 60) for  i - k - 1
      % expected type  nat
  mult_prod_mat_TCC1: OBLIGATION
    FORALL (k: nat, pn: posnat, FM, GM: [nat -> SquareMatrix(pn)], i: nat):
      NOT i <= k IMPLIES i - k - 1 >= 0;

  % Subtype TCC generated (at line 175, column 64) for  k - 1
      % expected type  nat
  prod_mat_expand_left_TCC1: OBLIGATION
    FORALL (k: nat, pn: posnat, FM: [nat -> SquareMatrix(pn)]):
      k > 0 IMPLIES k - 1 >= 0;

  % Subtype TCC generated (at line 179, column 23) for  k - i
      % expected type  nat
  transpose_prod_mat_TCC1: OBLIGATION
    FORALL (k: nat, pn: posnat, FM: [nat -> SquareMatrix(pn)], i: nat):
      i <= k IMPLIES k - i >= 0;

  % Subtype TCC generated (at line 179, column 10) for  transpose(FM(k - i))
      % expected type  SquareMatrix(pn)
  transpose_prod_mat_TCC2: OBLIGATION
    FORALL (k: nat, pn: posnat, FM: [nat -> SquareMatrix(pn)], i: nat):
      i <= k IMPLIES
       rows(transpose(FM(k - i))) = columns(transpose(FM(k - i))) AND
        rows(transpose(FM(k - i))) = pn;

  % Subtype TCC generated (at line 194, column 52) for  R * S
      % expected type  SquareMatrix(pn)
  mult_simple_prod_TCC1: OBLIGATION
    FORALL (include_scals, include_swaps: bool, pn: posnat,
            R, S: SquareMatrix(pn)):
      is_simple_prod?(pn, include_scals, include_swaps)(R) AND
       is_simple_prod?(pn, include_scals, include_swaps)(S)
       IMPLIES
       rows(R * S) = pn AND
        rows(R * S) = columns(R * S) AND
         rows(R * S) > 0 AND columns(R * S) > 0;

  % Subtype TCC generated (at line 219, column 52) for  transpose(S)
      % expected type  SquareMatrix(pn)
  transpose_simple_prod_TCC1: OBLIGATION
    FORALL (pn: posnat, S: SquareMatrix(pn)):
      rows(transpose(S)) = columns(transpose(S)) AND rows(transpose(S)) = pn;


body:
  matrix_upper_triang: THEORY


  BEGIN

    IMPORTING matrix_det


    SM,SM1,SM2: VAR FullMatrix

    r: VAR real

    nzr: VAR nzreal

    M,N,A,B: VAR Matrix

    v,v1,v2: VAR Vector

    i,j,k,p : VAR nat

    m,n : VAR nat

    pn,pm : VAR posnat

    F,G: VAR [[nat,nat]->real]

    Mp,Np: VAR (nonempty?)

    PFM,D1,D2,D: VAR PosFullMatrix

    SQ,IQ,GQ,
    SQ2,IQ2,GQ2,DQ,DQ2,
    Q,R,S,T,
    Q2,R2,S2,T2: VAR Square

    ut_point1(SQ)(j): bool = 
      j<rows(SQ) AND
      (FORALL (k,p):p<j AND k>p AND k<rows(SQ) IMPLIES entry(SQ)(k,p)=0)

    ut_point2(SQ,j)(i): bool =
      i<rows(SQ) AND i>=j AND
      (FORALL (k):k>i AND k<rows(SQ) IMPLIES entry(SQ)(k,j)=0)

    % j is the column, i is the row. j comes first as an input

    upper_triangulate(pn)(comp_matrix,comp_inverse:bool,
      S:SquareMatrix(pn),
      (Q:SquareMatrix(pn)|is_simple_prod?(pn,false,false)(Q)),
      (R:SquareMatrix(pn)|is_simple_prod?(pn,false,false)(R) 
                   AND (comp_matrix AND comp_inverse IMPLIES (R*Q=Id(pn) AND Q*R=Id(pn)))),
      (T:SquareMatrix(pn)|comp_matrix IMPLIES Q*T = S),
      (j|ut_point1(S)(j)),(i|ut_point2(S,j)(i)),stop_rec:bool,k): RECURSIVE
        {SGI:[SquareMatrix(pn),SquareMatrix(pn),SquareMatrix(pn)]|
          (not stop_rec) IMPLIES (LET (S2,Q2,R2)=SGI IN
  	 upper_triangular?(S2) AND
  	 (comp_matrix IMPLIES Q2*T=S2 AND is_simple_prod?(pn,false,false)(Q2)) AND
  	 (comp_matrix AND comp_inverse IMPLIES (R2*Q2=Id(pn) AND Q2*R2=Id(pn) AND 
  	        is_simple_prod?(pn,false,false)(R2))) AND
  	 det(S2)=det(S))} =
      IF (stop_rec AND k=0) OR (i=pn-1 AND j=pn-1) THEN (S,Q,R)
      ELSIF i=j THEN upper_triangulate(pn)(comp_matrix,comp_inverse,S,Q,R,T,j+1,pn-1,stop_rec,max(k-1,0))
      ELSIF entry(S)(i,j)=0 THEN upper_triangulate(pn)(comp_matrix,comp_inverse,S,Q,R,T,j,i-1,stop_rec,max(k-1,0))
      ELSIF entry(S)(j,j)=0 THEN 
        upper_triangulate(pn)(comp_matrix,comp_inverse,
  	                   replace_row(j,row(S)(j)+row(S)(i))(S),
  			   IF comp_matrix THEN replace_row(j,row(Q)(j)+row(Q)(i))(Q)
  				ELSE Id(pn) ENDIF,
  			   IF comp_matrix AND comp_inverse THEN R*Easr(pn)(j,i,-1) ELSE Id(pn) ENDIF,
  			   T,j,i,stop_rec,max(k-1,0))
      ELSE LET pivnum = -entry(S)(i,j)/entry(S)(j,j) IN
        upper_triangulate(pn)(comp_matrix,comp_inverse,
      			   replace_row(i,row(S)(i)+pivnum*row(S)(j))(S),
      			   IF comp_matrix THEN replace_row(i,row(Q)(i)+pivnum*row(Q)(j))(Q) ELSE Id(pn) ENDIF,
      			   IF comp_matrix AND comp_inverse THEN R*Easr(pn)(i,j,-pivnum) ELSE Id(pn) ENDIF,
      			   T,j,i-1,stop_rec,max(k-1,0))
      ENDIF MEASURE lex3(pn-j,i,IF entry(S)(i,j)/=0 AND entry(S)(j,j)=0 THEN 1 ELSE 0 ENDIF)




  END matrix_upper_triang

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 76, column 23) for  pn - j
      % expected type  nat
  upper_triangulate_TCC1: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i))):
      pn - j >= 0;

  % Subtype TCC generated (at line 76, column 23) for  pn1 - z`7
      % expected type  nat
  upper_triangulate_TCC2: OBLIGATION
    FORALL (pn1: posnat,
            z:
              [comp_matrix: bool, comp_inverse: bool, S: SquareMatrix(pn1),
               Q:
                 {Q: SquareMatrix(pn1) |
                          is_simple_prod?(pn1, FALSE, FALSE)(Q)},
               {R: SquareMatrix(pn1) |
                        is_simple_prod?(pn1, FALSE, FALSE)(R) AND
                         (comp_matrix AND comp_inverse IMPLIES
                           (R * Q = Id(pn1) AND Q * R = Id(pn1)))},
               {T: SquareMatrix(pn1) | comp_matrix IMPLIES Q * T = S},
               j: {j | ut_point1(S)(j)}, {i | ut_point2(S, j)(i)}, bool,
               nat]):
      pn1 - z`7 >= 0;

  % Subtype TCC generated (at line 76, column 23) for  pn - j
      % expected type  nat
  upper_triangulate_TCC3: OBLIGATION
    FORALL (pn, S: SquareMatrix(pn), (j: nat | ut_point1(S)(j))): pn - j >= 0;

  % Subtype TCC generated (at line 60, column 54) for  (S, Q, R)
      % expected type  {SGI:
                     %    [SquareMatrix(pn), SquareMatrix(pn),
                     %     SquareMatrix(pn)] |
                     %          (NOT stop_rec) IMPLIES
                     %           upper_triangular?(SGI`1) AND
                     %            (comp_matrix IMPLIES
                     %              SGI`2 * T = SGI`1 AND
                     %               is_simple_prod?(pn, FALSE, FALSE)
                     %                              (SGI`2))
                     %             AND
                     %             (comp_matrix AND comp_inverse IMPLIES
                     %               (SGI`3 * SGI`2 = Id(pn)
                     %                AND
                     %                SGI`2 * SGI`3 = Id(pn)
                     %                AND
                     %                is_simple_prod?
                     %                (pn, FALSE, FALSE)(SGI`3)))
                     %              AND det(SGI`1) = det(S)}
  upper_triangulate_TCC4: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      (stop_rec AND k = 0) OR (i = pn - 1 AND j = pn - 1) IMPLIES
       (NOT stop_rec) IMPLIES
        upper_triangular?(S) AND
         (comp_matrix IMPLIES
           Q * T = S AND is_simple_prod?(pn, FALSE, FALSE)(Q))
          AND
          (comp_matrix AND comp_inverse IMPLIES
            (R * Q = Id(pn) AND
              Q * R = Id(pn) AND is_simple_prod?(pn, FALSE, FALSE)(R)));

  % Subtype TCC generated (at line 61, column 74) for  j + 1
      % expected type  {j | ut_point1(S)(j)}
  upper_triangulate_TCC5: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      i = j AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES ut_point1(S)(j + 1);

  % Subtype TCC generated (at line 61, column 78) for  pn - 1
      % expected type  {i | ut_point2(S, 1 + j)(i)}
  upper_triangulate_TCC6: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      i = j AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES pn - 1 >= 0 AND ut_point2(S, 1 + j)(pn - 1);

  % Subtype TCC generated (at line 61, column 92) for  max(k - 1, 0)
      % expected type  nat
  upper_triangulate_TCC7: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      i = j AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES max(k - 1, 0) >= 0;

  % Termination TCC generated (at line 61, column 19) for
      % upper_triangulate(pn)
      %                  (comp_matrix, comp_inverse, S, Q, R, T, j + 1,
      %                   pn - 1, stop_rec, max(k - 1, 0))
  upper_triangulate_TCC8: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      i = j AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       lex3(pn - (j + 1), pn - 1,
            IF entry(S)(pn - 1, j + 1) /= 0 AND entry(S)(j + 1, j + 1) = 0
              THEN 1
            ELSE 0
            ENDIF)
        <
        lex3(pn - j, i,
             IF entry(S)(i, j) /= 0 AND entry(S)(j, j) = 0 THEN 1
             ELSE 0
             ENDIF);

  % Subtype TCC generated (at line 62, column 88) for  i - 1
      % expected type  {i | ut_point2(S, j)(i)}
  upper_triangulate_TCC9: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      entry(S)(i, j) = 0 AND
       NOT i = j AND
        NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES i - 1 >= 0 AND ut_point2(S, j)(i - 1);

  % Subtype TCC generated (at line 62, column 101) for  max(k - 1, 0)
      % expected type  nat
  upper_triangulate_TCC10: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      entry(S)(i, j) = 0 AND
       NOT i = j AND
        NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES max(k - 1, 0) >= 0;

  % Termination TCC generated (at line 62, column 31) for
      % upper_triangulate(pn)
      %                  (comp_matrix, comp_inverse, S, Q, R, T, j, i - 1,
      %                   stop_rec, max(k - 1, 0))
  upper_triangulate_TCC11: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      entry(S)(i, j) = 0 AND
       NOT i = j AND
        NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       lex3(pn - j, i - 1,
            IF entry(S)(i - 1, j) /= 0 AND entry(S)(j, j) = 0 THEN 1
            ELSE 0
            ENDIF)
        <
        lex3(pn - j, i,
             IF entry(S)(i, j) /= 0 AND entry(S)(j, j) = 0 THEN 1
             ELSE 0
             ENDIF);

  % Subtype TCC generated (at line 65, column 55) for  S
      % expected type  D: {D | columns(D) = length(row(S)(j) + row(S)(i))}
  upper_triangulate_TCC12: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES columns(S) = length[real](row(S)(j) + row(S)(i));

  % Subtype TCC generated (at line 65, column 20) for
      % replace_row(j, row(S)(j) + row(S)(i))(S)
      % expected type  SquareMatrix(pn)
  upper_triangulate_TCC13: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       rows(replace_row(j, row(S)(j) + row(S)(i))(S)) =
        columns(replace_row(j, row(S)(j) + row(S)(i))(S))
        AND rows(replace_row(j, row(S)(j) + row(S)(i))(S)) = pn;

  % Subtype TCC generated (at line 66, column 61) for  Q
      % expected type  D: {D | columns(D) = length(row(Q)(j) + row(Q)(i))}
  upper_triangulate_TCC14: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           comp_matrix AND entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0
       AND NOT i = j AND NOT (stop_rec AND k = 0)
       AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES columns(Q) = length[real](row(Q)(j) + row(Q)(i));

  % Subtype TCC generated (at line 66, column 26) for
      % replace_row(j, row(Q)(j) + row(Q)(i))(Q)
      % expected type  {Q: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(Q)}
  upper_triangulate_TCC15: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           comp_matrix AND entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0
       AND NOT i = j AND NOT (stop_rec AND k = 0)
       AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       rows(replace_row(j, row(Q)(j) + row(Q)(i))(Q)) =
        columns(replace_row(j, row(Q)(j) + row(Q)(i))(Q))
        AND
        rows(replace_row(j, row(Q)(j) + row(Q)(i))(Q)) = pn AND
         is_simple_prod?(pn, FALSE, FALSE)
                        (replace_row(j, row(Q)(j) + row(Q)(i))(Q));

  % Subtype TCC generated (at line 67, column 9) for  Id(pn)
      % expected type  {Q: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(Q)}
  upper_triangulate_TCC16: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT comp_matrix AND entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0
       AND NOT i = j AND NOT (stop_rec AND k = 0)
       AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES is_simple_prod?(pn, FALSE, FALSE)(Id(pn));

  % Subtype TCC generated (at line 68, column 43) for  R * Easr(pn)(j, i, -1)
      % expected type  {R: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(R) AND
                     %           (comp_matrix AND comp_inverse IMPLIES
                     %             (R *
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (j, row(Q)(j) + row(Q)(i))(Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %               = Id(pn)
                     %               AND
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (j, row(Q)(j) + row(Q)(i))(Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %                * R
                     %                = Id(pn)))}
  upper_triangulate_TCC17: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           comp_matrix AND comp_inverse AND entry(S)(j, j) = 0
       AND NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT (stop_rec AND k = 0)
       AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
            is_simple_prod?(pn, FALSE, FALSE)(R * Easr(pn)(j, i, -1))
        AND (comp_matrix AND comp_inverse IMPLIES
              (R * Easr(pn)(j, i, -1) *
                IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
                ELSE Id(pn)
                ENDIF
                = Id(pn)
                AND
                IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
                ELSE Id(pn)
                ENDIF
                 * (R * Easr(pn)(j, i, -1))
                 = Id(pn)))
        AND rows(R * Easr(pn)(j, i, -1)) = pn
        AND rows(R * Easr(pn)(j, i, -1)) = columns(R * Easr(pn)(j, i, -1))
        AND rows(R * Easr(pn)(j, i, -1)) > 0
        AND columns(R * Easr(pn)(j, i, -1)) > 0;

  % Subtype TCC generated (at line 68, column 67) for  Id(pn)
      % expected type  {R: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(R) AND
                     %           (comp_matrix AND comp_inverse IMPLIES
                     %             (R *
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (j, row(Q)(j) + row(Q)(i))(Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %               = Id(pn)
                     %               AND
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (j, row(Q)(j) + row(Q)(i))(Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %                * R
                     %                = Id(pn)))}
  upper_triangulate_TCC18: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT (comp_matrix AND comp_inverse) AND entry(S)(j, j) = 0
       AND NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT (stop_rec AND k = 0)
       AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       is_simple_prod?(pn, FALSE, FALSE)(Id(pn)) AND
        (comp_matrix AND comp_inverse IMPLIES
          (Id(pn) *
            IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
            ELSE Id(pn)
            ENDIF
            = Id(pn)
            AND
            IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
            ELSE Id(pn)
            ENDIF
             * Id(pn)
             = Id(pn)));

  % Subtype TCC generated (at line 69, column 6) for  T
      % expected type  {T: SquareMatrix(pn) |
                     %          comp_matrix IMPLIES
                     %           IF comp_matrix
                     %             THEN replace_row
                     %                  (j, row(Q)(j) + row(Q)(i))(Q)
                     %           ELSE Id(pn)
                     %           ENDIF
                     %            * T
                     %            = replace_row(j, row(S)(j) + row(S)(i))(S)}
  upper_triangulate_TCC19: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       comp_matrix IMPLIES
        IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
        ELSE Id(pn)
        ENDIF
         * T
         = replace_row(j, row(S)(j) + row(S)(i))(S);

  % Subtype TCC generated (at line 69, column 8) for  j
      % expected type  {j_1 |
                     %          ut_point1(replace_row
                     %                    (j, row(S)(j) + row(S)(i))(S))
                     %                   (j_1)}
  upper_triangulate_TCC20: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES ut_point1(replace_row(j, row(S)(j) + row(S)(i))(S))(j);

  % Subtype TCC generated (at line 69, column 10) for  i
      % expected type  {i_1 |
                     %          ut_point2(replace_row
                     %                    (j, row(S)(j) + row(S)(i))(S),
                     %                    j)
                     %                   (i_1)}
  upper_triangulate_TCC21: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES ut_point2(replace_row(j, row(S)(j) + row(S)(i))(S), j)(i);

  % Subtype TCC generated (at line 69, column 21) for  max(k - 1, 0)
      % expected type  nat
  upper_triangulate_TCC22: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES max(k - 1, 0) >= 0;

  % Termination TCC generated (at line 64, column 6) for
      % upper_triangulate(pn)
      %                  (comp_matrix, comp_inverse,
      %                   replace_row(j, row(S)(j) + row(S)(i))(S),
      %                   IF comp_matrix
      %                     THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
      %                   ELSE Id(pn)
      %                   ENDIF,
      %                   IF comp_matrix AND comp_inverse
      %                     THEN R * Easr(pn)(j, i, -1)
      %                   ELSE Id(pn)
      %                   ENDIF,
      %                   T, j, i, stop_rec, max(k - 1, 0))
  upper_triangulate_TCC23: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       lex3(pn - j, i,
            IF entry(replace_row(j, row(S)(j) + row(S)(i))(S))(i, j) /= 0 AND
                entry(replace_row(j, row(S)(j) + row(S)(i))(S))(j, j) = 0
              THEN 1
            ELSE 0
            ENDIF)
        <
        lex3(pn - j, i,
             IF entry(S)(i, j) /= 0 AND entry(S)(j, j) = 0 THEN 1
             ELSE 0
             ENDIF);

  % Subtype TCC generated (at line 64, column 6) for
      % upper_triangulate(pn)
      %                  (comp_matrix, comp_inverse,
      %                   replace_row(j, row(S)(j) + row(S)(i))(S),
      %                   IF comp_matrix
      %                     THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
      %                   ELSE Id(pn)
      %                   ENDIF,
      %                   IF comp_matrix AND comp_inverse
      %                     THEN R * Easr(pn)(j, i, -1)
      %                   ELSE Id(pn)
      %                   ENDIF,
      %                   T, j, i, stop_rec, max(k - 1, 0))
      % expected type  {SGI:
                     %    [SquareMatrix(pn), SquareMatrix(pn),
                     %     SquareMatrix(pn)] |
                     %          (NOT stop_rec) IMPLIES
                     %           upper_triangular?(SGI`1) AND
                     %            (comp_matrix IMPLIES
                     %              SGI`2 * T = SGI`1 AND
                     %               is_simple_prod?(pn, FALSE, FALSE)
                     %                              (SGI`2))
                     %             AND
                     %             (comp_matrix AND comp_inverse IMPLIES
                     %               (SGI`3 * SGI`2 = Id(pn)
                     %                AND
                     %                SGI`2 * SGI`3 = Id(pn)
                     %                AND
                     %                is_simple_prod?
                     %                (pn, FALSE, FALSE)(SGI`3)))
                     %              AND det(SGI`1) = det(S)}
  upper_triangulate_TCC24: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            v:
              [pn1: posnat ->
                 [d1:
                    {z:
                       [comp_matrix: bool, comp_inverse: bool,
                        S: SquareMatrix(pn1),
                        Q:
                          {Q: SquareMatrix(pn1) |
                                   is_simple_prod?(pn1, FALSE, FALSE)(Q)},
                        {R: SquareMatrix(pn1) |
                                 is_simple_prod?(pn1, FALSE, FALSE)(R) AND
                                  (comp_matrix AND comp_inverse IMPLIES
                                    (R * Q = Id(pn1) AND Q * R = Id(pn1)))},
                        {T: SquareMatrix(pn1) |
                                 comp_matrix IMPLIES Q * T = S},
                        j: {j | ut_point1(S)(j)}, {i | ut_point2(S, j)(i)},
                        bool, nat] |
                             lex3(pn1 - z`7, z`8,
                                  IF entry(z`3)(z`8, z`7) /= 0 AND
                                      entry(z`3)(z`7, z`7) = 0
                                    THEN 1
                                  ELSE 0
                                  ENDIF)
                              <
                              lex3(pn - j, i,
                                   IF entry(S)(i, j) /= 0
                                      AND
                                      entry(S)(j, j) = 0
                                     THEN 1
                                   ELSE 0
                                   ENDIF)} ->
                    {SGI:
                       [SquareMatrix(pn1), SquareMatrix(pn1),
                        SquareMatrix(pn1)] |
                             (NOT d1`9) IMPLIES
                              upper_triangular?(SGI`1) AND
                               (d1`1 IMPLIES
                                 SGI`2 * d1`6 = SGI`1 AND
                                  is_simple_prod?(pn1, FALSE, FALSE)(SGI`2))
                                AND
                                (d1`1 AND d1`2 IMPLIES
                                  (SGI`3 * SGI`2 = Id(pn1) AND
                                    SGI`2 * SGI`3 = Id(pn1) AND
                                     is_simple_prod?(pn1, FALSE, FALSE)
                                                    (SGI`3)))
                                 AND det(SGI`1) = det(d1`3)}]],
            stop_rec: bool, k: nat):
           entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (NOT stop_rec) IMPLIES
        upper_triangular?(v(pn)
                           (comp_matrix, comp_inverse,
                            replace_row(j, row(S)(j) + row(S)(i))(S),
                            IF comp_matrix
                              THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
                            ELSE Id(pn)
                            ENDIF,
                            IF comp_matrix AND comp_inverse
                              THEN R * Easr(pn)(j, i, -1)
                            ELSE Id(pn)
                            ENDIF,
                            T, j, i, stop_rec, max(k - 1, 0))`1)
         AND
         (comp_matrix IMPLIES
           v(pn)
            (comp_matrix, comp_inverse,
             replace_row(j, row(S)(j) + row(S)(i))(S),
             IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
             ELSE Id(pn)
             ENDIF,
             IF comp_matrix AND comp_inverse THEN R * Easr(pn)(j, i, -1)
             ELSE Id(pn)
             ENDIF,
             T, j, i, stop_rec, max(k - 1, 0))`2
            * T
            =
            v(pn)
             (comp_matrix, comp_inverse,
              replace_row(j, row(S)(j) + row(S)(i))(S),
              IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
              ELSE Id(pn)
              ENDIF,
              IF comp_matrix AND comp_inverse THEN R * Easr(pn)(j, i, -1)
              ELSE Id(pn)
              ENDIF,
              T, j, i, stop_rec, max(k - 1, 0))`1
            AND
            is_simple_prod?(pn, FALSE, FALSE)
                           (v(pn)
                             (comp_matrix, comp_inverse,
                              replace_row(j, row(S)(j) + row(S)(i))(S),
                              IF comp_matrix
                                THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
                              ELSE Id(pn)
                              ENDIF,
                              IF comp_matrix AND comp_inverse
                                THEN R * Easr(pn)(j, i, -1)
                              ELSE Id(pn)
                              ENDIF,
                              T, j, i, stop_rec, max(k - 1, 0))`2))
          AND
          (comp_matrix AND comp_inverse IMPLIES
            (v(pn)
              (comp_matrix, comp_inverse,
               replace_row(j, row(S)(j) + row(S)(i))(S),
               IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
               ELSE Id(pn)
               ENDIF,
               IF comp_matrix AND comp_inverse THEN R * Easr(pn)(j, i, -1)
               ELSE Id(pn)
               ENDIF,
               T, j, i, stop_rec, max(k - 1, 0))`3
              *
              v(pn)
               (comp_matrix, comp_inverse,
                replace_row(j, row(S)(j) + row(S)(i))(S),
                IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
                ELSE Id(pn)
                ENDIF,
                IF comp_matrix AND comp_inverse THEN R * Easr(pn)(j, i, -1)
                ELSE Id(pn)
                ENDIF,
                T, j, i, stop_rec, max(k - 1, 0))`2
              = Id(pn)
              AND
              v(pn)
               (comp_matrix, comp_inverse,
                replace_row(j, row(S)(j) + row(S)(i))(S),
                IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
                ELSE Id(pn)
                ENDIF,
                IF comp_matrix AND comp_inverse THEN R * Easr(pn)(j, i, -1)
                ELSE Id(pn)
                ENDIF,
                T, j, i, stop_rec, max(k - 1, 0))`2
               *
               v(pn)
                (comp_matrix, comp_inverse,
                 replace_row(j, row(S)(j) + row(S)(i))(S),
                 IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
                 ELSE Id(pn)
                 ENDIF,
                 IF comp_matrix AND comp_inverse THEN R * Easr(pn)(j, i, -1)
                 ELSE Id(pn)
                 ENDIF,
                 T, j, i, stop_rec, max(k - 1, 0))`3
               = Id(pn)
               AND
               is_simple_prod?(pn, FALSE, FALSE)
                              (v(pn)
                                (comp_matrix, comp_inverse,
                                 replace_row(j, row(S)(j) + row(S)(i))(S),
                                 IF comp_matrix
                                   THEN replace_row
                                        (j, row(Q)(j) + row(Q)(i))(Q)
                                 ELSE Id(pn)
                                 ENDIF,
                                 IF comp_matrix AND comp_inverse
                                   THEN R * Easr(pn)(j, i, -1)
                                 ELSE Id(pn)
                                 ENDIF,
                                 T, j, i, stop_rec, max(k - 1, 0))`3)))
           AND
           det(v(pn)
                (comp_matrix, comp_inverse,
                 replace_row(j, row(S)(j) + row(S)(i))(S),
                 IF comp_matrix THEN replace_row(j, row(Q)(j) + row(Q)(i))(Q)
                 ELSE Id(pn)
                 ENDIF,
                 IF comp_matrix AND comp_inverse THEN R * Easr(pn)(j, i, -1)
                 ELSE Id(pn)
                 ENDIF,
                 T, j, i, stop_rec, max(k - 1, 0))`1)
            = det(S);

  % Subtype TCC generated (at line 72, column 52) for  S
      % expected type  D:
                     %   {D |
                     %            columns(D) =
                     %             length(row(S)(i) + pivnum * row(S)(j))}
  upper_triangulate_TCC25: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           columns(S) = length[real](row(S)(i) + pivnum * row(S)(j)));

  % Subtype TCC generated (at line 72, column 10) for
      % replace_row(i, row(S)(i) + pivnum * row(S)(j))(S)
      % expected type  SquareMatrix(pn)
  upper_triangulate_TCC26: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           rows(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S)) =
            columns(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S))
            AND rows(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S)) = pn);

  % Subtype TCC generated (at line 73, column 72) for  Q
      % expected type  D:
                     %   {D |
                     %            columns(D) =
                     %             length(row(Q)(i) + pivnum * row(Q)(j))}
  upper_triangulate_TCC27: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          comp_matrix AND pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           columns(Q) = length[real](row(Q)(i) + pivnum * row(Q)(j)));

  % Subtype TCC generated (at line 73, column 30) for
      % replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
      % expected type  {Q: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(Q)}
  upper_triangulate_TCC28: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          comp_matrix AND pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           rows(replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)) =
            columns(replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q))
            AND
            rows(replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)) = pn AND
             is_simple_prod?(pn, FALSE, FALSE)
                            (replace_row(i, row(Q)(i) + pivnum * row(Q)(j))
                                        (Q)));

  % Subtype TCC generated (at line 73, column 80) for  Id(pn)
      % expected type  {Q: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(Q)}
  upper_triangulate_TCC29: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          NOT comp_matrix AND pivnum = -entry(S)(i, j) / entry(S)(j, j)
           IMPLIES is_simple_prod?(pn, FALSE, FALSE)(Id(pn)));

  % Subtype TCC generated (at line 74, column 47) for
      % R * Easr(pn)(i, j, -pivnum)
      % expected type  {R: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(R) AND
                     %           (comp_matrix AND comp_inverse IMPLIES
                     %             (R *
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (i,
                     %                       row(Q)(i) + pivnum * row(Q)(j))
                     %                      (Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %               = Id(pn)
                     %               AND
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (i,
                     %                       row(Q)(i) + pivnum * row(Q)(j))
                     %                      (Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %                * R
                     %                = Id(pn)))}
  upper_triangulate_TCC30: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          comp_matrix AND
           comp_inverse AND pivnum = -entry(S)(i, j) / entry(S)(j, j)
           IMPLIES
                is_simple_prod?(pn, FALSE, FALSE)(R * Easr(pn)(i, j, -pivnum))
            AND (comp_matrix AND comp_inverse IMPLIES
                  (R * Easr(pn)(i, j, -pivnum) *
                    IF comp_matrix
                      THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                    ELSE Id(pn)
                    ENDIF
                    = Id(pn)
                    AND
                    IF comp_matrix
                      THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                    ELSE Id(pn)
                    ENDIF
                     * (R * Easr(pn)(i, j, -pivnum))
                     = Id(pn)))
            AND rows(R * Easr(pn)(i, j, -pivnum)) = pn
            AND rows(R * Easr(pn)(i, j, -pivnum)) =
                 columns(R * Easr(pn)(i, j, -pivnum))
            AND rows(R * Easr(pn)(i, j, -pivnum)) > 0
            AND columns(R * Easr(pn)(i, j, -pivnum)) > 0);

  % Subtype TCC generated (at line 74, column 76) for  Id(pn)
      % expected type  {R: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(R) AND
                     %           (comp_matrix AND comp_inverse IMPLIES
                     %             (R *
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (i,
                     %                       row(Q)(i) + pivnum * row(Q)(j))
                     %                      (Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %               = Id(pn)
                     %               AND
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (i,
                     %                       row(Q)(i) + pivnum * row(Q)(j))
                     %                      (Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %                * R
                     %                = Id(pn)))}
  upper_triangulate_TCC31: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          NOT (comp_matrix AND comp_inverse) AND
           pivnum = -entry(S)(i, j) / entry(S)(j, j)
           IMPLIES
           is_simple_prod?(pn, FALSE, FALSE)(Id(pn)) AND
            (comp_matrix AND comp_inverse IMPLIES
              (Id(pn) *
                IF comp_matrix
                  THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                ELSE Id(pn)
                ENDIF
                = Id(pn)
                AND
                IF comp_matrix
                  THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                ELSE Id(pn)
                ENDIF
                 * Id(pn)
                 = Id(pn))));

  % Subtype TCC generated (at line 75, column 10) for  T
      % expected type  {T: SquareMatrix(pn) |
                     %          comp_matrix IMPLIES
                     %           IF comp_matrix
                     %             THEN replace_row
                     %                  (i, row(Q)(i) + pivnum * row(Q)(j))
                     %                  (Q)
                     %           ELSE Id(pn)
                     %           ENDIF
                     %            * T
                     %            =
                     %            replace_row(i,
                     %                        row(S)(i) + pivnum * row(S)(j))
                     %                       (S)}
  upper_triangulate_TCC32: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           comp_matrix IMPLIES
            IF comp_matrix
              THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
            ELSE Id(pn)
            ENDIF
             * T
             = replace_row(i, row(S)(i) + pivnum * row(S)(j))(S));

  % Subtype TCC generated (at line 75, column 12) for  j
      % expected type  {j_1 |
                     %          ut_point1(replace_row
                     %                    (i, row(S)(i) + pivnum * row(S)(j))
                     %                    (S))
                     %                   (j_1)}
  upper_triangulate_TCC33: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           ut_point1(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S))(j));

  % Subtype TCC generated (at line 75, column 14) for  i - 1
      % expected type  {i_1 |
                     %          ut_point2(replace_row
                     %                    (i, row(S)(i) + pivnum * row(S)(j))
                     %                    (S),
                     %                    j)
                     %                   (i_1)}
  upper_triangulate_TCC34: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           i - 1 >= 0 AND
            ut_point2(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S), j)
                     (i - 1));

  % Subtype TCC generated (at line 75, column 27) for  max(k - 1, 0)
      % expected type  nat
  upper_triangulate_TCC35: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           max(k - 1, 0) >= 0);

  % Termination TCC generated (at line 71, column 6) for
      % upper_triangulate(pn)
      %                  (comp_matrix, comp_inverse,
      %                   replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
      %                   IF comp_matrix
      %                     THEN replace_row(i,
      %                                      row(Q)(i) + pivnum * row(Q)(j))
      %                                     (Q)
      %                   ELSE Id(pn)
      %                   ENDIF,
      %                   IF comp_matrix AND comp_inverse
      %                     THEN R * Easr(pn)(i, j, -pivnum)
      %                   ELSE Id(pn)
      %                   ENDIF,
      %                   T, j, i - 1, stop_rec, max(k - 1, 0))
  upper_triangulate_TCC36: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           lex3(pn - j, i - 1,
                IF entry(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S))
                        (i - 1, j)
                    /= 0
                    AND
                    entry(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S))
                         (j, j)
                     = 0
                  THEN 1
                ELSE 0
                ENDIF)
            <
            lex3(pn - j, i,
                 IF entry(S)(i, j) /= 0 AND entry(S)(j, j) = 0 THEN 1
                 ELSE 0
                 ENDIF));

  % Subtype TCC generated (at line 71, column 6) for
      % upper_triangulate(pn)
      %                  (comp_matrix, comp_inverse,
      %                   replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
      %                   IF comp_matrix
      %                     THEN replace_row(i,
      %                                      row(Q)(i) + pivnum * row(Q)(j))
      %                                     (Q)
      %                   ELSE Id(pn)
      %                   ENDIF,
      %                   IF comp_matrix AND comp_inverse
      %                     THEN R * Easr(pn)(i, j, -pivnum)
      %                   ELSE Id(pn)
      %                   ENDIF,
      %                   T, j, i - 1, stop_rec, max(k - 1, 0))
      % expected type  {SGI:
                     %    [SquareMatrix(pn), SquareMatrix(pn),
                     %     SquareMatrix(pn)] |
                     %          (NOT stop_rec) IMPLIES
                     %           upper_triangular?(SGI`1) AND
                     %            (comp_matrix IMPLIES
                     %              SGI`2 * T = SGI`1 AND
                     %               is_simple_prod?(pn, FALSE, FALSE)
                     %                              (SGI`2))
                     %             AND
                     %             (comp_matrix AND comp_inverse IMPLIES
                     %               (SGI`3 * SGI`2 = Id(pn)
                     %                AND
                     %                SGI`2 * SGI`3 = Id(pn)
                     %                AND
                     %                is_simple_prod?
                     %                (pn, FALSE, FALSE)(SGI`3)))
                     %              AND det(SGI`1) = det(S)}
  upper_triangulate_TCC37: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            v:
              [pn1: posnat ->
                 [d1:
                    {z:
                       [comp_matrix: bool, comp_inverse: bool,
                        S: SquareMatrix(pn1),
                        Q:
                          {Q: SquareMatrix(pn1) |
                                   is_simple_prod?(pn1, FALSE, FALSE)(Q)},
                        {R: SquareMatrix(pn1) |
                                 is_simple_prod?(pn1, FALSE, FALSE)(R) AND
                                  (comp_matrix AND comp_inverse IMPLIES
                                    (R * Q = Id(pn1) AND Q * R = Id(pn1)))},
                        {T: SquareMatrix(pn1) |
                                 comp_matrix IMPLIES Q * T = S},
                        j: {j | ut_point1(S)(j)}, {i | ut_point2(S, j)(i)},
                        bool, nat] |
                             lex3(pn1 - z`7, z`8,
                                  IF entry(z`3)(z`8, z`7) /= 0 AND
                                      entry(z`3)(z`7, z`7) = 0
                                    THEN 1
                                  ELSE 0
                                  ENDIF)
                              <
                              lex3(pn - j, i,
                                   IF entry(S)(i, j) /= 0
                                      AND
                                      entry(S)(j, j) = 0
                                     THEN 1
                                   ELSE 0
                                   ENDIF)} ->
                    {SGI:
                       [SquareMatrix(pn1), SquareMatrix(pn1),
                        SquareMatrix(pn1)] |
                             (NOT d1`9) IMPLIES
                              upper_triangular?(SGI`1) AND
                               (d1`1 IMPLIES
                                 SGI`2 * d1`6 = SGI`1 AND
                                  is_simple_prod?(pn1, FALSE, FALSE)(SGI`2))
                                AND
                                (d1`1 AND d1`2 IMPLIES
                                  (SGI`3 * SGI`2 = Id(pn1) AND
                                    SGI`2 * SGI`3 = Id(pn1) AND
                                     is_simple_prod?(pn1, FALSE, FALSE)
                                                    (SGI`3)))
                                 AND det(SGI`1) = det(d1`3)}]],
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           (NOT stop_rec) IMPLIES
            upper_triangular?(v(pn)
                               (comp_matrix, comp_inverse,
                                replace_row(i, row(S)(i) + pivnum * row(S)(j))
                                           (S),
                                IF comp_matrix
                                  THEN replace_row
                                       (i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                                ELSE Id(pn)
                                ENDIF,
                                IF comp_matrix AND comp_inverse
                                  THEN R * Easr(pn)(i, j, -pivnum)
                                ELSE Id(pn)
                                ENDIF,
                                T, j, i - 1, stop_rec, max(k - 1, 0))`1)
             AND
             (comp_matrix IMPLIES
               v(pn)
                (comp_matrix, comp_inverse,
                 replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                 IF comp_matrix
                   THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                 ELSE Id(pn)
                 ENDIF,
                 IF comp_matrix AND comp_inverse
                   THEN R * Easr(pn)(i, j, -pivnum)
                 ELSE Id(pn)
                 ENDIF,
                 T, j, i - 1, stop_rec, max(k - 1, 0))`2
                * T
                =
                v(pn)
                 (comp_matrix, comp_inverse,
                  replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                  IF comp_matrix
                    THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                  ELSE Id(pn)
                  ENDIF,
                  IF comp_matrix AND comp_inverse
                    THEN R * Easr(pn)(i, j, -pivnum)
                  ELSE Id(pn)
                  ENDIF,
                  T, j, i - 1, stop_rec, max(k - 1, 0))`1
                AND
                is_simple_prod?(pn, FALSE, FALSE)
                               (v(pn)
                                 (comp_matrix, comp_inverse,
                                  replace_row(i,
                                              row(S)(i) + pivnum * row(S)(j))
                                             (S),
                                  IF comp_matrix
                                    THEN replace_row
                                         (i, row(Q)(i) + pivnum * row(Q)(j))
                                         (Q)
                                  ELSE Id(pn)
                                  ENDIF,
                                  IF comp_matrix AND comp_inverse
                                    THEN R * Easr(pn)(i, j, -pivnum)
                                  ELSE Id(pn)
                                  ENDIF,
                                  T, j, i - 1, stop_rec, max(k - 1, 0))`2))
              AND
              (comp_matrix AND comp_inverse IMPLIES
                (v(pn)
                  (comp_matrix, comp_inverse,
                   replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                   IF comp_matrix
                     THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                   ELSE Id(pn)
                   ENDIF,
                   IF comp_matrix AND comp_inverse
                     THEN R * Easr(pn)(i, j, -pivnum)
                   ELSE Id(pn)
                   ENDIF,
                   T, j, i - 1, stop_rec, max(k - 1, 0))`3
                  *
                  v(pn)
                   (comp_matrix, comp_inverse,
                    replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                    IF comp_matrix
                      THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                    ELSE Id(pn)
                    ENDIF,
                    IF comp_matrix AND comp_inverse
                      THEN R * Easr(pn)(i, j, -pivnum)
                    ELSE Id(pn)
                    ENDIF,
                    T, j, i - 1, stop_rec, max(k - 1, 0))`2
                  = Id(pn)
                  AND
                  v(pn)
                   (comp_matrix, comp_inverse,
                    replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                    IF comp_matrix
                      THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                    ELSE Id(pn)
                    ENDIF,
                    IF comp_matrix AND comp_inverse
                      THEN R * Easr(pn)(i, j, -pivnum)
                    ELSE Id(pn)
                    ENDIF,
                    T, j, i - 1, stop_rec, max(k - 1, 0))`2
                   *
                   v(pn)
                    (comp_matrix, comp_inverse,
                     replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                     IF comp_matrix
                       THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                     ELSE Id(pn)
                     ENDIF,
                     IF comp_matrix AND comp_inverse
                       THEN R * Easr(pn)(i, j, -pivnum)
                     ELSE Id(pn)
                     ENDIF,
                     T, j, i - 1, stop_rec, max(k - 1, 0))`3
                   = Id(pn)
                   AND
                   is_simple_prod?(pn, FALSE, FALSE)
                                  (v(pn)
                                    (comp_matrix, comp_inverse,
                                     replace_row(i,
                                                 row(S)(i)
                                                 +
                                                 pivnum * row(S)(j))
                                                (S),
                                     IF comp_matrix
                                       THEN replace_row
                                            (i,
                                             row(Q)(i) + pivnum * row(Q)(j))
                                            (Q)
                                     ELSE Id(pn)
                                     ENDIF,
                                     IF comp_matrix AND comp_inverse
                                       THEN R * Easr(pn)(i, j, -pivnum)
                                     ELSE Id(pn)
                                     ENDIF,
                                     T, j, i - 1, stop_rec,
                                     max(k - 1, 0))`3)))
               AND
               det(v(pn)
                    (comp_matrix, comp_inverse,
                     replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                     IF comp_matrix
                       THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                     ELSE Id(pn)
                     ENDIF,
                     IF comp_matrix AND comp_inverse
                       THEN R * Easr(pn)(i, j, -pivnum)
                     ELSE Id(pn)
                     ENDIF,
                     T, j, i - 1, stop_rec, max(k - 1, 0))`1)
                = det(S));

  % Subtype TCC generated (at line 70, column 37) for  entry(S)(j, j)
      % expected type  nznum
  upper_triangulate_TCC38: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool, S: SquareMatrix(pn),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn) | comp_matrix IMPLIES Q * T = S),
            (j: nat | ut_point1(S)(j)), (i: nat | ut_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(j, j) = 0 AND NOT entry(S)(i, j) = 0 AND NOT i = j
       AND NOT (stop_rec AND k = 0) AND NOT (i = pn - 1 AND j = pn - 1)
       IMPLIES entry(S)(j, j) /= 0;


body:
  linear_dependence  % [ parameters ]
  		: THEORY

    BEGIN

  IMPORTING matrices, matrix_props

   A,M,N: VAR PosFullMatrix
   
   m,i: VAR nat
   p: VAR posnat
   v: VAR Vector
   f,g: VAR [nat->real]
   zerow(p): PosFullMatrix = (: zero(p) :)
   zecolumn(p): PosFullMatrix = transpose(zerow(p))

   zerow_dim: LEMMA rows(zerow(p)) = 1 AND columns(zerow(p)) = p

   zecolumn_dim: LEMMA rows(zecolumn(p)) = p AND columns(zecolumn(p))=1
   

   row2mat(A, (j:below(rows(A)))): PosFullMatrix = (:row(A)(j):)
   
   row2mat_dim: LEMMA FORALL (j:below(rows(A))): rows(row2mat(A,j)) = 1 AND columns(row2mat(A,j)) = columns(A)

   sum_rows(A,f,(j:below(rows(A))), M): RECURSIVE PosFullMatrix = 
     IF j=0 THEN M+f(j)*row2mat(A,j)
     ELSE sum_rows(A,f,j-1, M+f(j)*row2mat(A,j))
     ENDIF
     MEASURE j

   sum_rows(A,f): PosFullMatrix = sum_rows(A,f, rows(A)-1, zerow(columns(A))) 

   sum_rows_eq: LEMMA FORALL (j:below(rows(A))): 
   	      	    	   (FORALL (k:subrange(0,j)): f(k) = g(k)) IMPLIES 
  			   sum_rows(A,f,j,M) = sum_rows(A,g,j,M)

   sum_rows_add_start: LEMMA FORALL (j:below(rows(A))):
             sum_rows(A, f, j, M+N) = sum_rows(A, f, j, M) + N

   subtract_same_scal: LEMMA FORALL (j:below(rows(A))):  (f(j) * row2mat(A, j) - f(j) * row2mat(A, j)) = 0 * row2mat(A, j)

   
   sum_lem_prep: LEMMA FORALL(j:below(rows(A)), k:below(j+1)):
           sum_rows(A,f WITH [k:=0], j, M) = sum_rows(A, f, j, M) - f(k)*row2mat(A,k)  

   sum_lem: LEMMA FORALL(j:below(rows(A))): sum_rows(A,f WITH [j:=0]) = sum_rows(A,f) -f(j)*row2mat(A,j) 

   
   row_dependent(A,(j:below(rows(A))),f): bool = 
       (sum_rows(A,f) = zerow(columns(A)))

   row_dependence_lem: LEMMA FORALL (j:below(rows(A)), (f|f(j)=-1)):
         row_dependent(A,j,f) IMPLIES
         %FORALL ((M|rows(M) = columns(A) AND columns(M) =1)):
         row2mat(A,j)*M = sum_rows(A, f WITH [j:=0])*M
    
   row_dep(A, (j:below(rows(A))), f): bool = ((f(j)=-1 AND row_dependent(A,j,f)) OR (f = LAMBDA(i:nat): 0))
   
   row_dep_fun(A, (j:below(rows(A))), (f: {g:[nat->real]| row_dep(A,j,g)})): [nat->real] = 
         f WITH [j:= f(j)+1] 

    

    END linear_dependence

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 14, column 27) for  (: zero(p) :)
      % expected type  PosFullMatrix
  zerow_TCC1: OBLIGATION
    FORALL (p: posnat):
      (null?[list[real]]((: zero(p) :)) OR
        (FORALL (i, j: below(length[list[real]]((: zero(p) :)))):
           length[real](nth[list[real]]((: zero(p) :), i)) =
            length[real](nth[list[real]]((: zero(p) :), j))))
       AND rows((: zero(p) :)) > 0 AND columns((: zero(p) :)) > 0;

  % Subtype TCC generated (at line 22, column 49) for  (: row(A)(j) :)
      % expected type  PosFullMatrix
  row2mat_TCC1: OBLIGATION
    FORALL (A: PosFullMatrix, (j: below(rows(A)))):
      (null?[list[real]]((: row(A)(j) :)) OR
        (FORALL (i, j_1: below(length[list[real]]((: row(A)(j) :)))):
           length[real](nth[list[real]]((: row(A)(j) :), i)) =
            length[real](nth[list[real]]((: row(A)(j) :), j_1))))
       AND rows((: row(A)(j) :)) > 0 AND columns((: row(A)(j) :)) > 0;

  % Subtype TCC generated (at line 27, column 15) for
      % M + f(j) * row2mat(A, j)
      % expected type  PosFullMatrix
  sum_rows_TCC1: OBLIGATION
    FORALL (A: PosFullMatrix, f: [nat -> real], (j: below(rows(A))),
            M: PosFullMatrix):
      j = 0 IMPLIES
       (null?[list[real]](M + f(j) * row2mat(A, j)) OR
         (FORALL (i,
                  j_1: below(length[list[real]](M + f(j) * row2mat(A, j)))):
            length[real](nth[list[real]](M + f(j) * row2mat(A, j), i)) =
             length[real](nth[list[real]](M + f(j) * row2mat(A, j), j_1))))
        AND
        rows(M + f(j) * row2mat(A, j)) > 0 AND
         columns(M + f(j) * row2mat(A, j)) > 0;

  % Subtype TCC generated (at line 28, column 21) for  j - 1
      % expected type  below(rows(A))
  sum_rows_TCC2: OBLIGATION
    FORALL (A: PosFullMatrix, (j: below(rows(A)))):
      NOT j = 0 IMPLIES j - 1 >= 0 AND j - 1 < rows(A);

  % Subtype TCC generated (at line 28, column 26) for
      % M + f(j) * row2mat(A, j)
      % expected type  PosFullMatrix
  sum_rows_TCC3: OBLIGATION
    FORALL (A: PosFullMatrix, f: [nat -> real], (j: below(rows(A))),
            M: PosFullMatrix):
      NOT j = 0 IMPLIES
       (null?[list[real]](M + f(j) * row2mat(A, j)) OR
         (FORALL (i,
                  j_1: below(length[list[real]](M + f(j) * row2mat(A, j)))):
            length[real](nth[list[real]](M + f(j) * row2mat(A, j), i)) =
             length[real](nth[list[real]](M + f(j) * row2mat(A, j), j_1))))
        AND
        rows(M + f(j) * row2mat(A, j)) > 0 AND
         columns(M + f(j) * row2mat(A, j)) > 0;

  % Termination TCC generated (at line 28, column 8) for
      % sum_rows(A, f, j - 1, M + f(j) * row2mat(A, j))
  sum_rows_TCC4: OBLIGATION
    FORALL (A: PosFullMatrix, (j: below(rows(A)))):
      NOT j = 0 IMPLIES j - 1 < j;

  % Subtype TCC generated (at line 32, column 46) for  rows(A) - 1
      % expected type  below(rows(A))
  sum_rows_TCC5: OBLIGATION
    FORALL (A: PosFullMatrix): rows(A) - 1 >= 0 AND rows(A) - 1 < rows(A);

  % Subtype TCC generated (at line 32, column 63) for  columns(A)
      % expected type  posnat
  sum_rows_TCC6: OBLIGATION FORALL (A: PosFullMatrix): columns(A) > 0;

  % Subtype TCC generated (at line 39, column 29) for  M + N
      % expected type  PosFullMatrix
  sum_rows_add_start_TCC1: OBLIGATION
    FORALL (A, M, N: PosFullMatrix, j: below(rows(A))):
      (null?[list[real]](M + N) OR
        (FORALL (i, j_1: below(length[list[real]](M + N))):
           length[real](nth[list[real]](M + N, i)) =
            length[real](nth[list[real]](M + N, j_1))))
       AND rows(M + N) > 0 AND columns(M + N) > 0;

  % Subtype TCC generated (at line 45, column 81) for  k
      % expected type  below(rows(A))
  sum_lem_prep_TCC1: OBLIGATION
    FORALL (A: PosFullMatrix, j: below(rows(A)), k: below(1 + j)):
      k < rows(A);


body:
  matrix_diag: THEORY


  BEGIN

    IMPORTING matrix_upper_triang


    SM,SM1,SM2: VAR FullMatrix

    r: VAR real

    nzr: VAR nzreal

    M,N,A,B: VAR Matrix

    v,v1,v2: VAR Vector

    i,j,k,p : VAR nat

    m,n : VAR nat

    pn,pm : VAR posnat

    F,G: VAR [[nat,nat]->real]

    Mp,Np: VAR (nonempty?)

    PFM,D1,D2,D: VAR PosFullMatrix

    comp_matrix,comp_inverse: VAR bool

    SQ,IQ,GQ,
    SQ2,IQ2,GQ2,DQ,DQ2,
    Q,R,S,T,
    Q2,R2,S2,T2: VAR Square

    d_point1(SQ)(j): bool = 
      j<rows(SQ) AND
      (FORALL (k,p):p>j AND k<p AND k<rows(SQ) IMPLIES (entry(SQ)(p,p)=0 OR entry(SQ)(k,p)=0))

    d_point2(SQ,j)(i): bool =
      i<rows(SQ) AND i<=j AND
      (FORALL (k):k<i AND k<rows(SQ) IMPLIES (entry(SQ)(j,j)=0 OR entry(SQ)(k,j)=0))

    diagonalize(pn)(comp_matrix,comp_inverse:bool,
      (S:SquareMatrix(pn)|upper_triangular?(S)),
      (Q:SquareMatrix(pn)|is_simple_prod?(pn,false,false)(Q)),
      (R:SquareMatrix(pn)|is_simple_prod?(pn,false,false)(R)
                   AND (comp_matrix AND comp_inverse IMPLIES (R*Q=Id(pn) AND Q*R=Id(pn)))),
      (T:SquareMatrix(pn)|upper_triangular?(T) AND (comp_matrix IMPLIES Q*T = S) 
             AND (FORALL (i):i<rows(T) IMPLIES entry(T)(i,i)=entry(S)(i,i))),
      (j|d_point1(S)(j)),(i|d_point2(S,j)(i)),stop_rec:bool,k): RECURSIVE
        {SGI:[SquareMatrix(pn),SquareMatrix(pn),SquareMatrix(pn)]|
          (not stop_rec) IMPLIES (LET (S2,Q2,R2)=SGI IN
    	 upper_triangular?(S2) AND
    	 (FORALL (k): k<rows(T) IMPLIES entry(T)(k,k)=entry(S2)(k,k)) AND
  	 (FORALL (k,p): k<rows(S2) AND k<rows(S2) AND k<p IMPLIES (entry(S2)(p,p)=0 OR entry(S2)(k,p)=0)) AND
    	 (comp_matrix IMPLIES Q2*T= S2 AND is_simple_prod?(pn,false,false)(Q2)) AND
    	 (comp_matrix AND comp_inverse IMPLIES (R2*Q2=Id(pn) AND Q2*R2=Id(pn) AND is_simple_prod?(pn,false,false)(R2))) AND
    	 det(S2)=det(S))} =
      IF (stop_rec AND k=0) OR (i=0 AND j=0) THEN (S,Q,R)
      ELSIF i=j OR entry(S)(j,j)=0 THEN diagonalize(pn)(comp_matrix,comp_inverse,S,Q,R,T,j-1,0,stop_rec,max(k-1,0))
      ELSIF entry(S)(i,j)=0 THEN diagonalize(pn)(comp_matrix,comp_inverse,S,Q,R,T,j,i+1,stop_rec,max(k-1,0))
      ELSE LET pivnum = -entry(S)(i,j)/entry(S)(j,j) IN
        diagonalize(pn)(comp_matrix,comp_inverse,
      			   replace_row(i,row(S)(i)+pivnum*row(S)(j))(S),
      			   IF comp_matrix THEN replace_row(i,row(Q)(i)+pivnum*row(Q)(j))(Q) ELSE Id(pn) ENDIF,
      			   IF comp_matrix AND comp_inverse THEN R*Easr(pn)(i,j,-pivnum) ELSE Id(pn) ENDIF,
      			   T,j,i+1,stop_rec,max(k-1,0))
      ENDIF MEASURE lex2(j,pn-i)


    diag(comp_matrix,comp_inverse:bool,S): {SGI : [# ans: SquareMatrix(rows(S)),
    					    multip: SquareMatrix(rows(S)),
    					    inv: SquareMatrix(rows(S)) #] |
      upper_triangular?(SGI`ans) AND
      (FORALL (k,p): k<rows(S) AND p<rows(S) AND entry(SGI`ans)(k,p)/=0 IMPLIES (k=p OR (k<p AND entry(SGI`ans)(p,p)=0))) AND
      (comp_matrix IMPLIES SGI`multip*S=SGI`ans AND is_simple_prod?(rows(S),false,false)(SGI`multip)) AND
      (comp_matrix AND comp_inverse IMPLIES (SGI`inv*SGI`multip=Id(rows(S)) AND SGI`multip*SGI`inv=Id(rows(S)) AND is_simple_prod?(rows(S),false,false)(SGI`inv))) AND
      det(SGI`ans)=det(S) AND
      (det(S) /=0 IFF (FORALL (k,p): k<rows(S) AND p<rows(S) IMPLIES (entry(SGI`ans)(k,p)/=0 IFF k=p)))} =
        LET (S2,Q2,R2) = upper_triangulate(rows(S))(comp_matrix,comp_inverse,S,Id(rows(S)),Id(rows(S)),S,0,rows(S)-1,false,0),
        	  (S3,Q3,R3) = diagonalize(rows(S))(comp_matrix,comp_inverse,S2,Id(rows(S)),Id(rows(S)),S2,rows(S)-1,0,false,0) IN
  	  (# ans:= S3, multip:= Q3*Q2, inv:=R2*R3 #)

    diag_det_zero_row: LEMMA comp_matrix AND
      det(S)=0 IMPLIES EXISTS (i): i<rows(S) AND 
        FORALL (j): entry(diag(comp_matrix,comp_inverse,S)`ans)(i,j)=0


    % Mult 

    det_mult: LEMMA rows(S)=rows(R) IMPLIES
      det(S*R)=det(S)*det(R)




  END matrix_diag

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 71, column 25) for  pn - i
      % expected type  nat
  diagonalize_TCC1: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i))):
      pn - i >= 0;

  % Subtype TCC generated (at line 71, column 25) for  pn1 - z`8
      % expected type  nat
  diagonalize_TCC2: OBLIGATION
    FORALL (pn1: posnat,
            z:
              [comp_matrix: bool, comp_inverse: bool,
               S: {S: SquareMatrix(pn1) | upper_triangular?(S)},
               Q:
                 {Q: SquareMatrix(pn1) |
                          is_simple_prod?(pn1, FALSE, FALSE)(Q)},
               {R: SquareMatrix(pn1) |
                        is_simple_prod?(pn1, FALSE, FALSE)(R) AND
                         (comp_matrix AND comp_inverse IMPLIES
                           (R * Q = Id(pn1) AND Q * R = Id(pn1)))},
               {T: SquareMatrix(pn1) |
                        upper_triangular?(T) AND
                         (comp_matrix IMPLIES Q * T = S) AND
                          (FORALL (i):
                             i < rows(T) IMPLIES
                              entry(T)(i, i) = entry(S)(i, i))},
               j: {j | d_point1(S)(j)}, {i | d_point2(S, j)(i)}, bool, nat]):
      pn1 - z`8 >= 0;

  % Subtype TCC generated (at line 71, column 25) for  pn - i
      % expected type  nat
  diagonalize_TCC3: OBLIGATION
    FORALL (pn, (S: SquareMatrix(pn) | upper_triangular?(S)),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i))):
      pn - i >= 0;

  % Subtype TCC generated (at line 62, column 48) for  (S, Q, R)
      % expected type  {SGI:
                     %    [SquareMatrix(pn), SquareMatrix(pn),
                     %     SquareMatrix(pn)] |
                     %          (NOT stop_rec) IMPLIES
                     %                upper_triangular?(SGI`1)
                     %            AND FORALL
                     %                (k):
                     %                k < rows(T)
                     %                IMPLIES
                     %                entry(T)(k, k) = entry(SGI`1)(k, k)
                     %            AND FORALL
                     %                (k, p):
                     %                k < rows(SGI`1)
                     %                AND
                     %                k < rows(SGI`1) AND k < p
                     %                IMPLIES
                     %                (entry(SGI`1)(p, p) = 0
                     %                 OR
                     %                 entry(SGI`1)(k, p) = 0)
                     %            AND (comp_matrix
                     %                 IMPLIES
                     %                 SGI`2 * T = SGI`1
                     %                 AND
                     %                 is_simple_prod?
                     %                 (pn, FALSE, FALSE)(SGI`2))
                     %            AND (comp_matrix AND comp_inverse
                     %                 IMPLIES
                     %                 (SGI`3 * SGI`2 = Id(pn)
                     %                  AND
                     %                  SGI`2 * SGI`3 = Id(pn)
                     %                  AND
                     %                  is_simple_prod?
                     %                  (pn, FALSE, FALSE)(SGI`3)))
                     %            AND det(SGI`1) = det(S)}
  diagonalize_TCC4: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      (stop_rec AND k = 0) OR (i = 0 AND j = 0) IMPLIES
       (NOT stop_rec) IMPLIES
             upper_triangular?(S)
         AND FORALL (k_1: nat):
               k_1 < rows(T) IMPLIES entry(T)(k_1, k_1) = entry(S)(k_1, k_1)
         AND FORALL (k_1: nat, p):
               k_1 < rows(S) AND k_1 < rows(S) AND k_1 < p IMPLIES
                (entry(S)(p, p) = 0 OR entry(S)(k_1, p) = 0)
         AND (comp_matrix IMPLIES
               Q * T = S AND is_simple_prod?(pn, FALSE, FALSE)(Q))
         AND (comp_matrix AND comp_inverse IMPLIES
               (R * Q = Id(pn) AND
                 Q * R = Id(pn) AND is_simple_prod?(pn, FALSE, FALSE)(R)));

  % Subtype TCC generated (at line 63, column 87) for  j - 1
      % expected type  {j | d_point1(S)(j)}
  diagonalize_TCC5: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      (i = j OR entry(S)(j, j) = 0) AND
       NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES j - 1 >= 0 AND d_point1(S)(j - 1);

  % Subtype TCC generated (at line 63, column 91) for  0
      % expected type  {i | d_point2(S, j - 1)(i)}
  diagonalize_TCC6: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      (i = j OR entry(S)(j, j) = 0) AND
       NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES d_point2(S, j - 1)(0);

  % Subtype TCC generated (at line 63, column 102) for  max(k - 1, 0)
      % expected type  nat
  diagonalize_TCC7: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      (i = j OR entry(S)(j, j) = 0) AND
       NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES max(k - 1, 0) >= 0;

  % Termination TCC generated (at line 63, column 38) for
      % diagonalize(pn)
      %            (comp_matrix, comp_inverse, S, Q, R, T, j - 1, 0,
      %             stop_rec, max(k - 1, 0))
  diagonalize_TCC8: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
      (i = j OR entry(S)(j, j) = 0) AND
       NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES lex2(j - 1, pn - 0) < lex2(j, pn - i);

  % Subtype TCC generated (at line 64, column 82) for  i + 1
      % expected type  {i | d_point2(S, j)(i)}
  diagonalize_TCC9: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES d_point2(S, j)(i + 1);

  % Subtype TCC generated (at line 64, column 95) for  max(k - 1, 0)
      % expected type  nat
  diagonalize_TCC10: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES max(k - 1, 0) >= 0;

  % Termination TCC generated (at line 64, column 31) for
      % diagonalize(pn)
      %            (comp_matrix, comp_inverse, S, Q, R, T, j, i + 1,
      %             stop_rec, max(k - 1, 0))
  diagonalize_TCC11: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES lex2(j, pn - (i + 1)) < lex2(j, pn - i);

  % Subtype TCC generated (at line 67, column 52) for  S
      % expected type  D:
                     %   {D |
                     %            columns(D) =
                     %             length(row(S)(i) + pivnum * row(S)(j))}
  diagonalize_TCC12: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           columns(S) = length[real](row(S)(i) + pivnum * row(S)(j)));

  % Subtype TCC generated (at line 67, column 10) for
      % replace_row(i, row(S)(i) + pivnum * row(S)(j))(S)
      % expected type  {S: SquareMatrix(pn) | upper_triangular?(S)}
  diagonalize_TCC13: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           rows(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S)) =
            columns(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S))
            AND
            rows(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S)) = pn AND
             upper_triangular?(replace_row(i, row(S)(i) + pivnum * row(S)(j))
                                          (S)));

  % Subtype TCC generated (at line 68, column 72) for  Q
      % expected type  D:
                     %   {D |
                     %            columns(D) =
                     %             length(row(Q)(i) + pivnum * row(Q)(j))}
  diagonalize_TCC14: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          comp_matrix AND pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           columns(Q) = length[real](row(Q)(i) + pivnum * row(Q)(j)));

  % Subtype TCC generated (at line 68, column 30) for
      % replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
      % expected type  {Q: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(Q)}
  diagonalize_TCC15: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          comp_matrix AND pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           rows(replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)) =
            columns(replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q))
            AND
            rows(replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)) = pn AND
             is_simple_prod?(pn, FALSE, FALSE)
                            (replace_row(i, row(Q)(i) + pivnum * row(Q)(j))
                                        (Q)));

  % Subtype TCC generated (at line 68, column 80) for  Id(pn)
      % expected type  {Q: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(Q)}
  diagonalize_TCC16: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          NOT comp_matrix AND pivnum = -entry(S)(i, j) / entry(S)(j, j)
           IMPLIES is_simple_prod?(pn, FALSE, FALSE)(Id(pn)));

  % Subtype TCC generated (at line 69, column 47) for
      % R * Easr(pn)(i, j, -pivnum)
      % expected type  {R: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(R) AND
                     %           (comp_matrix AND comp_inverse IMPLIES
                     %             (R *
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (i,
                     %                       row(Q)(i) + pivnum * row(Q)(j))
                     %                      (Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %               = Id(pn)
                     %               AND
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (i,
                     %                       row(Q)(i) + pivnum * row(Q)(j))
                     %                      (Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %                * R
                     %                = Id(pn)))}
  diagonalize_TCC17: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          comp_matrix AND
           comp_inverse AND pivnum = -entry(S)(i, j) / entry(S)(j, j)
           IMPLIES
                is_simple_prod?(pn, FALSE, FALSE)(R * Easr(pn)(i, j, -pivnum))
            AND (comp_matrix AND comp_inverse IMPLIES
                  (R * Easr(pn)(i, j, -pivnum) *
                    IF comp_matrix
                      THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                    ELSE Id(pn)
                    ENDIF
                    = Id(pn)
                    AND
                    IF comp_matrix
                      THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                    ELSE Id(pn)
                    ENDIF
                     * (R * Easr(pn)(i, j, -pivnum))
                     = Id(pn)))
            AND rows(R * Easr(pn)(i, j, -pivnum)) = pn
            AND rows(R * Easr(pn)(i, j, -pivnum)) =
                 columns(R * Easr(pn)(i, j, -pivnum))
            AND rows(R * Easr(pn)(i, j, -pivnum)) > 0
            AND columns(R * Easr(pn)(i, j, -pivnum)) > 0);

  % Subtype TCC generated (at line 69, column 76) for  Id(pn)
      % expected type  {R: SquareMatrix(pn) |
                     %          is_simple_prod?(pn, FALSE, FALSE)(R) AND
                     %           (comp_matrix AND comp_inverse IMPLIES
                     %             (R *
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (i,
                     %                       row(Q)(i) + pivnum * row(Q)(j))
                     %                      (Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %               = Id(pn)
                     %               AND
                     %               IF comp_matrix
                     %                 THEN replace_row
                     %                      (i,
                     %                       row(Q)(i) + pivnum * row(Q)(j))
                     %                      (Q)
                     %               ELSE Id(pn)
                     %               ENDIF
                     %                * R
                     %                = Id(pn)))}
  diagonalize_TCC18: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          NOT (comp_matrix AND comp_inverse) AND
           pivnum = -entry(S)(i, j) / entry(S)(j, j)
           IMPLIES
           is_simple_prod?(pn, FALSE, FALSE)(Id(pn)) AND
            (comp_matrix AND comp_inverse IMPLIES
              (Id(pn) *
                IF comp_matrix
                  THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                ELSE Id(pn)
                ENDIF
                = Id(pn)
                AND
                IF comp_matrix
                  THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                ELSE Id(pn)
                ENDIF
                 * Id(pn)
                 = Id(pn))));

  % Subtype TCC generated (at line 70, column 10) for  T
      % expected type  {T: SquareMatrix(pn) |
                     %          upper_triangular?(T) AND
                     %           (comp_matrix IMPLIES
                     %             IF comp_matrix
                     %               THEN replace_row
                     %                    (i, row(Q)(i) + pivnum * row(Q)(j))
                     %                    (Q)
                     %             ELSE Id(pn)
                     %             ENDIF
                     %              * T
                     %              =
                     %              replace_row(i,
                     %                          row(S)(i)
                     %                          +
                     %                          pivnum * row(S)(j))
                     %                         (S))
                     %            AND
                     %            (FORALL (i_1: nat):
                     %               i_1 < rows(T) IMPLIES
                     %                entry(T)(i_1, i_1)
                     %                =
                     %                entry
                     %                (replace_row
                     %                 (i, row(S)(i) + pivnum * row(S)(j))(S))
                     %                (i_1, i_1))}
  diagonalize_TCC19: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           upper_triangular?(T) AND
            (comp_matrix IMPLIES
              IF comp_matrix
                THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
              ELSE Id(pn)
              ENDIF
               * T
               = replace_row(i, row(S)(i) + pivnum * row(S)(j))(S))
             AND
             (FORALL (i_1: nat):
                i_1 < rows(T) IMPLIES
                 entry(T)(i_1, i_1) =
                  entry(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S))
                       (i_1, i_1)));

  % Subtype TCC generated (at line 70, column 12) for  j
      % expected type  {j_1 |
                     %          d_point1(replace_row
                     %                   (i, row(S)(i) + pivnum * row(S)(j))
                     %                   (S))
                     %                  (j_1)}
  diagonalize_TCC20: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           d_point1(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S))(j));

  % Subtype TCC generated (at line 70, column 14) for  i + 1
      % expected type  {i_1 |
                     %          d_point2(replace_row
                     %                   (i, row(S)(i) + pivnum * row(S)(j))
                     %                   (S),
                     %                   j)
                     %                  (i_1)}
  diagonalize_TCC21: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           d_point2(replace_row(i, row(S)(i) + pivnum * row(S)(j))(S), j)
                   (i + 1));

  % Subtype TCC generated (at line 70, column 27) for  max(k - 1, 0)
      % expected type  nat
  diagonalize_TCC22: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           max(k - 1, 0) >= 0);

  % Termination TCC generated (at line 66, column 6) for
      % diagonalize(pn)
      %            (comp_matrix, comp_inverse,
      %             replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
      %             IF comp_matrix
      %               THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
      %             ELSE Id(pn)
      %             ENDIF,
      %             IF comp_matrix AND comp_inverse
      %               THEN R * Easr(pn)(i, j, -pivnum)
      %             ELSE Id(pn)
      %             ENDIF,
      %             T, j, i + 1, stop_rec, max(k - 1, 0))
  diagonalize_TCC23: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           lex2(j, pn - (i + 1)) < lex2(j, pn - i));

  % Subtype TCC generated (at line 66, column 6) for
      % diagonalize(pn)
      %            (comp_matrix, comp_inverse,
      %             replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
      %             IF comp_matrix
      %               THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
      %             ELSE Id(pn)
      %             ENDIF,
      %             IF comp_matrix AND comp_inverse
      %               THEN R * Easr(pn)(i, j, -pivnum)
      %             ELSE Id(pn)
      %             ENDIF,
      %             T, j, i + 1, stop_rec, max(k - 1, 0))
      % expected type  {SGI:
                     %    [SquareMatrix(pn), SquareMatrix(pn),
                     %     SquareMatrix(pn)] |
                     %          (NOT stop_rec) IMPLIES
                     %                upper_triangular?(SGI`1)
                     %            AND FORALL
                     %                (k):
                     %                k < rows(T)
                     %                IMPLIES
                     %                entry(T)(k, k) = entry(SGI`1)(k, k)
                     %            AND FORALL
                     %                (k, p):
                     %                k < rows(SGI`1)
                     %                AND
                     %                k < rows(SGI`1) AND k < p
                     %                IMPLIES
                     %                (entry(SGI`1)(p, p) = 0
                     %                 OR
                     %                 entry(SGI`1)(k, p) = 0)
                     %            AND (comp_matrix
                     %                 IMPLIES
                     %                 SGI`2 * T = SGI`1
                     %                 AND
                     %                 is_simple_prod?
                     %                 (pn, FALSE, FALSE)(SGI`2))
                     %            AND (comp_matrix AND comp_inverse
                     %                 IMPLIES
                     %                 (SGI`3 * SGI`2 = Id(pn)
                     %                  AND
                     %                  SGI`2 * SGI`3 = Id(pn)
                     %                  AND
                     %                  is_simple_prod?
                     %                  (pn, FALSE, FALSE)(SGI`3)))
                     %            AND det(SGI`1) = det(S)}
  diagonalize_TCC24: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            v:
              [pn1: posnat ->
                 [d1:
                    {z:
                       [comp_matrix: bool, comp_inverse: bool,
                        S: {S: SquareMatrix(pn1) | upper_triangular?(S)},
                        Q:
                          {Q: SquareMatrix(pn1) |
                                   is_simple_prod?(pn1, FALSE, FALSE)(Q)},
                        {R: SquareMatrix(pn1) |
                                 is_simple_prod?(pn1, FALSE, FALSE)(R) AND
                                  (comp_matrix AND comp_inverse IMPLIES
                                    (R * Q = Id(pn1) AND Q * R = Id(pn1)))},
                        {T: SquareMatrix(pn1) |
                                 upper_triangular?(T) AND
                                  (comp_matrix IMPLIES Q * T = S) AND
                                   (FORALL (i):
                                      i < rows(T)
                                      IMPLIES
                                      entry(T)(i, i) = entry(S)(i, i))},
                        j: {j | d_point1(S)(j)}, {i | d_point2(S, j)(i)},
                        bool, nat] |
                             lex2(z`7, pn1 - z`8) < lex2(j, pn - i)} ->
                    {SGI:
                       [SquareMatrix(pn1), SquareMatrix(pn1),
                        SquareMatrix(pn1)] |
                             (NOT d1`9) IMPLIES
                                   upper_triangular?(SGI`1)
                               AND FORALL (k):
                                     k < rows(d1`6) IMPLIES
                                      entry(d1`6)(k, k) = entry(SGI`1)(k, k)
                               AND FORALL (k, p):
                                     k < rows(SGI`1) AND
                                      k < rows(SGI`1) AND k < p
                                      IMPLIES
                                      (entry(SGI`1)(p, p) = 0
                                       OR
                                       entry(SGI`1)(k, p) = 0)
                               AND (d1`1 IMPLIES
                                     SGI`2 * d1`6 = SGI`1 AND
                                      is_simple_prod?
                                      (pn1, FALSE, FALSE)(SGI`2))
                               AND (d1`1 AND d1`2 IMPLIES
                                     (SGI`3 * SGI`2 = Id(pn1)
                                      AND
                                      SGI`2 * SGI`3 = Id(pn1)
                                      AND
                                      is_simple_prod?
                                      (pn1, FALSE, FALSE)(SGI`3)))
                               AND det(SGI`1) = det(d1`3)}]],
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES
       (FORALL (pivnum: real):
          pivnum = -entry(S)(i, j) / entry(S)(j, j) IMPLIES
           (NOT stop_rec) IMPLIES
                 upper_triangular?(v(pn)
                                    (comp_matrix, comp_inverse,
                                     replace_row(i,
                                                 row(S)(i)
                                                 +
                                                 pivnum * row(S)(j))
                                                (S),
                                     IF comp_matrix
                                       THEN replace_row
                                            (i,
                                             row(Q)(i) + pivnum * row(Q)(j))
                                            (Q)
                                     ELSE Id(pn)
                                     ENDIF,
                                     IF comp_matrix AND comp_inverse
                                       THEN R * Easr(pn)(i, j, -pivnum)
                                     ELSE Id(pn)
                                     ENDIF,
                                     T, j, i + 1, stop_rec, max(k - 1, 0))`1)
             AND FORALL (k_1: nat):
                   k_1 < rows(T) IMPLIES
                    entry(T)(k_1, k_1) =
                     entry(v(pn)
                            (comp_matrix, comp_inverse,
                             replace_row(i, row(S)(i) + pivnum * row(S)(j))
                                        (S),
                             IF comp_matrix
                               THEN replace_row(i,
                                                row(Q)(i)
                                                +
                                                pivnum * row(Q)(j))
                                               (Q)
                             ELSE Id(pn)
                             ENDIF,
                             IF comp_matrix AND comp_inverse
                               THEN R * Easr(pn)(i, j, -pivnum)
                             ELSE Id(pn)
                             ENDIF,
                             T, j, i + 1, stop_rec, max(k - 1, 0))`1)
                          (k_1, k_1)
             AND FORALL (k_1: nat, p):
                   k_1 <
                    rows(v(pn)
                          (comp_matrix, comp_inverse,
                           replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                           IF comp_matrix
                             THEN replace_row(i,
                                              row(Q)(i) + pivnum * row(Q)(j))
                                             (Q)
                           ELSE Id(pn)
                           ENDIF,
                           IF comp_matrix AND comp_inverse
                             THEN R * Easr(pn)(i, j, -pivnum)
                           ELSE Id(pn)
                           ENDIF,
                           T, j, i + 1, stop_rec, max(k - 1, 0))`1)
                    AND
                    k_1 <
                     rows(v(pn)
                           (comp_matrix, comp_inverse,
                            replace_row(i, row(S)(i) + pivnum * row(S)(j))
                                       (S),
                            IF comp_matrix
                              THEN replace_row(i,
                                               row(Q)(i) + pivnum * row(Q)(j))
                                              (Q)
                            ELSE Id(pn)
                            ENDIF,
                            IF comp_matrix AND comp_inverse
                              THEN R * Easr(pn)(i, j, -pivnum)
                            ELSE Id(pn)
                            ENDIF,
                            T, j, i + 1, stop_rec, max(k - 1, 0))`1)
                     AND k_1 < p
                    IMPLIES
                    (entry(v(pn)
                            (comp_matrix, comp_inverse,
                             replace_row(i, row(S)(i) + pivnum * row(S)(j))
                                        (S),
                             IF comp_matrix
                               THEN replace_row(i,
                                                row(Q)(i)
                                                +
                                                pivnum * row(Q)(j))
                                               (Q)
                             ELSE Id(pn)
                             ENDIF,
                             IF comp_matrix AND comp_inverse
                               THEN R * Easr(pn)(i, j, -pivnum)
                             ELSE Id(pn)
                             ENDIF,
                             T, j, i + 1, stop_rec, max(k - 1, 0))`1)
                          (p, p)
                      = 0
                      OR
                      entry(v(pn)
                             (comp_matrix, comp_inverse,
                              replace_row(i, row(S)(i) + pivnum * row(S)(j))
                                         (S),
                              IF comp_matrix
                                THEN replace_row(i,
                                                 row(Q)(i)
                                                 +
                                                 pivnum * row(Q)(j))
                                                (Q)
                              ELSE Id(pn)
                              ENDIF,
                              IF comp_matrix AND comp_inverse
                                THEN R * Easr(pn)(i, j, -pivnum)
                              ELSE Id(pn)
                              ENDIF,
                              T, j, i + 1, stop_rec, max(k - 1, 0))`1)
                           (k_1, p)
                       = 0)
             AND (comp_matrix IMPLIES
                   v(pn)
                    (comp_matrix, comp_inverse,
                     replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                     IF comp_matrix
                       THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))(Q)
                     ELSE Id(pn)
                     ENDIF,
                     IF comp_matrix AND comp_inverse
                       THEN R * Easr(pn)(i, j, -pivnum)
                     ELSE Id(pn)
                     ENDIF,
                     T, j, i + 1, stop_rec, max(k - 1, 0))`2
                    * T
                    =
                    v(pn)
                     (comp_matrix, comp_inverse,
                      replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                      IF comp_matrix
                        THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))
                                        (Q)
                      ELSE Id(pn)
                      ENDIF,
                      IF comp_matrix AND comp_inverse
                        THEN R * Easr(pn)(i, j, -pivnum)
                      ELSE Id(pn)
                      ENDIF,
                      T, j, i + 1, stop_rec, max(k - 1, 0))`1
                    AND
                    is_simple_prod?(pn, FALSE, FALSE)
                                   (v(pn)
                                     (comp_matrix,
                                      comp_inverse,
                                      replace_row
                                      (i, row(S)(i) + pivnum * row(S)(j))(S),
                                      IF comp_matrix
                                      THEN replace_row
                                           (i, row(Q)(i) + pivnum * row(Q)(j))
                                           (Q)
                                      ELSE Id(pn)
                                      ENDIF,
                                      IF comp_matrix AND comp_inverse
                                      THEN R * Easr(pn)(i, j, -pivnum)
                                      ELSE Id(pn)
                                      ENDIF,
                                      T,
                                      j,
                                      i + 1,
                                      stop_rec,
                                      max(k - 1, 0))`2))
             AND (comp_matrix AND comp_inverse IMPLIES
                   (v(pn)
                     (comp_matrix, comp_inverse,
                      replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                      IF comp_matrix
                        THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))
                                        (Q)
                      ELSE Id(pn)
                      ENDIF,
                      IF comp_matrix AND comp_inverse
                        THEN R * Easr(pn)(i, j, -pivnum)
                      ELSE Id(pn)
                      ENDIF,
                      T, j, i + 1, stop_rec, max(k - 1, 0))`3
                     *
                     v(pn)
                      (comp_matrix, comp_inverse,
                       replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                       IF comp_matrix
                         THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))
                                         (Q)
                       ELSE Id(pn)
                       ENDIF,
                       IF comp_matrix AND comp_inverse
                         THEN R * Easr(pn)(i, j, -pivnum)
                       ELSE Id(pn)
                       ENDIF,
                       T, j, i + 1, stop_rec, max(k - 1, 0))`2
                     = Id(pn)
                     AND
                     v(pn)
                      (comp_matrix, comp_inverse,
                       replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                       IF comp_matrix
                         THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))
                                         (Q)
                       ELSE Id(pn)
                       ENDIF,
                       IF comp_matrix AND comp_inverse
                         THEN R * Easr(pn)(i, j, -pivnum)
                       ELSE Id(pn)
                       ENDIF,
                       T, j, i + 1, stop_rec, max(k - 1, 0))`2
                      *
                      v(pn)
                       (comp_matrix, comp_inverse,
                        replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                        IF comp_matrix
                          THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))
                                          (Q)
                        ELSE Id(pn)
                        ENDIF,
                        IF comp_matrix AND comp_inverse
                          THEN R * Easr(pn)(i, j, -pivnum)
                        ELSE Id(pn)
                        ENDIF,
                        T, j, i + 1, stop_rec, max(k - 1, 0))`3
                      = Id(pn)
                      AND
                      is_simple_prod?(pn, FALSE, FALSE)
                                     (v
                                      (pn)
                                      (comp_matrix,
                                       comp_inverse,
                                       replace_row
                                       (i, row(S)(i) + pivnum * row(S)(j))
                                       (S),
                                       IF comp_matrix
                                       THEN replace_row
                                            (i,
                                             row(Q)(i) + pivnum * row(Q)(j))
                                            (Q)
                                       ELSE Id(pn)
                                       ENDIF,
                                       IF comp_matrix AND comp_inverse
                                       THEN R * Easr(pn)(i, j, -pivnum)
                                       ELSE Id(pn)
                                       ENDIF,
                                       T,
                                       j,
                                       i + 1,
                                       stop_rec,
                                       max(k - 1, 0))`3)))
             AND det(v(pn)
                      (comp_matrix, comp_inverse,
                       replace_row(i, row(S)(i) + pivnum * row(S)(j))(S),
                       IF comp_matrix
                         THEN replace_row(i, row(Q)(i) + pivnum * row(Q)(j))
                                         (Q)
                       ELSE Id(pn)
                       ENDIF,
                       IF comp_matrix AND comp_inverse
                         THEN R * Easr(pn)(i, j, -pivnum)
                       ELSE Id(pn)
                       ENDIF,
                       T, j, i + 1, stop_rec, max(k - 1, 0))`1)
                  = det(S));

  % Subtype TCC generated (at line 65, column 37) for  entry(S)(j, j)
      % expected type  nznum
  diagonalize_TCC25: OBLIGATION
    FORALL (pn: posnat, comp_matrix, comp_inverse: bool,
            (S: SquareMatrix(pn) | upper_triangular?(S)),
            (Q: SquareMatrix(pn) | is_simple_prod?(pn, FALSE, FALSE)(Q)),
            (R: SquareMatrix(pn)
                 | is_simple_prod?(pn, FALSE, FALSE)(R) AND
                    (comp_matrix AND comp_inverse IMPLIES
                      (R * Q = Id(pn) AND Q * R = Id(pn)))),
            (T: SquareMatrix(pn)
                 | upper_triangular?(T) AND
                    (comp_matrix IMPLIES Q * T = S) AND
                     (FORALL (i):
                        i < rows(T) IMPLIES
                         entry(T)(i, i) = entry(S)(i, i))),
            (j: nat | d_point1(S)(j)), (i: nat | d_point2(S, j)(i)),
            stop_rec: bool, k: nat):
           NOT entry(S)(i, j) = 0 AND NOT i = j AND NOT entry(S)(j, j) = 0
       AND NOT (stop_rec AND k = 0) AND NOT (i = 0 AND j = 0)
       IMPLIES entry(S)(j, j) /= 0;

  % Subtype TCC generated (at line 74, column 69) for  rows(S)
      % expected type  posnat
  diag_TCC1: OBLIGATION FORALL (S): rows(S) > 0;

  % Subtype TCC generated (at line 83, column 77) for  Id(rows(S))
      % expected type  {Q: SquareMatrix(rows(S)) |
                     %          is_simple_prod?(rows(S), FALSE, FALSE)(Q)}
  diag_TCC2: OBLIGATION
    FORALL (S: Square): is_simple_prod?(rows(S), FALSE, FALSE)(Id(rows(S)));

  % Subtype TCC generated (at line 83, column 89) for  Id(rows(S))
      % expected type  {R: SquareMatrix(rows(S)) |
                     %          is_simple_prod?(rows(S), FALSE, FALSE)(R) AND
                     %           (comp_matrix AND comp_inverse IMPLIES
                     %             (R * Id(rows(S)) = Id(rows(S)) AND
                     %               Id(rows(S)) * R = Id(rows(S))))}
  diag_TCC3: OBLIGATION
    FORALL (comp_matrix, comp_inverse: bool, S: Square):
      is_simple_prod?(rows(S), FALSE, FALSE)(Id(rows(S))) AND
       (comp_matrix AND comp_inverse IMPLIES
         (Id(rows(S)) * Id(rows(S)) = Id(rows(S)) AND
           Id(rows(S)) * Id(rows(S)) = Id(rows(S))));

  % Subtype TCC generated (at line 83, column 101) for  S
      % expected type  {T: SquareMatrix(rows(S)) |
                     %          comp_matrix IMPLIES Id(rows(S)) * T = S}
  diag_TCC4: OBLIGATION
    FORALL (comp_matrix: bool, S: Square):
      comp_matrix IMPLIES Id(rows(S)) * S = S;

  % Subtype TCC generated (at line 83, column 103) for  0
      % expected type  {j | ut_point1(S)(j)}
  diag_TCC5: OBLIGATION FORALL (S: Square): ut_point1(S)(0);

  % Subtype TCC generated (at line 83, column 105) for  rows(S) - 1
      % expected type  {i | ut_point2(S, 0)(i)}
  diag_TCC6: OBLIGATION
    FORALL (S: Square): rows(S) - 1 >= 0 AND ut_point2(S, 0)(rows(S) - 1);

  % Subtype TCC generated (at line 84, column 68) for  S2
      % expected type  {S_1: SquareMatrix(rows(S)) | upper_triangular?(S_1)}
  diag_TCC7: OBLIGATION
    FORALL (comp_matrix, comp_inverse: bool, S: Square,
            S2: SquareMatrix(rows(S)), Q2: SquareMatrix(rows(S)),
            R2: SquareMatrix(rows(S))):
      R2 =
       upper_triangulate(rows(S))
                        (comp_matrix, comp_inverse, S, Id(rows(S)),
                         Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`3
       AND
       Q2 =
        upper_triangulate(rows(S))
                         (comp_matrix, comp_inverse, S, Id(rows(S)),
                          Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`2
        AND
        S2 =
         upper_triangulate(rows(S))
                          (comp_matrix, comp_inverse, S, Id(rows(S)),
                           Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`1
       IMPLIES upper_triangular?(S2);

  % Subtype TCC generated (at line 84, column 95) for  S2
      % expected type  {T: SquareMatrix(rows(S)) |
                     %          upper_triangular?(T) AND
                     %           (comp_matrix IMPLIES Id(rows(S)) * T = S2)
                     %            AND
                     %            (FORALL (i):
                     %               i < rows(T) IMPLIES
                     %                entry(T)(i, i) = entry(S2)(i, i))}
  diag_TCC8: OBLIGATION
    FORALL (comp_matrix, comp_inverse: bool, S: Square,
            S2: SquareMatrix(rows(S)), Q2: SquareMatrix(rows(S)),
            R2: SquareMatrix(rows(S))):
      R2 =
       upper_triangulate(rows(S))
                        (comp_matrix, comp_inverse, S, Id(rows(S)),
                         Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`3
       AND
       Q2 =
        upper_triangulate(rows(S))
                         (comp_matrix, comp_inverse, S, Id(rows(S)),
                          Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`2
        AND
        S2 =
         upper_triangulate(rows(S))
                          (comp_matrix, comp_inverse, S, Id(rows(S)),
                           Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`1
       IMPLIES
       upper_triangular?(S2) AND
        (comp_matrix IMPLIES Id(rows(S)) * S2 = S2) AND (FORALL (i): TRUE);

  % Subtype TCC generated (at line 84, column 98) for  rows(S) - 1
      % expected type  {j | d_point1(S2)(j)}
  diag_TCC9: OBLIGATION
    FORALL (comp_matrix, comp_inverse: bool, S: Square,
            S2: SquareMatrix(rows(S)), Q2: SquareMatrix(rows(S)),
            R2: SquareMatrix(rows(S))):
      R2 =
       upper_triangulate(rows(S))
                        (comp_matrix, comp_inverse, S, Id(rows(S)),
                         Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`3
       AND
       Q2 =
        upper_triangulate(rows(S))
                         (comp_matrix, comp_inverse, S, Id(rows(S)),
                          Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`2
        AND
        S2 =
         upper_triangulate(rows(S))
                          (comp_matrix, comp_inverse, S, Id(rows(S)),
                           Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`1
       IMPLIES rows(S) - 1 >= 0 AND d_point1(S2)(rows(S) - 1);

  % Subtype TCC generated (at line 84, column 108) for  0
      % expected type  {i | d_point2(S2, rows(S) - 1)(i)}
  diag_TCC10: OBLIGATION
    FORALL (comp_matrix, comp_inverse: bool, S: Square,
            S2: SquareMatrix(rows(S)), Q2: SquareMatrix(rows(S)),
            R2: SquareMatrix(rows(S))):
      R2 =
       upper_triangulate(rows(S))
                        (comp_matrix, comp_inverse, S, Id(rows(S)),
                         Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`3
       AND
       Q2 =
        upper_triangulate(rows(S))
                         (comp_matrix, comp_inverse, S, Id(rows(S)),
                          Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`2
        AND
        S2 =
         upper_triangulate(rows(S))
                          (comp_matrix, comp_inverse, S, Id(rows(S)),
                           Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`1
       IMPLIES d_point2(S2, rows(S) - 1)(0);

  % Subtype TCC generated (at line 85, column 37) for  R2 * R3
      % expected type  SquareMatrix(rows(S))
  diag_TCC11: OBLIGATION
    FORALL (comp_matrix, comp_inverse: bool, S: Square,
            S2: SquareMatrix(rows(S)), Q2: SquareMatrix(rows(S)),
            R2: SquareMatrix(rows(S))):
      R2 =
       upper_triangulate(rows(S))
                        (comp_matrix, comp_inverse, S, Id(rows(S)),
                         Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`3
       AND
       Q2 =
        upper_triangulate(rows(S))
                         (comp_matrix, comp_inverse, S, Id(rows(S)),
                          Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`2
        AND
        S2 =
         upper_triangulate(rows(S))
                          (comp_matrix, comp_inverse, S, Id(rows(S)),
                           Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`1
       IMPLIES
       (FORALL (S3: SquareMatrix(rows(S)), Q3: SquareMatrix(rows(S)),
                R3: SquareMatrix(rows(S))):
          R3 =
           diagonalize(rows(S))
                      (comp_matrix, comp_inverse, S2, Id(rows(S)),
                       Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`3
           AND
           Q3 =
            diagonalize(rows(S))
                       (comp_matrix, comp_inverse, S2, Id(rows(S)),
                        Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`2
            AND
            S3 =
             diagonalize(rows(S))
                        (comp_matrix, comp_inverse, S2, Id(rows(S)),
                         Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`1
           IMPLIES
           rows(R2 * R3) = rows(S) AND
            rows(R2 * R3) = columns(R2 * R3) AND
             rows(R2 * R3) > 0 AND columns(R2 * R3) > 0);

  % Subtype TCC generated (at line 85, column 25) for  Q3 * Q2
      % expected type  SquareMatrix(rows(S))
  diag_TCC12: OBLIGATION
    FORALL (comp_matrix, comp_inverse: bool, S: Square,
            S2: SquareMatrix(rows(S)), Q2: SquareMatrix(rows(S)),
            R2: SquareMatrix(rows(S))):
      R2 =
       upper_triangulate(rows(S))
                        (comp_matrix, comp_inverse, S, Id(rows(S)),
                         Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`3
       AND
       Q2 =
        upper_triangulate(rows(S))
                         (comp_matrix, comp_inverse, S, Id(rows(S)),
                          Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`2
        AND
        S2 =
         upper_triangulate(rows(S))
                          (comp_matrix, comp_inverse, S, Id(rows(S)),
                           Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`1
       IMPLIES
       (FORALL (S3: SquareMatrix(rows(S)), Q3: SquareMatrix(rows(S)),
                R3: SquareMatrix(rows(S))):
          R3 =
           diagonalize(rows(S))
                      (comp_matrix, comp_inverse, S2, Id(rows(S)),
                       Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`3
           AND
           Q3 =
            diagonalize(rows(S))
                       (comp_matrix, comp_inverse, S2, Id(rows(S)),
                        Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`2
            AND
            S3 =
             diagonalize(rows(S))
                        (comp_matrix, comp_inverse, S2, Id(rows(S)),
                         Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`1
           IMPLIES
           rows(Q3 * Q2) = rows(S) AND
            rows(Q3 * Q2) = columns(Q3 * Q2) AND
             rows(Q3 * Q2) > 0 AND columns(Q3 * Q2) > 0);

  % Subtype TCC generated (at line 85, column 3) for
      % (# ans := S3, multip := Q3 * Q2, inv := R2 * R3 #)
      % expected type  {SGI:
                     %    [# ans: SquareMatrix(rows(S)),
                     %       multip: SquareMatrix(rows(S)),
                     %       inv: SquareMatrix(rows(S)) #] |
                     %               upper_triangular?(SGI`ans)
                     %           AND (FORALL
                     %                (k, p):
                     %                k < rows(S)
                     %                AND
                     %                p < rows(S)
                     %                AND
                     %                entry(SGI`ans)(k, p) /= 0
                     %                IMPLIES
                     %                (k = p
                     %                 OR
                     %                 (k < p AND entry(SGI`ans)(p, p) = 0)))
                     %           AND (comp_matrix
                     %                IMPLIES
                     %                SGI`multip * S = SGI`ans
                     %                AND
                     %                is_simple_prod?
                     %                (rows(S), FALSE, FALSE)(SGI`multip))
                     %           AND (comp_matrix AND comp_inverse
                     %                IMPLIES
                     %                (SGI`inv * SGI`multip = Id(rows(S))
                     %                 AND
                     %                 SGI`multip * SGI`inv = Id(rows(S))
                     %                 AND
                     %                 is_simple_prod?
                     %                 (rows(S), FALSE, FALSE)(SGI`inv)))
                     %           AND det(SGI`ans) = det(S)
                     %           AND (det(S) /= 0
                     %                IFF
                     %                (FORALL
                     %                 (k, p):
                     %                 k < rows(S) AND p < rows(S)
                     %                 IMPLIES
                     %                 (entry(SGI`ans)(k, p) /= 0
                     %                  IFF
                     %                  k = p)))}
  diag_TCC13: OBLIGATION
    FORALL (comp_matrix, comp_inverse: bool, S: Square,
            S2: SquareMatrix(rows(S)), Q2: SquareMatrix(rows(S)),
            R2: SquareMatrix(rows(S))):
      R2 =
       upper_triangulate(rows(S))
                        (comp_matrix, comp_inverse, S, Id(rows(S)),
                         Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`3
       AND
       Q2 =
        upper_triangulate(rows(S))
                         (comp_matrix, comp_inverse, S, Id(rows(S)),
                          Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`2
        AND
        S2 =
         upper_triangulate(rows(S))
                          (comp_matrix, comp_inverse, S, Id(rows(S)),
                           Id(rows(S)), S, 0, rows(S) - 1, FALSE, 0)`1
       IMPLIES
       (FORALL (S3: SquareMatrix(rows(S)), Q3: SquareMatrix(rows(S)),
                R3: SquareMatrix(rows(S))):
          R3 =
           diagonalize(rows(S))
                      (comp_matrix, comp_inverse, S2, Id(rows(S)),
                       Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`3
           AND
           Q3 =
            diagonalize(rows(S))
                       (comp_matrix, comp_inverse, S2, Id(rows(S)),
                        Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`2
            AND
            S3 =
             diagonalize(rows(S))
                        (comp_matrix, comp_inverse, S2, Id(rows(S)),
                         Id(rows(S)), S2, rows(S) - 1, 0, FALSE, 0)`1
           IMPLIES
                upper_triangular?(S3)
            AND FORALL (k, p):
                  k < rows(S) AND p < rows(S) AND entry(S3)(k, p) /= 0
                   IMPLIES (k = p OR (k < p AND entry(S3)(p, p) = 0))
            AND (comp_matrix IMPLIES
                  Q3 * Q2 * S = S3 AND
                   is_simple_prod?(rows(S), FALSE, FALSE)(Q3 * Q2))
            AND (comp_matrix AND comp_inverse IMPLIES
                  (R2 * R3 * (Q3 * Q2) = Id(rows(S)) AND
                    Q3 * Q2 * (R2 * R3) = Id(rows(S)) AND
                     is_simple_prod?(rows(S), FALSE, FALSE)(R2 * R3)))
            AND det(S3) = det(S)
            AND (det(S) /= 0 IFF
                  (FORALL (k, p):
                     k < rows(S) AND p < rows(S) IMPLIES
                      (entry(S3)(k, p) /= 0 IFF k = p))));


body:
  matrix_inv: THEORY


  BEGIN

    IMPORTING matrix_diag


    SM,SM1,SM2: VAR FullMatrix

    r: VAR real

    nzr: VAR nzreal

    M,N,A,B: VAR Matrix

    v,v1,v2: VAR Vector

    i,j,k,p : VAR nat

    m,n : VAR nat

    pn,pm : VAR posnat

    F,G: VAR [[nat,nat]->real]

    Mp,Np: VAR (nonempty?)

    PFM,D1,D2,D: VAR PosFullMatrix

    SQ,IQ,GQ,
    SQ2,IQ2,GQ2,DQ,DQ2,
    Q,R,S,T,
    Q2,R2,S2,T2: VAR Square


    left_inv(S|det(S)/=0): {Q:SquareMatrix(rows(S))|Q*S=Id(rows(S))} =
      LET dg = diag(true,false,S), R=dg`multip,
      	newT = form_matrix(LAMBDA (i,j): IF i/=j OR entry(R*S)(i,i)=0 THEN 0
  	       			  	 ELSE 1/entry(R*S)(i,i) ENDIF,rows(S),rows(S))
      IN newT*R


    mult_left_inv_right: LEMMA det(S)/=0 IMPLIES
      S*left_inv(S)=Id(rows(S))

    invertible?(SQ): bool =
      EXISTS (IQ): rows(IQ) = rows(SQ) AND
        IQ*SQ = Id(rows(SQ)) AND SQ*IQ = Id(rows(SQ))

    invertible_rew: LEMMA
      invertible?(SQ) IFF
      (det(SQ)/=0 OR
       (EXISTS (IQ): rows(IQ) = rows(SQ) AND IQ*SQ=Id(rows(SQ))) OR
       (EXISTS (IQ): rows(IQ) = rows(SQ) AND SQ*IQ=Id(rows(SQ))))

    inverse(SQ|det(SQ)/=0 OR invertible?(SQ)): {IQ |
      rows(IQ) = rows(SQ) AND
        IQ*SQ = Id(rows(SQ)) AND SQ*IQ = Id(rows(SQ))} = left_inv(SQ)

     mult_inverse_left: LEMMA invertible?(SQ) IMPLIES
       inverse(SQ)*SQ = Id(rows(SQ))

     mult_inverse_right: LEMMA invertible?(SQ) IMPLIES
       SQ*inverse(SQ) = Id(rows(SQ))

     inverse_unique: LEMMA rows(IQ)=rows(SQ) AND (IQ*SQ = Id(rows(SQ)) OR 
       SQ*IQ = Id(rows(SQ)))
       IMPLIES (invertible?(SQ) AND det(SQ)/=0 AND IQ=inverse(SQ) AND
       IQ*SQ=Id(rows(SQ)) AND SQ*IQ=Id(rows(SQ)))

     invertible_det: LEMMA invertible?(SQ) IFF det(SQ)/=0

     invertible_mult: LEMMA rows(S)=rows(R) AND (det(S)/=0 OR invertible?(S)) AND
     		       (det(R)/=0 OR invertible?(R)) IMPLIES
       (det(S*R)/=0 AND invertible?(S*R))

     inverse_mult: LEMMA rows(S)=rows(R) AND (det(S)/=0 OR invertible?(S)) AND
     		       (det(R)/=0 OR invertible?(R)) IMPLIES
       inverse(S*R) = inverse(R)*inverse(S)

     det_inverse: LEMMA det(S)/=0 OR invertible?(S) IMPLIES
       det(inverse(S)) = 1/det(S)

     inverse_invertible: LEMMA det(S)/=0 OR invertible?(S) IMPLIES invertible?(inverse(S))

     inverse_inverse: LEMMA det(S)/=0 OR invertible?(S) IMPLIES
      inverse(inverse(S)) = S

     GH(pn:posnat): Square = form_matrix(LAMBDA (i,j): IF i<j THEN i^2+j^3+3 ELSE i*j-2+i^3+0.1^i ENDIF,pn,pn)

     det_nonzero_simple_prod: LEMMA det(S)/=0 IMPLIES
       is_simple_prod?(rows(S),true,false)(S)

     mult_induction: LEMMA FORALL (P:[SquareMatrix(rows(S))->bool]):
       (FORALL (i,j,r): i<rows(S) AND j<rows(S) AND i/=j IMPLIES 
         P(Easr(rows(S))(i,j,r))) AND
       (FORALL (i,r): i<rows(S) AND r/=0 IMPLIES 
         P(Esr(rows(S))(i,r))) AND
       P(Id(rows(S))) AND
       (FORALL (Q,R:SquareMatrix(rows(S))): P(Q) AND P(R) 
         IMPLIES P(Q*R)) AND
       det(S)/=0
       IMPLIES
       P(S)

     det_transpose: LEMMA FORALL (SM:PosFullMatrix):
       det(transpose(SM)) = det(SM)


  END matrix_inv

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 37, column 57) for  rows(S)
      % expected type  pm: posnat
  left_inv_TCC1: OBLIGATION
    FORALL (S: Square | det(S) /= 0, Q: SquareMatrix(rows(S))): rows(S) > 0;

  % Subtype TCC generated (at line 40, column 22) for  entry(R * S)(i, i)
      % expected type  nznum
  left_inv_TCC2: OBLIGATION
    FORALL (S: Square | det(S) /= 0,
            dg:
              {SGI:
                 [# ans: SquareMatrix(rows(S)),
                    inv: SquareMatrix(rows(S)),
                    multip: SquareMatrix(rows(S)) #] |
                            upper_triangular?(SGI`ans)
                        AND FORALL (k, p):
                              k < rows(S) AND
                               p < rows(S) AND entry(SGI`ans)(k, p) /= 0
                               IMPLIES
                               (k = p OR (k < p AND entry(SGI`ans)(p, p) = 0))
                        AND SGI`multip * S = SGI`ans
                        AND is_simple_prod?(rows(S), FALSE, FALSE)(SGI`multip)
                        AND det(SGI`ans) = det(S)
                        AND (det(S) /= 0 IFF
                              (FORALL (k, p):
                                 k < rows(S) AND p < rows(S) IMPLIES
                                  (entry(SGI`ans)(k, p) /= 0 IFF k = p)))}):
      dg = diag(TRUE, FALSE, S) IMPLIES
       (FORALL (R: SquareMatrix(rows(S))):
          R = dg`multip IMPLIES
           (FORALL (i: nat, j: nat):
              NOT i /= j AND NOT entry(R * S)(i, i) = 0 IMPLIES
               entry(R * S)(i, i) /= 0));

  % Subtype TCC generated (at line 41, column 7) for  newT * R
      % expected type  {Q: SquareMatrix(rows(S)) | Q * S = Id(rows(S))}
  left_inv_TCC3: OBLIGATION
    FORALL (S: Square | det(S) /= 0,
            dg:
              {SGI:
                 [# ans: SquareMatrix(rows(S)),
                    inv: SquareMatrix(rows(S)),
                    multip: SquareMatrix(rows(S)) #] |
                            upper_triangular?(SGI`ans)
                        AND FORALL (k, p):
                              k < rows(S) AND
                               p < rows(S) AND entry(SGI`ans)(k, p) /= 0
                               IMPLIES
                               (k = p OR (k < p AND entry(SGI`ans)(p, p) = 0))
                        AND SGI`multip * S = SGI`ans
                        AND is_simple_prod?(rows(S), FALSE, FALSE)(SGI`multip)
                        AND det(SGI`ans) = det(S)
                        AND (det(S) /= 0 IFF
                              (FORALL (k, p):
                                 k < rows(S) AND p < rows(S) IMPLIES
                                  (entry(SGI`ans)(k, p) /= 0 IFF k = p)))}):
      dg = diag(TRUE, FALSE, S) IMPLIES
       (FORALL (R: SquareMatrix(rows(S))):
          R = dg`multip IMPLIES
           (FORALL (newT:
                      {M: MatrixMN(rows(S), rows(S)) |
                               FORALL (i_1: below(rows(S)),
                                       j_1: below(rows(S))):
                                 nth[real](row(M)(i_1), j_1) =
                                  IF i_1 /= j_1 OR entry(R * S)(i_1, i_1) = 0
                                    THEN 0
                                  ELSE 1 / entry(R * S)(i_1, i_1)
                                  ENDIF}):
              newT =
               form_matrix(LAMBDA (i, j):
                             IF i /= j OR entry(R * S)(i, i) = 0 THEN 0
                             ELSE 1 / entry(R * S)(i, i)
                             ENDIF,
                           rows(S), rows(S))
               IMPLIES
                    newT * R * S = Id(rows(S)) AND rows(newT * R) = rows(S)
                AND rows(newT * R) = columns(newT * R) AND rows(newT * R) > 0
                AND columns(newT * R) > 0));

  % Subtype TCC generated (at line 45, column 21) for  rows(S)
      % expected type  pm: posnat
  mult_left_inv_right_TCC1: OBLIGATION
    FORALL (S: Square): det(S) /= 0 IMPLIES rows(S) > 0;

  % Subtype TCC generated (at line 49, column 17) for  rows(SQ)
      % expected type  pm: posnat
  invertible?_TCC1: OBLIGATION
    FORALL (SQ: Square, IQ: Square): rows(IQ) = rows(SQ) IMPLIES rows(SQ) > 0;

  % Subtype TCC generated (at line 59, column 64) for  SQ
      % expected type  S: {S | det(S) /= 0}
  inverse_TCC1: OBLIGATION
    FORALL (SQ: Square | det(SQ) /= 0 OR invertible?(SQ)): det(SQ) /= 0;

  % Subtype TCC generated (at line 59, column 55) for  left_inv(SQ)
      % expected type  {IQ |
                     %          rows(IQ) = rows(SQ) AND
                     %           IQ * SQ = Id(rows(SQ)) AND
                     %            SQ * IQ = Id(rows(SQ))}
  inverse_TCC2: OBLIGATION
    FORALL (SQ: Square | det(SQ) /= 0 OR invertible?(SQ)):
      rows(left_inv(SQ)) = rows(SQ) AND
       left_inv(SQ) * SQ = Id(rows(SQ)) AND SQ * left_inv(SQ) = Id(rows(SQ));

  % Subtype TCC generated (at line 62, column 13) for  SQ
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  mult_inverse_left_TCC1: OBLIGATION
    FORALL (SQ: Square):
      invertible?(SQ) IMPLIES det(SQ) /= 0 OR invertible?(SQ);

  % Subtype TCC generated (at line 62, column 25) for  rows(SQ)
      % expected type  pm: posnat
  mult_inverse_left_TCC2: OBLIGATION
    FORALL (SQ: Square): invertible?(SQ) IMPLIES rows(SQ) > 0;

  % Subtype TCC generated (at line 76, column 34) for  S * R
      % expected type  Square
  invertible_mult_TCC1: OBLIGATION
    FORALL (R, S: Square):
      (det(R) /= 0 OR invertible?(R)) AND
       (det(S) /= 0 OR invertible?(S)) AND
        rows(S) = rows(R) AND det(S * R) /= 0
       IMPLIES
       rows(S * R) = columns(S * R) AND
        rows(S * R) > 0 AND columns(S * R) > 0;

  % Subtype TCC generated (at line 80, column 13) for  S * R
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  inverse_mult_TCC1: OBLIGATION
    FORALL (R, S: Square):
      (det(R) /= 0 OR invertible?(R)) AND
       (det(S) /= 0 OR invertible?(S)) AND rows(S) = rows(R)
       IMPLIES
       (det(S * R) /= 0 OR invertible?(S * R)) AND
        rows(S * R) = columns(S * R) AND
         rows(S * R) > 0 AND columns(S * R) > 0;

  % Subtype TCC generated (at line 83, column 25) for  det(S)
      % expected type  nznum
  det_inverse_TCC1: OBLIGATION
    FORALL (S: Square): det(S) /= 0 OR invertible?(S) IMPLIES det(S) /= 0;

  % Subtype TCC generated (at line 88, column 12) for  inverse(S)
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  inverse_inverse_TCC1: OBLIGATION
    FORALL (S: Square):
      det(S) /= 0 OR invertible?(S) IMPLIES
       det(inverse(S)) /= 0 OR invertible?(inverse(S));

  % Subtype TCC generated (at line 90, column 67) for  2
      % expected type  {i_1: int | i /= 0 OR i_1 >= 0}
  GH_TCC1: OBLIGATION FORALL (i: nat, j: nat): i < j IMPLIES i /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 90, column 71) for  3
      % expected type  {i: int | j /= 0 OR i >= 0}
  GH_TCC2: OBLIGATION FORALL (i: nat, j: nat): i < j IMPLIES j /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 90, column 88) for  3
      % expected type  {i_1: int | i /= 0 OR i_1 >= 0}
  GH_TCC3: OBLIGATION
    FORALL (i: nat, j: nat): NOT i < j IMPLIES i /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 90, column 27) for
      % form_matrix(LAMBDA (i, j):
      %               IF i < j THEN i ^ 2 + j ^ 3 + 3
      %               ELSE i * j - 2 + i ^ 3 + 0.1 ^ i
      %               ENDIF,
      %             pn, pn)
      % expected type  Square
  GH_TCC4: OBLIGATION
    FORALL (pn: posnat):
      rows(form_matrix(LAMBDA (i, j):
                         IF i < j THEN i ^ 2 + j ^ 3 + 3
                         ELSE i * j - 2 + i ^ 3 + 0.1 ^ i
                         ENDIF,
                       pn, pn))
       =
       columns(form_matrix(LAMBDA (i, j):
                             IF i < j THEN i ^ 2 + j ^ 3 + 3
                             ELSE i * j - 2 + i ^ 3 + 0.1 ^ i
                             ENDIF,
                           pn, pn))
       AND
       rows(form_matrix(LAMBDA (i, j):
                          IF i < j THEN i ^ 2 + j ^ 3 + 3
                          ELSE i * j - 2 + i ^ 3 + 0.1 ^ i
                          ENDIF,
                        pn, pn))
        > 0
        AND
        columns(form_matrix(LAMBDA (i, j):
                              IF i < j THEN i ^ 2 + j ^ 3 + 3
                              ELSE i * j - 2 + i ^ 3 + 0.1 ^ i
                              ENDIF,
                            pn, pn))
         > 0;

  % Subtype TCC generated (at line 97, column 14) for  rows(S)
      % expected type  pn: posnat
  mult_induction_TCC1: OBLIGATION
    FORALL (S: Square, i: nat, j: nat):
      i < rows(S) AND j < rows(S) AND i /= j IMPLIES rows(S) > 0;

  % Subtype TCC generated (at line 99, column 13) for  rows(S)
      % expected type  pn: posnat
  mult_induction_TCC2: OBLIGATION
    FORALL (S: Square, P: [SquareMatrix(rows(S)) -> bool]):
      (FORALL (i, j, r):
         i < rows(S) AND j < rows(S) AND i /= j IMPLIES
          P(Easr(rows(S))(i, j, r)))
       IMPLIES
       (FORALL (i1: nat, r1: real):
          i1 < rows(S) AND r1 /= 0 IMPLIES rows(S) > 0);

  % Subtype TCC generated (at line 100, column 10) for  rows(S)
      % expected type  pm: posnat
  mult_induction_TCC3: OBLIGATION
    FORALL (S: Square, P: [SquareMatrix(rows(S)) -> bool]):
      ((FORALL (i, r): i < rows(S) AND r /= 0 IMPLIES P(Esr(rows(S))(i, r)))
        AND
        (FORALL (i, j, r):
           i < rows(S) AND j < rows(S) AND i /= j IMPLIES
            P(Easr(rows(S))(i, j, r))))
       IMPLIES rows(S) > 0;

  % Subtype TCC generated (at line 102, column 17) for  Q * R
      % expected type  SquareMatrix(rows(S))
  mult_induction_TCC4: OBLIGATION
    FORALL (S: Square, P: [SquareMatrix(rows(S)) -> bool]):
      (P(Id(rows(S))) AND
        (FORALL (i, r): i < rows(S) AND r /= 0 IMPLIES P(Esr(rows(S))(i, r)))
         AND
         (FORALL (i, j, r):
            i < rows(S) AND j < rows(S) AND i /= j IMPLIES
             P(Easr(rows(S))(i, j, r))))
       IMPLIES
       (FORALL (Q, R: SquareMatrix(rows(S))):
          P(Q) AND P(R) IMPLIES
           rows(Q * R) = rows(S) AND
            rows(Q * R) = columns(Q * R) AND
             rows(Q * R) > 0 AND columns(Q * R) > 0);


body:
  tensor_product  % [ parameters ]
  		: THEORY

    BEGIN

      


  IMPORTING matrices, matrix_props, matrix_inv, linear_dependence,  reals@base_repr, ints@mod_lems, reals@product


  m1, m2, n1, n2: VAR nat

  a,b: VAR {x:nat | x>1}

  Q: VAR Matrix

  M, N:  VAR FullMatrix
   
  A, B, A2, B2: VAR PosFullMatrix

  AA, BB: VAR Square

  v1, v2: VAR Vector

  f,g, F: VAR [nat->real]

  not_null: LEMMA nonempty?(Q) IMPLIES NOT null?(Q)
  mod_int: LEMMA FORALL (k:nat, n:posnat): 
                 integer_pred((k-mod(k,n))/n) AND (k-mod(k,n))/n>=0

  tensor_fun(A,B): [[nat,nat]->real] =
  		 LAMBDA(i,j:nat): IF i<rows(A)*rows(B) THEN
  		 		    IF j<columns(A)*columns(B) THEN
  				       entry(A)((i-mod(i, rows(B)))/rows(B), (j-mod(j, columns(B)))/columns(B))*
  				       entry(B)(mod(i, rows(B)), mod(j, columns(B))) 
  				    ELSE 0 ENDIF
  				  ELSE 0 ENDIF

  tensor_prod(A,B): PosFullMatrix = form_matrix(tensor_fun(A,B), rows(A)*rows(B), columns(A)*columns(B))

  entry_tensor_prod: LEMMA entry(tensor_prod(A,B)) = tensor_fun(A,B)

  tensor_rows: LEMMA rows(tensor_prod(A,B)) = rows(A)*rows(B)

  tensor_cols: LEMMA columns(tensor_prod(A,B)) = columns(A)*columns(B)

  tensor_mult_entry: LEMMA columns(A) = rows(A2) AND columns(B) = rows(B2)
  		   IMPLIES entry(tensor_prod(A,B)*tensor_prod(A2, B2))(m1, n1) = 
                     entry(A*A2)((m1-mod(m1, rows(B)))/rows(B), (n1-mod(n1, columns(B2)))/columns(B2))*
  		   entry(B*B2)(mod(m1, rows(B)), mod(n1, columns(B2)))
  		    

  invertible_tensor: LEMMA invertible?(AA) AND invertible?(BB) IMPLIES
                     invertible?(tensor_prod(AA,BB)) AND
                     inverse(tensor_prod(AA,BB)) = tensor_prod(inverse(AA), inverse(BB))


  TQMat: Square = (:(:1,1,1:), (:0,1,-1:), (:0,1,1:):)

  TQMatInv: Square = (:(:1,0,-1:), (:0, 1/2, 1/2:), (:0, -1/2, 1/2:):) 

  invTQ: LEMMA invertible?(TQMat) 

  is_invTQ: LEMMA inverse(TQMat) = TQMatInv

  tensor_power(A:PosFullMatrix,  n:posnat): RECURSIVE PosFullMatrix = IF n=1 THEN A ELSE tensor_prod(A, tensor_power(A, n-1)) ENDIF
                            MEASURE n  

  invertible_tensor_power: LEMMA FORALL(A:Square, n: posnat): invertible?(A) IMPLIES invertible?(tensor_power(A,n)) AND 
                           inverse(tensor_power(A,n)) = tensor_power(inverse(A), n) 

  tensor_power_rows: LEMMA FORALL(A:PosFullMatrix, n:posnat):
                     rows(A)^n = rows(tensor_power(A,n))

  tensor_power_columns: LEMMA FORALL(A:PosFullMatrix, n:posnat):
  		     columns(A)^n = columns(tensor_power(A,n))




  mod_eq_lem_alt: LEMMA FORALL (n,m:posnat,i:nat):
  	  (mod(i,n)+n*mod((i-mod(i,n))/n,m)-
    mod(mod(i,n)+n*mod((i-mod(i,n))/n,m),n))/n
     =mod((i-mod(i,n))/n,m)

  tensor_prod_assoc: LEMMA FORALL (A,B,C:PosFullMatrix):
    tensor_prod(A,tensor_prod(B,C)) = tensor_prod(tensor_prod(A,B),C)

  tensor_power_alt(A:PosFullMatrix, n:posnat):  RECURSIVE PosFullMatrix = IF n=1 THEN A ELSE tensor_prod(tensor_power_alt(A, n-1), A) ENDIF
                            MEASURE n 


  %% Prove this one...

  power_assoc: LEMMA FORALL (A:PosFullMatrix, n:posnat): 
  	     tensor_power(A, n) = tensor_power_alt(A, n) 

  tensor_power_rows_alt: LEMMA FORALL(A:PosFullMatrix, n:posnat):
                     rows(A)^n = rows(tensor_power_alt(A,n))

  tensor_power_columns_alt: LEMMA FORALL(A:PosFullMatrix, n:posnat):
  		     columns(A)^n = columns(tensor_power_alt(A,n))



  TQXL:    Square = (: (: 1,   1,   1, 0, 0, 0 :), 
        	       	     (: 0,   1,  -1, 0, 0, 0 :), 
  		     (: 0,   1,   1, 0, 0, 0 :), 
  		     (: 0,  -1,  -1, 1, 0, 0 :), 
  		     (:-1,  -1,   0, 0, 1, 0 :), 
  		     (:-1,   0,  -1, 0, 0, 1 :) :)

  TQXLinv: Square = (: (: 1,   0,  -1, 0, 0, 0 :), 
        	       	     (: 0, 1/2, 1/2, 0, 0, 0 :), 
  		     (: 0,-1/2, 1/2, 0, 0, 0 :), 
  		     (: 0,   0,   1, 1, 0, 0 :), 
  		     (: 1, 1/2,-1/2, 0, 1, 0 :), 
  		     (: 1,-1/2,-1/2, 0, 0, 1 :) :)

  invTQXL: LEMMA invertible?(TQXL) AND invertible?(TQXLinv) 

  is_invTQXL: LEMMA inverse(TQXL) = TQXLinv AND inverse(TQXLinv) = TQXL

  RowToMat(M:PosFullMatrix, k:below(rows(M))): PosFullMatrix = (:row(M)(k):)

  RtM: LEMMA FORALL (M:PosFullMatrix, k:below(rows(M))):
       RowToMat(M, k)  = row2mat(M, k)

  RowToMat_rows: LEMMA FORALL (M:PosFullMatrix, k:below(rows(M))):
   	       rows(RowToMat(M,k))=1

  RowToMat_columns: LEMMA FORALL (M:PosFullMatrix, k:below(rows(M))):
   	       columns(RowToMat(M,k))=columns(M)

  RowToMat_entry: LEMMA FORALL (M:PosFullMatrix, k:below(rows(M)), n:below(columns(M))):
               entry(RowToMat(M, k))(0,n) = entry(M)(k,n)

  RowToMat_tensor_prod: LEMMA FORALL(M, N:PosFullMatrix, k:below(rows(M)*rows(N))):
           RowToMat(tensor_prod(M, N), k) = 
  	 tensor_prod(RowToMat(M, (k-mod(k,rows(N)))/rows(N)), RowToMat(N, mod(k,rows(N))))

  RowTensor(M:PosFullMatrix, n: posnat, L:{ LL: list[below(rows(M))] | length(LL)=n}): RECURSIVE PosFullMatrix = 
  	      IF n=1 THEN RowToMat(M, car(L)) 
  	      ELSE tensor_prod( RowTensor(M, n-1, cdr(L)), RowToMat(M,car(L))) ENDIF
  	      MEASURE n

  RowTensorAlt(M:PosFullMatrix, n:posnat, f:[nat->below(rows(M))]): RECURSIVE PosFullMatrix = 
                IF n=1 THEN row2mat(M, f(0))
  	      ELSE tensor_prod(RowTensorAlt(M, n-1, LAMBDA(j:nat):f(j+1)), row2mat(M, f(0)))
  	      ENDIF 
  	      MEASURE n  

  RowTensors_same: LEMMA FORALL (M:{AA:PosFullMatrix|rows(AA)>1}, n:posnat, k:below(rows(M)^n)):	
  		 RowTensor(M, n, base_list(rows(M), k, n)) = RowTensorAlt(M, n, base_n(rows(M), k))

  RowTensor_is_TensorRow: LEMMA FORALL (M:PosFullMatrix, n:posnat, k:below(rows(M)^n)):
               rows(M)>1 IMPLIES 
  	     RowToMat(tensor_power_alt(M, n), k) = RowTensor(M, n, base_list(rows(M), k , n))

  RowTensor_is_TensorRow2: LEMMA FORALL (M:{AA:PosFullMatrix|rows(AA)>1}, n:posnat, k:below(rows(M)^n)):
  			 row2mat(tensor_power(M, n), k) = RowTensorAlt(M, n, base_n(rows(M), k))

  entry_pick(n, rdim, cdim:posnat, A:{AA:PosFullMatrix |rows(AA)=rdim AND columns(AA)=cdim},  
  	      R, C: [nat->nat])(i:nat):
            real = entry(A)(R(i), C(i))  

  tensor_entry: LEMMA FORALL (A:{M:PosFullMatrix | rows(M)>1 AND columns(M)>1}, n:posnat, k:below(rows(A)^n), m:below(columns(A)^n)):
  	      LET R = base_n(rows(A), k), 
  	          C = base_n(columns(A), m) IN
             entry(tensor_power_alt(A,n))(k,m) = product[nat](0, n-1, entry_pick(n, rows(A), columns(A), A, R, C))   

  tensor_entry_alt: LEMMA FORALL (A:{M:PosFullMatrix | rows(M)>1 AND columns(M)>1}, n:posnat, k:below(rows(A)^n), m:below(columns(A)^n)):
  	      LET R = base_n(rows(A), k), 
  	          C = base_n(columns(A), m) IN
             entry(tensor_power_alt(A,n))(k,m) = product[nat](0, n-1, entry_pick(n, rows(A), columns(A), A, R, C))  
    
  	  

    

    END tensor_product

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 36, column 30) for  rows(B)
      % expected type  nonzero_integer
  tensor_fun_TCC1: OBLIGATION
    FORALL (A: PosFullMatrix, B: PosFullMatrix, i, j: nat):
      j < columns(A) * columns(B) AND i < rows(A) * rows(B) IMPLIES
       rows(B) /= 0;

  % Subtype TCC generated (at line 36, column 20) for
      % (i - mod(i, rows(B))) / rows(B)
      % expected type  nat
  tensor_fun_TCC2: OBLIGATION
    FORALL (A: PosFullMatrix, B: PosFullMatrix, i, j: nat):
      j < columns(A) * columns(B) AND i < rows(A) * rows(B) IMPLIES
       integer_pred((i - mod(i, rows(B))) / rows(B)) AND
        (i - mod(i, rows(B))) / rows(B) >= 0;

  % Subtype TCC generated (at line 36, column 59) for  columns(B)
      % expected type  nonzero_integer
  tensor_fun_TCC3: OBLIGATION
    FORALL (A: PosFullMatrix, B: PosFullMatrix, i, j: nat):
      j < columns(A) * columns(B) AND i < rows(A) * rows(B) IMPLIES
       columns(B) /= 0;

  % Subtype TCC generated (at line 36, column 49) for
      % (j - mod(j, columns(B))) / columns(B)
      % expected type  nat
  tensor_fun_TCC4: OBLIGATION
    FORALL (A: PosFullMatrix, B: PosFullMatrix, i, j: nat):
      j < columns(A) * columns(B) AND i < rows(A) * rows(B) IMPLIES
       integer_pred((j - mod(j, columns(B))) / columns(B)) AND
        (j - mod(j, columns(B))) / columns(B) >= 0;

  % Subtype TCC generated (at line 37, column 20) for  mod(i, rows(B))
      % expected type  nat
  tensor_fun_TCC5: OBLIGATION
    FORALL (A: PosFullMatrix, B: PosFullMatrix, i, j: nat):
      j < columns(A) * columns(B) AND i < rows(A) * rows(B) IMPLIES
       mod(i, rows(B)) >= 0;

  % Subtype TCC generated (at line 37, column 37) for  mod(j, columns(B))
      % expected type  nat
  tensor_fun_TCC6: OBLIGATION
    FORALL (A: PosFullMatrix, B: PosFullMatrix, i, j: nat):
      j < columns(A) * columns(B) AND i < rows(A) * rows(B) IMPLIES
       mod(j, columns(B)) >= 0;

  % Subtype TCC generated (at line 41, column 34) for
      % form_matrix(tensor_fun(A, B), rows(A) * rows(B),
      %             columns(A) * columns(B))
      % expected type  PosFullMatrix
  tensor_prod_TCC1: OBLIGATION
    FORALL (A: PosFullMatrix, B: PosFullMatrix):
      rows(form_matrix(tensor_fun(A, B), rows(A) * rows(B),
                       columns(A) * columns(B)))
       > 0
       AND
       columns(form_matrix(tensor_fun(A, B), rows(A) * rows(B),
                           columns(A) * columns(B)))
        > 0;

  % Subtype TCC generated (at line 51, column 43) for  rows(B)
      % expected type  nonzero_integer
  tensor_mult_entry_TCC1: OBLIGATION
    FORALL (A, A2, B, B2: PosFullMatrix):
      columns(B) = rows(B2) AND columns(A) = rows(A2) IMPLIES rows(B) /= 0;

  % Subtype TCC generated (at line 51, column 31) for
      % (m1 - mod(m1, rows(B))) / rows(B)
      % expected type  nat
  tensor_mult_entry_TCC2: OBLIGATION
    FORALL (A, A2, B, B2: PosFullMatrix, m1: nat):
      columns(B) = rows(B2) AND columns(A) = rows(A2) IMPLIES
       integer_pred((m1 - mod(m1, rows(B))) / rows(B)) AND
        (m1 - mod(m1, rows(B))) / rows(B) >= 0;

  % Subtype TCC generated (at line 51, column 74) for  columns(B2)
      % expected type  nonzero_integer
  tensor_mult_entry_TCC3: OBLIGATION
    FORALL (A, A2, B, B2: PosFullMatrix):
      columns(B) = rows(B2) AND columns(A) = rows(A2) IMPLIES
       columns(B2) /= 0;

  % Subtype TCC generated (at line 51, column 62) for
      % (n1 - mod(n1, columns(B2))) / columns(B2)
      % expected type  nat
  tensor_mult_entry_TCC4: OBLIGATION
    FORALL (A, A2, B, B2: PosFullMatrix, n1: nat):
      columns(B) = rows(B2) AND columns(A) = rows(A2) IMPLIES
       integer_pred((n1 - mod(n1, columns(B2))) / columns(B2)) AND
        (n1 - mod(n1, columns(B2))) / columns(B2) >= 0;

  % Subtype TCC generated (at line 52, column 17) for  mod(m1, rows(B))
      % expected type  nat
  tensor_mult_entry_TCC5: OBLIGATION
    FORALL (A, A2, B, B2: PosFullMatrix, m1: nat):
      columns(B) = rows(B2) AND columns(A) = rows(A2) IMPLIES
       mod(m1, rows(B)) >= 0;

  % Subtype TCC generated (at line 52, column 35) for  mod(n1, columns(B2))
      % expected type  nat
  tensor_mult_entry_TCC6: OBLIGATION
    FORALL (A, A2, B, B2: PosFullMatrix, n1: nat):
      columns(B) = rows(B2) AND columns(A) = rows(A2) IMPLIES
       mod(n1, columns(B2)) >= 0;

  % Subtype TCC generated (at line 56, column 31) for  tensor_prod(AA, BB)
      % expected type  Square
  invertible_tensor_TCC1: OBLIGATION
    FORALL (AA, BB: Square):
      invertible?(BB) AND invertible?(AA) IMPLIES
       rows(tensor_prod(AA, BB)) = columns(tensor_prod(AA, BB));

  % Subtype TCC generated (at line 57, column 27) for  tensor_prod(AA, BB)
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  invertible_tensor_TCC2: OBLIGATION
    FORALL (AA, BB: Square):
      invertible?(BB) AND
       invertible?(AA) AND invertible?(tensor_prod(AA, BB))
       IMPLIES
       rows(tensor_prod(AA, BB)) = columns(tensor_prod(AA, BB)) AND
        (det(tensor_prod(AA, BB)) /= 0 OR invertible?(tensor_prod(AA, BB)));

  % Subtype TCC generated (at line 57, column 69) for  AA
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  invertible_tensor_TCC3: OBLIGATION
    FORALL (AA, BB: Square):
      invertible?(BB) AND
       invertible?(AA) AND invertible?(tensor_prod(AA, BB))
       IMPLIES det(AA) /= 0 OR invertible?(AA);

  % Subtype TCC generated (at line 57, column 82) for  BB
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  invertible_tensor_TCC4: OBLIGATION
    FORALL (AA, BB: Square):
      invertible?(BB) AND
       invertible?(AA) AND invertible?(tensor_prod(AA, BB))
       IMPLIES det(BB) /= 0 OR invertible?(BB);

  % Subtype TCC generated (at line 60, column 18) for  (: 1, 1, 1 :)
      % expected type  list[real]
  TQMat_TCC1: OBLIGATION
    every[number]
        (LAMBDA (x: number): number_field_pred(x) AND real_pred(x))
        ((: 1, 1, 1 :));

  % Subtype TCC generated (at line 60, column 29) for
      % (: (: 0, 1, -1 :), (: 0, 1, 1 :) :)
      % expected type  list[list[real]]
  TQMat_TCC2: OBLIGATION
    every[list[number]]
        (LAMBDA (x: list[number]):
           every[number]
               (LAMBDA (x: number): number_field_pred(x) AND real_pred(x))(x))
        ((: (: 0, 1, -1 :), (: 0, 1, 1 :) :));

  % Subtype TCC generated (at line 60, column 16) for
      % (: (: 1, 1, 1 :), (: 0, 1, -1 :), (: 0, 1, 1 :) :)
      % expected type  Square
  TQMat_TCC3: OBLIGATION
    (null?[list[real]]((: (: 1, 1, 1 :), (: 0, 1, -1 :), (: 0, 1, 1 :) :)) OR
      (FORALL (i,
               j:
                 below(length[list[real]]
                           ((: (: 1, 1, 1 :), (: 0, 1, -1 :),
                               (: 0, 1, 1 :) :)))):
         length[real]
             (nth[list[real]]
                  ((: (: 1, 1, 1 :), (: 0, 1, -1 :), (: 0, 1, 1 :) :), i))
          =
          length[real]
              (nth[list[real]]
                   ((: (: 1, 1, 1 :), (: 0, 1, -1 :), (: 0, 1, 1 :) :), j))))
     AND
     (rows((: (: 1, 1, 1 :), (: 0, 1, -1 :), (: 0, 1, 1 :) :)) > 0 AND
       columns((: (: 1, 1, 1 :), (: 0, 1, -1 :), (: 0, 1, 1 :) :)) > 0)
      AND
      rows((: (: 1, 1, 1 :), (: 0, 1, -1 :), (: 0, 1, 1 :) :)) =
       columns((: (: 1, 1, 1 :), (: 0, 1, -1 :), (: 0, 1, 1 :) :));

  % Subtype TCC generated (at line 62, column 21) for  (: 1, 0, -1 :)
      % expected type  list[real]
  TQMatInv_TCC1: OBLIGATION
    every[number]
        (LAMBDA (x: number): number_field_pred(x) AND real_pred(x))
        ((: 1, 0, -1 :));

  % Subtype TCC generated (at line 62, column 33) for
      % (: (: 0, 1 / 2, 1 / 2 :), (: 0, -1 / 2, 1 / 2 :) :)
      % expected type  list[list[real]]
  TQMatInv_TCC2: OBLIGATION
    every[list[number]]
        (LAMBDA (x: list[number]):
           every[number]
               (LAMBDA (x: number): number_field_pred(x) AND real_pred(x))(x))
        ((: (: 0, 1 / 2, 1 / 2 :), (: 0, -1 / 2, 1 / 2 :) :));

  % Subtype TCC generated (at line 62, column 19) for
      % (: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :), (: 0, -1 / 2, 1 / 2 :) :)
      % expected type  Square
  TQMatInv_TCC3: OBLIGATION
    (null?[list[real]]
         ((: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :),
             (: 0, -1 / 2, 1 / 2 :) :))
      OR
      (FORALL (i,
               j:
                 below(length[list[real]]
                           ((: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :),
                               (: 0, -1 / 2, 1 / 2 :) :)))):
         length[real]
             (nth[list[real]]
                  ((: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :),
                      (: 0, -1 / 2, 1 / 2 :) :),
                   i))
          =
          length[real]
              (nth[list[real]]
                   ((: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :),
                       (: 0, -1 / 2, 1 / 2 :) :),
                    j))))
     AND
     (rows((: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :),
              (: 0, -1 / 2, 1 / 2 :) :))
       > 0
       AND
       columns((: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :),
                  (: 0, -1 / 2, 1 / 2 :) :))
        > 0)
      AND
      rows((: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :),
              (: 0, -1 / 2, 1 / 2 :) :))
       =
       columns((: (: 1, 0, -1 :), (: 0, 1 / 2, 1 / 2 :),
                  (: 0, -1 / 2, 1 / 2 :) :));

  % Subtype TCC generated (at line 66, column 24) for  TQMat
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  is_invTQ_TCC1: OBLIGATION det(TQMat) /= 0 OR invertible?(TQMat);

  % Subtype TCC generated (at line 68, column 118) for  n - 1
      % expected type  posnat
  tensor_power_TCC1: OBLIGATION
    FORALL (n: posnat): NOT n = 1 IMPLIES n - 1 >= 0 AND n - 1 > 0;

  % Termination TCC generated (at line 68, column 102) for
      % tensor_power(A, n - 1)
  tensor_power_TCC2: OBLIGATION
    FORALL (n: posnat): NOT n = 1 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 71, column 95) for  tensor_power(A, n)
      % expected type  Square
  invertible_tensor_power_TCC1: OBLIGATION
    FORALL (A: Square, n: posnat):
      invertible?(A) IMPLIES
       rows(tensor_power(A, n)) = columns(tensor_power(A, n));

  % Subtype TCC generated (at line 72, column 33) for  tensor_power(A, n)
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  invertible_tensor_power_TCC2: OBLIGATION
    FORALL (A: Square, n: posnat):
      invertible?(tensor_power(A, n)) AND invertible?(A) IMPLIES
       rows(tensor_power(A, n)) = columns(tensor_power(A, n)) AND
        (det(tensor_power(A, n)) /= 0 OR invertible?(tensor_power(A, n)));

  % Subtype TCC generated (at line 72, column 75) for  A
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  invertible_tensor_power_TCC3: OBLIGATION
    FORALL (A: Square, n: posnat):
      invertible?(tensor_power(A, n)) AND invertible?(A) IMPLIES
       det(A) /= 0 OR invertible?(A);

  % Subtype TCC generated (at line 75, column 27) for  n
      % expected type  {i: int | rows(A) /= 0 OR i >= 0}
  tensor_power_rows_TCC1: OBLIGATION
    FORALL (A: PosFullMatrix, n: posnat): rows(A) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 78, column 18) for  n
      % expected type  {i: int | columns(A) /= 0 OR i >= 0}
  tensor_power_columns_TCC1: OBLIGATION
    FORALL (A: PosFullMatrix, n: posnat): columns(A) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 84, column 19) for  (i - mod(i, n)) / n
      % expected type  int
  mod_eq_lem_alt_TCC1: OBLIGATION
    FORALL (n: posnat, i: nat): integer_pred((i - mod(i, n)) / n);

  % Subtype TCC generated (at line 108, column 21) for  (: 1, 1, 1, 0, 0, 0 :)
      % expected type  list[real]
  TQXL_TCC1: OBLIGATION
    every[number]
        (LAMBDA (x: number): number_field_pred(x) AND real_pred(x))
        ((: 1, 1, 1, 0, 0, 0 :));

  % Subtype TCC generated (at line 109, column 20) for
      % (: (: 0, 1, -1, 0, 0, 0 :), (: 0, 1, 1, 0, 0, 0 :),
      %    (: 0, -1, -1, 1, 0, 0 :), (: -1, -1, 0, 0, 1, 0 :),
      %    (: -1, 0, -1, 0, 0, 1 :) :)
      % expected type  list[list[real]]
  TQXL_TCC2: OBLIGATION
    every[list[number]]
        (LAMBDA (x: list[number]):
           every[number]
               (LAMBDA (x: number): number_field_pred(x) AND real_pred(x))(x))
        ((: (: 0, 1, -1, 0, 0, 0 :), (: 0, 1, 1, 0, 0, 0 :),
            (: 0, -1, -1, 1, 0, 0 :), (: -1, -1, 0, 0, 1, 0 :),
            (: -1, 0, -1, 0, 0, 1 :) :));

  % Subtype TCC generated (at line 108, column 18) for
      % (: (: 1, 1, 1, 0, 0, 0 :), (: 0, 1, -1, 0, 0, 0 :),
      %    (: 0, 1, 1, 0, 0, 0 :), (: 0, -1, -1, 1, 0, 0 :),
      %    (: -1, -1, 0, 0, 1, 0 :), (: -1, 0, -1, 0, 0, 1 :) :)
      % expected type  Square
  TQXL_TCC3: OBLIGATION
    (null?[list[real]]
         ((: (: 1, 1, 1, 0, 0, 0 :), (: 0, 1, -1, 0, 0, 0 :),
             (: 0, 1, 1, 0, 0, 0 :), (: 0, -1, -1, 1, 0, 0 :),
             (: -1, -1, 0, 0, 1, 0 :), (: -1, 0, -1, 0, 0, 1 :) :))
      OR
      (FORALL (i,
               j:
                 below(length[list[real]]
                           ((: (: 1, 1, 1, 0, 0, 0 :),
                               (: 0, 1, -1, 0, 0, 0 :),
                               (: 0, 1, 1, 0, 0, 0 :),
                               (: 0, -1, -1, 1, 0, 0 :),
                               (: -1, -1, 0, 0, 1, 0 :),
                               (: -1, 0, -1, 0, 0, 1 :) :)))):
         length[real]
             (nth[list[real]]
                  ((: (: 1, 1, 1, 0, 0, 0 :), (: 0, 1, -1, 0, 0, 0 :),
                      (: 0, 1, 1, 0, 0, 0 :), (: 0, -1, -1, 1, 0, 0 :),
                      (: -1, -1, 0, 0, 1, 0 :), (: -1, 0, -1, 0, 0, 1 :) :),
                   i))
          =
          length[real]
              (nth[list[real]]
                   ((: (: 1, 1, 1, 0, 0, 0 :), (: 0, 1, -1, 0, 0, 0 :),
                       (: 0, 1, 1, 0, 0, 0 :), (: 0, -1, -1, 1, 0, 0 :),
                       (: -1, -1, 0, 0, 1, 0 :), (: -1, 0, -1, 0, 0, 1 :) :),
                    j))))
     AND
     (rows((: (: 1, 1, 1, 0, 0, 0 :), (: 0, 1, -1, 0, 0, 0 :),
              (: 0, 1, 1, 0, 0, 0 :), (: 0, -1, -1, 1, 0, 0 :),
              (: -1, -1, 0, 0, 1, 0 :), (: -1, 0, -1, 0, 0, 1 :) :))
       > 0
       AND
       columns((: (: 1, 1, 1, 0, 0, 0 :), (: 0, 1, -1, 0, 0, 0 :),
                  (: 0, 1, 1, 0, 0, 0 :), (: 0, -1, -1, 1, 0, 0 :),
                  (: -1, -1, 0, 0, 1, 0 :), (: -1, 0, -1, 0, 0, 1 :) :))
        > 0)
      AND
      rows((: (: 1, 1, 1, 0, 0, 0 :), (: 0, 1, -1, 0, 0, 0 :),
              (: 0, 1, 1, 0, 0, 0 :), (: 0, -1, -1, 1, 0, 0 :),
              (: -1, -1, 0, 0, 1, 0 :), (: -1, 0, -1, 0, 0, 1 :) :))
       =
       columns((: (: 1, 1, 1, 0, 0, 0 :), (: 0, 1, -1, 0, 0, 0 :),
                  (: 0, 1, 1, 0, 0, 0 :), (: 0, -1, -1, 1, 0, 0 :),
                  (: -1, -1, 0, 0, 1, 0 :), (: -1, 0, -1, 0, 0, 1 :) :));

  % Subtype TCC generated (at line 115, column 21) for
      % (: 1, 0, -1, 0, 0, 0 :)
      % expected type  list[real]
  TQXLinv_TCC1: OBLIGATION
    every[number]
        (LAMBDA (x: number): number_field_pred(x) AND real_pred(x))
        ((: 1, 0, -1, 0, 0, 0 :));

  % Subtype TCC generated (at line 116, column 20) for
      % (: (: 0, 1 / 2, 1 / 2, 0, 0, 0 :), (: 0, -1 / 2, 1 / 2, 0, 0, 0 :),
      %    (: 0, 0, 1, 1, 0, 0 :), (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
      %    (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :)
      % expected type  list[list[real]]
  TQXLinv_TCC2: OBLIGATION
    every[list[number]]
        (LAMBDA (x: list[number]):
           every[number]
               (LAMBDA (x: number): number_field_pred(x) AND real_pred(x))(x))
        ((: (: 0, 1 / 2, 1 / 2, 0, 0, 0 :), (: 0, -1 / 2, 1 / 2, 0, 0, 0 :),
            (: 0, 0, 1, 1, 0, 0 :), (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
            (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :));

  % Subtype TCC generated (at line 115, column 18) for
      % (: (: 1, 0, -1, 0, 0, 0 :), (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
      %    (: 0, -1 / 2, 1 / 2, 0, 0, 0 :), (: 0, 0, 1, 1, 0, 0 :),
      %    (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
      %    (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :)
      % expected type  Square
  TQXLinv_TCC3: OBLIGATION
    (null?[list[real]]
         ((: (: 1, 0, -1, 0, 0, 0 :), (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
             (: 0, -1 / 2, 1 / 2, 0, 0, 0 :), (: 0, 0, 1, 1, 0, 0 :),
             (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
             (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :))
      OR
      (FORALL (i,
               j:
                 below(length[list[real]]
                           ((: (: 1, 0, -1, 0, 0, 0 :),
                               (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
                               (: 0, -1 / 2, 1 / 2, 0, 0, 0 :),
                               (: 0, 0, 1, 1, 0, 0 :),
                               (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
                               (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :)))):
         length[real]
             (nth[list[real]]
                  ((: (: 1, 0, -1, 0, 0, 0 :),
                      (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
                      (: 0, -1 / 2, 1 / 2, 0, 0, 0 :),
                      (: 0, 0, 1, 1, 0, 0 :),
                      (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
                      (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :),
                   i))
          =
          length[real]
              (nth[list[real]]
                   ((: (: 1, 0, -1, 0, 0, 0 :),
                       (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
                       (: 0, -1 / 2, 1 / 2, 0, 0, 0 :),
                       (: 0, 0, 1, 1, 0, 0 :),
                       (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
                       (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :),
                    j))))
     AND
     (rows((: (: 1, 0, -1, 0, 0, 0 :), (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
              (: 0, -1 / 2, 1 / 2, 0, 0, 0 :), (: 0, 0, 1, 1, 0, 0 :),
              (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
              (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :))
       > 0
       AND
       columns((: (: 1, 0, -1, 0, 0, 0 :), (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
                  (: 0, -1 / 2, 1 / 2, 0, 0, 0 :), (: 0, 0, 1, 1, 0, 0 :),
                  (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
                  (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :))
        > 0)
      AND
      rows((: (: 1, 0, -1, 0, 0, 0 :), (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
              (: 0, -1 / 2, 1 / 2, 0, 0, 0 :), (: 0, 0, 1, 1, 0, 0 :),
              (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
              (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :))
       =
       columns((: (: 1, 0, -1, 0, 0, 0 :), (: 0, 1 / 2, 1 / 2, 0, 0, 0 :),
                  (: 0, -1 / 2, 1 / 2, 0, 0, 0 :), (: 0, 0, 1, 1, 0, 0 :),
                  (: 1, 1 / 2, -1 / 2, 0, 1, 0 :),
                  (: 1, -1 / 2, -1 / 2, 0, 0, 1 :) :));

  % Subtype TCC generated (at line 124, column 26) for  TQXL
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  is_invTQXL_TCC1: OBLIGATION det(TQXL) /= 0 OR invertible?(TQXL);

  % Subtype TCC generated (at line 124, column 54) for  TQXLinv
      % expected type  SQ: {SQ | det(SQ) /= 0 OR invertible?(SQ)}
  is_invTQXL_TCC2: OBLIGATION
    inverse(TQXL) = TQXLinv IMPLIES det(TQXLinv) /= 0 OR invertible?(TQXLinv);

  % Subtype TCC generated (at line 126, column 61) for  (: row(M)(k) :)
      % expected type  PosFullMatrix
  RowToMat_TCC1: OBLIGATION
    FORALL (M: PosFullMatrix, k: below(rows(M))):
      (null?[list[real]]((: row(M)(k) :)) OR
        (FORALL (i, j: below(length[list[real]]((: row(M)(k) :)))):
           length[real](nth[list[real]]((: row(M)(k) :), i)) =
            length[real](nth[list[real]]((: row(M)(k) :), j))))
       AND rows((: row(M)(k) :)) > 0 AND columns((: row(M)(k) :)) > 0;

  % Subtype TCC generated (at line 141, column 37) for  k
      % expected type  below(rows(tensor_prod(M, N)))
  RowToMat_tensor_prod_TCC1: OBLIGATION
    FORALL (M, N: PosFullMatrix, k: below(rows(M) * rows(N))):
      k < rows(tensor_prod(M, N));

  % Subtype TCC generated (at line 142, column 35) for  rows(N)
      % expected type  nonzero_integer
  RowToMat_tensor_prod_TCC2: OBLIGATION
    FORALL (M, N: PosFullMatrix, k: below(rows(M) * rows(N))): rows(N) /= 0;

  % Subtype TCC generated (at line 142, column 26) for
      % (k - mod(k, rows(N))) / rows(N)
      % expected type  below(rows(M))
  RowToMat_tensor_prod_TCC3: OBLIGATION
    FORALL (M, N: PosFullMatrix, k: below(rows(M) * rows(N))):
      integer_pred((k - mod(k, rows(N))) / rows(N)) AND
       (k - mod(k, rows(N))) / rows(N) >= 0 AND
        (k - mod(k, rows(N))) / rows(N) < rows(M);

  % Subtype TCC generated (at line 142, column 67) for  mod(k, rows(N))
      % expected type  below(rows(N))
  RowToMat_tensor_prod_TCC4: OBLIGATION
    FORALL (M, N: PosFullMatrix, k: below(rows(M) * rows(N))):
      mod(k, rows(N)) >= 0 AND mod(k, rows(N)) < rows(N);

  % Subtype TCC generated (at line 145, column 35) for  L
      % expected type  (cons?[below(rows(M))])
  RowTensor_TCC1: OBLIGATION
    FORALL (M: PosFullMatrix, n: posnat,
            L: {LL: list[below(rows(M))] | length[below(rows(M))](LL) = n}):
      n = 1 IMPLIES cons?[below(rows(M))](L);

  % Subtype TCC generated (at line 146, column 47) for  L
      % expected type  (cons?[below(rows(M))])
  RowTensor_TCC2: OBLIGATION
    FORALL (M: PosFullMatrix, n: posnat,
            L: {LL: list[below(rows(M))] | length[below(rows(M))](LL) = n}):
      NOT n = 1 IMPLIES cons?[below(rows(M))](L);

  % Subtype TCC generated (at line 146, column 43) for  cdr(L)
      % expected type  {LL: list[below(rows(M))] | length(LL) = n - 1}
  RowTensor_TCC3: OBLIGATION
    FORALL (M: PosFullMatrix, n: posnat,
            L: {LL: list[below(rows(M))] | length[below(rows(M))](LL) = n}):
      NOT n = 1 IMPLIES
       length[below(rows(M))](cdr[below(rows(M))](L)) = n - 1;

  % Subtype TCC generated (at line 156, column 29) for  rows(M)
      % expected type  {x: nat | x > 1}
  RowTensors_same_TCC1: OBLIGATION
    FORALL (M: {AA: PosFullMatrix | rows(AA) > 1}, n: posnat,
            k: below(rows(M) ^ n)):
      rows(M) > 1;

  % Subtype TCC generated (at line 156, column 66) for  base_n(rows(M), k)
      % expected type  [nat -> below(rows(M))]
  RowTensors_same_TCC2: OBLIGATION
    FORALL (M: {AA: PosFullMatrix | rows(AA) > 1}, n: posnat,
            k: below(rows(M) ^ n)):
      FORALL (x1: nat): base_n(rows(M), k)(x1) < rows(M);

  % Subtype TCC generated (at line 160, column 39) for  k
      % expected type  below(rows(tensor_power_alt(M, n)))
  RowTensor_is_TensorRow_TCC1: OBLIGATION
    FORALL (M: PosFullMatrix, n: posnat, k: below(rows(M) ^ n)):
      rows(M) > 1 IMPLIES k < rows(tensor_power_alt(M, n));

  % Subtype TCC generated (at line 163, column 32) for  k
      % expected type  below(rows(tensor_power(M, n)))
  RowTensor_is_TensorRow2_TCC1: OBLIGATION
    FORALL (M: {AA: PosFullMatrix | rows(AA) > 1}, n: posnat,
            k: below(rows(M) ^ n)):
      k < rows(tensor_power(M, n));

  % Subtype TCC generated (at line 170, column 22) for  rows(A)
      % expected type  {x: nat | x > 1}
  tensor_entry_TCC1: OBLIGATION
    FORALL (A: {M: PosFullMatrix | rows(M) > 1 AND columns(M) > 1},
            n: posnat, k: below(rows(A) ^ n), m: below(columns(A) ^ n)):
      rows(A) > 1;

  % Subtype TCC generated (at line 171, column 22) for  columns(A)
      % expected type  {x: nat | x > 1}
  tensor_entry_TCC2: OBLIGATION
    FORALL (A: {M: PosFullMatrix | rows(M) > 1 AND columns(M) > 1},
            n: posnat, k: below(rows(A) ^ n), m: below(columns(A) ^ n),
            R: [nat -> nat]):
      R = base_n(rows(A), k) IMPLIES columns(A) > 1;

  % Subtype TCC generated (at line 172, column 63) for  n - 1
      % expected type  T_high[nat]
  tensor_entry_TCC3: OBLIGATION
    FORALL (A: {M: PosFullMatrix | rows(M) > 1 AND columns(M) > 1},
            n: posnat, k: below(rows(A) ^ n), m: below(columns(A) ^ n),
            R: [nat -> nat]):
      R = base_n(rows(A), k) IMPLIES
       (FORALL (C: [nat -> nat]):
          C = base_n(columns(A), m) IMPLIES
           n - 1 >= 0 OR (EXISTS (j: nat): n - 1 <= j));

  % Subtype TCC generated (at line 172, column 82) for  rows(A)
      % expected type  posnat
  tensor_entry_TCC4: OBLIGATION
    FORALL (A: {M: PosFullMatrix | rows(M) > 1 AND columns(M) > 1},
            n: posnat, k: below(rows(A) ^ n), m: below(columns(A) ^ n),
            R: [nat -> nat]):
      R = base_n(rows(A), k) IMPLIES
       (FORALL (C: [nat -> nat]):
          C = base_n(columns(A), m) IMPLIES rows(A) > 0);

  % Subtype TCC generated (at line 172, column 91) for  columns(A)
      % expected type  posnat
  tensor_entry_TCC5: OBLIGATION
    FORALL (A: {M: PosFullMatrix | rows(M) > 1 AND columns(M) > 1},
            n: posnat, k: below(rows(A) ^ n), m: below(columns(A) ^ n),
            R: [nat -> nat]):
      R = base_n(rows(A), k) IMPLIES
       (FORALL (C: [nat -> nat]):
          C = base_n(columns(A), m) IMPLIES columns(A) > 0);

  % Assuming TCC generated (at line 24, column 4) for  reals@product[nat]
      % generated from assumption product.connected_domain
  tensor_entry_TCC6: OBLIGATION
    FORALL (A: {M: PosFullMatrix | rows(M) > 1 AND columns(M) > 1},
            n: posnat, k: below(rows(A) ^ n), m: below(columns(A) ^ n),
            R: [nat -> nat]):
      R = base_n(rows(A), k) IMPLIES
       (FORALL (C: [nat -> nat]):
          C = base_n(columns(A), m) IMPLIES
           (FORALL (x, y: nat), (z: integer):
              x <= z AND z <= y IMPLIES z >= 0));


body:
  query_coeff  % [ parameters ]
  		: THEORY

    BEGIN

    % STURM : LIBRARY = "../Sturm"


  IMPORTING tensor_product %, STURM@tarski_query

  f: VAR  [nat->below(3)]
  i,j,k: VAR  nat


  % First, we define a function that gets the base 3 representation of k+1 from the base 3 representation
  % of k.    

  bump_one_ind(j:posnat, (f| FORALL( k:above(j)): f(k)=0), (i:upto(j+1))): 
           RECURSIVE {ff:[nat->below(3)]| FORALL(k:above(j+1)): ff(k) = 0} = 
  	    IF f(i)<2 THEN
  	       f WITH [i:=f(i)+1]
  	    ELSE 
  	       bump_one_ind (j, f,i+1) WITH [i:=0]
  	    ENDIF
  	    MEASURE (j+1-i)


      % list version...

  switch_one_entry(L:{ll:list[below(3)]|cons?[below(3)](ll)}, n: below(length(L)), new:below(3)): RECURSIVE
    {ll:list[below(3)]| length(ll) = length(L) AND FORALL (i:below(length(L))): i/=n IMPLIES nth(ll, i) = nth(L, i)} = 
     IF n=0 THEN cons(new, cdr(L)) 
     ELSE cons(car(L), switch_one_entry(cdr(L), n-1, new))
     ENDIF
     MEASURE n

  switch_is_with: LEMMA FORALL (L:{ll:list[below(3)]|cons?[below(3)](ll)}, n: below(length(L)), new:below(3), (f|array2list[below(3)](length(L))(f) = L)):
           switch_one_entry(L, n, new) = array2list[below(3)](length(L))(f WITH [n:=new])

  bump_one_ind_list(j:posnat, L:listn[below(3)](j+1), i:upto(j+1)): RECURSIVE listn[below(3)](j+1) = 
  	    IF i=j+1 THEN L 
  	    ELSE LET ent = nth(L,i) IN
  	    	 IF ent<2 THEN
  		    switch_one_entry(L, i, ent+1)
  		 ELSE switch_one_entry(bump_one_ind_list(j, L, i+1), i, 0)
  		 ENDIF
  	    ENDIF
  	    MEASURE j+1-i



     

  % Wonder if it's worth the trouble....  

  % speed_test1(i:nat, n:posnat, l:listn[below(3)](n+1) ): RECURSIVE list[below(3)] = 
  % IF i=0 THEN l
  % ELSE LET L = bump_one_ind_list(n, l, 0) IN
  %   speed_test1(i-1, n, L)
  % ENDIF
  % MEASURE i 

  % speed_test1(3^17-2, 16, (: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 :))

  % speed_test2(i:nat, n:posnat, f): RECURSIVE [nat->below(3)] = 
  % IF i=0 THEN f
  % ELSE LET F = bump_one_ind(n, f, 0) IN
  %    speed_test2(i-1, n, F)
  % ENDIF
  % MEASURE i

  % array2list[below(3)](17)(speed_test2(3^17-2, 16, LAMBDA(j:nat): 0))

  	       
  	  

  bump_one_below: LEMMA FORALL (j:posnat, (f| FORALL( k:above(j)): f(k)=0),(i:upto(j+1)), (k:nat)):
  	  k<i IMPLIES bump_one_ind (j,f,i)(k) = f(k)  

  bump_one_ind_lem: LEMMA  FORALL(j:posnat, (f| FORALL( k:above(j)): f(k)=0), (i:upto(j+1))):
   		  base_n_to_nat(3, bump_one_ind(j,f,i), j+1) = 
  		  IF f(i)<2 THEN base_n_to_nat(3, f, j+1) + 3^i
   		  ELSE base_n_to_nat(3, bump_one_ind(j, f, i+1), j+1) - f(i)*3^i
  		  ENDIF

  bump_one_ind_lem2: LEMMA  FORALL(j:posnat, (f| FORALL( k:above(j)): f(k)=0), (i:upto(j+1))):
   		  (FORALL(m:nat): m<=i IMPLIES f(m) =2) IMPLIES  
  		  base_n_to_nat(3, bump_one_ind(j,f,0), j+1) = 
  		   base_n_to_nat(3, bump_one_ind(j, f, i+1), j+1) - sigma(0,i, LAMBDA (s:nat): 2*3^s)

  low2(j:posnat, (f| FORALL( k:above(j)): f(k)=0), i:{ii:upto(j+1)|f(ii)<2} ): RECURSIVE {ii:upto(j+1)|f(ii)<2}= 
                 IF (EXISTS(m:nat): m<i AND f(m)<2) THEN low2(j, f, choose({m:nat| m<i AND f(m)<2}))  
  	       ELSE i 
  	       ENDIF
  	       MEASURE i

  low2_lem: LEMMA FORALL (j:posnat, (f| FORALL( k:above(j)): f(k)=0), i:{ii:upto(j+1)|f(ii)<2}):
  	  LET M =  low2(j, f, i) IN 
  	  f(M)<2 AND (FORALL (m:nat): m<M IMPLIES f(m)=2)



  bump_one_prep: LEMMA FORALL(j:posnat, (f| FORALL( k:above(j)): f(k)=0)):
  	       base_n_to_nat(3, bump_one_ind(j, f, 0), j+1) = 
  	       base_n_to_nat(3, f, j+1) +1

  bump_one_prep2: LEMMA FORALL (k:nat, (f| f=base_n(3,k))): 
  		bump_one_ind(upper_index(3,k)+1, f, 0) = base_n(3, k+1)

  % This function gets the base 3 representation of k+1 without switching back to a natural number. 

  bump_one(k:nat, (f| f=base_n(3,k))): {ff:[nat->below(3)]| ff = base_n(3,k+1)} = 
  		   bump_one_ind(upper_index(3,k)+1, f, 0)



  % A lemma to relate the function version to the list version

  switch_to_array: LEMMA FORALL (j:posnat, L:listn[below(3)](j+1), (f| FORALL( k:above(j)): f(k)=0), i:upto(j+1)):
         array2list[below(3)](j+1)(f) = L IMPLIES 
         bump_one_ind_list(j, L, i) = array2list[below(3)](j+1)(bump_one_ind(j,f,i))

  bump_one_list(j:posnat, k:below(3^(j+1)), L:{ll:listn[below(3)](j+1)| ll=base_list(3,k,j+1)}):
      {ll:listn[below(3)](j+1)| ll= base_list(3, k+1, j+1)}  
  		     = bump_one_ind_list(j, L, 0) 


                      


  % Here's a function that takes a list, two functions on the list, and returns the product if the first is non-zero. 
  % In this way, we avoid computing G when the product is zero anyway. 

  is_nonzero(j:posnat, l:{ll:list[below(3)]| length(ll)=j}, F, G: [{ll:list[below(3)]| length(ll)=j}->real]): {x:real| x = F(l)*G(l)} = 
  		     IF F(l) = 0 THEN 0
  		     ELSE F(l)*G(l)
  		     ENDIF

  % This is bad right now...

  dot_tail_sum2plus(n:{x:nat|x>1}, F, G: [{ll:list[below(3)]| length(ll)=n}->real], a:real, i:upto(3^n), L:{ll:list[below(3)]| ll = base_list(3, i, n)}): RECURSIVE real = 
  		IF i=3^n THEN a
  		ELSE LET A = a+ is_nonzero(n, L, F, G) IN 
  		    dot_tail_sum2plus(n, F, G, A, i+1, bump_one_list(n-1, i, L))
  		ENDIF
  		MEASURE 3^n-i

  dot_tail_sum_lem: LEMMA FORALL (n:{x:nat|x>1}, F, G: [{ll:list[below(3)]| length(ll)=n}->real], a:real, i:upto(3^n), L:{ll:list[below(3)]| ll = base_list(3, i, n)}):
  		  dot_tail_sum2plus(n, F, G, a, i, L) = a+sigma( i, 3^n-1, LAMBDA(j:nat): F(base_list(3, j, n))*G(base_list(3, j, n)))
   

  is_nz(j:posnat, f, (F,G: [[nat->below(3)]->real])): 	{x:real| x = F(f)*G(f)} = 
  		     IF F(f) = 0 THEN 0
  		     ELSE F(f)*G(f)
  		     ENDIF	

  dot_tail_sum2(n:posnat,  F,G: [[nat->below(3)]->real], a:real, i:upto(3^n), (f|f=base_n(3,i)) ): RECURSIVE real = 
  		IF i=3^n THEN a
  		ELSE LET A = a+ is_nz(n, f, F, G) IN 
  		    dot_tail_sum2(n, F, G, A, i+1, bump_one(i, f))
  		ENDIF
  		MEASURE 3^n-i

  dot_tail_sum_lem2: LEMMA FORALL (n:posnat, F, G: [[nat->below(3)]->real], a:real, i:upto(3^n)):
  		  dot_tail_sum2(n, F, G, a, i, base_n(3,i)) = a+sigma( i, 3^n-1, LAMBDA(j:nat): F(base_n(3, j) )*G(base_n(3, j)))



    End query_coeff

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 25, column 14) for  (j + 1 - i)
      % expected type  naturalnumber
  bump_one_ind_TCC1: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      (j + 1 - i) >= 0;

  % Subtype TCC generated (at line 21, column 19) for  f(i) + 1
      % expected type  below(3)
  bump_one_ind_TCC2: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      f(i) < 2 IMPLIES f(i) + 1 < 3;

  % Subtype TCC generated (at line 21, column 8) for  f WITH [i := f(i) + 1]
      % expected type  {ff: [nat -> below(3)] |
                     %          FORALL (k: above(j + 1)): ff(k) = 0}
  bump_one_ind_TCC3: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      f(i) < 2 IMPLIES
       (FORALL (k: above(j + 1)): (f WITH [i := f(i) + 1])(k) = 0);

  % Subtype TCC generated (at line 23, column 27) for  i + 1
      % expected type  upto(1 + j)
  bump_one_ind_TCC4: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      NOT f(i) < 2 IMPLIES i + 1 <= 1 + j;

  % Termination TCC generated (at line 23, column 8) for
      % bump_one_ind(j, f, i + 1)
  bump_one_ind_TCC5: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      NOT f(i) < 2 IMPLIES (j + 1 - (i + 1)) < (j + 1 - i);

  % Subtype TCC generated (at line 23, column 8) for
      % bump_one_ind(j, f, i + 1) WITH [i := 0]
      % expected type  {ff: [nat -> below(3)] |
                     %          FORALL (k: above(j + 1)): ff(k) = 0}
  bump_one_ind_TCC6: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      NOT f(i) < 2 IMPLIES
       (FORALL (k: above(j + 1)),
               (v:
                  [d1:
                     {z:
                        [j: posnat, {f | FORALL (k: above(j)): f(k) = 0},
                         upto(1 + j)] |
                              (z`1 + 1 - z`3) < (j + 1 - i)} ->
                     {ff: [nat -> below(3)] |
                              FORALL (k: above(1 + d1`1)): ff(k) = 0}]):
          (v(j, f, i + 1) WITH [i := 0])(k) = 0);

  % Subtype TCC generated (at line 31, column 99) for  i
      % expected type  below[length[below(3)](ll)]
  switch_one_entry_TCC1: OBLIGATION
    FORALL (L: {ll: list[below(3)] | cons?[below(3)](ll)},
            n: below(length(L)), ll: list[below(3)]):
      length(ll) = length(L) IMPLIES
       (FORALL (i: below(length[below(3)](L))):
          i /= n IMPLIES i < length[below(3)](ll));

  % Subtype TCC generated (at line 32, column 15) for  cons(new, cdr(L))
      % expected type  {ll: list[below(3)] |
                     %          length(ll) = length(L) AND
                     %           (FORALL (i: below(length(L))):
                     %              i /= n IMPLIES nth(ll, i) = nth(L, i))}
  switch_one_entry_TCC2: OBLIGATION
    FORALL (L: {ll: list[below(3)] | cons?[below(3)](ll)},
            n: below(length[below(3)](L)), new: below(3)):
      n = 0 IMPLIES
       length[below(3)](cons[below(3)](new, cdr[below(3)](L))) =
        length[below(3)](L)
        AND
        (FORALL (i: below(length[below(3)](L))):
           i /= n IMPLIES
            nth[below(3)](cons[below(3)](new, cdr[below(3)](L)), i) =
             nth[below(3)](L, i));

  % Subtype TCC generated (at line 33, column 38) for  cdr(L)
      % expected type  {ll: list[below(3)] | cons?[below(3)](ll)}
  switch_one_entry_TCC3: OBLIGATION
    FORALL (L: {ll: list[below(3)] | cons?[below(3)](ll)},
            n: below(length[below(3)](L)), new: below(3)):
      NOT n = 0 IMPLIES cons?[below(3)](cdr[below(3)](L));

  % Subtype TCC generated (at line 33, column 46) for  n - 1
      % expected type  below(length(cdr(L)))
  switch_one_entry_TCC4: OBLIGATION
    FORALL (L: {ll: list[below(3)] | cons?[below(3)](ll)},
            n: below(length[below(3)](L)), new: below(3)):
      NOT n = 0 IMPLIES
       n - 1 >= 0 AND n - 1 < length[below(3)](cdr[below(3)](L));

  % Termination TCC generated (at line 33, column 21) for
      % switch_one_entry(cdr(L), n - 1, new)
  switch_one_entry_TCC5: OBLIGATION
    FORALL (L: {ll: list[below(3)] | cons?[below(3)](ll)},
            n: below(length[below(3)](L)), new: below(3)):
      NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 33, column 8) for
      % cons(car(L), switch_one_entry(cdr(L), n - 1, new))
      % expected type  {ll: list[below(3)] |
                     %          length(ll) = length(L) AND
                     %           (FORALL (i: below(length(L))):
                     %              i /= n IMPLIES nth(ll, i) = nth(L, i))}
  switch_one_entry_TCC6: OBLIGATION
    FORALL (L: {ll: list[below(3)] | cons?[below(3)](ll)},
            n: below(length[below(3)](L)),
            v:
              [d1:
                 {z:
                    [L: {ll: list[below(3)] | cons?[below(3)](ll)},
                     below(length(L)), below(3)] |
                          z`2 < n} ->
                 {ll: list[below(3)] |
                          length(ll) = length(d1`1) AND
                           (FORALL (i: below(length(d1`1))):
                              i /= d1`2 IMPLIES nth(ll, i) = nth(d1`1, i))}],
            new: below(3)):
      NOT n = 0 IMPLIES
       length[below(3)]
           (cons[below(3)]
                (car[below(3)](L), v(cdr[below(3)](L), n - 1, new)))
        = length[below(3)](L)
        AND
        (FORALL (i: below(length[below(3)](L))):
           i /= n IMPLIES
            nth[below(3)]
                (cons[below(3)]
                     (car[below(3)](L), v(cdr[below(3)](L), n - 1, new)),
                 i)
             = nth[below(3)](L, i));

  % Existence TCC generated (at line 37, column 111) for  array2list[below(3)]
  switch_is_with_TCC1: OBLIGATION
    FORALL (L: {ll: list[below(3)] | cons?[below(3)](ll)},
            n: below(length[below(3)](L)), new: below(3),
            f: [nat -> below(3)]):
      EXISTS (x: below(3)): TRUE;

  % Subtype TCC generated (at line 48, column 13) for  j + 1 - i
      % expected type  naturalnumber
  bump_one_ind_list_TCC1: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1)):
      j + 1 - i >= 0;

  % Subtype TCC generated (at line 44, column 23) for  L
      % expected type  {ll: list[below(3)] | cons?[below(3)](ll)}
  bump_one_ind_list_TCC2: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1)):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          ent < 2 AND ent = nth(L, i) IMPLIES cons?[below(3)](L));

  % Subtype TCC generated (at line 44, column 26) for  i
      % expected type  below(length(L))
  bump_one_ind_list_TCC3: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1)):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          ent < 2 AND ent = nth(L, i) IMPLIES i < length[below(3)](L));

  % Subtype TCC generated (at line 44, column 29) for  ent + 1
      % expected type  below(3)
  bump_one_ind_list_TCC4: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1)):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          ent < 2 AND ent = nth(L, i) IMPLIES ent + 1 < 3);

  % Subtype TCC generated (at line 44, column 6) for
      % switch_one_entry(L, i, ent + 1)
      % expected type  listn[below(3)](1 + j)
  bump_one_ind_list_TCC5: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1)):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          ent < 2 AND ent = nth(L, i) IMPLIES
           length[below(3)](switch_one_entry(L, i, ent + 1)) = 1 + j);

  % Subtype TCC generated (at line 45, column 49) for  i + 1
      % expected type  upto(1 + j)
  bump_one_ind_list_TCC6: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1)):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          NOT ent < 2 AND ent = nth(L, i) IMPLIES i + 1 <= 1 + j);

  % Termination TCC generated (at line 45, column 25) for
      % bump_one_ind_list(j, L, i + 1)
  bump_one_ind_list_TCC7: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1)):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          NOT ent < 2 AND ent = nth(L, i) IMPLIES
           j + 1 - (i + 1) < j + 1 - i);

  % Subtype TCC generated (at line 45, column 25) for
      % bump_one_ind_list(j, L, i + 1)
      % expected type  {ll: list[below(3)] | cons?[below(3)](ll)}
  bump_one_ind_list_TCC8: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1),
            v:
              [d1:
                 {z: [j: posnat, listn[below(3)](1 + j), upto(1 + j)] |
                          z`1 + 1 - z`3 < j + 1 - i} ->
                 listn[below(3)](1 + d1`1)]):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          NOT ent < 2 AND ent = nth(L, i) IMPLIES
           cons?[below(3)](v(j, L, i + 1)));

  % Subtype TCC generated (at line 45, column 55) for  i
      % expected type  below(length(bump_one_ind_list(j, L, 1 + i)))
  bump_one_ind_list_TCC9: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1),
            v:
              [d1:
                 {z: [j: posnat, listn[below(3)](1 + j), upto(1 + j)] |
                          z`1 + 1 - z`3 < j + 1 - i} ->
                 listn[below(3)](1 + d1`1)]):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          NOT ent < 2 AND ent = nth(L, i) IMPLIES
           i < length[below(3)](v(j, L, 1 + i)));

  % Subtype TCC generated (at line 45, column 8) for
      % switch_one_entry(bump_one_ind_list(j, L, i + 1), i, 0)
      % expected type  listn[below(3)](1 + j)
  bump_one_ind_list_TCC10: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1),
            v:
              [d1:
                 {z: [j: posnat, listn[below(3)](1 + j), upto(1 + j)] |
                          z`1 + 1 - z`3 < j + 1 - i} ->
                 listn[below(3)](1 + d1`1)]):
      NOT i = j + 1 IMPLIES
       (FORALL (ent: below(3)):
          NOT ent < 2 AND ent = nth(L, i) IMPLIES
           length[below(3)](switch_one_entry(v(j, L, i + 1), i, 0)) = 1 + j);

  % Subtype TCC generated (at line 42, column 26) for  i
      % expected type  below[length[below(3)](L)]
  bump_one_ind_list_TCC11: OBLIGATION
    FORALL (j: posnat, L: listn[below(3)](j + 1), i: upto(j + 1)):
      NOT i = j + 1 IMPLIES i < length[below(3)](L);

  % Subtype TCC generated (at line 88, column 38) for  0
      % expected type  upto(1 + j)
  bump_one_ind_lem2_TCC1: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      (FORALL (m: nat): m <= i IMPLIES f(m) = 2) IMPLIES 0 <= 1 + j;

  % Subtype TCC generated (at line 89, column 41) for  i + 1
      % expected type  upto(1 + j)
  bump_one_ind_lem2_TCC2: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      (FORALL (m: nat): m <= i IMPLIES f(m) = 2) IMPLIES i + 1 <= 1 + j;

  % Subtype TCC generated (at line 89, column 62) for  i
      % expected type  T_high[nat]
  bump_one_ind_lem2_TCC3: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            (i: upto(j + 1))):
      (FORALL (m: nat): m <= i IMPLIES f(m) = 2) IMPLIES
       i >= 0 OR (EXISTS (j_1: nat): i <= j_1);

  % Subtype TCC generated (at line 92, column 73) for
      % {m: nat | m < i AND f(m) < 2}
      % expected type  p: (nonempty?[nat])
  low2_TCC1: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            i: {ii: upto(j + 1) | f(ii) < 2}):
      (EXISTS (m: nat): m < i AND f(m) < 2) IMPLIES
       nonempty?[nat]({m: nat | m < i AND f(m) < 2});

  % Subtype TCC generated (at line 92, column 66) for
      % choose({m: nat | m < i AND f(m) < 2})
      % expected type  {ii: upto(1 + j) | f(ii) < 2}
  low2_TCC2: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0),
            i: {ii: upto(j + 1) | f(ii) < 2}):
      (EXISTS (m: nat): m < i AND f(m) < 2) IMPLIES
       choose[nat]({m: nat | m < i AND f(m) < 2}) <= 1 + j AND
        f(choose[nat]({m: nat | m < i AND f(m) < 2})) < 2;

  % Subtype TCC generated (at line 104, column 44) for  0
      % expected type  upto(1 + j)
  bump_one_prep_TCC1: OBLIGATION
    FORALL (j: posnat,
            (f: [nat -> below(3)] | FORALL (k: above(j)): f(k) = 0)):
      0 <= 1 + j;

  % Subtype TCC generated (at line 108, column 35) for  f
      % expected type  {f |
                     %          FORALL (k_1: above(1 + upper_index(3, k))):
                     %            f(k_1) = 0}
  bump_one_prep2_TCC1: OBLIGATION
    FORALL (k: nat, (f: [nat -> below(3)] | f = base_n(3, k))):
      FORALL (k_1: above(1 + upper_index(3, k))): f(k_1) = 0;

  % Subtype TCC generated (at line 108, column 38) for  0
      % expected type  upto(2 + upper_index(3, k))
  bump_one_prep2_TCC2: OBLIGATION
    FORALL (k: nat, (f: [nat -> below(3)] | f = base_n(3, k))):
      0 <= 2 + upper_index(3, k);

  % Subtype TCC generated (at line 113, column 5) for
      % bump_one_ind(upper_index(3, k) + 1, f, 0)
      % expected type  {ff: [nat -> below(3)] | ff = base_n(3, 1 + k)}
  bump_one_TCC1: OBLIGATION
    FORALL (k: nat, (f: [nat -> below(3)] | f = base_n(3, k))):
      bump_one_ind(upper_index(3, k) + 1, f, 0) = base_n(3, 1 + k);

  % Subtype TCC generated (at line 125, column 33) for  0
      % expected type  upto(1 + j)
  bump_one_list_TCC1: OBLIGATION
    FORALL (j: posnat, k: below(3 ^ (j + 1)),
            L: {ll: listn[below(3)](j + 1) | ll = base_list(3, k, j + 1)}):
      0 <= 1 + j;

  % Subtype TCC generated (at line 125, column 9) for
      % bump_one_ind_list(j, L, 0)
      % expected type  {ll: listn[below(3)](j + 1) |
                     %          ll = base_list(3, 1 + k, 1 + j)}
  bump_one_list_TCC2: OBLIGATION
    FORALL (j: posnat, k: below(3 ^ (j + 1)),
            L: {ll: listn[below(3)](j + 1) | ll = base_list(3, k, j + 1)}):
      bump_one_ind_list(j, L, 0) = base_list(3, 1 + k, 1 + j);

  % Subtype TCC generated (at line 135, column 24) for  0
      % expected type  {x: real | x = F(l) * G(l)}
  is_nonzero_TCC1: OBLIGATION
    FORALL (j: posnat, l: {ll: list[below(3)] | length[below(3)](ll) = j},
            F, G: [{ll: list[below(3)] | length[below(3)](ll) = j} -> real]):
      F(l) = 0 IMPLIES 0 = F(l) * G(l);

  % Subtype TCC generated (at line 141, column 146) for  n
      % expected type  posnat
  dot_tail_sum2plus_TCC1: OBLIGATION FORALL (n: {x: nat | x > 1}): n > 0;

  % Subtype TCC generated (at line 146, column 10) for  3 ^ n - i
      % expected type  naturalnumber
  dot_tail_sum2plus_TCC2: OBLIGATION
    FORALL (n: {x: nat | x > 1}, i: upto(3 ^ n),
            L: {ll: list[below(3)] | ll = base_list(3, i, n)}):
      3 ^ n - i >= 0;

  % Subtype TCC generated (at line 144, column 36) for  i + 1
      % expected type  upto(3 ^ n)
  dot_tail_sum2plus_TCC3: OBLIGATION
    FORALL (n: {x: nat | x > 1},
            F, G: [{ll: list[below(3)] | length[below(3)](ll) = n} -> real],
            a: real, i: upto(3 ^ n),
            L: {ll: list[below(3)] | ll = base_list(3, i, n)}):
      NOT i = 3 ^ n IMPLIES
       (FORALL (A: real):
          A = a + is_nonzero(n, L, F, G) IMPLIES i + 1 <= 3 ^ n);

  % Subtype TCC generated (at line 144, column 55) for  n - 1
      % expected type  posnat
  dot_tail_sum2plus_TCC4: OBLIGATION
    FORALL (n: {x: nat | x > 1},
            F, G: [{ll: list[below(3)] | length[below(3)](ll) = n} -> real],
            a: real, i: upto(3 ^ n),
            L: {ll: list[below(3)] | ll = base_list(3, i, n)}):
      NOT i = 3 ^ n IMPLIES
       (FORALL (A: real):
          A = a + is_nonzero(n, L, F, G) IMPLIES n - 1 >= 0 AND n - 1 > 0);

  % Subtype TCC generated (at line 144, column 60) for  i
      % expected type  below(3 ^ n)
  dot_tail_sum2plus_TCC5: OBLIGATION
    FORALL (n: {x: nat | x > 1},
            F, G: [{ll: list[below(3)] | length[below(3)](ll) = n} -> real],
            a: real, i: upto(3 ^ n),
            L: {ll: list[below(3)] | ll = base_list(3, i, n)}):
      NOT i = 3 ^ n IMPLIES
       (FORALL (A: real): A = a + is_nonzero(n, L, F, G) IMPLIES i < 3 ^ n);

  % Subtype TCC generated (at line 144, column 63) for  L
      % expected type  {ll: listn[below(3)](n) | ll = base_list(3, i, n)}
  dot_tail_sum2plus_TCC6: OBLIGATION
    FORALL (n: {x: nat | x > 1},
            F, G: [{ll: list[below(3)] | length[below(3)](ll) = n} -> real],
            a: real, i: upto(3 ^ n),
            L: {ll: list[below(3)] | ll = base_list(3, i, n)}):
      NOT i = 3 ^ n IMPLIES
       (FORALL (A: real):
          A = a + is_nonzero(n, L, F, G) IMPLIES
           length[below(3)](L) = n AND L = base_list(3, i, n));

  % Termination TCC generated (at line 144, column 6) for
      % dot_tail_sum2plus(n, F, G, A, i + 1, bump_one_list(n - 1, i, L))
  dot_tail_sum2plus_TCC7: OBLIGATION
    FORALL (n: {x: nat | x > 1},
            F, G: [{ll: list[below(3)] | length[below(3)](ll) = n} -> real],
            a: real, i: upto(3 ^ n),
            L: {ll: list[below(3)] | ll = base_list(3, i, n)}):
      NOT i = 3 ^ n IMPLIES
       (FORALL (A: real):
          A = a + is_nonzero(n, L, F, G) IMPLIES 3 ^ n - (i + 1) < 3 ^ n - i);

  % Subtype TCC generated (at line 143, column 32) for  L
      % expected type  {ll: list[below(3)] | length(ll) = n}
  dot_tail_sum2plus_TCC8: OBLIGATION
    FORALL (n: {x: nat | x > 1}, i: upto(3 ^ n),
            L: {ll: list[below(3)] | ll = base_list(3, i, n)}):
      NOT i = 3 ^ n IMPLIES length[below(3)](L) = n;

  % Subtype TCC generated (at line 149, column 54) for  3 ^ n - 1
      % expected type  T_high[nat]
  dot_tail_sum_lem_TCC1: OBLIGATION
    FORALL (n: {x: nat | x > 1}, i: upto(3 ^ n),
            L: {ll: list[below(3)] | ll = base_list(3, i, n)}):
      3 ^ n - 1 >= 0 OR (EXISTS (j: nat): 3 ^ n - 1 <= j);

  % Subtype TCC generated (at line 153, column 24) for  0
      % expected type  {x: real | x = F(f) * G(f)}
  is_nz_TCC1: OBLIGATION
    FORALL (f: [nat -> below(3)], (F, G: [[nat -> below(3)] -> real])):
      F(f) = 0 IMPLIES 0 = F(f) * G(f);

  % Subtype TCC generated (at line 162, column 10) for  3 ^ n - i
      % expected type  naturalnumber
  dot_tail_sum2_TCC1: OBLIGATION
    FORALL (n: posnat, i: upto(3 ^ n),
            (f: [nat -> below(3)] | f = base_n(3, i))):
      3 ^ n - i >= 0;

  % Subtype TCC generated (at line 160, column 32) for  i + 1
      % expected type  upto(3 ^ n)
  dot_tail_sum2_TCC2: OBLIGATION
    FORALL (n: posnat, F, G: [[nat -> below(3)] -> real], a: real,
            i: upto(3 ^ n), (f: [nat -> below(3)] | f = base_n(3, i))):
      NOT i = 3 ^ n IMPLIES
       (FORALL (A: real): A = a + is_nz(n, f, F, G) IMPLIES i + 1 <= 3 ^ n);

  % Termination TCC generated (at line 160, column 6) for
      % dot_tail_sum2(n, F, G, A, i + 1, bump_one(i, f))
  dot_tail_sum2_TCC3: OBLIGATION
    FORALL (n: posnat, F, G: [[nat -> below(3)] -> real], a: real,
            i: upto(3 ^ n), (f: [nat -> below(3)] | f = base_n(3, i))):
      NOT i = 3 ^ n IMPLIES
       (FORALL (A: real):
          A = a + is_nz(n, f, F, G) IMPLIES 3 ^ n - (i + 1) < 3 ^ n - i);

  % Subtype TCC generated (at line 165, column 33) for  base_n(3, i)
      % expected type  {f | f = base_n(3, i)}
  dot_tail_sum_lem2_TCC1: OBLIGATION
    FORALL (n: posnat, i: upto(3 ^ n)):
      FORALL (x1: nat): base_n(3, i)(x1) < 3;

  % Subtype TCC generated (at line 165, column 60) for  3 ^ n - 1
      % expected type  T_high[nat]
  dot_tail_sum_lem2_TCC2: OBLIGATION
    FORALL (n: posnat): 3 ^ n - 1 >= 0 OR (EXISTS (j: nat): 3 ^ n - 1 <= j);

  % Subtype TCC generated (at line 165, column 84) for  base_n(3, j)
      % expected type  [nat -> below(3)]
  dot_tail_sum_lem2_TCC3: OBLIGATION
    FORALL (j: nat): FORALL (x1: nat): base_n(3, j)(x1) < 3;


body:
  %------------------------------------------------------------------------------
  % Top file for measure_integration_fnd
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            1/5/07   Initial Version
  %------------------------------------------------------------------------------

  top: THEORY

  BEGIN

    IMPORTING

  % Local Extras
      partitions,              % Partitioning a set into a setofsets
      pointwise_convergence,   % Pointwise functional convergence
      sup_norm,                % sup_norm(f) = sup(abs(f))
      product_sections,        % sections of sets [T1,T2]

  % Borel sets and functions
      subset_algebra_def,      % Definitions of Sigma/Subset Algebras
      subset_algebra,          % Properties of Subset Algebras
      sigma_algebra,           % Properties of Sigma Algebras
      product_sigma_def,       % Product sigma-algebra definition
      product_sigma,           % product sigma-algebras properties
      borel,                   % Borel sets
      hausdorff_borel,         % In Hausdorff Space singletons are Borel
      borel_functions,         % Borel Functions 
      identity_borel,          % ... preserved by identity and ...
      composition_borel,       % ... and composition
      real_borel,              % Borel sets of the reals

  % Measures
      generalized_measure_def, % Measures over setofsets containing emptyset
      measure_def,             % Measures over a _subset_ algebra
      measure_space_def,       % Measurable sets and functions on a sigma-algebra
      measure_space,           % Simple functions and their limits
      outer_measure_def,       % Outer measure definition
      ast_def,                 % Generalized Measure-induced outer measures
      outer_measure,           %  ... as above on subset algebras
      outer_measure_props,     % outer measure properties
      measure_props,           % measure properties
      measure_theory,          % negligible/null definitions; also ae properties
      monotone_classes,        % Monotone Class Lemma
      hahn_kolmogorov,         % Hahn-Kolmogorov extension theorem

  % Finite Measures
      finite_measure,

  % Extras for complete measures
      complete_measure_theory, % Extras for complete measures
      measure_completion_aux,  % The gory details for ...
      measure_completion,      % Completing the measure, by making all
                               %    negligible sets null

  % Integration
      isf,                     % integrable simple functions
      nn_integral,             % integrals of functions [T->nnreal]
      integral,                % integrals of functions [T->real]
      finite_integral,         % integrals over finite measures
      integral_convergence_scaf, % Preliminary for Monotone Convergence theorem
      integral_convergence,    % Monotone and dominated convergence theorems
      complete_integral,       % Simplified form of above for complete measures
      indefinite_integral,     % Indefinite integrals
      measure_equality,        % Integrals on equal measures
      measure_contraction,     % Measures on subsets of T ...
      measure_contraction_props,  % ... and integrability
      sigma_finite_measure_props, % specialization for sigma-finite measures

  % Products
      product_finite_measure,  % Products of finite measures
      product_measure,         % Products of sigma-finite measures

  % Product Integrals
      product_integral_def,    % Product integral defs
      finite_fubini_scaf,      % Fubini-Tonelli Lemmas for finite measures and
                               %   integrable simple functions
      finite_fubini_tonelli,   % Fubini-Tonelli Lemmas for finite measures
      finite_fubini,           % Fubini's Theorem for finite measures
      fubini_tonelli_scaf,     % Preparatory results for ...
      fubini_tonelli,          % Fubini-Tonelli Lemmas for sigma-finite measures
      fubini                   % Fubini's Theorem for sigma-finite measures

  END top


body:
  %-------------------------------------------------------------------------
  % Measure Theory Definition file.
  %
  %     Author: David Lester, Manchester University
  %
  %  EXPORTS: finite_measure?
  %
  %     Version 1.0           10/04/05
  %     Version 1.1           20/08/07	Extended to subset algebra (DRL)
  %-------------------------------------------------------------------------

  generalized_measure_def[T:TYPE,S:setofsets[T]]: THEORY

  BEGIN

    ASSUMING

      S_empty:        ASSUMPTION S(emptyset)

    ENDASSUMING

    IMPORTING series@series,
              sets_aux@indexed_sets_aux[nat,T],
              sets_aux@nat_indexed_sets[T],
              metric_space@convergence_aux,
              extended_nnreal@extended_nnreal

  %  limit: MACRO [(convergence_sequences.convergent?)->real]
  %                                          = convergence_sequences.limit ;

    i,j,n: VAR nat
    f:     VAR [(S)->extended_nnreal]
    g:     VAR [(S)->nnreal]
    A:     VAR [nat->(S)]
    a,b:   VAR (S)
    x:     VAR set[T]

    disjoint_indexed_measurable?(A):bool = disjoint?(A)

    disjoint_indexed_measurable: TYPE+ = 
         (disjoint_indexed_measurable?) CONTAINING (LAMBDA i: emptyset[T])

    disjoint_indexed_measurable_is_disjoint_indexed_set: JUDGEMENT
         disjoint_indexed_measurable SUBTYPE_OF disjoint_indexed_set[nat,T]

    X:   VAR disjoint_indexed_measurable

    measure_empty?(f):bool
      = f(emptyset[T]) = (TRUE,0)

    measure_countably_additive?(f): bool
      = FORALL X: S(IUnion(X)) => x_eq(x_sum(f o X),f(IUnion(X)))

    measure_complete?(f):bool
      = (FORALL x,a: (subset?(x,a) AND f(a) = (TRUE,0)) => S(x))

    measure?(f):bool              = measure_empty?(f) AND
                                    measure_countably_additive?(f)
    complete_measure?(f):bool     = measure?(f) AND measure_complete?(f)

    zero_measure(a):extended_nnreal = (TRUE,0)

    measure_type:         TYPE+ = (measure?)              CONTAINING zero_measure

    trivial_measure:measure_type
     = lambda a: IF empty?(a) THEN (TRUE,0) ELSE (FALSE,0) ENDIF

    complete_measure: TYPE+ = (complete_measure?) CONTAINING trivial_measure

    complete_measure_is_measure:
                  JUDGEMENT complete_measure     SUBTYPE_OF measure_type

    measure_disjoint_union: LEMMA
      measure?(f) AND disjoint?(a,b) AND S(union(a,b)) =>
                                            x_eq(f(union(a,b)),x_add(f(a),f(b)))

    finite_measure?(g):bool
      = g(emptyset[T]) = 0 AND
        FORALL X: S(IUnion(X)) => convergence(series(g o X),g(IUnion(X)))

    complete_finite_measure?(g):bool
      = finite_measure?(g) AND FORALL x,a: subset?(x,a) AND g(a) = 0 => S(x)

    trivial_finite_measure(A:(S)):[nnreal] = 0

    finite_measure:   TYPE+ = (finite_measure?) CONTAINING trivial_finite_measure
    complete_finite_measure: TYPE  = (complete_finite_measure?)

    complete_finite_measure_is_finite_measure:
                     JUDGEMENT complete_finite_measure SUBTYPE_OF finite_measure

    to_measure(m:finite_measure):measure_type = lambda a: (TRUE,m(a))

    F: VAR sequence[measure_type]

    x_sum_measure:   LEMMA measure?(lambda a: (x_sum(lambda i: F(i)(a))))

  END generalized_measure_def

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 41, column 60) for  emptyset[T]
      % expected type  (S)
  disjoint_indexed_measurable_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 41, column 50) for  (LAMBDA i: emptyset[T])
      % expected type  disjoint_indexed_measurable
  disjoint_indexed_measurable_TCC2: OBLIGATION
    disjoint_indexed_measurable?((LAMBDA i: emptyset[T]));

  % Judgement subtype TCC generated (at line 44, column 7) for  x
      % expected type  disjoint_indexed_set[nat, T]
  disjoint_indexed_measurable_is_disjoint_indexed_set: OBLIGATION
    FORALL (x: disjoint_indexed_measurable): disjoint?[nat, T](x);

  % Subtype TCC generated (at line 63, column 67) for  zero_measure
      % expected type  measure_type
  measure_type_TCC1: OBLIGATION measure?(zero_measure);

  % Subtype TCC generated (at line 66, column 5) for
      % LAMBDA a: IF empty?(a) THEN (TRUE, 0) ELSE (FALSE, 0) ENDIF
      % expected type  measure_type
  trivial_measure_TCC1: OBLIGATION
    measure?(LAMBDA a: IF empty?[T](a) THEN (TRUE, 0) ELSE (FALSE, 0) ENDIF);

  % Subtype TCC generated (at line 68, column 59) for  trivial_measure
      % expected type  complete_measure
  complete_measure_TCC1: OBLIGATION complete_measure?(trivial_measure);

  % Judgement subtype TCC generated (at line 71, column 26) for  x
      % expected type  measure_type
  complete_measure_is_measure: OBLIGATION
    FORALL (x: complete_measure): measure?(x);

  % Subtype TCC generated (at line 86, column 57) for  trivial_finite_measure
      % expected type  finite_measure
  finite_measure_TCC1: OBLIGATION finite_measure?(trivial_finite_measure);

  % Judgement subtype TCC generated (at line 90, column 29) for  x
      % expected type  finite_measure
  complete_finite_measure_is_finite_measure: OBLIGATION
    FORALL (x: complete_finite_measure): finite_measure?(x);

  % Subtype TCC generated (at line 92, column 46) for  LAMBDA a: (TRUE, m(a))
      % expected type  measure_type
  to_measure_TCC1: OBLIGATION
    FORALL (m: finite_measure): measure?(LAMBDA a: (TRUE, m(a)));


body:
  %------------------------------------------------------------------------------
  % Subset Algebra Definition File
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  %     Version 1.0            8/7/04   Initial Version
  %------------------------------------------------------------------------------
  subset_algebra_def[T:TYPE]: THEORY

  BEGIN

    IMPORTING sets_aux@countable_props,
              structures@fun_preds_partial[nat,set[T],reals.<=,subset?[T]],
              sets_aux@indexed_sets_aux[nat,T],   % Proof only
              sets_aux@countable_indexed_sets[T], % Proof only
              sets_aux@nat_indexed_sets[T],       % Proof only
              sets_aux@countable_image    % Proof only

    n,i:   VAR nat
    a,b:   VAR set[T]
    S,X,Y: VAR setofsets[T]
    NX:    VAR (nonempty?[set[T]])
    E:     VAR sequence[set[T]]

    subset_algebra_empty?(S):      bool = member(emptyset[T],S)
    subset_algebra_complement?(S): bool = FORALL (x:(S)): member(complement(x),S)
    subset_algebra_union?(S):      bool = FORALL (x,y:(S)): member(union(x,y),S)

    subset_algebra?(S):bool = subset_algebra_empty?(S)      AND
                              subset_algebra_complement?(S) AND
                              subset_algebra_union?(S)

    sigma_algebra_union?(S): bool = FORALL X: is_countable[set[T]](X) AND
                                    (FORALL (x:(X)): member(x,S)) =>
                                    member(Union(X),S)

    sigma_algebra?(S):bool = subset_algebra_empty?(S)      AND
                             subset_algebra_complement?(S) AND
                             sigma_algebra_union?(S)

    sigma_union_implies_subset_union: LEMMA
      sigma_algebra_union?(S) => subset_algebra_union?(S)

    sigma_algebra_implies_subset_algebra: LEMMA
      sigma_algebra?(S) => subset_algebra?(S)

    trivial_subset_algebra:(subset_algebra?)
       = union(singleton(emptyset[T]),singleton(fullset[T]))

    subset_algebra: TYPE+ = (subset_algebra?) CONTAINING trivial_subset_algebra

    sigma_algebra:  TYPE+ = (sigma_algebra?)  CONTAINING trivial_subset_algebra

    A: VAR sigma_algebra
    I: VAR set[sigma_algebra]

    sigma_algebra_is_subset_algebra:
                                JUDGEMENT sigma_algebra SUBTYPE_OF subset_algebra

    powerset_is_sigma_algebra: LEMMA sigma_algebra?(powerset(fullset[T]))

    generated_sigma_algebra(X):sigma_algebra
      = Intersection({Y | sigma_algebra?(Y) AND subset?(X,Y)})

    generated_sigma_algebra_subset1: LEMMA
                        subset?(X,generated_sigma_algebra(X))

    generated_sigma_algebra_subset2: LEMMA
                    subset?(X,Y) AND sigma_algebra?(Y) =>
                        subset?(generated_sigma_algebra(X),Y)

    generated_sigma_algebra_idempotent: LEMMA generated_sigma_algebra(A) = A

    intersection_sigma_algebra: LEMMA FORALL (A,B:sigma_algebra):
                                      sigma_algebra?(intersection(A,B))

    sigma(I):sigma_algebra = generated_sigma_algebra(Union(I))

    sigma_member: LEMMA member(A,I) => subset?(A,sigma(I))

    B: VAR subset_algebra
    J: VAR set[subset_algebra]

    powerset_is_subset_algebra: LEMMA subset_algebra?(powerset(fullset[T]))

    generated_subset_algebra(X):subset_algebra
      = Intersection({Y | subset_algebra?(Y) AND subset?(X,Y)})

    generated_subset_algebra_subset1: LEMMA
                        subset?(X,generated_subset_algebra(X))

    generated_subset_algebra_subset2: LEMMA
                    subset?(X,Y) AND subset_algebra?(Y) =>
                        subset?(generated_subset_algebra(X),Y)

    generated_subset_algebra_idempotent: LEMMA generated_subset_algebra(B) = B

    intersection_subset_algebra: LEMMA FORALL (A,B:subset_algebra):
                                       subset_algebra?(intersection(A,B))

    subset(J):subset_algebra = generated_subset_algebra(Union(J))

    subset_member: LEMMA member(B,J) => subset?(B,subset(J))

    finite_disjoint_union?(X)(a):bool
      = EXISTS E,n: disjoint?(E) AND a = IUnion(E) AND
                    (FORALL i: (i < n  => member(E(i),X)) AND
                               (i >= n => empty?(E(i))))

    finite_disjoint_union_of?(X)(a)(E,n):bool
      = disjoint?(E) AND a = IUnion(E) AND
        (FORALL i: (i < n  => member(E(i),X)) AND (i >= n => empty?(E(i))))

    card(X:setofsets[T],a:(finite_disjoint_union?(X))):nat
      = min({n:nat | EXISTS E: finite_disjoint_union_of?(X)(a)(E,n)})

    finite_disjoint_unions(X):setofsets[T] = fullset[(finite_disjoint_union?(X))]

    disjoint_algebra_construction: LEMMA                             % SKB 4.6.1
      (FORALL (a,b:(NX)): member(intersection(a,b),NX)) AND
      (FORALL (a:(NX)): finite_disjoint_union?(NX)(complement(a))) =>
      generated_subset_algebra(NX) = finite_disjoint_unions(NX)

    monotone?(X):bool
      = FORALL E: (FORALL n: member(E(n),X)) =>                      % SKB 4.6.4
                  ((increasing?(E) => member(IUnion(E),X)) AND
                   (decreasing?(E) => member(IIntersection(E),X)))

    monotone_class: TYPE+ = (monotone?) CONTAINING trivial_subset_algebra

    powerset_is_monotone: LEMMA monotone?(powerset(fullset[T]))

    sigma_algebra_is_monotone_class:
                               JUDGEMENT sigma_algebra SUBTYPE_OF monotone_class

    monotone_algebra_is_sigma: LEMMA subset_algebra?(X) AND monotone?(X) =>
                                     sigma_algebra?(X)

    C: VAR monotone_class
    K: VAR set[monotone_class]

    monotone_class_Intersection: LEMMA monotone?(Intersection(K))

    monotone_class: THEOREM                                           % SKB 4.6.6
      subset?(B,C) => subset?(generated_sigma_algebra(B),C)

  END subset_algebra_def

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 48, column 7) for
      % union(singleton(emptyset[T]), singleton(fullset[T]))
      % expected type  (subset_algebra?)
  trivial_subset_algebra_TCC1: OBLIGATION
    subset_algebra?(union[set[T]]
                        (singleton[set[T]](emptyset[T]),
                         singleton[set[T]](fullset[T])));

  % Subtype TCC generated (at line 52, column 55) for  trivial_subset_algebra
      % expected type  sigma_algebra
  sigma_algebra_TCC1: OBLIGATION sigma_algebra?(trivial_subset_algebra);

  % Judgement subtype TCC generated (at line 58, column 40) for  x
      % expected type  subset_algebra
  sigma_algebra_is_subset_algebra: OBLIGATION
    FORALL (x: sigma_algebra): subset_algebra?(x);

  % Subtype TCC generated (at line 63, column 6) for
      % Intersection({Y | sigma_algebra?(Y) AND subset?(X, Y)})
      % expected type  sigma_algebra
  generated_sigma_algebra_TCC1: OBLIGATION
    FORALL (X: setofsets[T]):
      sigma_algebra?(Intersection[setof[T]]
                         ({Y |
                             sigma_algebra?(Y) AND subset?[setof[T]](X, Y)}));

  % Subtype TCC generated (at line 87, column 6) for
      % Intersection({Y | subset_algebra?(Y) AND subset?(X, Y)})
      % expected type  subset_algebra
  generated_subset_algebra_TCC1: OBLIGATION
    FORALL (X: setofsets[T]):
      subset_algebra?(Intersection[setof[T]]
                          ({Y |
                              subset_algebra?(Y) AND
                               subset?[setof[T]](X, Y)}));

  % Subtype TCC generated (at line 115, column 10) for
      % {n: nat | EXISTS E: finite_disjoint_union_of?(X)(a)(E, n)}
      % expected type  S: (nonempty?[nat])
  card_TCC1: OBLIGATION
    FORALL (X: setofsets[T], a: (finite_disjoint_union?(X))):
      nonempty?[nat]
          ({n: nat | EXISTS E: finite_disjoint_union_of?(X)(a)(E, n)});

  % Subtype TCC generated (at line 129, column 49) for  trivial_subset_algebra
      % expected type  monotone_class
  monotone_class_TCC1: OBLIGATION monotone?(trivial_subset_algebra);

  % Judgement subtype TCC generated (at line 134, column 39) for  x
      % expected type  monotone_class
  sigma_algebra_is_monotone_class: OBLIGATION
    FORALL (x: sigma_algebra): monotone?(x);


body:
  %------------------------------------------------------------------------------
  % Subset Algebra
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  %     Version 1.0            1/5/07   Initial Version
  %------------------------------------------------------------------------------
  subset_algebra[T:TYPE, (IMPORTING subset_algebra_def[T])
                 S:subset_algebra[T]]: THEORY

  BEGIN

    x,y: VAR (S)

    subset_algebra_emptyset:     JUDGEMENT emptyset[T]       HAS_TYPE (S)
    subset_algebra_fullset:      JUDGEMENT fullset[T]        HAS_TYPE (S)
    subset_algebra_complement:   JUDGEMENT complement(x)     HAS_TYPE (S)
    subset_algebra_union:        JUDGEMENT union(x,y)        HAS_TYPE (S)
    subset_algebra_intersection: JUDGEMENT intersection(x,y) HAS_TYPE (S)
    subset_algebra_difference:   JUDGEMENT difference(x,y)   HAS_TYPE (S)

  END subset_algebra

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 15, column 41) for  emptyset[T]
      % expected type  (S)
  subset_algebra_emptyset: OBLIGATION S(emptyset[T]);

  % Judgement subtype TCC generated (at line 16, column 41) for  fullset[T]
      % expected type  (S)
  subset_algebra_fullset: OBLIGATION S(fullset[T]);

  % Judgement subtype TCC generated (at line 17, column 41) for  complement(x)
      % expected type  (S)
  subset_algebra_complement: OBLIGATION FORALL (x): S(complement[T](x));

  % Judgement subtype TCC generated (at line 18, column 41) for  union(x, y)
      % expected type  (S)
  subset_algebra_union: OBLIGATION FORALL (x, y): S(union[T](x, y));

  % Judgement subtype TCC generated (at line 19, column 41) for
      % intersection(x, y)
      % expected type  (S)
  subset_algebra_intersection: OBLIGATION
    FORALL (x, y): S(intersection[T](x, y));

  % Judgement subtype TCC generated (at line 20, column 41) for
      % difference(x, y)
      % expected type  (S)
  subset_algebra_difference: OBLIGATION FORALL (x, y): S(difference[T](x, y));


body:
  %-------------------------------------------------------------------------
  % Measure Theory Definition file.
  %
  %     Author: David Lester, Manchester University
  %
  %  EXPORTS: finite_measure?
  %
  %     Version 1.0           10/04/05
  %     Version 1.1           20/08/07	Extended to subset algebra (DRL)
  %-------------------------------------------------------------------------

  measure_def[T:TYPE,(IMPORTING subset_algebra_def[T])
              S:subset_algebra]: THEORY

  BEGIN

    IMPORTING subset_algebra[T,S],
              generalized_measure_def[T,S]

    convergent: MACRO pred[sequence[real]] = convergence_sequences.convergent?;
    limit:      MACRO [(convergent)->real] = convergence_sequences.limit ;

    i,j,n: VAR nat
    f:     VAR [(S)->extended_nnreal]
    g:     VAR [(S)->nnreal]
    A:     VAR [nat->(S)]
    a,b:   VAR (S)
    x:     VAR set[T]
    X:     VAR disjoint_indexed_measurable

    increasing_indexed_measurable?(A):bool = increasing_indexed?(A)

    increasing_indexed_measurable: TYPE+ = 
         (increasing_indexed_measurable?) CONTAINING (LAMBDA i: fullset[T])

    P:   VAR increasing_indexed_measurable

    measure_sigma_finite?(f):bool
      = EXISTS X: IUnion(X) = fullset[T] AND FORALL i: f(X(i))`1

    sigma_finite_measure?(f):bool = measure?(f) AND measure_sigma_finite?(f)
    complete_sigma_finite?(f):bool = measure?(f) AND measure_complete?(f) AND
                                     measure_sigma_finite?(f)

    sigma_finite_measure: TYPE+ = (sigma_finite_measure?) CONTAINING zero_measure
    complete_sigma_finite:TYPE  = (complete_sigma_finite?)

    discrete_measure:measure_type
     = lambda a: IF is_finite(a) THEN (TRUE,card[T](a)) ELSE (FALSE,0) ENDIF

    sigma_finite_measure_is_measure:
                  JUDGEMENT sigma_finite_measure SUBTYPE_OF measure_type
    complete_sigma_finite_is_complete_measure:
                  JUDGEMENT complete_sigma_finite SUBTYPE_OF complete_measure
    complete_sigma_finite_is_sigma_finite_measure:
                  JUDGEMENT complete_sigma_finite SUBTYPE_OF sigma_finite_measure

    measure_monotone: LEMMA measure?(f) AND subset?(a,b) => x_le(f(a),f(b))
    measure_union:    LEMMA measure?(f) => x_le(f(union(a,b)),x_add(f(a),f(b)))

    measure_def: LEMMA                                 % generalized SKB 2.6 Ex 4
     (measure?(f) <=>
      (measure_empty?(f) AND
       (FORALL (a,b:(S)): disjoint?(a,b)
                              => x_eq(f(union(a,b)),x_add(f(a),f(b)))) AND
       (FORALL X: S(IUnion(X)) => x_le(f(IUnion(X)),x_sum(f o X)))))

    finite_measure_def: LEMMA
      finite_measure?(g) <=>
       (g(emptyset[T]) = 0 AND
        (FORALL (a,b:(S)): disjoint?(a,b) => g(union(a,b)) = g(a)+g(b)) AND
        (FORALL X: S(IUnion(X)) AND convergent(series(g o X)) =>
                   g(IUnion(X)) <= limit(series(g o X))))

    A_of(f:sigma_finite_measure):disjoint_indexed_measurable
      = choose({X | IUnion(X) = fullset[T] AND FORALL i: f(X(i))`1})

    P_of(f:sigma_finite_measure)(n):(S)
      = IUnion(lambda i: IF i <= n THEN A_of(f)(i) ELSE emptyset[T] ENDIF)

    mu: VAR sigma_finite_measure

    A_of_def1: LEMMA IUnion(A_of(mu)) = fullset[T]
    A_of_def2: LEMMA FORALL n: mu(A_of(mu)(n))`1
    P_of_def1: LEMMA IUnion(P_of(mu)) = fullset[T]
    P_of_def2: LEMMA FORALL n: mu(P_of(mu)(n))`1
    P_of_def3: LEMMA FORALL i,j: i <= j => subset?(P_of(mu)(i),P_of(mu)(j))

    sigma_finite_def1: LEMMA
      sigma_finite_measure?(f) <=>
      (measure?(f) AND EXISTS X: IUnion(X) = fullset[T] AND FORALL i: f(X(i))`1)

    sigma_finite_def2: LEMMA
      sigma_finite_measure?(f) <=>
      (measure?(f) AND EXISTS P: IUnion(P) = fullset[T] AND FORALL i: f(P(i))`1)

  END measure_def

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 18, column 12) for
      % generalized_measure_def[T, S]
      % generated from assumption generalized_measure_def.S_empty
  IMP_generalized_measure_def_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 34, column 52) for  (LAMBDA i: fullset[T])
      % expected type  increasing_indexed_measurable
  increasing_indexed_measurable_TCC1: OBLIGATION
    increasing_indexed_measurable?((LAMBDA i: fullset[T]));

  % Subtype TCC generated (at line 45, column 67) for  zero_measure
      % expected type  sigma_finite_measure
  sigma_finite_measure_TCC1: OBLIGATION
    sigma_finite_measure?(zero_measure[T, S]);

  % Subtype TCC generated (at line 49, column 5) for
      % LAMBDA a:
      %   IF is_finite(a) THEN (TRUE, card[T](a)) ELSE (FALSE, 0) ENDIF
      % expected type  measure_type[T, S]
  discrete_measure_TCC1: OBLIGATION
    measure?[T, S]
        (LAMBDA a:
           IF is_finite[T](a) THEN (TRUE, card[T](a)) ELSE (FALSE, 0) ENDIF);

  % Judgement subtype TCC generated (at line 52, column 26) for  x
      % expected type  measure_type[T, S]
  sigma_finite_measure_is_measure: OBLIGATION
    FORALL (x: sigma_finite_measure): measure?[T, S](x);

  % Judgement subtype TCC generated (at line 54, column 26) for  x
      % expected type  complete_measure[T, S]
  complete_sigma_finite_is_complete_measure: OBLIGATION
    FORALL (x: complete_sigma_finite): complete_measure?[T, S](x);

  % Judgement subtype TCC generated (at line 56, column 26) for  x
      % expected type  sigma_finite_measure
  complete_sigma_finite_is_sigma_finite_measure: OBLIGATION
    FORALL (x: complete_sigma_finite): sigma_finite_measure?(x);

  % Subtype TCC generated (at line 76, column 13) for
      % {X | IUnion(X) = fullset[T] AND (FORALL i: f(X(i))`1)}
      % expected type  p: (nonempty?[disjoint_indexed_measurable[T, S]])
  A_of_TCC1: OBLIGATION
    FORALL (f: sigma_finite_measure):
      nonempty?[disjoint_indexed_measurable[T, S]]
          ({X | IUnion[nat, T](X) = fullset[T] AND (FORALL i: f(X(i))`1)});

  % Subtype TCC generated (at line 79, column 6) for
      % IUnion(LAMBDA i: IF i <= n THEN A_of(f)(i) ELSE emptyset[T] ENDIF)
      % expected type  (S)
  P_of_TCC1: OBLIGATION
    FORALL (f: sigma_finite_measure, n: nat):
      S(IUnion[nat, T]
            (LAMBDA i: IF i <= n THEN A_of(f)(i) ELSE emptyset[T] ENDIF));


body:
  %------------------------------------------------------------------------------
  % Sigma Algebra
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  %     Version 1.0            1/5/07   Initial Version
  %------------------------------------------------------------------------------

  sigma_algebra[T:TYPE,(IMPORTING subset_algebra_def[T])
                S:sigma_algebra]: THEORY

  BEGIN

    IMPORTING subset_algebra[T,S],
              sets_aux@countable_image % Proof only

    x,y: VAR (S)
    SS:  VAR sequence[(S)]

    sigma_algebra_emptyset:      LEMMA member(emptyset[T],S)
    sigma_algebra_fullset:       LEMMA member(fullset[T],S)
    sigma_algebra_complement:    LEMMA member(complement(x),S)
    sigma_algebra_union:         LEMMA member(union(x,y),S)
    sigma_algebra_intersection:  LEMMA member(intersection(x,y),S)
    sigma_algebra_difference:    LEMMA member(difference(x,y),S)
    sigma_algebra_IUnion:        LEMMA member(IUnion(SS),S)
    sigma_algebra_IIntersection: LEMMA member(IIntersection(SS),S)

    sigma_algebra_emptyset_rew:      JUDGEMENT emptyset[T]       HAS_TYPE (S)
    sigma_algebra_fullset_rew:       JUDGEMENT fullset[T]        HAS_TYPE (S)
    sigma_algebra_complement_rew:    JUDGEMENT complement(x)     HAS_TYPE (S)
    sigma_algebra_union_rew:         JUDGEMENT union(x,y)        HAS_TYPE (S)
    sigma_algebra_intersection_rew:  JUDGEMENT intersection(x,y) HAS_TYPE (S)
    sigma_algebra_difference_rew:    JUDGEMENT difference(x,y)   HAS_TYPE (S)
    sigma_algebra_IUnion_rew:        JUDGEMENT IUnion(SS)        HAS_TYPE (S)
    sigma_algebra_IIntersection_rew: JUDGEMENT IIntersection(SS) HAS_TYPE (S)

  END sigma_algebra

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 35, column 45) for  IUnion(SS)
      % expected type  (S)
  sigma_algebra_IUnion_rew: OBLIGATION FORALL (SS): S(IUnion[nat, T](SS));

  % Judgement subtype TCC generated (at line 36, column 45) for
      % IIntersection(SS)
      % expected type  (S)
  sigma_algebra_IIntersection_rew: OBLIGATION
    FORALL (SS): S(IIntersection[nat, T](SS));


body:
  %------------------------------------------------------------------------------
  % Borel
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  %     Version 1.0            1/05/07  Initial Version
  %------------------------------------------------------------------------------
  borel[T:TYPE, (IMPORTING topology@topology_def[T]) S:topology]: THEORY

  BEGIN

    IMPORTING subset_algebra_def[T],
              topology@topology[T,S],
              topology@basis[T],
              sets_aux@countability

    x: VAR T
    X: VAR open
    Y: VAR closed
    Z: VAR set[T]
    B: VAR (base?[T](S))
  %  A: VAR sigma_algebra

    borel?:sigma_algebra = generated_sigma_algebra(fullset[open])

    borel: TYPE+ = (borel?) CONTAINING emptyset[T]

    IMPORTING sigma_algebra[T,(borel?)]

    a,b: VAR borel
    A:   VAR countable_set[borel]
    C:   VAR set[borel]

    emptyset_is_borel:     LEMMA borel?(emptyset[T])
    fullset_is_borel:      LEMMA borel?(fullset[T])
    open_is_borel:         LEMMA borel?(X)
    closed_is_borel:       LEMMA borel?(Y)
    complement_is_borel:   LEMMA borel?(complement(a))
    union_is_borel:        LEMMA borel?(union(a,b))
    intersection_is_borel: LEMMA borel?(intersection(a,b))
    difference_is_borel:   LEMMA borel?(difference(a,b))
    Union_is_borel:        LEMMA borel?(Union(A))
    Complement_is_borel:   LEMMA every(borel?,Complement(C))
    Intersection_is_borel: LEMMA borel?(Intersection(A))

    emptyset_is_borel_judge:     JUDGEMENT emptyset[T]        HAS_TYPE   borel
    fullset_is_borel_judge:      JUDGEMENT fullset[T]         HAS_TYPE   borel
    open_is_borel_judge:         JUDGEMENT open               SUBTYPE_OF borel
    closed_is_borel_judge:       JUDGEMENT closed             SUBTYPE_OF borel
    complement_is_borel_judge:   JUDGEMENT complement(a)      HAS_TYPE   borel
    union_is_borel_judge:        JUDGEMENT union(a,b)         HAS_TYPE   borel
    intersection_is_borel_judge: JUDGEMENT intersection(a,b)  HAS_TYPE   borel
    difference_is_borel_judge:   JUDGEMENT difference(a,b)    HAS_TYPE   borel

    borel_basis: LEMMA generated_sigma_algebra(B)(Z) => borel?(Z)

    borel_countable_basis: LEMMA is_countable(B) =>
                                        borel? = generated_sigma_algebra(B)

  END borel

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 26, column 37) for  emptyset[T]
      % expected type  borel
  borel_TCC1: OBLIGATION borel?(emptyset[T]);

  % Judgement subtype TCC generated (at line 48, column 41) for  x
      % expected type  borel
  open_is_borel_judge: OBLIGATION FORALL (x: open): borel?(x);

  % Judgement subtype TCC generated (at line 49, column 41) for  x
      % expected type  borel
  closed_is_borel_judge: OBLIGATION FORALL (x: closed): borel?(x);


body:
  %------------------------------------------------------------------------------
  % Borel Sets for Hausdorff Spaces
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  % All references are to WA Sutherland "Introduction to Metric and
  % Topological Spaces", OUP, 1981
  %
  %     Version 1.0            1/5/07   Initial Version
  %------------------------------------------------------------------------------

  hausdorff_borel[T:TYPE, (IMPORTING topology@topology_def[T])
                  S:hausdorff]: THEORY

  BEGIN

    IMPORTING topology@hausdorff_convergence[T,S],
              borel[T,S]

    x: VAR T

    singleton_is_borel:        LEMMA borel?(singleton(x))

    singleton_is_borel_judge:  JUDGEMENT singleton(x)       HAS_TYPE   borel

  END hausdorff_borel


body:
  %------------------------------------------------------------------------------
  % Linking real topology and borel sets
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            17/08/07  Initial Version
  %     Version 1.1            23/03/11  Extras for probability
  %------------------------------------------------------------------------------
  real_borel: THEORY

  BEGIN

    IMPORTING metric_space@real_topology,
              borel[real,metric_induced_topology],
              hausdorff_borel[real,metric_induced_topology]

    real_borel:sigma_algebra = (borel?)

    borel_generated_by_rational_open_interval: LEMMA
      borel? = generated_sigma_algebra(fullset[rational_open_interval])

    borel_generated_by_open_interval: LEMMA
      borel? = generated_sigma_algebra(fullset[open_interval])

  % From borel and hausdorff_borel:
  % singleton_is_borel:        LEMMA borel?(singleton(x))
  % singleton_is_borel_judge:  JUDGEMENT singleton(x)       HAS_TYPE   borel
  % emptyset_is_borel:     LEMMA borel?(emptyset[T])
  % fullset_is_borel:      LEMMA borel?(fullset[T])
  % open_is_borel:         LEMMA borel?(X)
  % closed_is_borel:       LEMMA borel?(Y)
  % complement_is_borel:   LEMMA borel?(complement(a))
  % union_is_borel:        LEMMA borel?(union(a,b))
  % intersection_is_borel: LEMMA borel?(intersection(a,b))
  % difference_is_borel:   LEMMA borel?(difference(a,b))
  % Union_is_borel:        LEMMA borel?(Union(A))
  % Complement_is_borel:   LEMMA every(borel?,Complement(C))
  % Intersection_is_borel: LEMMA borel?(Intersection(A))

    A: VAR open_interval
    B: VAR closed_interval
    L: VAR left_semiclosed_interval
    R: VAR right_semiclosed_interval

    open_interval_borel_rew:             LEMMA real_borel(A)
    closed_interval_borel_rew:           LEMMA real_borel(B)
    left_semiclosed_interval_borel_rew:  LEMMA real_borel(L)
    right_semiclosed_interval_borel_rew: LEMMA real_borel(R)

    AUTO_REWRITE+ open_interval_borel_rew
    AUTO_REWRITE+ closed_interval_borel_rew
    AUTO_REWRITE+ left_semiclosed_interval_borel_rew
    AUTO_REWRITE+ right_semiclosed_interval_borel_rew

    open_interval_is_borel:   JUDGEMENT open_interval   SUBTYPE_OF borel
    closed_interval_is_borel: JUDGEMENT closed_interval SUBTYPE_OF borel
    left_semiclosed_interval_is_borel:
                             JUDGEMENT left_semiclosed_interval  SUBTYPE_OF borel
    right_semiclosed_interval_is_borel:
                             JUDGEMENT right_semiclosed_interval SUBTYPE_OF borel

  %  IMPORTING sigma_algebra % Proof Only

    borel_generated_by_left_semiclosed_interval: LEMMA
      borel? = generated_sigma_algebra(fullset[left_semiclosed_interval])

    borel_generated_by_right_semiclosed_interval: LEMMA
      borel? = generated_sigma_algebra(fullset[right_semiclosed_interval])

  END real_borel

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 55, column 38) for  x
      % expected type  borel[real, metric_induced_topology]
  open_interval_is_borel: OBLIGATION
    FORALL (x1: open_interval):
      borel?
          [real,
           metric_induced_topology[real, (LAMBDA (x, y: real): abs(x - y))]]
          (x1);

  % Judgement subtype TCC generated (at line 56, column 38) for  x
      % expected type  borel[real, metric_induced_topology]
  closed_interval_is_borel: OBLIGATION
    FORALL (x1: closed_interval):
      borel?
          [real,
           metric_induced_topology[real, (LAMBDA (x, y: real): abs(x - y))]]
          (x1);

  % Judgement subtype TCC generated (at line 58, column 37) for  x
      % expected type  borel[real, metric_induced_topology]
  left_semiclosed_interval_is_borel: OBLIGATION
    FORALL (x1: left_semiclosed_interval):
      borel?
          [real,
           metric_induced_topology[real, (LAMBDA (x, y: real): abs(x - y))]]
          (x1);

  % Judgement subtype TCC generated (at line 60, column 37) for  x
      % expected type  borel[real, metric_induced_topology]
  right_semiclosed_interval_is_borel: OBLIGATION
    FORALL (x1: right_semiclosed_interval):
      borel?
          [real,
           metric_induced_topology[real, (LAMBDA (x, y: real): abs(x - y))]]
          (x1);


body:
  %-------------------------------------------------------------------------
  % Measure Space Definitions
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0           04/05/09    Initial (DRL)
  %-------------------------------------------------------------------------

  measure_space_def[T:TYPE, (IMPORTING subset_algebra_def[T])
                    S:sigma_algebra]: THEORY

  BEGIN

    IMPORTING sigma_algebra[T,S],
              reals@real_fun_ops_aux[T],
              structures@const_fun_def[T,real],
              metric_space@real_topology,
              topology@basis[real],
              borel[real,metric_induced_topology],
              real_borel,
              sets_aux@countable_props,
              sets_aux@inverse_image_Union,      % Proof Only
              sets_aux@countable_image,  % Proof Only
              sets_aux@countable_set     % Proof Only

    X: VAR set[T]
    Y: VAR set[real]
    x,y,z: VAR T
    f: VAR [T->real]
    B: VAR borel
    c: VAR real
    q: VAR rational
    r: VAR posreal

    measurable_set?(X):bool = S(X)

    measurable_set: TYPE+ = (measurable_set?) CONTAINING emptyset[T]

    a,b: VAR measurable_set
    SS:  VAR sequence[measurable_set]
    M:   VAR countable_set[(S)]

    measurable_emptyset:      JUDGEMENT emptyset[T]       HAS_TYPE measurable_set
    measurable_fullset:       JUDGEMENT fullset[T]        HAS_TYPE measurable_set
    measurable_complement:    JUDGEMENT complement(a)     HAS_TYPE measurable_set
    measurable_union:         JUDGEMENT union(a,b)        HAS_TYPE measurable_set
    measurable_intersection:  JUDGEMENT intersection(a,b) HAS_TYPE measurable_set
    measurable_difference:    JUDGEMENT difference(a,b)   HAS_TYPE measurable_set
    measurable_Union:         JUDGEMENT Union(M)          HAS_TYPE measurable_set
    measurable_Intersection:  JUDGEMENT Intersection(M)   HAS_TYPE measurable_set
    measurable_IUnion:        JUDGEMENT IUnion(SS)        HAS_TYPE measurable_set
    measurable_IIntersection: JUDGEMENT IIntersection(SS) HAS_TYPE measurable_set

    measurable_function?(f):bool = FORALL B: measurable_set?(inverse_image(f,B))

    measurable_function: TYPE+ = (measurable_function?) CONTAINING (LAMBDA x: 0)

    g,g1,g2: VAR measurable_function

    measurable_is_function: JUDGEMENT measurable_function SUBTYPE_OF [T->real]
    constant_is_measurable: JUDGEMENT (constant?[T,real]) SUBTYPE_OF
                                                              measurable_function

    U: VAR setofsets[real]

    measurable_def: LEMMA borel? = generated_sigma_algebra(U) =>
                          (measurable_function?(f) <=>
                           FORALL (X:(U)): S(inverse_image(f,X)))

    measurable_def2: LEMMA measurable_function?(f) <=> 
                           FORALL (i:open_interval): S(inverse_image(f,i))

    measurable_gt: LEMMA measurable_function?(f) <=> FORALL c: S({z| f(z) >  c})
    measurable_le: LEMMA measurable_function?(f) <=> FORALL c: S({z| f(z) <= c})
    measurable_lt: LEMMA measurable_function?(f) <=> FORALL c: S({z| f(z) <  c})
    measurable_ge: LEMMA measurable_function?(f) <=> FORALL c: S({z| f(z) >= c})

    measurable_gt2: LEMMA measurable_function?(f) <=> FORALL q: S({z| f(z) >  q})
    measurable_le2: LEMMA measurable_function?(f) <=> FORALL q: S({z| f(z) <= q})
    measurable_lt2: LEMMA measurable_function?(f) <=> FORALL q: S({z| f(z) <  q})
    measurable_ge2: LEMMA measurable_function?(f) <=> FORALL q: S({z| f(z) >= q})

    scal_measurable:  JUDGEMENT *(c,g)   HAS_TYPE measurable_function
    sum_measurable:   JUDGEMENT +(g1,g2) HAS_TYPE measurable_function
    opp_measurable:   JUDGEMENT -(g)     HAS_TYPE measurable_function
    diff_measurable:  JUDGEMENT -(g1,g2) HAS_TYPE measurable_function

  END measure_space_def

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 37, column 55) for  emptyset[T]
      % expected type  measurable_set
  measurable_set_TCC1: OBLIGATION measurable_set?(emptyset[T]);

  % Judgement subtype TCC generated (at line 43, column 38) for  emptyset[T]
      % expected type  measurable_set
  measurable_emptyset: OBLIGATION measurable_set?(emptyset[T]);

  % Judgement subtype TCC generated (at line 44, column 38) for  fullset[T]
      % expected type  measurable_set
  measurable_fullset: OBLIGATION measurable_set?(fullset[T]);

  % Judgement subtype TCC generated (at line 45, column 38) for  complement(a)
      % expected type  measurable_set
  measurable_complement: OBLIGATION
    FORALL (a): measurable_set?(complement[T](a));

  % Judgement subtype TCC generated (at line 46, column 38) for  union(a, b)
      % expected type  measurable_set
  measurable_union: OBLIGATION FORALL (a, b): measurable_set?(union[T](a, b));

  % Judgement subtype TCC generated (at line 47, column 38) for
      % intersection(a, b)
      % expected type  measurable_set
  measurable_intersection: OBLIGATION
    FORALL (a, b): measurable_set?(intersection[T](a, b));

  % Judgement subtype TCC generated (at line 48, column 38) for
      % difference(a, b)
      % expected type  measurable_set
  measurable_difference: OBLIGATION
    FORALL (a, b): measurable_set?(difference[T](a, b));

  % Subtype TCC generated (at line 49, column 44) for  M
      % expected type  setofsets[T]
  measurable_Union_TCC1: OBLIGATION
    FORALL (M, x: setof[T]): M(x) IMPLIES (S)(x);

  % Judgement subtype TCC generated (at line 49, column 38) for  Union(M)
      % expected type  measurable_set
  measurable_Union: OBLIGATION FORALL (M): measurable_set?(Union[T](M));

  % Judgement subtype TCC generated (at line 50, column 38) for
      % Intersection(M)
      % expected type  measurable_set
  measurable_Intersection: OBLIGATION
    FORALL (M): measurable_set?(Intersection[T](M));

  % Judgement subtype TCC generated (at line 51, column 38) for  IUnion(SS)
      % expected type  measurable_set
  measurable_IUnion: OBLIGATION
    FORALL (SS): measurable_set?(IUnion[nat, T](SS));

  % Judgement subtype TCC generated (at line 52, column 38) for
      % IIntersection(SS)
      % expected type  measurable_set
  measurable_IIntersection: OBLIGATION
    FORALL (SS): measurable_set?(IIntersection[nat, T](SS));

  % Subtype TCC generated (at line 56, column 66) for  (LAMBDA x: 0)
      % expected type  measurable_function
  measurable_function_TCC1: OBLIGATION measurable_function?((LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 61, column 36) for  x
      % expected type  measurable_function
  constant_is_measurable: OBLIGATION
    FORALL (x: (constant?[T, real])): measurable_function?(x);

  % Judgement subtype TCC generated (at line 83, column 30) for  c * g
      % expected type  measurable_function
  scal_measurable: OBLIGATION FORALL (c, g): measurable_function?(*[T](c, g));

  % Judgement subtype TCC generated (at line 84, column 30) for  g1 + g2
      % expected type  measurable_function
  sum_measurable: OBLIGATION
    FORALL (g1, g2): measurable_function?((+[T])(g1, g2));

  % Judgement subtype TCC generated (at line 85, column 30) for  -g
      % expected type  measurable_function
  opp_measurable: OBLIGATION FORALL (g): measurable_function?(-g);

  % Judgement subtype TCC generated (at line 86, column 30) for  g1 - g2
      % expected type  measurable_function
  diff_measurable: OBLIGATION
    FORALL (g1, g2): measurable_function?((-[T])(g1, g2));


body:
  %------------------------------------------------------------------------------
  % Basic properties of measures
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            1/5/07   Initial Version
  %------------------------------------------------------------------------------

  measure_props[T:TYPE,          (IMPORTING subset_algebra_def[T])
                S:sigma_algebra, (IMPORTING measure_def[T,S])
                m:measure_type]: THEORY

  BEGIN

    IMPORTING measure_space_def[T,S],
              sigma_algebra[T,S],
              structures@fun_preds_partial[nat,set[T],reals.<=,subset?[T]],
              measure_def[T,S],
              series@series_aux

    n,i:   VAR nat
    a,b,M: VAR measurable_set
    x,y:   VAR extended_nnreal
    X:     VAR sequence[extended_nnreal]
    DX:    VAR disjoint_indexed_measurable
    E:     VAR sequence[measurable_set]

    mu_fin?(M):bool                   = m(M)`1
    mu(M:{m:(S) | mu_fin?(m)}):nnreal = m(M)`2

    m_emptyset:           LEMMA m(emptyset[T]) = (TRUE,0)
    m_countably_additive: LEMMA x_eq(x_sum(m o DX), m(IUnion(DX)))

    m_disjoint_union:LEMMA disjoint?(a,b) => x_eq(m(union(a,b)),x_add(m(a),m(b)))
    m_monotone:      LEMMA subset?(a,b) => x_le(m(a),m(b))                % 2.6.1
    m_union:         LEMMA x_le(m(union(a,b)),x_add(m(a),m(b)))

    m_increasing_convergence: LEMMA increasing?(E) =>                     % 2.6.2
                                    x_converges?(m o E, m(IUnion(E)))

    m_decreasing_convergence: LEMMA decreasing?(E) AND mu_fin?(E(0)) =>   % 2.6.3
                                    x_converges?(m o E, m(IIntersection(E)))
  END measure_props

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 31, column 40) for  M
      % expected type  (S)
  mu_fin?_TCC1: OBLIGATION FORALL (M: measurable_set[T, S]): S(M);

  % Subtype TCC generated (at line 32, column 24) for  m
      % expected type  measurable_set[T, S]
  mu_TCC1: OBLIGATION FORALL (m: (S)): measurable_set?[T, S](m);

  % Subtype TCC generated (at line 37, column 50) for  union(a, b)
      % expected type  (S)
  m_disjoint_union_TCC1: OBLIGATION
    FORALL (a, b: measurable_set[T, S]):
      disjoint?(a, b) IMPLIES S(union[T](a, b));

  % Subtype TCC generated (at line 37, column 75) for  b
      % expected type  (S)
  m_disjoint_union_TCC2: OBLIGATION
    FORALL (a, b: measurable_set[T, S]): disjoint?(a, b) IMPLIES S(b);

  % Subtype TCC generated (at line 38, column 53) for  b
      % expected type  (S)
  m_monotone_TCC1: OBLIGATION
    FORALL (a, b: measurable_set[T, S]): subset?(a, b) IMPLIES S(b);

  % Subtype TCC generated (at line 39, column 32) for  union(a, b)
      % expected type  (S)
  m_union_TCC1: OBLIGATION
    FORALL (a, b: measurable_set[T, S]): S(union[T](a, b));

  % Subtype TCC generated (at line 42, column 51) for  E
      % expected type  [nat -> (S)]
  m_increasing_convergence_TCC1: OBLIGATION
    FORALL (E: sequence[measurable_set]):
      increasing?(E) IMPLIES (FORALL (x1: nat): S(E(x1)));

  % Subtype TCC generated (at line 42, column 56) for  IUnion(E)
      % expected type  (S)
  m_increasing_convergence_TCC2: OBLIGATION
    FORALL (E: sequence[measurable_set]):
      increasing?(E) IMPLIES S(IUnion[nat, T](E));

  % Subtype TCC generated (at line 45, column 51) for  E
      % expected type  [nat -> (S)]
  m_decreasing_convergence_TCC1: OBLIGATION
    FORALL (E: sequence[measurable_set]):
      mu_fin?(E(0)) AND decreasing?(E) IMPLIES (FORALL (x1: nat): S(E(x1)));

  % Subtype TCC generated (at line 45, column 56) for  IIntersection(E)
      % expected type  (S)
  m_decreasing_convergence_TCC2: OBLIGATION
    FORALL (E: sequence[measurable_set]):
      mu_fin?(E(0)) AND decreasing?(E) IMPLIES S(IIntersection[nat, T](E));


body:
  %------------------------------------------------------------------------------
  % Measure Theory
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            05/11/07  Initial Version
  %------------------------------------------------------------------------------
  measure_theory[T:TYPE,          (IMPORTING subset_algebra_def[T])
                 S:sigma_algebra, (IMPORTING measure_def[T,S])
                 m:measure_type]: THEORY

  BEGIN

    IMPORTING measure_space_def[T,S],
              sigma_algebra[T,S],
              measure_props[T,S,m],
              sets_aux@countable_indexed_sets

    a,b: VAR measurable_set
    X,Y: VAR set[T]
    P:   VAR set[T]
    p:   VAR pred[[real,real]]
    f,g: VAR [T->real]
    F,G: VAR sequence[[T->real]]
    x:   VAR T
    i,j,n: VAR nat
    Z:   VAR setofsets[T]

    null_set?(X):bool = measurable_set?(X) AND mu_fin?(X) AND mu(X) = 0   % 4.2.1

    negligible_set?(Y):bool = EXISTS X: null_set?(X) AND subset?(Y,X)

    null_set:   TYPE+ = (null_set?)       CONTAINING emptyset[T]
    negligible: TYPE+ = (negligible_set?) CONTAINING emptyset[T]

    N,N1,N2: VAR null_set
    NS:      VAR sequence[null_set]
    E,E1,E2: VAR negligible
    ES:      VAR sequence[negligible]

    negligible_iff_measurable_null: LEMMA
      (negligible_set?(X) AND measurable_set?(X)) <=> null_set?(X)

    null_set_is_measurable: JUDGEMENT null_set    SUBTYPE_OF measurable_set
    null_is_negligible:     JUDGEMENT null_set    SUBTYPE_OF negligible

    null_emptyset:     JUDGEMENT emptyset[T]         HAS_TYPE null_set
    null_union:        JUDGEMENT union(N1,N2)        HAS_TYPE null_set
    null_intersection: JUDGEMENT intersection(N1,N2) HAS_TYPE null_set
    null_difference:   JUDGEMENT difference(N1,N2)   HAS_TYPE null_set
    null_IUnion:       JUDGEMENT IUnion(NS)          HAS_TYPE null_set

    null_Union: LEMMA every(null_set?,Z) AND is_countable(Z) =>
                      null_set?(Union(Z))

    negligible_emptyset:     JUDGEMENT emptyset[T]         HAS_TYPE negligible
    negligible_union:        JUDGEMENT union(E1,E2)        HAS_TYPE negligible
    negligible_intersection: JUDGEMENT intersection(E1,E2) HAS_TYPE negligible
    negligible_IUnion:       JUDGEMENT IUnion(ES)          HAS_TYPE negligible

    negligible_Union:  LEMMA every(negligible_set?,Z) AND is_countable(Z) =>
                             negligible_set?(Union(Z))

    negligible_subset: LEMMA subset?(X,E) => negligible_set?(X)

    ae_in?(P)(X):bool = EXISTS E: FORALL (x:(X)):
                                  (NOT member(x,E)) => member(x,P)
    ae?(P):bool       = ae_in?(P)(fullset[T])                             % 4.2.3

    pointwise_ae?(p)(f,g):bool = ae?(LAMBDA x: p(f(x),g(x)))              % 4.2.4

  % It's just too cumbersome to use the above directly, so we introduce
  % some useful special cases.

    ae?(p)(f,g):   bool = pointwise_ae?(p)(f,g)
    ae_0?(f):      bool = pointwise_ae?(=)(f,lambda x: 0)
    ae_nonneg?(f): bool = pointwise_ae?(<=)((lambda x: 0),f)
    ae_pos?(f):    bool = pointwise_ae?(<)((lambda x: 0),f)
    ae_le?(f,g):   bool = pointwise_ae?(<=)(f,g)
    ae_eq?(f,g):   bool = pointwise_ae?(=)(f,g)

    ae_eq_equivalence:   LEMMA equivalence?(ae_eq?)
    ae_le_reflexive:     LEMMA reflexive?(ae_le?)
    ae_le_antisymmetric: LEMMA ae_le?(f,g) AND ae_le?(g,f) => ae_eq?(f,g)
    ae_le_transitive:    LEMMA transitive?(ae_le?)

    ae_convergence_in?(X)(F,f):bool
      = ae_in?(LAMBDA x:convergence?(LAMBDA n:F(n)(x),f(x)))(X)
    ae_cauchy_in?(X)(F):bool
      = ae_in?(LAMBDA x: cauchy?(LAMBDA n: F(n)(x)))(X)

    ae_convergence?(F,f):bool = ae_convergence_in?(fullset[T])(F,f)
    ae_cauchy?(F):bool        = ae_cauchy_in?(fullset[T])(F)

    ae_convergence_cauchy: LEMMA ae_convergence?(F,f) => ae_cauchy?(F)    % 4.2.5
    ae_convergence_eq:     LEMMA ae_convergence?(F,f) =>
                                 (ae_convergence?(F,g) <=> ae_eq?(f,g))
    ae_eq_convergence:     LEMMA ae_convergence?(F,f) AND
                                 (FORALL n: ae_eq?(F(n),G(n))) =>
                                 ae_convergence?(G,f)
    ae_increasing?(F):bool
      = EXISTS E: FORALL x: NOT member(x,E) =>
               FORALL i,j: i <= j => F(i)(x) <= F(j)(x)

    ae_decreasing?(F):bool
      = EXISTS E: FORALL x: NOT member(x,E) =>
               FORALL i,j: i <= j => F(j)(x) <= F(i)(x)

    ae_monotonic_converges?(F,f):bool
      = ae_convergence?(F,f) AND (ae_increasing?(F) OR ae_decreasing?(F))

  %  ae_pointwise_bounded?(F):bool
  %    = EXISTS E:
  %             pointwise_bounded?(lambda n: phi(complement(E))*F(n))

    ae_convergent?(F):bool = EXISTS f: ae_convergence?(F,f)


  END measure_theory

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 29, column 63) for  X
      % expected type  {m1: (S) | mu_fin?(m1)}
  null_set?_TCC1: OBLIGATION
    FORALL (X: set[T]): mu_fin?(X) AND measurable_set?(X) IMPLIES S(X);

  % Subtype TCC generated (at line 33, column 51) for  emptyset[T]
      % expected type  null_set
  null_set_TCC1: OBLIGATION null_set?(emptyset[T]);

  % Subtype TCC generated (at line 34, column 51) for  emptyset[T]
      % expected type  negligible
  negligible_TCC1: OBLIGATION negligible_set?(emptyset[T]);

  % Judgement subtype TCC generated (at line 44, column 36) for  x
      % expected type  measurable_set[T, S]
  null_set_is_measurable: OBLIGATION
    FORALL (x: null_set): measurable_set?[T, S](x);

  % Judgement subtype TCC generated (at line 45, column 36) for  x
      % expected type  negligible
  null_is_negligible: OBLIGATION FORALL (x: null_set): negligible_set?(x);

  % Judgement subtype TCC generated (at line 47, column 31) for  emptyset[T]
      % expected type  null_set
  null_emptyset: OBLIGATION null_set?(emptyset[T]);

  % Judgement subtype TCC generated (at line 48, column 31) for  union(N1, N2)
      % expected type  null_set
  null_union: OBLIGATION FORALL (N1, N2): null_set?(union[T](N1, N2));

  % Judgement subtype TCC generated (at line 49, column 31) for
      % intersection(N1, N2)
      % expected type  null_set
  null_intersection: OBLIGATION
    FORALL (N1, N2): null_set?(intersection[T](N1, N2));

  % Judgement subtype TCC generated (at line 50, column 31) for
      % difference(N1, N2)
      % expected type  null_set
  null_difference: OBLIGATION
    FORALL (N1, N2): null_set?(difference[T](N1, N2));

  % Judgement subtype TCC generated (at line 51, column 31) for  IUnion(NS)
      % expected type  null_set
  null_IUnion: OBLIGATION FORALL (NS): null_set?(IUnion[nat, T](NS));

  % Judgement subtype TCC generated (at line 57, column 37) for  union(E1, E2)
      % expected type  negligible
  negligible_union: OBLIGATION
    FORALL (E1, E2): negligible_set?(union[T](E1, E2));

  % Judgement subtype TCC generated (at line 58, column 37) for
      % intersection(E1, E2)
      % expected type  negligible
  negligible_intersection: OBLIGATION
    FORALL (E1, E2): negligible_set?(intersection[T](E1, E2));

  % Judgement subtype TCC generated (at line 59, column 37) for  IUnion(ES)
      % expected type  negligible
  negligible_IUnion: OBLIGATION
    FORALL (ES): negligible_set?(IUnion[nat, T](ES));


body:
  %-------------------------------------------------------------------------
  % Pointwise Convergence
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0           04/05/09    Initial (DRL)
  %-------------------------------------------------------------------------

  pointwise_convergence[T:TYPE]: THEORY

  BEGIN

    IMPORTING metric_space@convergence_aux

    u,v:     VAR sequence[[T->real]]
    f,f0,f1: VAR [T->real]
    g:   VAR [T->nnreal]
    x:   VAR T
    c:   VAR real
    n,m: VAR nat
    P:   VAR pred[sequence[real]]


    zero_seq(n)(x):real = 0

    pointwise?(P)(u):bool = FORALL x: P(LAMBDA n: u(n)(x))

    pointwise_bounded_above?(u):bool = pointwise?(bounded_above?)(u)
    pointwise_bounded_below?(u):bool = pointwise?(bounded_below?)(u)
    pointwise_bounded?(u):bool       = pointwise?(bounded_seq?)(u)

    pointwise_bounded_def: LEMMA pointwise_bounded?(u) <=>
                                  (pointwise_bounded_above?(u) AND
                                   pointwise_bounded_below?(u))

    pointwise_bounded_above:TYPE+ =(pointwise_bounded_above?) CONTAINING zero_seq
    pointwise_bounded_below:TYPE+ =(pointwise_bounded_below?) CONTAINING zero_seq
    pointwise_bounded:      TYPE+ =(pointwise_bounded?)       CONTAINING zero_seq

    pointwise_bounded_is_bounded_above:
          JUDGEMENT pointwise_bounded        SUBTYPE_OF pointwise_bounded_above
    pointwise_bounded_is_bounded_below:
          JUDGEMENT pointwise_bounded        SUBTYPE_OF pointwise_bounded_below

    pointwise_convergence?(u,f):bool=FORALL x:convergence?(LAMBDA n:u(n)(x),f(x))
    pointwise_convergent?(u):bool   =EXISTS f:pointwise_convergence?(u,f)

    pointwise_convergent: TYPE+ = (pointwise_convergent?)    CONTAINING zero_seq

    IMPORTING reals@real_fun_ops_aux[T]
  ;
    +(u,v):  sequence[[T->real]]   = LAMBDA n: u(n)+v(n);
    *(c,u):  sequence[[T->real]]   = LAMBDA n: c*u(n);
    -(u):    sequence[[T->real]]   = LAMBDA n: -(u(n));
    -(u,v):  sequence[[T->real]]   = LAMBDA n: u(n)-v(n);
    plus(u): sequence[[T->nnreal]] = LAMBDA n: plus(u(n));
    minus(u):sequence[[T->nnreal]] = LAMBDA n: minus(u(n));

    pointwise_convergence_sum:  LEMMA pointwise_convergence?(u,f0) AND
                                      pointwise_convergence?(v,f1)      =>
                                      pointwise_convergence?(u+v,f0+f1)

    pointwise_convergence_scal: LEMMA pointwise_convergence?(u,f)       =>
                                      pointwise_convergence?(c*u,c*f)

    pointwise_convergence_opp:  LEMMA pointwise_convergence?(u,f)       =>
                                      pointwise_convergence?(-u,-f)

    pointwise_convergence_diff: LEMMA pointwise_convergence?(u,f0) AND
                                      pointwise_convergence?(v,f1)      =>
                                      pointwise_convergence?(u-v,f0-f1)

    w,w0,w1: VAR pointwise_convergent

    pointwise_convergent_sum:  JUDGEMENT +(w0,w1) HAS_TYPE pointwise_convergent
    pointwise_convergent_scal: JUDGEMENT *(c,w)   HAS_TYPE pointwise_convergent
    pointwise_convergent_opp:  JUDGEMENT -(w)     HAS_TYPE pointwise_convergent
    pointwise_convergent_diff: JUDGEMENT -(w0,w1) HAS_TYPE pointwise_convergent

    pointwise_convergent_is_pointwise_bounded:
                      JUDGEMENT pointwise_convergent SUBTYPE_OF pointwise_bounded

    pointwise_increasing?(u):bool = FORALL x: increasing?(LAMBDA n: u(n)(x))
    pointwise_decreasing?(u):bool = FORALL x: decreasing?(LAMBDA n: u(n)(x))

    pointwise_converges_upto?(u,f):bool
             = pointwise_convergence?(u,f) AND pointwise_increasing?(u)

    pointwise_converges_downto?(u,f):bool
             = pointwise_convergence?(u,f) AND pointwise_decreasing?(u)

    plus_minus_pointwise_convergence: LEMMA
      pointwise_convergence?(u,f)                    <=>
      (pointwise_convergence?(plus(u), plus(f))  AND 
       pointwise_convergence?(minus(u),minus(f)))

    p: VAR pointwise_bounded_below
    a: VAR pointwise_bounded_above
    b: VAR pointwise_bounded

    inf(p)(n)(x):real = inf(image[nat,real](LAMBDA m: p(m)(x),{m| m >= n}))
    limsup(b)(x):real = sup(image[nat,real](LAMBDA m: inf(b)(m)(x),fullset[nat]))
    sup(a)(n)(x):real = sup(image[nat,real](LAMBDA m: a(m)(x),{m| m >= n}))
    liminf(b)(x):real = inf(image[nat,real](LAMBDA m: sup(b)(m)(x),fullset[nat]))

    sup_inf_def:       LEMMA sup(a)    = -inf(-a)
    liminf_limsup_def: LEMMA liminf(b) = -limsup(-b)

    inf_pointwise_increasing: LEMMA pointwise_increasing?(inf(p))
    inf_le:                   LEMMA inf(p)(n)(x) <= p(n)(x)
    inf_pointwise_le:         LEMMA pointwise_convergence?(p,f)        =>
                                    (FORALL n,x: inf(p)(n)(x) <= f(x))

    limsup_pointwise_convergence: LEMMA pointwise_convergence?(inf(b),limsup(b))

    inf_pointwise_convergence_upto: LEMMA pointwise_convergence?(p,f) =>
                                          pointwise_converges_upto?(inf(p),f)

    pointwise_convergence_plus_minus_def: LEMMA
      pointwise_convergence?(u,f)                               =>
       (pointwise_converges_upto?(inf(plus(u)),  plus(f))   AND
        pointwise_converges_upto?(inf(minus(u)), minus(f)))

  END pointwise_convergence

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 36, column 71) for  zero_seq
      % expected type  pointwise_bounded_above
  pointwise_bounded_above_TCC1: OBLIGATION pointwise_bounded_above?(zero_seq);

  % Subtype TCC generated (at line 37, column 71) for  zero_seq
      % expected type  pointwise_bounded_below
  pointwise_bounded_below_TCC1: OBLIGATION pointwise_bounded_below?(zero_seq);

  % Subtype TCC generated (at line 38, column 71) for  zero_seq
      % expected type  pointwise_bounded
  pointwise_bounded_TCC1: OBLIGATION pointwise_bounded?(zero_seq);

  % Judgement subtype TCC generated (at line 41, column 18) for  x
      % expected type  pointwise_bounded_above
  pointwise_bounded_is_bounded_above: OBLIGATION
    FORALL (x: pointwise_bounded): pointwise_bounded_above?(x);

  % Judgement subtype TCC generated (at line 43, column 18) for  x
      % expected type  pointwise_bounded_below
  pointwise_bounded_is_bounded_below: OBLIGATION
    FORALL (x: pointwise_bounded): pointwise_bounded_below?(x);

  % Subtype TCC generated (at line 48, column 70) for  zero_seq
      % expected type  pointwise_convergent
  pointwise_convergent_TCC1: OBLIGATION pointwise_convergent?(zero_seq);

  % Judgement subtype TCC generated (at line 75, column 39) for  w0 + w1
      % expected type  pointwise_convergent
  pointwise_convergent_sum: OBLIGATION
    FORALL (w0, w1): pointwise_convergent?(w0 + w1);

  % Judgement subtype TCC generated (at line 76, column 39) for  c * w
      % expected type  pointwise_convergent
  pointwise_convergent_scal: OBLIGATION
    FORALL (c, w): pointwise_convergent?(c * w);

  % Judgement subtype TCC generated (at line 77, column 39) for  -w
      % expected type  pointwise_convergent
  pointwise_convergent_opp: OBLIGATION FORALL (w): pointwise_convergent?(-w);

  % Judgement subtype TCC generated (at line 78, column 39) for  w0 - w1
      % expected type  pointwise_convergent
  pointwise_convergent_diff: OBLIGATION
    FORALL (w0, w1): pointwise_convergent?(w0 - w1);

  % Judgement subtype TCC generated (at line 81, column 30) for  x
      % expected type  pointwise_bounded
  pointwise_convergent_is_pointwise_bounded: OBLIGATION
    FORALL (x: pointwise_convergent): pointwise_bounded?(x);

  % Subtype TCC generated (at line 101, column 26) for
      % image[nat, real](LAMBDA m: p(m)(x), {m | m >= n})
      % expected type  Sl: inf_set[real]
  inf_TCC1: OBLIGATION
    FORALL (p: pointwise_bounded_below, n: nat, x: T):
      nonempty?[real](image[nat, real](LAMBDA m: p(m)(x), {m | m >= n})) AND
       below_bounded[real](image[nat, real](LAMBDA m: p(m)(x), {m | m >= n}));

  % Subtype TCC generated (at line 102, column 26) for
      % image[nat, real](LAMBDA m: inf(b)(m)(x), fullset[nat])
      % expected type  Su: sup_set[real]
  limsup_TCC1: OBLIGATION
    FORALL (b: pointwise_bounded, x: T):
      nonempty?[real](image[nat, real](LAMBDA m: inf(b)(m)(x), fullset[nat]))
       AND
       above_bounded[real]
           (image[nat, real](LAMBDA m: inf(b)(m)(x), fullset[nat]));

  % Subtype TCC generated (at line 103, column 26) for
      % image[nat, real](LAMBDA m: a(m)(x), {m | m >= n})
      % expected type  Su: sup_set[real]
  sup_TCC1: OBLIGATION
    FORALL (a: pointwise_bounded_above, n: nat, x: T):
      nonempty?[real](image[nat, real](LAMBDA m: a(m)(x), {m | m >= n})) AND
       above_bounded[real](image[nat, real](LAMBDA m: a(m)(x), {m | m >= n}));

  % Subtype TCC generated (at line 104, column 26) for
      % image[nat, real](LAMBDA m: sup(b)(m)(x), fullset[nat])
      % expected type  Sl: inf_set[real]
  liminf_TCC1: OBLIGATION
    FORALL (b: pointwise_bounded, x: T):
      nonempty?[real](image[nat, real](LAMBDA m: sup(b)(m)(x), fullset[nat]))
       AND
       below_bounded[real]
           (image[nat, real](LAMBDA m: sup(b)(m)(x), fullset[nat]));

  % Subtype TCC generated (at line 106, column 44) for  -a
      % expected type  pointwise_bounded_below
  sup_inf_def_TCC1: OBLIGATION
    FORALL (a: pointwise_bounded_above): pointwise_bounded_below?(-a);

  % Subtype TCC generated (at line 107, column 47) for  -b
      % expected type  pointwise_bounded
  liminf_limsup_def_TCC1: OBLIGATION
    FORALL (b: pointwise_bounded): pointwise_bounded?(-b);

  % Subtype TCC generated (at line 121, column 36) for  plus(u)
      % expected type  pointwise_bounded_below
  pointwise_convergence_plus_minus_def_TCC1: OBLIGATION
    FORALL (f: [T -> real], u: sequence[[T -> real]]):
      pointwise_convergence?(u, f) IMPLIES pointwise_bounded_below?(plus(u));

  % Subtype TCC generated (at line 122, column 36) for  minus(u)
      % expected type  pointwise_bounded_below
  pointwise_convergence_plus_minus_def_TCC2: OBLIGATION
    FORALL (f: [T -> real], u: sequence[[T -> real]]):
      pointwise_convergence?(u, f) AND
       pointwise_converges_upto?(inf(plus(u)), plus(f))
       IMPLIES pointwise_bounded_below?(minus(u));


body:
  %------------------------------------------------------------------------------
  % Properties of sup norm for functions
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            1/5/07   Initial Version
  %------------------------------------------------------------------------------

  sup_norm[T:TYPE]: THEORY

  BEGIN

    epsilon: VAR posreal
    c:   VAR nnreal
    y:   VAR real
    x:   VAR T
    i,n: VAR nat

    IMPORTING reals@real_fun_ops_aux[T],
              reals@bounded_reals[real],
              structures@const_fun_def[T,real]

    bounded?(f:[T->real]):bool = EXISTS c: FORALL x: abs(f(x)) <= c

    bounded: TYPE+ = (bounded?) CONTAINING (LAMBDA x: 0)

    f,f1,f2: VAR bounded

    bounded_add:  JUDGEMENT +(f1,f2) HAS_TYPE bounded
    bounded_scal: JUDGEMENT *(y,f)   HAS_TYPE bounded
    bounded_opp:  JUDGEMENT -(f)     HAS_TYPE bounded
    bounded_diff: JUDGEMENT -(f1,f2) HAS_TYPE bounded

    sup_norm(f):nnreal = IF EXISTS x: TRUE THEN sup({c | EXISTS x: abs(f(x))=c})
                                           ELSE 0 ENDIF

    sup_norm_eq_0: LEMMA sup_norm(f) = 0 <=> f = const_fun[T,real](0)
    sup_norm_neg:  LEMMA sup_norm(-f) = sup_norm(f)
    sup_norm_sum:  LEMMA sup_norm(f1+f2) <= sup_norm(f1)+sup_norm(f2)

    sup_norm_prop: LEMMA
         (FORALL x: abs(f(x)) <= sup_norm(f)) AND
         (FORALL c: (FORALL x: abs(f(x)) <= c) => sup_norm(f) <= c)

    u: VAR sequence[bounded]

    sup_norm_converges_to?(u,f):bool
      = FORALL epsilon: EXISTS n: FORALL i: i >= n => sup_norm(u(i)-f) < epsilon

    sup_norm_convergent?(u):bool = EXISTS f: sup_norm_converges_to?(u,f)

    sup_norm_convergent: TYPE+ = (sup_norm_convergent?) CONTAINING
                                      (LAMBDA n: LAMBDA x: 0)

    IMPORTING pointwise_convergence[T]

    sup_norm_convergent_is_pointwise_convergent: JUDGEMENT
                              sup_norm_convergent SUBTYPE_OF pointwise_convergent

    sup_norm_converges_to_pointwise_convergence: LEMMA
       sup_norm_converges_to?(u,f) => pointwise_convergence?(u,f)

  END sup_norm

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 28, column 42) for  (LAMBDA x: 0)
      % expected type  bounded
  bounded_TCC1: OBLIGATION bounded?((LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 32, column 26) for  f1 + f2
      % expected type  bounded
  bounded_add: OBLIGATION FORALL (f1, f2): bounded?((+[T])(f1, f2));

  % Judgement subtype TCC generated (at line 33, column 26) for  y * f
      % expected type  bounded
  bounded_scal: OBLIGATION FORALL (f, y): bounded?(*[T](y, f));

  % Judgement subtype TCC generated (at line 34, column 26) for  -f
      % expected type  bounded
  bounded_opp: OBLIGATION FORALL (f): bounded?(-f);

  % Judgement subtype TCC generated (at line 35, column 26) for  f1 - f2
      % expected type  bounded
  bounded_diff: OBLIGATION FORALL (f1, f2): bounded?((-[T])(f1, f2));

  % Subtype TCC generated (at line 37, column 50) for
      % extend[real, nnreal, bool, FALSE]({c | EXISTS x: abs(f(x)) = c})
      % expected type  Su: sup_set[real]
  sup_norm_TCC1: OBLIGATION
    FORALL (f: bounded):
      (EXISTS x: TRUE) IMPLIES
       nonempty?[real]
           (extend[real, nnreal, bool, FALSE]({c | EXISTS x: abs(f(x)) = c}))
        AND
        above_bounded[real]
            (extend[real, nnreal, bool, FALSE]
                 ({c | EXISTS x: abs(f(x)) = c}));

  % Subtype TCC generated (at line 37, column 46) for
      % sup(extend[real, nnreal, bool, FALSE]({c | EXISTS x: abs(f(x)) = c}))
      % expected type  nnreal
  sup_norm_TCC2: OBLIGATION
    FORALL (f: bounded):
      (EXISTS x: TRUE) IMPLIES
       sup[real]
           (extend[real, nnreal, bool, FALSE]({c | EXISTS x: abs(f(x)) = c}))
        >= 0;

  % Subtype TCC generated (at line 56, column 37) for  (LAMBDA n: LAMBDA x: 0)
      % expected type  sup_norm_convergent
  sup_norm_convergent_TCC1: OBLIGATION
    sup_norm_convergent?((LAMBDA n: LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 61, column 28) for  x
      % expected type  pointwise_convergent[T]
  sup_norm_convergent_is_pointwise_convergent: OBLIGATION
    FORALL (x: sup_norm_convergent): pointwise_convergent?[T](x);


body:
  %------------------------------------------------------------------------------
  % Partitions
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  % Partitioning a set into a set of sets. Note pleasant combining function
  % "join"
  %
  %     Version 1.0            1/5/07   Initial Version
  %------------------------------------------------------------------------------

  partitions[T:TYPE]: THEORY

  BEGIN

    a,a1,a2: VAR set[T]
    A:       VAR setofsets[T]

    partition?(A,a):bool
      = Union(A) = a AND FORALL (x,y:(A)): x /= y => disjoint?(x,y)

    finite_partition?(A,a):bool = partition?(A,a) AND is_finite(A)

    partition: TYPE+ = (LAMBDA A: partition?(A,fullset[T])) CONTAINING
                                                  singleton[set[T]](fullset[T])

    finite_partition: TYPE+ = (LAMBDA A: finite_partition?(A,fullset[T]))
                                  CONTAINING singleton[set[T]](fullset[T])

    p1,p2: VAR finite_partition

    IMPORTING finite_sets@finite_cross

    join(p1,p2):finite_partition
      = {a | EXISTS (a1:(p1),a2:(p2)): a = intersection(a1,a2)}

  END partitions

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 28, column 48) for
      % singleton[set[T]](fullset[T])
      % expected type  partition
  partition_TCC1: OBLIGATION
    partition?(singleton[set[T]](fullset[T]), fullset[T]);

  % Subtype TCC generated (at line 31, column 43) for
      % singleton[set[T]](fullset[T])
      % expected type  finite_partition
  finite_partition_TCC1: OBLIGATION
    finite_partition?(singleton[set[T]](fullset[T]), fullset[T]);

  % Subtype TCC generated (at line 38, column 6) for
      % {a | EXISTS (a1: (p1), a2: (p2)): a = intersection(a1, a2)}
      % expected type  finite_partition
  join_TCC1: OBLIGATION
    FORALL (p1: finite_partition, p2: finite_partition):
      finite_partition?({a |
                           EXISTS (a1: (p1), a2: (p2)):
                             a = intersection[T](a1, a2)},
                        fullset[T]);


body:
  %------------------------------------------------------------------------------
  % Borel functions
  %
  %     Author: David Lester, Manchester University, NIA, Université Perpignan
  %
  %     Version 1.0            1/05/07  Initial Version
  %------------------------------------------------------------------------------
  borel_functions[(IMPORTING topology@topology_def)
                  T1:Type, S:topology[T1],
                  T2:Type, T:topology[T2]]: THEORY

  BEGIN

    IMPORTING borel,
              structures@const_fun_def[T1,T2],
              topology@continuity_def[T1,S,T2,T],
              topology@continuity[T1,S,T2,T]

    f: VAR [T1->T2]
    c: VAR T2
    X: VAR open[T2,T]
    B: VAR borel[T2,T]

    borel_function?(f):bool = (FORALL B: borel?[T1,S](inverse_image(f,B)))

    borel_function_def: LEMMA borel_function?(f) IFF
                              FORALL X: borel?[T1,S](inverse_image[T1,T2](f,X))

    borel_function: TYPE = (borel_function?)

    const_borel_function: LEMMA borel_function?(const_fun[T1,T2](c))

    continuous_is_borel: JUDGEMENT continuous SUBTYPE_OF borel_function

  END borel_functions

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 33, column 33) for  x
      % expected type  borel_function
  continuous_is_borel: OBLIGATION FORALL (x: continuous): borel_function?(x);


body:
  %-------------------------------------------------------------------------
  % Measure Space
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0           04/05/09    Initial (DRL)
  %
  % Most of Chapter 4, section 1 of Berberian
  %
  %-------------------------------------------------------------------------

  measure_space[T:TYPE, (IMPORTING subset_algebra_def[T])
                S:sigma_algebra]: THEORY

  BEGIN

    IMPORTING
       measure_space_def[T,S],
       reals@real_fun_ops_aux[T],
       power@real_fun_power[T],
       real_borel,
       borel_functions[real,metric_induced_topology,
                       real,metric_induced_topology],
       topology@constant_continuity[real,metric_induced_topology,
                                    real,metric_induced_topology],
       metric_space@metric_continuity[real,(lambda (x,y:real): abs(x-y)),
                                       real,(lambda (x,y:real): abs(x-y))],
       metric_space@real_continuity[real,(lambda (x,y:real): abs(x-y))],
       pointwise_convergence[T],
       reals@bounded_reals[real],
       finite_sets@finite_cross,
       finite_sets@finite_sets_minmax_props[real,<=] % proof only


    f:       VAR [T->real]
    g,g1,g2: VAR measurable_function[T,S]
    phi:     VAR borel_function
    i,j,n,m: VAR nat
    s:       VAR sequence[[T->real]]
    u:       VAR sequence[measurable_function[T,S]]
    x:       VAR T
    c,c1,c2,y:     VAR real
    X:       VAR set[T]
    Y:       VAR set[real]
    a:       VAR posreal

    borel_comp_measurable_is_measurable:
         JUDGEMENT o(phi,g) HAS_TYPE measurable_function[T,S]        % SKB 4.1.12

    const_measurable: LEMMA  measurable_function?(lambda x: c)

    nn_measurable?(f):bool = measurable_function?(f) AND FORALL x: 0 <= f(x)
    nn_measurable: TYPE+ = (nn_measurable?) CONTAINING (lambda x: 0)

    nn_measurable_is_measurable:
                      JUDGEMENT nn_measurable SUBTYPE_OF measurable_function

    abs_measurable:      JUDGEMENT abs(g)       HAS_TYPE measurable_function[T,S]
    expt_nat_measurable: JUDGEMENT expt(g,n)    HAS_TYPE measurable_function[T,S]
    sq_measurable:       JUDGEMENT sq(g)        HAS_TYPE measurable_function[T,S]
    min_measurable:      JUDGEMENT min(g1,g2)   HAS_TYPE measurable_function[T,S]
    max_measurable:      JUDGEMENT max(g1,g2)   HAS_TYPE measurable_function[T,S]
    minimum_measurable:  JUDGEMENT minimum(u,n) HAS_TYPE measurable_function[T,S]
    maximum_measurable:  JUDGEMENT maximum(u,n) HAS_TYPE measurable_function[T,S]
    plus_measurable:     JUDGEMENT plus(g)      HAS_TYPE measurable_function[T,S]
    minus_measurable:    JUDGEMENT minus(g)     HAS_TYPE measurable_function[T,S]
    prod_measurable:     JUDGEMENT *(g1,g2)     HAS_TYPE measurable_function[T,S]
    expt_measurable:     JUDGEMENT ^(g:nn_measurable,a)
                                                HAS_TYPE measurable_function[T,S]

                                                                     % SKB 4.1.13
    measurable_plus_minus: LEMMA
         measurable_function?[T,S](f) <=>
                    (measurable_function?[T,S](plus(f)) AND
                     measurable_function?[T,S](minus(f)))            % SKB 4.1.15

    measurable_bounded_above?(u):bool = pointwise_bounded_above?(u)
    measurable_bounded_below?(u):bool = pointwise_bounded_below?(u)
    measurable_bounded?(u):bool
      = measurable_bounded_above?(u) AND measurable_bounded_below?(u)

    measurable_bounded_above: TYPE+ = (measurable_bounded_above?)
                                               CONTAINING (lambda n: lambda x: 0)
    measurable_bounded_below: TYPE+ = (measurable_bounded_below?)
                                               CONTAINING (lambda n: lambda x: 0)
    measurable_bounded:       TYPE+ = (measurable_bounded?)
                                               CONTAINING (lambda n: lambda x: 0)


    measurable_bounded_above_is_bounded_above:
          JUDGEMENT measurable_bounded_above SUBTYPE_OF pointwise_bounded_above
    measurable_bounded_below_is_bounded_below:
          JUDGEMENT measurable_bounded_below SUBTYPE_OF pointwise_bounded_below
    measurable_bounded_is_measurable_bounded_above:
          JUDGEMENT measurable_bounded       SUBTYPE_OF measurable_bounded_above
    measurable_bounded_is_measurable_bounded_below:
          JUDGEMENT measurable_bounded       SUBTYPE_OF measurable_bounded_below
    measurable_bounded_is_bounded:
          JUDGEMENT measurable_bounded       SUBTYPE_OF pointwise_bounded

    inf_measurable: LEMMA FORALL (u:measurable_bounded_below):
                          measurable_function?[T,S](inf(u)(n))

    sup_measurable: LEMMA FORALL (u:measurable_bounded_above):
                          measurable_function?[T,S](sup(u)(n))       % SKB 4.1.19

    pointwise_measurable: LEMMA pointwise_convergence?(u,f) =>       % SKB 4.1.20
                                                     measurable_function?[T,S](f)

    simple?(f):bool = measurable_function?[T,S](f) AND
                      is_finite(image(f,fullset[T]))                 % SKB 4.1.21

    simple: TYPE+ = (simple?) CONTAINING (lambda x: 0)

    simple_is_measurable: JUDGEMENT simple SUBTYPE_OF measurable_function
    simple_const:         LEMMA simple?(lambda x: c)

    nn_simple?(f):bool = (FORALL x: 0 <= f(x)) AND simple?(f)
    nn_simple: TYPE+ = (nn_simple?) CONTAINING (lambda x: 0)

    nn_simple_is_simple: JUDGEMENT nn_simple SUBTYPE_OF simple

    h,h1,h2: VAR simple
    v: VAR sequence[simple]

    simple_sq:       JUDGEMENT sq(h)        HAS_TYPE simple
    simple_add:      JUDGEMENT +(h1,h2)     HAS_TYPE simple
    simple_scal:     JUDGEMENT *(c,h)       HAS_TYPE simple
    simple_neg:      JUDGEMENT -(h)         HAS_TYPE simple
    simple_diff:     JUDGEMENT -(h1,h2)     HAS_TYPE simple
    simple_abs:      JUDGEMENT abs(h)       HAS_TYPE simple
    simple_min:      JUDGEMENT min(h1,h2)   HAS_TYPE simple
    simple_max:      JUDGEMENT max(h1,h2)   HAS_TYPE simple
    simple_maximum:  JUDGEMENT maximum(v,n) HAS_TYPE simple
    simple_minimum:  JUDGEMENT minimum(v,n) HAS_TYPE simple
    simple_plus:     JUDGEMENT plus(h)      HAS_TYPE simple
    simple_minus:    JUDGEMENT minus(h)     HAS_TYPE simple
    simple_times:    JUDGEMENT *(h1,h2)     HAS_TYPE simple
    simple_expt_nat: JUDGEMENT expt(h,n)    HAS_TYPE simple
    simple_expt:     JUDGEMENT ^(h:nn_simple,a) HAS_TYPE simple      % SKB 4.1.22

    phi(X)(x):nat = IF member(x,X) THEN 1 ELSE 0 ENDIF

    phi_is_simple: JUDGEMENT phi(X:(S)) HAS_TYPE simple

    IMPORTING hausdorff_borel[real,metric_induced_topology],
              partitions[T]

    P: VAR finite_partition[T]

    simple_def1: LEMMA simple?(f) <=>                                % SKB 4.1.23
        (is_finite(image(f,fullset[T])) AND
         (FORALL (y:(image(f,fullset[T]))): measurable_set?({x | y = f(x)})))

    constant_over?(f)(X):bool = EXISTS y: FORALL (x:(X)): y = f(x)

    simple_def2: LEMMA simple?(f) <=>
                       EXISTS P: every(S,P) AND every(constant_over?(f),P)

    simple_def3: LEMMA simple?(f) <=> EXISTS c1,c2,h1,h2: c1*h1+c2*h2 = f

    IMPORTING sup_norm[T]

    bounded_measurable?(f):bool = bounded?(f) AND measurable_function?(f)
    bounded_measurable: TYPE+ = (bounded_measurable?) CONTAINING (lambda x: 0)

    bounded_measurable_is_bounded:
                      JUDGEMENT bounded_measurable SUBTYPE_OF bounded
    bounded_measurable_is_measurable:
                      JUDGEMENT bounded_measurable SUBTYPE_OF measurable_function
    simple_is_bounded_measurable:
                      JUDGEMENT simple             SUBTYPE_OF bounded_measurable

    nn_bounded_measurable?(f):bool = bounded_measurable?(f) AND FORALL x: 0<=f(x)

    nn_bounded_measurable: TYPE+ = (nn_bounded_measurable?)
                                            CONTAINING (lambda x: 0)

    nn_bounded_measurable_is_bounded_measurable:
                    JUDGEMENT nn_bounded_measurable SUBTYPE_OF bounded_measurable

    increasing_nn_simple?(u):bool = (FORALL n: nn_simple?(u(n))) AND 
                                    pointwise_increasing?(u)

    increasing_nn_simple: TYPE+ = (increasing_nn_simple?)
                                               CONTAINING (lambda n: lambda x: 0)

    p: VAR nn_bounded_measurable
    w: VAR increasing_nn_simple

    sup_norm_simple: LEMMA EXISTS h: (forall x: 0 <= h(x) & h(x) <= p(x)) AND
                                     sup_norm(p-h) <= sup_norm(p)/2  % SKB 4.1.24

    nn_simple_approx(p):nn_simple
      = choose({h | (forall x: 0 <= h(x) & h(x) <= p(x)) AND
                                 sup_norm(p-h) <= sup_norm(p)/2})

  % The following IMPORT and recursive definition for proof only.
    IMPORTING reals@sigma_nat

    nn_simple_sequence(p)(n): RECURSIVE {h | forall x: 0 <= h(x) & h(x) <= p(x)}
      = IF n = 0 THEN nn_simple_approx(p)
                 ELSE nn_simple_sequence(p-nn_simple_approx(p))(n-1) ENDIF
        MEASURE (lambda p: lambda n: n)

    nn_bounded_measurable_as_increasing_simple_sequence:             % SKB 4.1.25
                         LEMMA EXISTS w: sup_norm_converges_to?(w,p)

    nn_bounded_measurable_as_sequence_prop: LEMMA sup_norm_converges_to?(w,p) =>
                                                  (FORALL n,x: w(n)(x) <= p(x))

    bounded_measurable_as_increasing_sequence: LEMMA                 % SKB 4.1.25
      bounded_measurable?(f) => EXISTS v: sup_norm_converges_to?(v,f)

    nn_measurable_def: LEMMA (FORALL x: 0 <= f(x)) =>                % SKB 4.1.26
      (measurable_function?(f) <=> EXISTS w: pointwise_converges_upto?(w,f))

    measurable_as_limit_simple_def: LEMMA                            % SKB 4.1.26
      measurable_function?(f) <=> EXISTS v: pointwise_convergence?(v,f)

  END measure_space

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 26, column 42) for
      % (LAMBDA (x, y: real): abs(x - y))
      % expected type  metric[real]
  IMP_metric_continuity_TCC1: OBLIGATION
    metric?[real]((LAMBDA (x, y: real): abs(x - y)));

  % Judgement subtype TCC generated (at line 48, column 17) for  phi o g
      % expected type  measurable_function[T, S]
  borel_comp_measurable_is_measurable: OBLIGATION
    FORALL (g, phi): measurable_function?[T, S](o[T, real, real](phi, g));

  % Subtype TCC generated (at line 53, column 54) for  (LAMBDA x: 0)
      % expected type  nn_measurable
  nn_measurable_TCC1: OBLIGATION nn_measurable?((LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 56, column 30) for  x
      % expected type  measurable_function[T, S]
  nn_measurable_is_measurable: OBLIGATION
    FORALL (x: nn_measurable): measurable_function?[T, S](x);

  % Judgement subtype TCC generated (at line 58, column 33) for  abs(g)
      % expected type  measurable_function[T, S]
  abs_measurable: OBLIGATION
    FORALL (g): measurable_function?[T, S](abs[T](g));

  % Judgement subtype TCC generated (at line 59, column 33) for  expt(g, n)
      % expected type  measurable_function[T, S]
  expt_nat_measurable: OBLIGATION
    FORALL (g, n): measurable_function?[T, S](expt[T](g, n));

  % Judgement subtype TCC generated (at line 60, column 33) for  sq(g)
      % expected type  measurable_function[T, S]
  sq_measurable: OBLIGATION FORALL (g): measurable_function?[T, S](sq[T](g));

  % Judgement subtype TCC generated (at line 61, column 33) for  min(g1, g2)
      % expected type  measurable_function[T, S]
  min_measurable: OBLIGATION
    FORALL (g1, g2): measurable_function?[T, S](min[T](g1, g2));

  % Judgement subtype TCC generated (at line 62, column 33) for  max(g1, g2)
      % expected type  measurable_function[T, S]
  max_measurable: OBLIGATION
    FORALL (g1, g2): measurable_function?[T, S](max[T](g1, g2));

  % Judgement subtype TCC generated (at line 63, column 33) for  minimum(u, n)
      % expected type  measurable_function[T, S]
  minimum_measurable: OBLIGATION
    FORALL (n, u): measurable_function?[T, S](minimum[T](u, n));

  % Judgement subtype TCC generated (at line 64, column 33) for  maximum(u, n)
      % expected type  measurable_function[T, S]
  maximum_measurable: OBLIGATION
    FORALL (n, u): measurable_function?[T, S](maximum[T](u, n));

  % Judgement subtype TCC generated (at line 65, column 33) for  plus(g)
      % expected type  measurable_function[T, S]
  plus_measurable: OBLIGATION
    FORALL (g): measurable_function?[T, S](plus[T](g));

  % Judgement subtype TCC generated (at line 66, column 33) for  minus(g)
      % expected type  measurable_function[T, S]
  minus_measurable: OBLIGATION
    FORALL (g): measurable_function?[T, S](minus[T](g));

  % Judgement subtype TCC generated (at line 67, column 33) for  g1 * g2
      % expected type  measurable_function[T, S]
  prod_measurable: OBLIGATION
    FORALL (g1, g2): measurable_function?[T, S](*[T](g1, g2));

  % Subtype TCC generated (at line 68, column 35) for  g
      % expected type  [T -> nnreal]
  expt_measurable_TCC1: OBLIGATION
    FORALL (g: nn_measurable, x1: T): g(x1) >= 0;

  % Judgement subtype TCC generated (at line 68, column 33) for  g ^ a
      % expected type  measurable_function[T, S]
  expt_measurable: OBLIGATION
    FORALL (a, g: nn_measurable): measurable_function?[T, S](^[T](g, a));

  % Subtype TCC generated (at line 83, column 67) for  LAMBDA x: 0
      % expected type  measurable_function[T, S]
  measurable_bounded_above_TCC1: OBLIGATION
    measurable_function?[T, S](LAMBDA x: 0);

  % Subtype TCC generated (at line 83, column 57) for  (LAMBDA n: LAMBDA x: 0)
      % expected type  measurable_bounded_above
  measurable_bounded_above_TCC2: OBLIGATION
    measurable_bounded_above?((LAMBDA n: LAMBDA x: 0));

  % Subtype TCC generated (at line 85, column 57) for  (LAMBDA n: LAMBDA x: 0)
      % expected type  measurable_bounded_below
  measurable_bounded_below_TCC1: OBLIGATION
    measurable_bounded_below?((LAMBDA n: LAMBDA x: 0));

  % Subtype TCC generated (at line 87, column 57) for  (LAMBDA n: LAMBDA x: 0)
      % expected type  measurable_bounded
  measurable_bounded_TCC1: OBLIGATION
    measurable_bounded?((LAMBDA n: LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 91, column 18) for  x
      % expected type  pointwise_bounded_above[T]
  measurable_bounded_above_is_bounded_above: OBLIGATION
    FORALL (x: measurable_bounded_above): pointwise_bounded_above?[T](x);

  % Judgement subtype TCC generated (at line 93, column 18) for  x
      % expected type  pointwise_bounded_below[T]
  measurable_bounded_below_is_bounded_below: OBLIGATION
    FORALL (x: measurable_bounded_below): pointwise_bounded_below?[T](x);

  % Judgement subtype TCC generated (at line 95, column 18) for  x
      % expected type  measurable_bounded_above
  measurable_bounded_is_measurable_bounded_above: OBLIGATION
    FORALL (x: measurable_bounded): measurable_bounded_above?(x);

  % Judgement subtype TCC generated (at line 97, column 18) for  x
      % expected type  measurable_bounded_below
  measurable_bounded_is_measurable_bounded_below: OBLIGATION
    FORALL (x: measurable_bounded): measurable_bounded_below?(x);

  % Judgement subtype TCC generated (at line 99, column 18) for  x
      % expected type  pointwise_bounded[T]
  measurable_bounded_is_bounded: OBLIGATION
    FORALL (x: measurable_bounded): pointwise_bounded?[T](x);

  % Subtype TCC generated (at line 113, column 40) for  (LAMBDA x: 0)
      % expected type  simple
  simple_TCC1: OBLIGATION simple?((LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 115, column 34) for  x
      % expected type  measurable_function[T, S]
  simple_is_measurable: OBLIGATION
    FORALL (x: simple): measurable_function?[T, S](x);

  % Subtype TCC generated (at line 119, column 46) for  (LAMBDA x: 0)
      % expected type  nn_simple
  nn_simple_TCC1: OBLIGATION nn_simple?((LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 121, column 33) for  x
      % expected type  simple
  nn_simple_is_simple: OBLIGATION FORALL (x: nn_simple): simple?(x);

  % Judgement subtype TCC generated (at line 126, column 29) for  sq(h)
      % expected type  simple
  simple_sq: OBLIGATION FORALL (h): simple?(sq[T](h));

  % Judgement subtype TCC generated (at line 127, column 29) for  h1 + h2
      % expected type  simple
  simple_add: OBLIGATION FORALL (h1, h2): simple?((+[T])(h1, h2));

  % Judgement subtype TCC generated (at line 128, column 29) for  c * h
      % expected type  simple
  simple_scal: OBLIGATION FORALL (c, h): simple?(*[T](c, h));

  % Judgement subtype TCC generated (at line 129, column 29) for  -h
      % expected type  simple
  simple_neg: OBLIGATION FORALL (h): simple?(-h);

  % Judgement subtype TCC generated (at line 130, column 29) for  h1 - h2
      % expected type  simple
  simple_diff: OBLIGATION FORALL (h1, h2): simple?((-[T])(h1, h2));

  % Judgement subtype TCC generated (at line 131, column 29) for  abs(h)
      % expected type  simple
  simple_abs: OBLIGATION FORALL (h): simple?(abs[T](h));

  % Judgement subtype TCC generated (at line 132, column 29) for  min(h1, h2)
      % expected type  simple
  simple_min: OBLIGATION FORALL (h1, h2): simple?(min[T](h1, h2));

  % Judgement subtype TCC generated (at line 133, column 29) for  max(h1, h2)
      % expected type  simple
  simple_max: OBLIGATION FORALL (h1, h2): simple?(max[T](h1, h2));

  % Judgement subtype TCC generated (at line 134, column 29) for  maximum(v, n)
      % expected type  simple
  simple_maximum: OBLIGATION FORALL (n, v): simple?(maximum[T](v, n));

  % Judgement subtype TCC generated (at line 135, column 29) for  minimum(v, n)
      % expected type  simple
  simple_minimum: OBLIGATION FORALL (n, v): simple?(minimum[T](v, n));

  % Judgement subtype TCC generated (at line 136, column 29) for  plus(h)
      % expected type  simple
  simple_plus: OBLIGATION FORALL (h): simple?(plus[T](h));

  % Judgement subtype TCC generated (at line 137, column 29) for  minus(h)
      % expected type  simple
  simple_minus: OBLIGATION FORALL (h): simple?(minus[T](h));

  % Judgement subtype TCC generated (at line 138, column 29) for  h1 * h2
      % expected type  simple
  simple_times: OBLIGATION FORALL (h1, h2): simple?(*[T](h1, h2));

  % Judgement subtype TCC generated (at line 139, column 29) for  expt(h, n)
      % expected type  simple
  simple_expt_nat: OBLIGATION FORALL (h, n): simple?(expt[T](h, n));

  % Subtype TCC generated (at line 140, column 31) for  h
      % expected type  [T -> nnreal]
  simple_expt_TCC1: OBLIGATION FORALL (h: nn_simple, x1: T): h(x1) >= 0;

  % Judgement subtype TCC generated (at line 140, column 29) for  h ^ a
      % expected type  simple
  simple_expt: OBLIGATION FORALL (a, h: nn_simple): simple?(^[T](h, a));

  % Judgement subtype TCC generated (at line 144, column 27) for  phi(X)
      % expected type  simple
  phi_is_simple: OBLIGATION FORALL (X: (S)): simple?(phi(X));

  % Subtype TCC generated (at line 165, column 64) for  (LAMBDA x: 0)
      % expected type  bounded_measurable
  bounded_measurable_TCC1: OBLIGATION bounded_measurable?((LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 168, column 30) for  x
      % expected type  bounded[T]
  bounded_measurable_is_bounded: OBLIGATION
    FORALL (x: bounded_measurable): bounded?[T](x);

  % Judgement subtype TCC generated (at line 170, column 30) for  x
      % expected type  measurable_function[T, S]
  bounded_measurable_is_measurable: OBLIGATION
    FORALL (x: bounded_measurable): measurable_function?[T, S](x);

  % Judgement subtype TCC generated (at line 172, column 30) for  x
      % expected type  bounded_measurable
  simple_is_bounded_measurable: OBLIGATION
    FORALL (x: simple): bounded_measurable?(x);

  % Subtype TCC generated (at line 177, column 54) for  (LAMBDA x: 0)
      % expected type  nn_bounded_measurable
  nn_bounded_measurable_TCC1: OBLIGATION
    nn_bounded_measurable?((LAMBDA x: 0));

  % Judgement subtype TCC generated (at line 180, column 28) for  x
      % expected type  bounded_measurable
  nn_bounded_measurable_is_bounded_measurable: OBLIGATION
    FORALL (x: nn_bounded_measurable): bounded_measurable?(x);

  % Subtype TCC generated (at line 186, column 57) for
      % (LAMBDA n: LAMBDA x: 0)
      % expected type  increasing_nn_simple
  increasing_nn_simple_TCC1: OBLIGATION
    increasing_nn_simple?((LAMBDA n: LAMBDA x: 0));

  % Subtype TCC generated (at line 195, column 13) for
      % {h |
      %    (FORALL x: 0 <= h(x) & h(x) <= p(x)) AND
      %     sup_norm(p - h) <= sup_norm(p) / 2}
      % expected type  p: (nonempty?[simple])
  nn_simple_approx_TCC1: OBLIGATION
    FORALL (p: nn_bounded_measurable):
      nonempty?[simple]
          ({h |
              (FORALL x: 0 <= h(x) & h(x) <= p(x)) AND
               sup_norm[T]((-[T])(p, h)) <= sup_norm[T](p) / 2});

  % Subtype TCC generated (at line 195, column 6) for
      % choose({h |
      %           (FORALL x: 0 <= h(x) & h(x) <= p(x)) AND
      %            sup_norm(p - h) <= sup_norm(p) / 2})
      % expected type  nn_simple
  nn_simple_approx_TCC2: OBLIGATION
    FORALL (p: nn_bounded_measurable):
      nn_simple?(choose[simple]
                     ({h |
                         (FORALL x: 0 <= h(x) & h(x) <= p(x)) AND
                          sup_norm[T]((-[T])(p, h)) <= sup_norm[T](p) / 2}));

  % Subtype TCC generated (at line 202, column 20) for  nn_simple_approx(p)
      % expected type  {h | FORALL x: 0 <= h(x) & h(x) <= p(x)}
  nn_simple_sequence_TCC1: OBLIGATION
    FORALL (p: nn_bounded_measurable, n: nat):
      n = 0 IMPLIES
       (FORALL x:
          0 <= nn_simple_approx(p)(x) & nn_simple_approx(p)(x) <= p(x));

  % Subtype TCC generated (at line 203, column 39) for
      % p - nn_simple_approx(p)
      % expected type  p: nn_bounded_measurable
  nn_simple_sequence_TCC2: OBLIGATION
    FORALL (p: nn_bounded_measurable, n: nat):
      NOT n = 0 IMPLIES
       nn_bounded_measurable?((-[T])(p, nn_simple_approx(p)));

  % Subtype TCC generated (at line 203, column 62) for  n - 1
      % expected type  nat
  nn_simple_sequence_TCC3: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Termination TCC generated (at line 203, column 20) for
      % nn_simple_sequence(p - nn_simple_approx(p))(n - 1)
  nn_simple_sequence_TCC4: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 203, column 20) for
      % nn_simple_sequence(p - nn_simple_approx(p))(n - 1)
      % expected type  {h | FORALL x: 0 <= h(x) & h(x) <= p(x)}
  nn_simple_sequence_TCC5: OBLIGATION
    FORALL (p: nn_bounded_measurable, n: nat):
      NOT n = 0 IMPLIES
       (FORALL x,
               (v:
                  [p1: nn_bounded_measurable ->
                     [{z: nat | z < n} ->
                        {h | FORALL x: 0 <= h(x) & h(x) <= p1(x)}]]):
          0 <= v((-[T])(p, nn_simple_approx(p)))(n - 1)(x) &
           v((-[T])(p, nn_simple_approx(p)))(n - 1)(x) <= p(x));

  % Subtype TCC generated (at line 207, column 62) for  w
      % expected type  sequence[bounded[T]]
  nn_bounded_measurable_as_increasing_simple_sequence_TCC1: OBLIGATION
    FORALL (w): FORALL (x1: nat): bounded?[T](w(x1));

  % Subtype TCC generated (at line 213, column 65) for  f
      % expected type  bounded[T]
  bounded_measurable_as_increasing_sequence_TCC1: OBLIGATION
    FORALL (f: [T -> real]): bounded_measurable?(f) IMPLIES bounded?[T](f);


