# TheoryBodies

body:
  %% taylor.pvs

  interval_taylor[(IMPORTING interval) X:StrictInterval]: THEORY
  BEGIN

    IMPORTING interval_deriv[X],
              reals@factorial,
              analysis@taylors[Xt]

    x,a,y : VAR Xt
    n     : VAR nat

    Taylor : THEOREM
      FORALL (f:(Diffn?(n)),DF:ARRAY[nat->Interval]):
        (FORALL (k:below(n)):Dn(k,f)(a) ## DF(k)) AND
        (FORALL (y):Dn(n,f)(y) ## DF(n))
        IMPLIES
        f(x) ## Sigma(0,n,LAMBDA(k:nat):(Div(Mult(DF(k),Pow(Sub(X,[|a|]),k)),[|factorial(k)|])))

    Midpoint: MACRO Interval =
      [|midpoint(X)|]

    F,DF,D2F : VAR [Interval->Interval]
    f        : VAR (Diff?)
    f2       : VAR (Diffn?(2))
    DF0      : VAR Interval

    Taylor1(F,DF,DF0) : Interval =
      Add(Mult(DF(DF0),Sub(X,Midpoint)),F(Midpoint))

    Taylor1_Midpoint : THEOREM
      f(midpoint(X)) ## F(Midpoint) AND
      (FORALL (y): D(f)(y) ## DF(X))
      IMPLIES
        f(x) ## Taylor1(F,DF,X)

    Taylor2(F,DF,D2F) : Interval =
      Add(Div(Mult(D2F(X),Sq(Sub(X,Midpoint))),[|2|]),Taylor1(F,DF,Midpoint))

    Taylor2_Midpoint : THEOREM
      f2(midpoint(X))    ## F(Midpoint)  AND
      D(f2)(midpoint(X)) ## DF(Midpoint) AND
      (FORALL (y): D(D(f2))(y) ## D2F(X))
      IMPLIES
        f2(x) ## Taylor2(F,DF,D2F)

  END interval_taylor

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

  % Assuming TCC generated (at line 8, column 12) for  analysis@taylors[Xt]
      % generated from assumption taylors.connected_domain
  IMP_taylors_TCC1: OBLIGATION connected?[Xt[X]];

  % Assuming TCC generated (at line 8, column 12) for  analysis@taylors[Xt]
      % generated from assumption taylors.not_one_element
  IMP_taylors_TCC2: OBLIGATION not_one_element?[Xt[X]];

  % Subtype TCC generated (at line 15, column 32) for  f
      % expected type  (Diffn?(k))
  Taylor_TCC1: OBLIGATION
    FORALL (n: nat, f: (Diffn?[X](n)), k: below(n)): Diffn?[X](k)(f);

  % Subtype TCC generated (at line 42, column 6) for  f2
      % expected type  (Diff?)
  Taylor2_Midpoint_TCC1: OBLIGATION
    FORALL (F: [Interval -> Interval], f2: (Diffn?(2))):
      f2(midpoint(X)) ## F([|midpoint(X)|]) IMPLIES Diff?[X](f2);

  % Subtype TCC generated (at line 43, column 19) for  D(f2)
      % expected type  (Diff?)
  Taylor2_Midpoint_TCC2: OBLIGATION
    FORALL (DF, F: [Interval -> Interval], f2: (Diffn?(2))):
      f2(midpoint(X)) ## F([|midpoint(X)|]) AND
       D(f2)(midpoint(X)) ## DF([|midpoint(X)|])
       IMPLIES (FORALL (y: Xt[X]): Diff?[X](D[X](f2)));


body:
  %% interval_chain.pvs

  interval_chain[(IMPORTING interval) X,Y:(StrictInterval?)]: THEORY
  BEGIN

    IMPORTING interval_deriv

    XT : TYPE = Xt[X]
    YT : TYPE = Xt[Y] 

    IMPORTING analysis@chain_rule[XT,YT]
   
    Closed?(f:(Diff?[X])) : MACRO bool = 
      FORALL(t:XT): f(t) ## Y

    f : VAR (Closed?)
    g : VAR (Diff?[Y])
    t : VAR XT

    Diff_comp   : LEMMA Diff?(LAMBDA(t):g(f(t))) 

    Deriv_comp  : LEMMA D(LAMBDA(t):g(f(t))) = 
                        LAMBDA(t):(D(g)(f(t))*D(f)(t))

  END interval_chain

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

  % Assuming TCC generated (at line 11, column 12) for
      % analysis@chain_rule[XT, YT]
      % generated from assumption chain_rule.deriv_domain1
  IMP_chain_rule_TCC1: OBLIGATION deriv_domain?[XT];

  % Assuming TCC generated (at line 11, column 12) for
      % analysis@chain_rule[XT, YT]
      % generated from assumption chain_rule.not_one_element1
  IMP_chain_rule_TCC2: OBLIGATION not_one_element?[XT];

  % Assuming TCC generated (at line 11, column 12) for
      % analysis@chain_rule[XT, YT]
      % generated from assumption chain_rule.deriv_domain2
  IMP_chain_rule_TCC3: OBLIGATION deriv_domain?[YT];

  % Assuming TCC generated (at line 11, column 12) for
      % analysis@chain_rule[XT, YT]
      % generated from assumption chain_rule.not_one_element2
  IMP_chain_rule_TCC4: OBLIGATION not_one_element?[YT];

  % Subtype TCC generated (at line 20, column 40) for  f(t)
      % expected type  Xt[Y]
  Diff_comp_TCC1: OBLIGATION
    FORALL (f: (LAMBDA (f: (Diff?[X])): FORALL (t: XT): f(t) ## Y), t: XT):
      f(t) ## Y;

  % Subtype TCC generated (at line 22, column 24) for  LAMBDA (t): g(f(t))
      % expected type  (Diff?[X])
  Deriv_comp_TCC1: OBLIGATION
    FORALL (f: (LAMBDA (f: (Diff?[X])): FORALL (t: XT): f(t) ## Y),
            g: (Diff?[Y])):
      Diff?[X](LAMBDA (t): g(f(t)));


body:
  %% subinterval_deriv.pvs

  subinterval_deriv : THEORY
  BEGIN

    IMPORTING interval_deriv, analysis@deriv_domain

    n : VAR nat 

    deriv_domain_Xt: LEMMA FORALL(X:(StrictInterval?)): deriv_domain?[Xt[X]]

    subinterval_deriv : LEMMA
      FORALL(X,Y:(StrictInterval?),f:[Xt[X]->real]):
        Y << X AND
        Diff?(f) IMPLIES
        (Diff?(LAMBDA(x:Xt[Y]):f(x)) AND
         D(LAMBDA(x:Xt[Y]):f(x)) = LAMBDA(x:Xt[Y]):D(f)(x)) 

    subinterval_derivn : LEMMA
      FORALL(X,Y:(StrictInterval?),f:[Xt[X]->real]):
        Y << X AND
        Diffn?(n)(f) IMPLIES
        (Diffn?(n)(LAMBDA(x:Xt[Y]):f(x)) AND
         Dn(n,LAMBDA(x:Xt[Y]):f(x)) = LAMBDA(x:Xt[Y]):Dn(n,f)(x)) 
      

  END subinterval_deriv

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

  % Subtype TCC generated (at line 16, column 31) for  x
      % expected type  Xt[X]
  subinterval_deriv_TCC1: OBLIGATION
    FORALL (X, Y: (StrictInterval?), f: [Xt[X] -> real]):
      Y << X AND Diff?(f) IMPLIES (FORALL (x: Xt[Y]): x ## X);

  % Subtype TCC generated (at line 23, column 35) for  x
      % expected type  Xt[X]
  subinterval_derivn_TCC1: OBLIGATION
    FORALL (n: nat, X, Y: (StrictInterval?), f: [Xt[X] -> real]):
      Y << X AND Diffn?(n)(f) IMPLIES (FORALL (x: Xt[Y]): x ## X);


body:
  %% interval_bolzano.pvs
  %%
  %% This theory was originally defined in the reals library in collaboration 
  %% with J. Fleuriot. It was moved to the interval package by C. Munoz on 
  %% March 28 2005.
  %%----------------------------------------------------------------------------

  interval_bolzano : THEORY
  BEGIN
    IMPORTING interval,reals@log_nat,reals@sqrt

    eps   : VAR posreal
    Prop? : VAR PRED[(Proper?)]
    X,Y   : VAR (Proper?)
    x     : VAR nnreal

    Continuous?(Prop?): bool =
      FORALL(X:(Prop?)): Prop?(HalfLeft(X)) OR Prop?(HalfRight(X))

    % Returns a subinterval of X of size less than eps that satisfies Prop? 
    bolzano_bisect((Prop?:(Continuous?)),(X:(Prop?)),eps) : RECURSIVE 
      {Y | Y << X AND Prop?(Y) AND size(Y) <= eps} =
      if size(X) < eps then X
      else 
        let Y1 = HalfLeft(X) in
        let Y2 = HalfRight(X) in
        if Prop?(Y1) then
          bolzano_bisect(Prop?,Y1,eps)
        else 
          bolzano_bisect(Prop?,Y2,eps)
        endif 
      endif
    measure if size(X) < eps then 0 else 1+log_nat(size(X)/eps,2)`1 endif

    SqrtProp?(x)(X):bool = sq(lb(X)) <= x AND x <= sq(ub(X))

    SqrtProp : JUDGEMENT
     SqrtProp?(x) HAS_TYPE (Continuous?)

    % Alternative definition of square root using the bisection method
    sqrt_bisect(x,eps) : (NonNeg?) =
      bolzano_bisect(SqrtProp?(x),[|0,max(1,x)|],eps)

    sqrt_bisect_inclusion : LEMMA
      sqrt(x) ## sqrt_bisect(x,eps) 

  END interval_bolzano

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

  % Subtype TCC generated (at line 33, column 49) for  size(X) / eps
      % expected type  {x: real | x >= 1}
  bolzano_bisect_TCC1: OBLIGATION
    FORALL ((Prop?: (Continuous?)), (X: (Prop?)), eps: posreal):
      NOT size(X) < eps IMPLIES size(X) / eps >= 1;

  % Subtype TCC generated (at line 33, column 49) for  size(z`2) / z`3
      % expected type  {x: real | x >= 1}
  bolzano_bisect_TCC2: OBLIGATION
    FORALL (z: [Prop?: (Continuous?), (Prop?), posreal]):
      NOT size(z`2) < z`3 IMPLIES size(z`2) / z`3 >= 1;

  % Subtype TCC generated (at line 23, column 26) for  X
      % expected type  {Y | Y << X AND Prop?(Y) AND size(Y) <= eps}
  bolzano_bisect_TCC3: OBLIGATION
    FORALL ((Prop?: (Continuous?)), (X: (Prop?)), eps: posreal):
      size(X) < eps IMPLIES X << X AND Prop?(X) AND size(X) <= eps;

  % Termination TCC generated (at line 28, column 8) for
      % bolzano_bisect(Prop?, Y1, eps)
  bolzano_bisect_TCC4: OBLIGATION
    FORALL ((Prop?: (Continuous?)), (X: (Prop?)), eps: posreal):
      NOT size(X) < eps IMPLIES
       (FORALL (Y1: ProperInterval):
          Y1 = HalfLeft(X) IMPLIES
           (FORALL (Y2: ProperInterval):
              Prop?(Y1) AND Y2 = HalfRight(X) IMPLIES
               IF size(Y1) < eps THEN 0
               ELSE 1 + log_nat(size(Y1) / eps, 2)`1
               ENDIF
                <
                IF size(X) < eps THEN 0
                ELSE 1 + log_nat(size(X) / eps, 2)`1
                ENDIF));

  % Subtype TCC generated (at line 28, column 8) for
      % bolzano_bisect(Prop?, Y1, eps)
      % expected type  {Y | Y << X AND Prop?(Y) AND size(Y) <= eps}
  bolzano_bisect_TCC5: OBLIGATION
    FORALL ((Prop?: (Continuous?)), (X: (Prop?)), eps: posreal,
            v:
              [d1:
                 {z: [Prop?: (Continuous?), (Prop?), posreal] |
                          IF size(z`2) < z`3 THEN 0
                          ELSE 1 + log_nat(size(z`2) / z`3, 2)`1
                          ENDIF
                           <
                           IF size(X) < eps THEN 0
                           ELSE 1 + log_nat(size(X) / eps, 2)`1
                           ENDIF} ->
                 {Y | Y << d1`2 AND d1`1(Y) AND size(Y) <= d1`3}]):
      NOT size(X) < eps IMPLIES
       (FORALL (Y1: ProperInterval):
          Y1 = HalfLeft(X) IMPLIES
           (FORALL (Y2: ProperInterval):
              Prop?(Y1) AND Y2 = HalfRight(X) IMPLIES
               v(Prop?, Y1, eps) << X AND
                Prop?(v(Prop?, Y1, eps)) AND size(v(Prop?, Y1, eps)) <= eps));

  % Subtype TCC generated (at line 30, column 29) for  Y2
      % expected type  (Prop?)
  bolzano_bisect_TCC6: OBLIGATION
    FORALL ((Prop?: (Continuous?)), (X: (Prop?)), eps: posreal):
      NOT size(X) < eps IMPLIES
       (FORALL (Y1: ProperInterval):
          Y1 = HalfLeft(X) IMPLIES
           (FORALL (Y2: ProperInterval):
              NOT Prop?(Y1) AND Y2 = HalfRight(X) IMPLIES Prop?(Y2)));

  % Termination TCC generated (at line 30, column 8) for
      % bolzano_bisect(Prop?, Y2, eps)
  bolzano_bisect_TCC7: OBLIGATION
    FORALL ((Prop?: (Continuous?)), (X: (Prop?)), eps: posreal):
      NOT size(X) < eps IMPLIES
       (FORALL (Y1: ProperInterval):
          Y1 = HalfLeft(X) IMPLIES
           (FORALL (Y2: ProperInterval):
              NOT Prop?(Y1) AND Y2 = HalfRight(X) IMPLIES
               IF size(Y2) < eps THEN 0
               ELSE 1 + log_nat(size(Y2) / eps, 2)`1
               ENDIF
                <
                IF size(X) < eps THEN 0
                ELSE 1 + log_nat(size(X) / eps, 2)`1
                ENDIF));

  % Subtype TCC generated (at line 30, column 8) for
      % bolzano_bisect(Prop?, Y2, eps)
      % expected type  {Y | Y << X AND Prop?(Y) AND size(Y) <= eps}
  bolzano_bisect_TCC8: OBLIGATION
    FORALL ((Prop?: (Continuous?)), (X: (Prop?)), eps: posreal,
            v:
              [d1:
                 {z: [Prop?: (Continuous?), (Prop?), posreal] |
                          IF size(z`2) < z`3 THEN 0
                          ELSE 1 + log_nat(size(z`2) / z`3, 2)`1
                          ENDIF
                           <
                           IF size(X) < eps THEN 0
                           ELSE 1 + log_nat(size(X) / eps, 2)`1
                           ENDIF} ->
                 {Y | Y << d1`2 AND d1`1(Y) AND size(Y) <= d1`3}]):
      NOT size(X) < eps IMPLIES
       (FORALL (Y1: ProperInterval):
          Y1 = HalfLeft(X) IMPLIES
           (FORALL (Y2: ProperInterval):
              NOT Prop?(Y1) AND Y2 = HalfRight(X) IMPLIES
               v(Prop?, Y2, eps) << X AND
                Prop?(v(Prop?, Y2, eps)) AND size(v(Prop?, Y2, eps)) <= eps));

  % Judgement subtype TCC generated (at line 38, column 3) for  SqrtProp?(x)
      % expected type  (Continuous?)
  SqrtProp: OBLIGATION FORALL (x): Continuous?(SqrtProp?(x));

  % Subtype TCC generated (at line 42, column 32) for  [|0, max(1, x)|]
      % expected type  (SqrtProp?(x))
  sqrt_bisect_TCC1: OBLIGATION
    FORALL (x: nnreal):
      Proper?([|0, max(1, x)|]) AND SqrtProp?(x)([|0, max(1, x)|]);

  % Subtype TCC generated (at line 42, column 4) for
      % bolzano_bisect(SqrtProp?(x), [|0, max(1, x)|], eps)
      % expected type  (NonNeg?)
  sqrt_bisect_TCC2: OBLIGATION
    FORALL (x: nnreal, eps: posreal):
      NonNeg?(bolzano_bisect(SqrtProp?(x), [|0, max(1, x)|], eps));


body:
  %%% ADT file generated from IntervalExpr

  IntervalExpr_adt: THEORY
   BEGIN

    IntervalExpr: TYPE

    IMPORTING interval

    IMPORTING structures@Unit

    IMPORTING reals@real_orders

    const?, varidx?, add?, abs?, neg?, sub?, mult?, sq?, pow?, div?, fun?,
    letin?, bconst?, bnot?, band?, bor?, bimplies?, brel?, bincludes?, bite?,
    bletin?: [IntervalExpr -> boolean]

    RealExpr(x: IntervalExpr):  boolean =
            const?(x) OR varidx?(x) OR add?(x) OR abs?(x) OR neg?(x)
         OR sub?(x) OR mult?(x) OR sq?(x) OR pow?(x) OR div?(x) OR fun?(x)
         OR letin?(x);

    RealExpr: TYPE =
          {x: IntervalExpr |
                       const?(x) OR varidx?(x) OR add?(x) OR abs?(x)
                    OR neg?(x) OR sub?(x) OR mult?(x) OR sq?(x) OR pow?(x)
                    OR div?(x) OR fun?(x) OR letin?(x)}

    BoolExpr(x: IntervalExpr):  boolean =
            bconst?(x) OR bnot?(x) OR band?(x) OR bor?(x) OR bimplies?(x)
         OR brel?(x) OR bincludes?(x) OR bite?(x) OR bletin?(x);

    BoolExpr: TYPE =
          {x: IntervalExpr |
                       bconst?(x) OR bnot?(x) OR band?(x) OR bor?(x)
                    OR bimplies?(x) OR brel?(x) OR bincludes?(x) OR bite?(x)
                    OR bletin?(x)}

    JUDGEMENT (const?) SUBTYPE_OF RealExpr

    JUDGEMENT (varidx?) SUBTYPE_OF RealExpr

    JUDGEMENT (add?) SUBTYPE_OF RealExpr

    JUDGEMENT (abs?) SUBTYPE_OF RealExpr

    JUDGEMENT (neg?) SUBTYPE_OF RealExpr

    JUDGEMENT (sub?) SUBTYPE_OF RealExpr

    JUDGEMENT (mult?) SUBTYPE_OF RealExpr

    JUDGEMENT (sq?) SUBTYPE_OF RealExpr

    JUDGEMENT (pow?) SUBTYPE_OF RealExpr

    JUDGEMENT (div?) SUBTYPE_OF RealExpr

    JUDGEMENT (fun?) SUBTYPE_OF RealExpr

    JUDGEMENT (letin?) SUBTYPE_OF RealExpr

    JUDGEMENT (bconst?) SUBTYPE_OF BoolExpr

    JUDGEMENT (bnot?) SUBTYPE_OF BoolExpr

    JUDGEMENT (band?) SUBTYPE_OF BoolExpr

    JUDGEMENT (bor?) SUBTYPE_OF BoolExpr

    JUDGEMENT (bimplies?) SUBTYPE_OF BoolExpr

    JUDGEMENT (brel?) SUBTYPE_OF BoolExpr

    JUDGEMENT (bincludes?) SUBTYPE_OF BoolExpr

    JUDGEMENT (bite?) SUBTYPE_OF BoolExpr

    JUDGEMENT (bletin?) SUBTYPE_OF BoolExpr

    opc: [(const?) -> [Unit -> real]]

    opC: [d: (const?) -> (Includes?(opc(d)(unit)))]

    varidx: [(varidx?) -> nat]

    op1:
          [{x: IntervalExpr |
                        brel?(x) OR div?(x) OR mult?(x) OR sub?(x)
                     OR add?(x)} ->
             RealExpr]

    op2:
          [{x: IntervalExpr |
                        brel?(x) OR div?(x) OR mult?(x) OR sub?(x)
                     OR add?(x)} ->
             RealExpr]

    op:
          [{x: IntervalExpr |
                        bincludes?(x) OR fun?(x) OR pow?(x) OR sq?(x)
                     OR neg?(x) OR abs?(x)} ->
             RealExpr]

    opn: [(pow?) -> nat]

    pre: [(fun?) -> (Precondition?)]

    opf: [(fun?) -> [real -> real]]

    opF:
          [d: (fun?) ->
             {F: [Interval -> Interval] |
                      Inclusion?(pre(d), opf(d))(F) AND
                       Fundamental?(pre(d))(F)}]

    rlet: [(letin?) -> RealExpr]

    rin: [(letin?) -> RealExpr]

    opb: [(bconst?) -> boolean]

    bop: [(bnot?) -> BoolExpr]

    bop1:
          [{x: IntervalExpr | bimplies?(x) OR bor?(x) OR band?(x)} ->
             BoolExpr]

    bop2:
          [{x: IntervalExpr | bimplies?(x) OR bor?(x) OR band?(x)} ->
             BoolExpr]

    rel: [(brel?) -> RealOrder]

    opi: [(bincludes?) -> Interval]

    bif: [(bite?) -> BoolExpr]

    bthen: [(bite?) -> BoolExpr]

    belse: [(bite?) -> BoolExpr]

    blet: [(bletin?) -> IntervalExpr]

    bin: [(bletin?) -> BoolExpr]

    CONST: [[opc: [Unit -> real], (Includes?(opc(unit)))] -> (const?)]

    VARIDX: [nat -> (varidx?)]

    ADD: [[RealExpr, RealExpr] -> (add?)]

    ABS: [RealExpr -> (abs?)]

    NEG: [RealExpr -> (neg?)]

    SUB: [[RealExpr, RealExpr] -> (sub?)]

    MULT: [[RealExpr, RealExpr] -> (mult?)]

    SQ: [RealExpr -> (sq?)]

    POW: [[RealExpr, nat] -> (pow?)]

    DIV: [[RealExpr, RealExpr] -> (div?)]

    FUN:
          [[pre: (Precondition?), opf: [real -> real],
            {F: [Interval -> Interval] |
                     Inclusion?(pre, opf)(F) AND Fundamental?(pre)(F)},
            RealExpr] ->
             (fun?)]

    LETIN: [[RealExpr, RealExpr] -> (letin?)]

    BCONST: [boolean -> (bconst?)]

    BNOT: [BoolExpr -> (bnot?)]

    BAND: [[BoolExpr, BoolExpr] -> (band?)]

    BOR: [[BoolExpr, BoolExpr] -> (bor?)]

    BIMPLIES: [[BoolExpr, BoolExpr] -> (bimplies?)]

    BREL: [[RealOrder, RealExpr, RealExpr] -> (brel?)]

    BINCLUDES: [[RealExpr, Interval] -> (bincludes?)]

    BITE: [[BoolExpr, BoolExpr, BoolExpr] -> (bite?)]

    BLETIN: [[IntervalExpr, BoolExpr] -> (bletin?)]

    IntervalExpr_ord: [IntervalExpr -> upto(20)]

    IntervalExpr_ord_defaxiom: AXIOM
           (FORALL (opc: [Unit -> real], opC: (Includes?(opc(unit)))):
              IntervalExpr_ord(CONST(opc, opC)) = 0)
       AND (FORALL (varidx: nat): IntervalExpr_ord(VARIDX(varidx)) = 1)
       AND (FORALL (op1: RealExpr, op2: RealExpr):
              IntervalExpr_ord(ADD(op1, op2)) = 2)
       AND (FORALL (op: RealExpr): IntervalExpr_ord(ABS(op)) = 3)
       AND (FORALL (op: RealExpr): IntervalExpr_ord(NEG(op)) = 4)
       AND (FORALL (op1: RealExpr, op2: RealExpr):
              IntervalExpr_ord(SUB(op1, op2)) = 5)
       AND (FORALL (op1: RealExpr, op2: RealExpr):
              IntervalExpr_ord(MULT(op1, op2)) = 6)
       AND (FORALL (op: RealExpr): IntervalExpr_ord(SQ(op)) = 7)
       AND (FORALL (op: RealExpr, opn: nat):
              IntervalExpr_ord(POW(op, opn)) = 8)
       AND (FORALL (op1: RealExpr, op2: RealExpr):
              IntervalExpr_ord(DIV(op1, op2)) = 9)
       AND (FORALL (pre: (Precondition?), opf: [real -> real],
                    opF:
                      {F: [Interval -> Interval] |
                               Inclusion?(pre, opf)(F) AND
                                Fundamental?(pre)(F)},
                    op: RealExpr):
              IntervalExpr_ord(FUN(pre, opf, opF, op)) = 10)
       AND (FORALL (rlet: RealExpr, rin: RealExpr):
              IntervalExpr_ord(LETIN(rlet, rin)) = 11)
       AND (FORALL (opb: bool): IntervalExpr_ord(BCONST(opb)) = 12)
       AND (FORALL (bop: BoolExpr): IntervalExpr_ord(BNOT(bop)) = 13)
       AND (FORALL (bop1: BoolExpr, bop2: BoolExpr):
              IntervalExpr_ord(BAND(bop1, bop2)) = 14)
       AND (FORALL (bop1: BoolExpr, bop2: BoolExpr):
              IntervalExpr_ord(BOR(bop1, bop2)) = 15)
       AND (FORALL (bop1: BoolExpr, bop2: BoolExpr):
              IntervalExpr_ord(BIMPLIES(bop1, bop2)) = 16)
       AND (FORALL (rel: RealOrder, op1: RealExpr, op2: RealExpr):
              IntervalExpr_ord(BREL(rel, op1, op2)) = 17)
       AND (FORALL (op: RealExpr, opi: Interval):
              IntervalExpr_ord(BINCLUDES(op, opi)) = 18)
       AND (FORALL (bif: BoolExpr, bthen: BoolExpr, belse: BoolExpr):
              IntervalExpr_ord(BITE(bif, bthen, belse)) = 19)
       AND (FORALL (blet: IntervalExpr, bin: BoolExpr):
              IntervalExpr_ord(BLETIN(blet, bin)) = 20);

    ord(x: IntervalExpr): [IntervalExpr -> upto(20)] =
        CASES x
          OF CONST(CONST1_var, CONST2_var): 0,
             VARIDX(VARIDX1_var): 1,
             ADD(ADD1_var, ADD2_var): 2,
             ABS(ABS1_var): 3,
             NEG(NEG1_var): 4,
             SUB(SUB1_var, SUB2_var): 5,
             MULT(MULT1_var, MULT2_var): 6,
             SQ(SQ1_var): 7,
             POW(POW1_var, POW2_var): 8,
             DIV(DIV1_var, DIV2_var): 9,
             FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var): 10,
             LETIN(LETIN1_var, LETIN2_var): 11,
             BCONST(BCONST1_var): 12,
             BNOT(BNOT1_var): 13,
             BAND(BAND1_var, BAND2_var): 14,
             BOR(BOR1_var, BOR2_var): 15,
             BIMPLIES(BIMPLIES1_var, BIMPLIES2_var): 16,
             BREL(BREL1_var, BREL2_var, BREL3_var): 17,
             BINCLUDES(BINCLUDES1_var, BINCLUDES2_var): 18,
             BITE(BITE1_var, BITE2_var, BITE3_var): 19,
             BLETIN(BLETIN1_var, BLETIN2_var): 20
          ENDCASES

    IntervalExpr_CONST_extensionality: AXIOM
      FORALL (const?_var: (const?), const?_var2: (const?)):
        opc(const?_var) = opc(const?_var2) AND
         opC(const?_var) = opC(const?_var2)
         IMPLIES const?_var = const?_var2;

    IntervalExpr_CONST_eta: AXIOM
      FORALL (const?_var: (const?)):
        CONST(opc(const?_var), opC(const?_var)) = const?_var;

    IntervalExpr_VARIDX_extensionality: AXIOM
      FORALL (varidx?_var: (varidx?), varidx?_var2: (varidx?)):
        varidx(varidx?_var) = varidx(varidx?_var2) IMPLIES
         varidx?_var = varidx?_var2;

    IntervalExpr_VARIDX_eta: AXIOM
      FORALL (varidx?_var: (varidx?)):
        VARIDX(varidx(varidx?_var)) = varidx?_var;

    IntervalExpr_ADD_extensionality: AXIOM
      FORALL (add?_var: (add?), add?_var2: (add?)):
        op1(add?_var) = op1(add?_var2) AND op2(add?_var) = op2(add?_var2)
         IMPLIES add?_var = add?_var2;

    IntervalExpr_ADD_eta: AXIOM
      FORALL (add?_var: (add?)): ADD(op1(add?_var), op2(add?_var)) = add?_var;

    IntervalExpr_ABS_extensionality: AXIOM
      FORALL (abs?_var: (abs?), abs?_var2: (abs?)):
        op(abs?_var) = op(abs?_var2) IMPLIES abs?_var = abs?_var2;

    IntervalExpr_ABS_eta: AXIOM
      FORALL (abs?_var: (abs?)): ABS(op(abs?_var)) = abs?_var;

    IntervalExpr_NEG_extensionality: AXIOM
      FORALL (neg?_var: (neg?), neg?_var2: (neg?)):
        op(neg?_var) = op(neg?_var2) IMPLIES neg?_var = neg?_var2;

    IntervalExpr_NEG_eta: AXIOM
      FORALL (neg?_var: (neg?)): NEG(op(neg?_var)) = neg?_var;

    IntervalExpr_SUB_extensionality: AXIOM
      FORALL (sub?_var: (sub?), sub?_var2: (sub?)):
        op1(sub?_var) = op1(sub?_var2) AND op2(sub?_var) = op2(sub?_var2)
         IMPLIES sub?_var = sub?_var2;

    IntervalExpr_SUB_eta: AXIOM
      FORALL (sub?_var: (sub?)): SUB(op1(sub?_var), op2(sub?_var)) = sub?_var;

    IntervalExpr_MULT_extensionality: AXIOM
      FORALL (mult?_var: (mult?), mult?_var2: (mult?)):
        op1(mult?_var) = op1(mult?_var2) AND op2(mult?_var) = op2(mult?_var2)
         IMPLIES mult?_var = mult?_var2;

    IntervalExpr_MULT_eta: AXIOM
      FORALL (mult?_var: (mult?)):
        MULT(op1(mult?_var), op2(mult?_var)) = mult?_var;

    IntervalExpr_SQ_extensionality: AXIOM
      FORALL (sq?_var: (sq?), sq?_var2: (sq?)):
        op(sq?_var) = op(sq?_var2) IMPLIES sq?_var = sq?_var2;

    IntervalExpr_SQ_eta: AXIOM
      FORALL (sq?_var: (sq?)): SQ(op(sq?_var)) = sq?_var;

    IntervalExpr_POW_extensionality: AXIOM
      FORALL (pow?_var: (pow?), pow?_var2: (pow?)):
        op(pow?_var) = op(pow?_var2) AND opn(pow?_var) = opn(pow?_var2)
         IMPLIES pow?_var = pow?_var2;

    IntervalExpr_POW_eta: AXIOM
      FORALL (pow?_var: (pow?)): POW(op(pow?_var), opn(pow?_var)) = pow?_var;

    IntervalExpr_DIV_extensionality: AXIOM
      FORALL (div?_var: (div?), div?_var2: (div?)):
        op1(div?_var) = op1(div?_var2) AND op2(div?_var) = op2(div?_var2)
         IMPLIES div?_var = div?_var2;

    IntervalExpr_DIV_eta: AXIOM
      FORALL (div?_var: (div?)): DIV(op1(div?_var), op2(div?_var)) = div?_var;

    IntervalExpr_FUN_extensionality: AXIOM
      FORALL (fun?_var: (fun?), fun?_var2: (fun?)):
        pre(fun?_var) = pre(fun?_var2) AND
         opf(fun?_var) = opf(fun?_var2) AND
          opF(fun?_var) = opF(fun?_var2) AND op(fun?_var) = op(fun?_var2)
         IMPLIES fun?_var = fun?_var2;

    IntervalExpr_FUN_eta: AXIOM
      FORALL (fun?_var: (fun?)):
        FUN(pre(fun?_var), opf(fun?_var), opF(fun?_var), op(fun?_var)) =
         fun?_var;

    IntervalExpr_LETIN_extensionality: AXIOM
      FORALL (letin?_var: (letin?), letin?_var2: (letin?)):
        rlet(letin?_var) = rlet(letin?_var2) AND
         rin(letin?_var) = rin(letin?_var2)
         IMPLIES letin?_var = letin?_var2;

    IntervalExpr_LETIN_eta: AXIOM
      FORALL (letin?_var: (letin?)):
        LETIN(rlet(letin?_var), rin(letin?_var)) = letin?_var;

    IntervalExpr_BCONST_extensionality: AXIOM
      FORALL (bconst?_var: (bconst?), bconst?_var2: (bconst?)):
        opb(bconst?_var) = opb(bconst?_var2) IMPLIES
         bconst?_var = bconst?_var2;

    IntervalExpr_BCONST_eta: AXIOM
      FORALL (bconst?_var: (bconst?)): BCONST(opb(bconst?_var)) = bconst?_var;

    IntervalExpr_BNOT_extensionality: AXIOM
      FORALL (bnot?_var: (bnot?), bnot?_var2: (bnot?)):
        bop(bnot?_var) = bop(bnot?_var2) IMPLIES bnot?_var = bnot?_var2;

    IntervalExpr_BNOT_eta: AXIOM
      FORALL (bnot?_var: (bnot?)): BNOT(bop(bnot?_var)) = bnot?_var;

    IntervalExpr_BAND_extensionality: AXIOM
      FORALL (band?_var: (band?), band?_var2: (band?)):
        bop1(band?_var) = bop1(band?_var2) AND
         bop2(band?_var) = bop2(band?_var2)
         IMPLIES band?_var = band?_var2;

    IntervalExpr_BAND_eta: AXIOM
      FORALL (band?_var: (band?)):
        BAND(bop1(band?_var), bop2(band?_var)) = band?_var;

    IntervalExpr_BOR_extensionality: AXIOM
      FORALL (bor?_var: (bor?), bor?_var2: (bor?)):
        bop1(bor?_var) = bop1(bor?_var2) AND bop2(bor?_var) = bop2(bor?_var2)
         IMPLIES bor?_var = bor?_var2;

    IntervalExpr_BOR_eta: AXIOM
      FORALL (bor?_var: (bor?)):
        BOR(bop1(bor?_var), bop2(bor?_var)) = bor?_var;

    IntervalExpr_BIMPLIES_extensionality: AXIOM
      FORALL (bimplies?_var: (bimplies?), bimplies?_var2: (bimplies?)):
        bop1(bimplies?_var) = bop1(bimplies?_var2) AND
         bop2(bimplies?_var) = bop2(bimplies?_var2)
         IMPLIES bimplies?_var = bimplies?_var2;

    IntervalExpr_BIMPLIES_eta: AXIOM
      FORALL (bimplies?_var: (bimplies?)):
        BIMPLIES(bop1(bimplies?_var), bop2(bimplies?_var)) = bimplies?_var;

    IntervalExpr_BREL_extensionality: AXIOM
      FORALL (brel?_var: (brel?), brel?_var2: (brel?)):
        rel(brel?_var) = rel(brel?_var2) AND
         op1(brel?_var) = op1(brel?_var2) AND
          op2(brel?_var) = op2(brel?_var2)
         IMPLIES brel?_var = brel?_var2;

    IntervalExpr_BREL_eta: AXIOM
      FORALL (brel?_var: (brel?)):
        BREL(rel(brel?_var), op1(brel?_var), op2(brel?_var)) = brel?_var;

    IntervalExpr_BINCLUDES_extensionality: AXIOM
      FORALL (bincludes?_var: (bincludes?), bincludes?_var2: (bincludes?)):
        op(bincludes?_var) = op(bincludes?_var2) AND
         opi(bincludes?_var) = opi(bincludes?_var2)
         IMPLIES bincludes?_var = bincludes?_var2;

    IntervalExpr_BINCLUDES_eta: AXIOM
      FORALL (bincludes?_var: (bincludes?)):
        BINCLUDES(op(bincludes?_var), opi(bincludes?_var)) = bincludes?_var;

    IntervalExpr_BITE_extensionality: AXIOM
      FORALL (bite?_var: (bite?), bite?_var2: (bite?)):
        bif(bite?_var) = bif(bite?_var2) AND
         bthen(bite?_var) = bthen(bite?_var2) AND
          belse(bite?_var) = belse(bite?_var2)
         IMPLIES bite?_var = bite?_var2;

    IntervalExpr_BITE_eta: AXIOM
      FORALL (bite?_var: (bite?)):
        BITE(bif(bite?_var), bthen(bite?_var), belse(bite?_var)) = bite?_var;

    IntervalExpr_BLETIN_extensionality: AXIOM
      FORALL (bletin?_var: (bletin?), bletin?_var2: (bletin?)):
        blet(bletin?_var) = blet(bletin?_var2) AND
         bin(bletin?_var) = bin(bletin?_var2)
         IMPLIES bletin?_var = bletin?_var2;

    IntervalExpr_BLETIN_eta: AXIOM
      FORALL (bletin?_var: (bletin?)):
        BLETIN(blet(bletin?_var), bin(bletin?_var)) = bletin?_var;

    IntervalExpr_opc_CONST: AXIOM
      FORALL (CONST1_var: [Unit -> real],
              CONST2_var: (Includes?(CONST1_var(unit)))):
        opc(CONST(CONST1_var, CONST2_var)) = CONST1_var;

    IntervalExpr_opC_CONST: AXIOM
      FORALL (CONST1_var: [Unit -> real],
              CONST2_var: (Includes?(CONST1_var(unit)))):
        opC(CONST(CONST1_var, CONST2_var)) = CONST2_var;

    IntervalExpr_varidx_VARIDX: AXIOM
      FORALL (VARIDX1_var: nat): varidx(VARIDX(VARIDX1_var)) = VARIDX1_var;

    IntervalExpr_op1_ADD: AXIOM
      FORALL (ADD1_var: RealExpr, ADD2_var: RealExpr):
        op1(ADD(ADD1_var, ADD2_var)) = ADD1_var;

    IntervalExpr_op2_ADD: AXIOM
      FORALL (ADD1_var: RealExpr, ADD2_var: RealExpr):
        op2(ADD(ADD1_var, ADD2_var)) = ADD2_var;

    IntervalExpr_op_ABS: AXIOM
      FORALL (ABS1_var: RealExpr): op(ABS(ABS1_var)) = ABS1_var;

    IntervalExpr_op_NEG: AXIOM
      FORALL (NEG1_var: RealExpr): op(NEG(NEG1_var)) = NEG1_var;

    IntervalExpr_op1_SUB: AXIOM
      FORALL (SUB1_var: RealExpr, SUB2_var: RealExpr):
        op1(SUB(SUB1_var, SUB2_var)) = SUB1_var;

    IntervalExpr_op2_SUB: AXIOM
      FORALL (SUB1_var: RealExpr, SUB2_var: RealExpr):
        op2(SUB(SUB1_var, SUB2_var)) = SUB2_var;

    IntervalExpr_op1_MULT: AXIOM
      FORALL (MULT1_var: RealExpr, MULT2_var: RealExpr):
        op1(MULT(MULT1_var, MULT2_var)) = MULT1_var;

    IntervalExpr_op2_MULT: AXIOM
      FORALL (MULT1_var: RealExpr, MULT2_var: RealExpr):
        op2(MULT(MULT1_var, MULT2_var)) = MULT2_var;

    IntervalExpr_op_SQ: AXIOM
      FORALL (SQ1_var: RealExpr): op(SQ(SQ1_var)) = SQ1_var;

    IntervalExpr_op_POW: AXIOM
      FORALL (POW1_var: RealExpr, POW2_var: nat):
        op(POW(POW1_var, POW2_var)) = POW1_var;

    IntervalExpr_opn_POW: AXIOM
      FORALL (POW1_var: RealExpr, POW2_var: nat):
        opn(POW(POW1_var, POW2_var)) = POW2_var;

    IntervalExpr_op1_DIV: AXIOM
      FORALL (DIV1_var: RealExpr, DIV2_var: RealExpr):
        op1(DIV(DIV1_var, DIV2_var)) = DIV1_var;

    IntervalExpr_op2_DIV: AXIOM
      FORALL (DIV1_var: RealExpr, DIV2_var: RealExpr):
        op2(DIV(DIV1_var, DIV2_var)) = DIV2_var;

    IntervalExpr_pre_FUN: AXIOM
      FORALL (FUN1_var: (Precondition?), FUN2_var: [real -> real],
              FUN3_var:
                {F: [Interval -> Interval] |
                         Inclusion?(FUN1_var, FUN2_var)(F) AND
                          Fundamental?(FUN1_var)(F)},
              FUN4_var: RealExpr):
        pre(FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var)) = FUN1_var;

    IntervalExpr_opf_FUN: AXIOM
      FORALL (FUN1_var: (Precondition?), FUN2_var: [real -> real],
              FUN3_var:
                {F: [Interval -> Interval] |
                         Inclusion?(FUN1_var, FUN2_var)(F) AND
                          Fundamental?(FUN1_var)(F)},
              FUN4_var: RealExpr):
        opf(FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var)) = FUN2_var;

    IntervalExpr_opF_FUN: AXIOM
      FORALL (FUN1_var: (Precondition?), FUN2_var: [real -> real],
              FUN3_var:
                {F: [Interval -> Interval] |
                         Inclusion?(FUN1_var, FUN2_var)(F) AND
                          Fundamental?(FUN1_var)(F)},
              FUN4_var: RealExpr):
        opF(FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var)) = FUN3_var;

    IntervalExpr_op_FUN: AXIOM
      FORALL (FUN1_var: (Precondition?), FUN2_var: [real -> real],
              FUN3_var:
                {F: [Interval -> Interval] |
                         Inclusion?(FUN1_var, FUN2_var)(F) AND
                          Fundamental?(FUN1_var)(F)},
              FUN4_var: RealExpr):
        op(FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var)) = FUN4_var;

    IntervalExpr_rlet_LETIN: AXIOM
      FORALL (LETIN1_var: RealExpr, LETIN2_var: RealExpr):
        rlet(LETIN(LETIN1_var, LETIN2_var)) = LETIN1_var;

    IntervalExpr_rin_LETIN: AXIOM
      FORALL (LETIN1_var: RealExpr, LETIN2_var: RealExpr):
        rin(LETIN(LETIN1_var, LETIN2_var)) = LETIN2_var;

    IntervalExpr_opb_BCONST: AXIOM
      FORALL (BCONST1_var: bool): opb(BCONST(BCONST1_var)) = BCONST1_var;

    IntervalExpr_bop_BNOT: AXIOM
      FORALL (BNOT1_var: BoolExpr): bop(BNOT(BNOT1_var)) = BNOT1_var;

    IntervalExpr_bop1_BAND: AXIOM
      FORALL (BAND1_var: BoolExpr, BAND2_var: BoolExpr):
        bop1(BAND(BAND1_var, BAND2_var)) = BAND1_var;

    IntervalExpr_bop2_BAND: AXIOM
      FORALL (BAND1_var: BoolExpr, BAND2_var: BoolExpr):
        bop2(BAND(BAND1_var, BAND2_var)) = BAND2_var;

    IntervalExpr_bop1_BOR: AXIOM
      FORALL (BOR1_var: BoolExpr, BOR2_var: BoolExpr):
        bop1(BOR(BOR1_var, BOR2_var)) = BOR1_var;

    IntervalExpr_bop2_BOR: AXIOM
      FORALL (BOR1_var: BoolExpr, BOR2_var: BoolExpr):
        bop2(BOR(BOR1_var, BOR2_var)) = BOR2_var;

    IntervalExpr_bop1_BIMPLIES: AXIOM
      FORALL (BIMPLIES1_var: BoolExpr, BIMPLIES2_var: BoolExpr):
        bop1(BIMPLIES(BIMPLIES1_var, BIMPLIES2_var)) = BIMPLIES1_var;

    IntervalExpr_bop2_BIMPLIES: AXIOM
      FORALL (BIMPLIES1_var: BoolExpr, BIMPLIES2_var: BoolExpr):
        bop2(BIMPLIES(BIMPLIES1_var, BIMPLIES2_var)) = BIMPLIES2_var;

    IntervalExpr_rel_BREL: AXIOM
      FORALL (BREL1_var: RealOrder, BREL2_var: RealExpr,
              BREL3_var: RealExpr):
        rel(BREL(BREL1_var, BREL2_var, BREL3_var)) = BREL1_var;

    IntervalExpr_op1_BREL: AXIOM
      FORALL (BREL1_var: RealOrder, BREL2_var: RealExpr,
              BREL3_var: RealExpr):
        op1(BREL(BREL1_var, BREL2_var, BREL3_var)) = BREL2_var;

    IntervalExpr_op2_BREL: AXIOM
      FORALL (BREL1_var: RealOrder, BREL2_var: RealExpr,
              BREL3_var: RealExpr):
        op2(BREL(BREL1_var, BREL2_var, BREL3_var)) = BREL3_var;

    IntervalExpr_op_BINCLUDES: AXIOM
      FORALL (BINCLUDES1_var: RealExpr, BINCLUDES2_var: Interval):
        op(BINCLUDES(BINCLUDES1_var, BINCLUDES2_var)) = BINCLUDES1_var;

    IntervalExpr_opi_BINCLUDES: AXIOM
      FORALL (BINCLUDES1_var: RealExpr, BINCLUDES2_var: Interval):
        opi(BINCLUDES(BINCLUDES1_var, BINCLUDES2_var)) = BINCLUDES2_var;

    IntervalExpr_bif_BITE: AXIOM
      FORALL (BITE1_var: BoolExpr, BITE2_var: BoolExpr, BITE3_var: BoolExpr):
        bif(BITE(BITE1_var, BITE2_var, BITE3_var)) = BITE1_var;

    IntervalExpr_bthen_BITE: AXIOM
      FORALL (BITE1_var: BoolExpr, BITE2_var: BoolExpr, BITE3_var: BoolExpr):
        bthen(BITE(BITE1_var, BITE2_var, BITE3_var)) = BITE2_var;

    IntervalExpr_belse_BITE: AXIOM
      FORALL (BITE1_var: BoolExpr, BITE2_var: BoolExpr, BITE3_var: BoolExpr):
        belse(BITE(BITE1_var, BITE2_var, BITE3_var)) = BITE3_var;

    IntervalExpr_blet_BLETIN: AXIOM
      FORALL (BLETIN1_var: IntervalExpr, BLETIN2_var: BoolExpr):
        blet(BLETIN(BLETIN1_var, BLETIN2_var)) = BLETIN1_var;

    IntervalExpr_bin_BLETIN: AXIOM
      FORALL (BLETIN1_var: IntervalExpr, BLETIN2_var: BoolExpr):
        bin(BLETIN(BLETIN1_var, BLETIN2_var)) = BLETIN2_var;

    IntervalExpr_inclusive: AXIOM
      FORALL (IntervalExpr_var: IntervalExpr):
            const?(IntervalExpr_var) OR varidx?(IntervalExpr_var)
         OR add?(IntervalExpr_var) OR abs?(IntervalExpr_var)
         OR neg?(IntervalExpr_var) OR sub?(IntervalExpr_var)
         OR mult?(IntervalExpr_var) OR sq?(IntervalExpr_var)
         OR pow?(IntervalExpr_var) OR div?(IntervalExpr_var)
         OR fun?(IntervalExpr_var) OR letin?(IntervalExpr_var)
         OR bconst?(IntervalExpr_var) OR bnot?(IntervalExpr_var)
         OR band?(IntervalExpr_var) OR bor?(IntervalExpr_var)
         OR bimplies?(IntervalExpr_var) OR brel?(IntervalExpr_var)
         OR bincludes?(IntervalExpr_var) OR bite?(IntervalExpr_var)
         OR bletin?(IntervalExpr_var);

    IntervalExpr_induction: AXIOM
      FORALL (p: [IntervalExpr -> boolean]):
        (     FORALL (CONST1_var: [Unit -> real],
                      CONST2_var: (Includes?(CONST1_var(unit)))):
                p(CONST(CONST1_var, CONST2_var))
          AND FORALL (VARIDX1_var: nat): p(VARIDX(VARIDX1_var))
          AND FORALL (ADD1_var: RealExpr, ADD2_var: RealExpr):
                p(ADD1_var) AND p(ADD2_var) IMPLIES p(ADD(ADD1_var, ADD2_var))
          AND FORALL (ABS1_var: RealExpr):
                p(ABS1_var) IMPLIES p(ABS(ABS1_var))
          AND FORALL (NEG1_var: RealExpr):
                p(NEG1_var) IMPLIES p(NEG(NEG1_var))
          AND FORALL (SUB1_var: RealExpr, SUB2_var: RealExpr):
                p(SUB1_var) AND p(SUB2_var) IMPLIES p(SUB(SUB1_var, SUB2_var))
          AND FORALL (MULT1_var: RealExpr, MULT2_var: RealExpr):
                p(MULT1_var) AND p(MULT2_var) IMPLIES
                 p(MULT(MULT1_var, MULT2_var))
          AND FORALL (SQ1_var: RealExpr): p(SQ1_var) IMPLIES p(SQ(SQ1_var))
          AND FORALL (POW1_var: RealExpr, POW2_var: nat):
                p(POW1_var) IMPLIES p(POW(POW1_var, POW2_var))
          AND FORALL (DIV1_var: RealExpr, DIV2_var: RealExpr):
                p(DIV1_var) AND p(DIV2_var) IMPLIES p(DIV(DIV1_var, DIV2_var))
          AND FORALL (FUN1_var: (Precondition?), FUN2_var: [real -> real],
                      FUN3_var:
                        {F: [Interval -> Interval] |
                                 Inclusion?(FUN1_var, FUN2_var)(F) AND
                                  Fundamental?(FUN1_var)(F)},
                      FUN4_var: RealExpr):
                p(FUN4_var) IMPLIES
                 p(FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var))
          AND FORALL (LETIN1_var: RealExpr, LETIN2_var: RealExpr):
                p(LETIN1_var) AND p(LETIN2_var) IMPLIES
                 p(LETIN(LETIN1_var, LETIN2_var))
          AND FORALL (BCONST1_var: bool): p(BCONST(BCONST1_var))
          AND FORALL (BNOT1_var: BoolExpr):
                p(BNOT1_var) IMPLIES p(BNOT(BNOT1_var))
          AND FORALL (BAND1_var: BoolExpr, BAND2_var: BoolExpr):
                p(BAND1_var) AND p(BAND2_var) IMPLIES
                 p(BAND(BAND1_var, BAND2_var))
          AND FORALL (BOR1_var: BoolExpr, BOR2_var: BoolExpr):
                p(BOR1_var) AND p(BOR2_var) IMPLIES p(BOR(BOR1_var, BOR2_var))
          AND FORALL (BIMPLIES1_var: BoolExpr, BIMPLIES2_var: BoolExpr):
                p(BIMPLIES1_var) AND p(BIMPLIES2_var) IMPLIES
                 p(BIMPLIES(BIMPLIES1_var, BIMPLIES2_var))
          AND FORALL (BREL1_var: RealOrder, BREL2_var: RealExpr,
                      BREL3_var: RealExpr):
                p(BREL2_var) AND p(BREL3_var) IMPLIES
                 p(BREL(BREL1_var, BREL2_var, BREL3_var))
          AND FORALL (BINCLUDES1_var: RealExpr, BINCLUDES2_var: Interval):
                p(BINCLUDES1_var) IMPLIES
                 p(BINCLUDES(BINCLUDES1_var, BINCLUDES2_var))
          AND FORALL (BITE1_var: BoolExpr, BITE2_var: BoolExpr,
                      BITE3_var: BoolExpr):
                p(BITE1_var) AND p(BITE2_var) AND p(BITE3_var) IMPLIES
                 p(BITE(BITE1_var, BITE2_var, BITE3_var))
          AND FORALL (BLETIN1_var: IntervalExpr, BLETIN2_var: BoolExpr):
                p(BLETIN1_var) AND p(BLETIN2_var) IMPLIES
                 p(BLETIN(BLETIN1_var, BLETIN2_var)))
         IMPLIES
         (FORALL (IntervalExpr_var: IntervalExpr): p(IntervalExpr_var));

    subterm(x: IntervalExpr, y: IntervalExpr):  boolean =
        x = y OR
         CASES y
           OF CONST(CONST1_var, CONST2_var): FALSE,
              VARIDX(VARIDX1_var): FALSE,
              ADD(ADD1_var, ADD2_var):
                subterm(x, ADD1_var) OR subterm(x, ADD2_var),
              ABS(ABS1_var): subterm(x, ABS1_var),
              NEG(NEG1_var): subterm(x, NEG1_var),
              SUB(SUB1_var, SUB2_var):
                subterm(x, SUB1_var) OR subterm(x, SUB2_var),
              MULT(MULT1_var, MULT2_var):
                subterm(x, MULT1_var) OR subterm(x, MULT2_var),
              SQ(SQ1_var): subterm(x, SQ1_var),
              POW(POW1_var, POW2_var): subterm(x, POW1_var),
              DIV(DIV1_var, DIV2_var):
                subterm(x, DIV1_var) OR subterm(x, DIV2_var),
              FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var):
                subterm(x, FUN4_var),
              LETIN(LETIN1_var, LETIN2_var):
                subterm(x, LETIN1_var) OR subterm(x, LETIN2_var),
              BCONST(BCONST1_var): FALSE,
              BNOT(BNOT1_var): subterm(x, BNOT1_var),
              BAND(BAND1_var, BAND2_var):
                subterm(x, BAND1_var) OR subterm(x, BAND2_var),
              BOR(BOR1_var, BOR2_var):
                subterm(x, BOR1_var) OR subterm(x, BOR2_var),
              BIMPLIES(BIMPLIES1_var, BIMPLIES2_var):
                subterm(x, BIMPLIES1_var) OR subterm(x, BIMPLIES2_var),
              BREL(BREL1_var, BREL2_var, BREL3_var):
                subterm(x, BREL2_var) OR subterm(x, BREL3_var),
              BINCLUDES(BINCLUDES1_var, BINCLUDES2_var):
                subterm(x, BINCLUDES1_var),
              BITE(BITE1_var, BITE2_var, BITE3_var):
                subterm(x, BITE1_var) OR
                 subterm(x, BITE2_var) OR subterm(x, BITE3_var),
              BLETIN(BLETIN1_var, BLETIN2_var):
                subterm(x, BLETIN1_var) OR subterm(x, BLETIN2_var)
           ENDCASES;

    <<:  (strict_well_founded?[IntervalExpr]) =
        LAMBDA (x, y: IntervalExpr):
          CASES y
            OF CONST(CONST1_var, CONST2_var): FALSE,
               VARIDX(VARIDX1_var): FALSE,
               ADD(ADD1_var, ADD2_var):
                 (x = ADD1_var OR x << ADD1_var) OR
                  x = ADD2_var OR x << ADD2_var,
               ABS(ABS1_var): x = ABS1_var OR x << ABS1_var,
               NEG(NEG1_var): x = NEG1_var OR x << NEG1_var,
               SUB(SUB1_var, SUB2_var):
                 (x = SUB1_var OR x << SUB1_var) OR
                  x = SUB2_var OR x << SUB2_var,
               MULT(MULT1_var, MULT2_var):
                 (x = MULT1_var OR x << MULT1_var) OR
                  x = MULT2_var OR x << MULT2_var,
               SQ(SQ1_var): x = SQ1_var OR x << SQ1_var,
               POW(POW1_var, POW2_var): x = POW1_var OR x << POW1_var,
               DIV(DIV1_var, DIV2_var):
                 (x = DIV1_var OR x << DIV1_var) OR
                  x = DIV2_var OR x << DIV2_var,
               FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var):
                 x = FUN4_var OR x << FUN4_var,
               LETIN(LETIN1_var, LETIN2_var):
                 (x = LETIN1_var OR x << LETIN1_var) OR
                  x = LETIN2_var OR x << LETIN2_var,
               BCONST(BCONST1_var): FALSE,
               BNOT(BNOT1_var): x = BNOT1_var OR x << BNOT1_var,
               BAND(BAND1_var, BAND2_var):
                 (x = BAND1_var OR x << BAND1_var) OR
                  x = BAND2_var OR x << BAND2_var,
               BOR(BOR1_var, BOR2_var):
                 (x = BOR1_var OR x << BOR1_var) OR
                  x = BOR2_var OR x << BOR2_var,
               BIMPLIES(BIMPLIES1_var, BIMPLIES2_var):
                 (x = BIMPLIES1_var OR x << BIMPLIES1_var) OR
                  x = BIMPLIES2_var OR x << BIMPLIES2_var,
               BREL(BREL1_var, BREL2_var, BREL3_var):
                 (x = BREL2_var OR x << BREL2_var) OR
                  x = BREL3_var OR x << BREL3_var,
               BINCLUDES(BINCLUDES1_var, BINCLUDES2_var):
                 x = BINCLUDES1_var OR x << BINCLUDES1_var,
               BITE(BITE1_var, BITE2_var, BITE3_var):
                     x = BITE1_var OR x << BITE1_var OR x = BITE2_var
                  OR x << BITE2_var OR x = BITE3_var OR x << BITE3_var,
               BLETIN(BLETIN1_var, BLETIN2_var):
                 (x = BLETIN1_var OR x << BLETIN1_var) OR
                  x = BLETIN2_var OR x << BLETIN2_var
            ENDCASES;

    IntervalExpr_well_founded: AXIOM strict_well_founded?[IntervalExpr](<<);

    reduce_nat(const?_fun:
                 [[CONST1_var: [Unit -> real],
                   (Includes?(CONST1_var(unit)))] ->
                    nat],
               varidx?_fun: [nat -> nat], add?_fun: [[nat, nat] -> nat],
               abs?_fun: [nat -> nat], neg?_fun: [nat -> nat],
               sub?_fun: [[nat, nat] -> nat], mult?_fun: [[nat, nat] -> nat],
               sq?_fun: [nat -> nat], pow?_fun: [[nat, nat] -> nat],
               div?_fun: [[nat, nat] -> nat],
               fun?_fun:
                 [[FUN1_var: (Precondition?), FUN2_var: [real -> real],
                   {F: [Interval -> Interval] |
                            Inclusion?(FUN1_var, FUN2_var)(F) AND
                             Fundamental?(FUN1_var)(F)},
                   nat] ->
                    nat],
               letin?_fun: [[nat, nat] -> nat], bconst?_fun: [bool -> nat],
               bnot?_fun: [nat -> nat], band?_fun: [[nat, nat] -> nat],
               bor?_fun: [[nat, nat] -> nat],
               bimplies?_fun: [[nat, nat] -> nat],
               brel?_fun: [[RealOrder, nat, nat] -> nat],
               bincludes?_fun: [[nat, Interval] -> nat],
               bite?_fun: [[nat, nat, nat] -> nat],
               bletin?_fun: [[nat, nat] -> nat]):
          [IntervalExpr -> nat] =
        LAMBDA (IntervalExpr_adtvar: IntervalExpr):
          LET red: [IntervalExpr -> nat] =
                reduce_nat(const?_fun, varidx?_fun, add?_fun, abs?_fun,
                           neg?_fun, sub?_fun, mult?_fun, sq?_fun, pow?_fun,
                           div?_fun, fun?_fun, letin?_fun, bconst?_fun,
                           bnot?_fun, band?_fun, bor?_fun, bimplies?_fun,
                           brel?_fun, bincludes?_fun, bite?_fun, bletin?_fun)
            IN
            CASES IntervalExpr_adtvar
              OF CONST(CONST1_var, CONST2_var):
                   const?_fun(CONST1_var, CONST2_var),
                 VARIDX(VARIDX1_var): varidx?_fun(VARIDX1_var),
                 ADD(ADD1_var, ADD2_var):
                   add?_fun(red(ADD1_var), red(ADD2_var)),
                 ABS(ABS1_var): abs?_fun(red(ABS1_var)),
                 NEG(NEG1_var): neg?_fun(red(NEG1_var)),
                 SUB(SUB1_var, SUB2_var):
                   sub?_fun(red(SUB1_var), red(SUB2_var)),
                 MULT(MULT1_var, MULT2_var):
                   mult?_fun(red(MULT1_var), red(MULT2_var)),
                 SQ(SQ1_var): sq?_fun(red(SQ1_var)),
                 POW(POW1_var, POW2_var): pow?_fun(red(POW1_var), POW2_var),
                 DIV(DIV1_var, DIV2_var):
                   div?_fun(red(DIV1_var), red(DIV2_var)),
                 FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var):
                   fun?_fun(FUN1_var, FUN2_var, FUN3_var, red(FUN4_var)),
                 LETIN(LETIN1_var, LETIN2_var):
                   letin?_fun(red(LETIN1_var), red(LETIN2_var)),
                 BCONST(BCONST1_var): bconst?_fun(BCONST1_var),
                 BNOT(BNOT1_var): bnot?_fun(red(BNOT1_var)),
                 BAND(BAND1_var, BAND2_var):
                   band?_fun(red(BAND1_var), red(BAND2_var)),
                 BOR(BOR1_var, BOR2_var):
                   bor?_fun(red(BOR1_var), red(BOR2_var)),
                 BIMPLIES(BIMPLIES1_var, BIMPLIES2_var):
                   bimplies?_fun(red(BIMPLIES1_var), red(BIMPLIES2_var)),
                 BREL(BREL1_var, BREL2_var, BREL3_var):
                   brel?_fun(BREL1_var, red(BREL2_var), red(BREL3_var)),
                 BINCLUDES(BINCLUDES1_var, BINCLUDES2_var):
                   bincludes?_fun(red(BINCLUDES1_var), BINCLUDES2_var),
                 BITE(BITE1_var, BITE2_var, BITE3_var):
                   bite?_fun(red(BITE1_var), red(BITE2_var), red(BITE3_var)),
                 BLETIN(BLETIN1_var, BLETIN2_var):
                   bletin?_fun(red(BLETIN1_var), red(BLETIN2_var))
              ENDCASES;

    REDUCE_nat(const?_fun:
                 [[CONST1_var: [Unit -> real], (Includes?(CONST1_var(unit))),
                   IntervalExpr] ->
                    nat],
               varidx?_fun: [[nat, IntervalExpr] -> nat],
               add?_fun: [[nat, nat, IntervalExpr] -> nat],
               abs?_fun: [[nat, IntervalExpr] -> nat],
               neg?_fun: [[nat, IntervalExpr] -> nat],
               sub?_fun: [[nat, nat, IntervalExpr] -> nat],
               mult?_fun: [[nat, nat, IntervalExpr] -> nat],
               sq?_fun: [[nat, IntervalExpr] -> nat],
               pow?_fun: [[nat, nat, IntervalExpr] -> nat],
               div?_fun: [[nat, nat, IntervalExpr] -> nat],
               fun?_fun:
                 [[FUN1_var: (Precondition?), FUN2_var: [real -> real],
                   {F: [Interval -> Interval] |
                            Inclusion?(FUN1_var, FUN2_var)(F) AND
                             Fundamental?(FUN1_var)(F)},
                   nat, IntervalExpr] ->
                    nat],
               letin?_fun: [[nat, nat, IntervalExpr] -> nat],
               bconst?_fun: [[bool, IntervalExpr] -> nat],
               bnot?_fun: [[nat, IntervalExpr] -> nat],
               band?_fun: [[nat, nat, IntervalExpr] -> nat],
               bor?_fun: [[nat, nat, IntervalExpr] -> nat],
               bimplies?_fun: [[nat, nat, IntervalExpr] -> nat],
               brel?_fun: [[RealOrder, nat, nat, IntervalExpr] -> nat],
               bincludes?_fun: [[nat, Interval, IntervalExpr] -> nat],
               bite?_fun: [[nat, nat, nat, IntervalExpr] -> nat],
               bletin?_fun: [[nat, nat, IntervalExpr] -> nat]):
          [IntervalExpr -> nat] =
        LAMBDA (IntervalExpr_adtvar: IntervalExpr):
          LET red: [IntervalExpr -> nat] =
                REDUCE_nat(const?_fun, varidx?_fun, add?_fun, abs?_fun,
                           neg?_fun, sub?_fun, mult?_fun, sq?_fun, pow?_fun,
                           div?_fun, fun?_fun, letin?_fun, bconst?_fun,
                           bnot?_fun, band?_fun, bor?_fun, bimplies?_fun,
                           brel?_fun, bincludes?_fun, bite?_fun, bletin?_fun)
            IN
            CASES IntervalExpr_adtvar
              OF CONST(CONST1_var, CONST2_var):
                   const?_fun(CONST1_var, CONST2_var, IntervalExpr_adtvar),
                 VARIDX(VARIDX1_var):
                   varidx?_fun(VARIDX1_var, IntervalExpr_adtvar),
                 ADD(ADD1_var, ADD2_var):
                   add?_fun(red(ADD1_var), red(ADD2_var),
                            IntervalExpr_adtvar),
                 ABS(ABS1_var): abs?_fun(red(ABS1_var), IntervalExpr_adtvar),
                 NEG(NEG1_var): neg?_fun(red(NEG1_var), IntervalExpr_adtvar),
                 SUB(SUB1_var, SUB2_var):
                   sub?_fun(red(SUB1_var), red(SUB2_var),
                            IntervalExpr_adtvar),
                 MULT(MULT1_var, MULT2_var):
                   mult?_fun(red(MULT1_var), red(MULT2_var),
                             IntervalExpr_adtvar),
                 SQ(SQ1_var): sq?_fun(red(SQ1_var), IntervalExpr_adtvar),
                 POW(POW1_var, POW2_var):
                   pow?_fun(red(POW1_var), POW2_var, IntervalExpr_adtvar),
                 DIV(DIV1_var, DIV2_var):
                   div?_fun(red(DIV1_var), red(DIV2_var),
                            IntervalExpr_adtvar),
                 FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var):
                   fun?_fun(FUN1_var, FUN2_var, FUN3_var, red(FUN4_var),
                            IntervalExpr_adtvar),
                 LETIN(LETIN1_var, LETIN2_var):
                   letin?_fun(red(LETIN1_var), red(LETIN2_var),
                              IntervalExpr_adtvar),
                 BCONST(BCONST1_var):
                   bconst?_fun(BCONST1_var, IntervalExpr_adtvar),
                 BNOT(BNOT1_var):
                   bnot?_fun(red(BNOT1_var), IntervalExpr_adtvar),
                 BAND(BAND1_var, BAND2_var):
                   band?_fun(red(BAND1_var), red(BAND2_var),
                             IntervalExpr_adtvar),
                 BOR(BOR1_var, BOR2_var):
                   bor?_fun(red(BOR1_var), red(BOR2_var),
                            IntervalExpr_adtvar),
                 BIMPLIES(BIMPLIES1_var, BIMPLIES2_var):
                   bimplies?_fun(red(BIMPLIES1_var), red(BIMPLIES2_var),
                                 IntervalExpr_adtvar),
                 BREL(BREL1_var, BREL2_var, BREL3_var):
                   brel?_fun(BREL1_var, red(BREL2_var), red(BREL3_var),
                             IntervalExpr_adtvar),
                 BINCLUDES(BINCLUDES1_var, BINCLUDES2_var):
                   bincludes?_fun(red(BINCLUDES1_var), BINCLUDES2_var,
                                  IntervalExpr_adtvar),
                 BITE(BITE1_var, BITE2_var, BITE3_var):
                   bite?_fun(red(BITE1_var), red(BITE2_var), red(BITE3_var),
                             IntervalExpr_adtvar),
                 BLETIN(BLETIN1_var, BLETIN2_var):
                   bletin?_fun(red(BLETIN1_var), red(BLETIN2_var),
                               IntervalExpr_adtvar)
              ENDCASES;

    reduce_ordinal(const?_fun:
                     [[CONST1_var: [Unit -> real],
                       (Includes?(CONST1_var(unit)))] ->
                        ordinal],
                   varidx?_fun: [nat -> ordinal],
                   add?_fun: [[ordinal, ordinal] -> ordinal],
                   abs?_fun: [ordinal -> ordinal],
                   neg?_fun: [ordinal -> ordinal],
                   sub?_fun: [[ordinal, ordinal] -> ordinal],
                   mult?_fun: [[ordinal, ordinal] -> ordinal],
                   sq?_fun: [ordinal -> ordinal],
                   pow?_fun: [[ordinal, nat] -> ordinal],
                   div?_fun: [[ordinal, ordinal] -> ordinal],
                   fun?_fun:
                     [[FUN1_var: (Precondition?), FUN2_var: [real -> real],
                       {F: [Interval -> Interval] |
                                Inclusion?(FUN1_var, FUN2_var)(F) AND
                                 Fundamental?(FUN1_var)(F)},
                       ordinal] ->
                        ordinal],
                   letin?_fun: [[ordinal, ordinal] -> ordinal],
                   bconst?_fun: [bool -> ordinal],
                   bnot?_fun: [ordinal -> ordinal],
                   band?_fun: [[ordinal, ordinal] -> ordinal],
                   bor?_fun: [[ordinal, ordinal] -> ordinal],
                   bimplies?_fun: [[ordinal, ordinal] -> ordinal],
                   brel?_fun: [[RealOrder, ordinal, ordinal] -> ordinal],
                   bincludes?_fun: [[ordinal, Interval] -> ordinal],
                   bite?_fun: [[ordinal, ordinal, ordinal] -> ordinal],
                   bletin?_fun: [[ordinal, ordinal] -> ordinal]):
          [IntervalExpr -> ordinal] =
        LAMBDA (IntervalExpr_adtvar: IntervalExpr):
          LET red: [IntervalExpr -> ordinal] =
                reduce_ordinal(const?_fun, varidx?_fun, add?_fun, abs?_fun,
                               neg?_fun, sub?_fun, mult?_fun, sq?_fun,
                               pow?_fun, div?_fun, fun?_fun, letin?_fun,
                               bconst?_fun, bnot?_fun, band?_fun, bor?_fun,
                               bimplies?_fun, brel?_fun, bincludes?_fun,
                               bite?_fun, bletin?_fun)
            IN
            CASES IntervalExpr_adtvar
              OF CONST(CONST1_var, CONST2_var):
                   const?_fun(CONST1_var, CONST2_var),
                 VARIDX(VARIDX1_var): varidx?_fun(VARIDX1_var),
                 ADD(ADD1_var, ADD2_var):
                   add?_fun(red(ADD1_var), red(ADD2_var)),
                 ABS(ABS1_var): abs?_fun(red(ABS1_var)),
                 NEG(NEG1_var): neg?_fun(red(NEG1_var)),
                 SUB(SUB1_var, SUB2_var):
                   sub?_fun(red(SUB1_var), red(SUB2_var)),
                 MULT(MULT1_var, MULT2_var):
                   mult?_fun(red(MULT1_var), red(MULT2_var)),
                 SQ(SQ1_var): sq?_fun(red(SQ1_var)),
                 POW(POW1_var, POW2_var): pow?_fun(red(POW1_var), POW2_var),
                 DIV(DIV1_var, DIV2_var):
                   div?_fun(red(DIV1_var), red(DIV2_var)),
                 FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var):
                   fun?_fun(FUN1_var, FUN2_var, FUN3_var, red(FUN4_var)),
                 LETIN(LETIN1_var, LETIN2_var):
                   letin?_fun(red(LETIN1_var), red(LETIN2_var)),
                 BCONST(BCONST1_var): bconst?_fun(BCONST1_var),
                 BNOT(BNOT1_var): bnot?_fun(red(BNOT1_var)),
                 BAND(BAND1_var, BAND2_var):
                   band?_fun(red(BAND1_var), red(BAND2_var)),
                 BOR(BOR1_var, BOR2_var):
                   bor?_fun(red(BOR1_var), red(BOR2_var)),
                 BIMPLIES(BIMPLIES1_var, BIMPLIES2_var):
                   bimplies?_fun(red(BIMPLIES1_var), red(BIMPLIES2_var)),
                 BREL(BREL1_var, BREL2_var, BREL3_var):
                   brel?_fun(BREL1_var, red(BREL2_var), red(BREL3_var)),
                 BINCLUDES(BINCLUDES1_var, BINCLUDES2_var):
                   bincludes?_fun(red(BINCLUDES1_var), BINCLUDES2_var),
                 BITE(BITE1_var, BITE2_var, BITE3_var):
                   bite?_fun(red(BITE1_var), red(BITE2_var), red(BITE3_var)),
                 BLETIN(BLETIN1_var, BLETIN2_var):
                   bletin?_fun(red(BLETIN1_var), red(BLETIN2_var))
              ENDCASES;

    REDUCE_ordinal(const?_fun:
                     [[CONST1_var: [Unit -> real],
                       (Includes?(CONST1_var(unit))), IntervalExpr] ->
                        ordinal],
                   varidx?_fun: [[nat, IntervalExpr] -> ordinal],
                   add?_fun: [[ordinal, ordinal, IntervalExpr] -> ordinal],
                   abs?_fun: [[ordinal, IntervalExpr] -> ordinal],
                   neg?_fun: [[ordinal, IntervalExpr] -> ordinal],
                   sub?_fun: [[ordinal, ordinal, IntervalExpr] -> ordinal],
                   mult?_fun: [[ordinal, ordinal, IntervalExpr] -> ordinal],
                   sq?_fun: [[ordinal, IntervalExpr] -> ordinal],
                   pow?_fun: [[ordinal, nat, IntervalExpr] -> ordinal],
                   div?_fun: [[ordinal, ordinal, IntervalExpr] -> ordinal],
                   fun?_fun:
                     [[FUN1_var: (Precondition?), FUN2_var: [real -> real],
                       {F: [Interval -> Interval] |
                                Inclusion?(FUN1_var, FUN2_var)(F) AND
                                 Fundamental?(FUN1_var)(F)},
                       ordinal, IntervalExpr] ->
                        ordinal],
                   letin?_fun: [[ordinal, ordinal, IntervalExpr] -> ordinal],
                   bconst?_fun: [[bool, IntervalExpr] -> ordinal],
                   bnot?_fun: [[ordinal, IntervalExpr] -> ordinal],
                   band?_fun: [[ordinal, ordinal, IntervalExpr] -> ordinal],
                   bor?_fun: [[ordinal, ordinal, IntervalExpr] -> ordinal],
                   bimplies?_fun:
                     [[ordinal, ordinal, IntervalExpr] -> ordinal],
                   brel?_fun:
                     [[RealOrder, ordinal, ordinal, IntervalExpr] ->
                        ordinal],
                   bincludes?_fun:
                     [[ordinal, Interval, IntervalExpr] -> ordinal],
                   bite?_fun:
                     [[ordinal, ordinal, ordinal, IntervalExpr] -> ordinal],
                   bletin?_fun:
                     [[ordinal, ordinal, IntervalExpr] -> ordinal]):
          [IntervalExpr -> ordinal] =
        LAMBDA (IntervalExpr_adtvar: IntervalExpr):
          LET red: [IntervalExpr -> ordinal] =
                REDUCE_ordinal(const?_fun, varidx?_fun, add?_fun, abs?_fun,
                               neg?_fun, sub?_fun, mult?_fun, sq?_fun,
                               pow?_fun, div?_fun, fun?_fun, letin?_fun,
                               bconst?_fun, bnot?_fun, band?_fun, bor?_fun,
                               bimplies?_fun, brel?_fun, bincludes?_fun,
                               bite?_fun, bletin?_fun)
            IN
            CASES IntervalExpr_adtvar
              OF CONST(CONST1_var, CONST2_var):
                   const?_fun(CONST1_var, CONST2_var, IntervalExpr_adtvar),
                 VARIDX(VARIDX1_var):
                   varidx?_fun(VARIDX1_var, IntervalExpr_adtvar),
                 ADD(ADD1_var, ADD2_var):
                   add?_fun(red(ADD1_var), red(ADD2_var),
                            IntervalExpr_adtvar),
                 ABS(ABS1_var): abs?_fun(red(ABS1_var), IntervalExpr_adtvar),
                 NEG(NEG1_var): neg?_fun(red(NEG1_var), IntervalExpr_adtvar),
                 SUB(SUB1_var, SUB2_var):
                   sub?_fun(red(SUB1_var), red(SUB2_var),
                            IntervalExpr_adtvar),
                 MULT(MULT1_var, MULT2_var):
                   mult?_fun(red(MULT1_var), red(MULT2_var),
                             IntervalExpr_adtvar),
                 SQ(SQ1_var): sq?_fun(red(SQ1_var), IntervalExpr_adtvar),
                 POW(POW1_var, POW2_var):
                   pow?_fun(red(POW1_var), POW2_var, IntervalExpr_adtvar),
                 DIV(DIV1_var, DIV2_var):
                   div?_fun(red(DIV1_var), red(DIV2_var),
                            IntervalExpr_adtvar),
                 FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var):
                   fun?_fun(FUN1_var, FUN2_var, FUN3_var, red(FUN4_var),
                            IntervalExpr_adtvar),
                 LETIN(LETIN1_var, LETIN2_var):
                   letin?_fun(red(LETIN1_var), red(LETIN2_var),
                              IntervalExpr_adtvar),
                 BCONST(BCONST1_var):
                   bconst?_fun(BCONST1_var, IntervalExpr_adtvar),
                 BNOT(BNOT1_var):
                   bnot?_fun(red(BNOT1_var), IntervalExpr_adtvar),
                 BAND(BAND1_var, BAND2_var):
                   band?_fun(red(BAND1_var), red(BAND2_var),
                             IntervalExpr_adtvar),
                 BOR(BOR1_var, BOR2_var):
                   bor?_fun(red(BOR1_var), red(BOR2_var),
                            IntervalExpr_adtvar),
                 BIMPLIES(BIMPLIES1_var, BIMPLIES2_var):
                   bimplies?_fun(red(BIMPLIES1_var), red(BIMPLIES2_var),
                                 IntervalExpr_adtvar),
                 BREL(BREL1_var, BREL2_var, BREL3_var):
                   brel?_fun(BREL1_var, red(BREL2_var), red(BREL3_var),
                             IntervalExpr_adtvar),
                 BINCLUDES(BINCLUDES1_var, BINCLUDES2_var):
                   bincludes?_fun(red(BINCLUDES1_var), BINCLUDES2_var,
                                  IntervalExpr_adtvar),
                 BITE(BITE1_var, BITE2_var, BITE3_var):
                   bite?_fun(red(BITE1_var), red(BITE2_var), red(BITE3_var),
                             IntervalExpr_adtvar),
                 BLETIN(BLETIN1_var, BLETIN2_var):
                   bletin?_fun(red(BLETIN1_var), red(BLETIN2_var),
                               IntervalExpr_adtvar)
              ENDCASES;
   END IntervalExpr_adt


body:
  IntervalExpr_adt_reduce[range: TYPE]: THEORY
   BEGIN

    IMPORTING IntervalExpr_adt

    IMPORTING interval, structures@Unit, reals@real_orders

    reduce(const?_fun:
             [[CONST1_var: [Unit -> real], (Includes?(CONST1_var(unit)))] ->
                range],
           varidx?_fun: [nat -> range], add?_fun: [[range, range] -> range],
           abs?_fun: [range -> range], neg?_fun: [range -> range],
           sub?_fun: [[range, range] -> range],
           mult?_fun: [[range, range] -> range], sq?_fun: [range -> range],
           pow?_fun: [[range, nat] -> range],
           div?_fun: [[range, range] -> range],
           fun?_fun:
             [[FUN1_var: (Precondition?), FUN2_var: [real -> real],
               {F: [Interval -> Interval] |
                        Inclusion?(FUN1_var, FUN2_var)(F) AND
                         Fundamental?(FUN1_var)(F)},
               range] ->
                range],
           letin?_fun: [[range, range] -> range],
           bconst?_fun: [bool -> range], bnot?_fun: [range -> range],
           band?_fun: [[range, range] -> range],
           bor?_fun: [[range, range] -> range],
           bimplies?_fun: [[range, range] -> range],
           brel?_fun: [[RealOrder, range, range] -> range],
           bincludes?_fun: [[range, Interval] -> range],
           bite?_fun: [[range, range, range] -> range],
           bletin?_fun: [[range, range] -> range]):
          [IntervalExpr -> range] =
        LAMBDA (IntervalExpr_adtvar: IntervalExpr):
          LET red: [IntervalExpr -> range] =
                reduce(const?_fun, varidx?_fun, add?_fun, abs?_fun, neg?_fun,
                       sub?_fun, mult?_fun, sq?_fun, pow?_fun, div?_fun,
                       fun?_fun, letin?_fun, bconst?_fun, bnot?_fun,
                       band?_fun, bor?_fun, bimplies?_fun, brel?_fun,
                       bincludes?_fun, bite?_fun, bletin?_fun)
            IN
            CASES IntervalExpr_adtvar
              OF CONST(CONST1_var, CONST2_var):
                   const?_fun(CONST1_var, CONST2_var),
                 VARIDX(VARIDX1_var): varidx?_fun(VARIDX1_var),
                 ADD(ADD1_var, ADD2_var):
                   add?_fun(red(ADD1_var), red(ADD2_var)),
                 ABS(ABS1_var): abs?_fun(red(ABS1_var)),
                 NEG(NEG1_var): neg?_fun(red(NEG1_var)),
                 SUB(SUB1_var, SUB2_var):
                   sub?_fun(red(SUB1_var), red(SUB2_var)),
                 MULT(MULT1_var, MULT2_var):
                   mult?_fun(red(MULT1_var), red(MULT2_var)),
                 SQ(SQ1_var): sq?_fun(red(SQ1_var)),
                 POW(POW1_var, POW2_var): pow?_fun(red(POW1_var), POW2_var),
                 DIV(DIV1_var, DIV2_var):
                   div?_fun(red(DIV1_var), red(DIV2_var)),
                 FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var):
                   fun?_fun(FUN1_var, FUN2_var, FUN3_var, red(FUN4_var)),
                 LETIN(LETIN1_var, LETIN2_var):
                   letin?_fun(red(LETIN1_var), red(LETIN2_var)),
                 BCONST(BCONST1_var): bconst?_fun(BCONST1_var),
                 BNOT(BNOT1_var): bnot?_fun(red(BNOT1_var)),
                 BAND(BAND1_var, BAND2_var):
                   band?_fun(red(BAND1_var), red(BAND2_var)),
                 BOR(BOR1_var, BOR2_var):
                   bor?_fun(red(BOR1_var), red(BOR2_var)),
                 BIMPLIES(BIMPLIES1_var, BIMPLIES2_var):
                   bimplies?_fun(red(BIMPLIES1_var), red(BIMPLIES2_var)),
                 BREL(BREL1_var, BREL2_var, BREL3_var):
                   brel?_fun(BREL1_var, red(BREL2_var), red(BREL3_var)),
                 BINCLUDES(BINCLUDES1_var, BINCLUDES2_var):
                   bincludes?_fun(red(BINCLUDES1_var), BINCLUDES2_var),
                 BITE(BITE1_var, BITE2_var, BITE3_var):
                   bite?_fun(red(BITE1_var), red(BITE2_var), red(BITE3_var)),
                 BLETIN(BLETIN1_var, BLETIN2_var):
                   bletin?_fun(red(BLETIN1_var), red(BLETIN2_var))
              ENDCASES;

    REDUCE(const?_fun:
             [[CONST1_var: [Unit -> real], (Includes?(CONST1_var(unit))),
               IntervalExpr] ->
                range],
           varidx?_fun: [[nat, IntervalExpr] -> range],
           add?_fun: [[range, range, IntervalExpr] -> range],
           abs?_fun: [[range, IntervalExpr] -> range],
           neg?_fun: [[range, IntervalExpr] -> range],
           sub?_fun: [[range, range, IntervalExpr] -> range],
           mult?_fun: [[range, range, IntervalExpr] -> range],
           sq?_fun: [[range, IntervalExpr] -> range],
           pow?_fun: [[range, nat, IntervalExpr] -> range],
           div?_fun: [[range, range, IntervalExpr] -> range],
           fun?_fun:
             [[FUN1_var: (Precondition?), FUN2_var: [real -> real],
               {F: [Interval -> Interval] |
                        Inclusion?(FUN1_var, FUN2_var)(F) AND
                         Fundamental?(FUN1_var)(F)},
               range, IntervalExpr] ->
                range],
           letin?_fun: [[range, range, IntervalExpr] -> range],
           bconst?_fun: [[bool, IntervalExpr] -> range],
           bnot?_fun: [[range, IntervalExpr] -> range],
           band?_fun: [[range, range, IntervalExpr] -> range],
           bor?_fun: [[range, range, IntervalExpr] -> range],
           bimplies?_fun: [[range, range, IntervalExpr] -> range],
           brel?_fun: [[RealOrder, range, range, IntervalExpr] -> range],
           bincludes?_fun: [[range, Interval, IntervalExpr] -> range],
           bite?_fun: [[range, range, range, IntervalExpr] -> range],
           bletin?_fun: [[range, range, IntervalExpr] -> range]):
          [IntervalExpr -> range] =
        LAMBDA (IntervalExpr_adtvar: IntervalExpr):
          LET red: [IntervalExpr -> range] =
                REDUCE(const?_fun, varidx?_fun, add?_fun, abs?_fun, neg?_fun,
                       sub?_fun, mult?_fun, sq?_fun, pow?_fun, div?_fun,
                       fun?_fun, letin?_fun, bconst?_fun, bnot?_fun,
                       band?_fun, bor?_fun, bimplies?_fun, brel?_fun,
                       bincludes?_fun, bite?_fun, bletin?_fun)
            IN
            CASES IntervalExpr_adtvar
              OF CONST(CONST1_var, CONST2_var):
                   const?_fun(CONST1_var, CONST2_var, IntervalExpr_adtvar),
                 VARIDX(VARIDX1_var):
                   varidx?_fun(VARIDX1_var, IntervalExpr_adtvar),
                 ADD(ADD1_var, ADD2_var):
                   add?_fun(red(ADD1_var), red(ADD2_var),
                            IntervalExpr_adtvar),
                 ABS(ABS1_var): abs?_fun(red(ABS1_var), IntervalExpr_adtvar),
                 NEG(NEG1_var): neg?_fun(red(NEG1_var), IntervalExpr_adtvar),
                 SUB(SUB1_var, SUB2_var):
                   sub?_fun(red(SUB1_var), red(SUB2_var),
                            IntervalExpr_adtvar),
                 MULT(MULT1_var, MULT2_var):
                   mult?_fun(red(MULT1_var), red(MULT2_var),
                             IntervalExpr_adtvar),
                 SQ(SQ1_var): sq?_fun(red(SQ1_var), IntervalExpr_adtvar),
                 POW(POW1_var, POW2_var):
                   pow?_fun(red(POW1_var), POW2_var, IntervalExpr_adtvar),
                 DIV(DIV1_var, DIV2_var):
                   div?_fun(red(DIV1_var), red(DIV2_var),
                            IntervalExpr_adtvar),
                 FUN(FUN1_var, FUN2_var, FUN3_var, FUN4_var):
                   fun?_fun(FUN1_var, FUN2_var, FUN3_var, red(FUN4_var),
                            IntervalExpr_adtvar),
                 LETIN(LETIN1_var, LETIN2_var):
                   letin?_fun(red(LETIN1_var), red(LETIN2_var),
                              IntervalExpr_adtvar),
                 BCONST(BCONST1_var):
                   bconst?_fun(BCONST1_var, IntervalExpr_adtvar),
                 BNOT(BNOT1_var):
                   bnot?_fun(red(BNOT1_var), IntervalExpr_adtvar),
                 BAND(BAND1_var, BAND2_var):
                   band?_fun(red(BAND1_var), red(BAND2_var),
                             IntervalExpr_adtvar),
                 BOR(BOR1_var, BOR2_var):
                   bor?_fun(red(BOR1_var), red(BOR2_var),
                            IntervalExpr_adtvar),
                 BIMPLIES(BIMPLIES1_var, BIMPLIES2_var):
                   bimplies?_fun(red(BIMPLIES1_var), red(BIMPLIES2_var),
                                 IntervalExpr_adtvar),
                 BREL(BREL1_var, BREL2_var, BREL3_var):
                   brel?_fun(BREL1_var, red(BREL2_var), red(BREL3_var),
                             IntervalExpr_adtvar),
                 BINCLUDES(BINCLUDES1_var, BINCLUDES2_var):
                   bincludes?_fun(red(BINCLUDES1_var), BINCLUDES2_var,
                                  IntervalExpr_adtvar),
                 BITE(BITE1_var, BITE2_var, BITE3_var):
                   bite?_fun(red(BITE1_var), red(BITE2_var), red(BITE3_var),
                             IntervalExpr_adtvar),
                 BLETIN(BLETIN1_var, BLETIN2_var):
                   bletin?_fun(red(BLETIN1_var), red(BLETIN2_var),
                               IntervalExpr_adtvar)
              ENDCASES;
   END IntervalExpr_adt_reduce


body:
  %------------------------------------------------------------------------------
  % Top file for Lebesgue Integration
  %
  %     Author: David Lester, Manchester University
  %
  % References: AJ Weir, "Lebesgue Integration and Measure" CUP, 1973.
  %
  %     Version 1.0            26/2/10   Initial Version
  %
  % In order for this theory to typecheck, you must first kill bins (i.e. rm pvsbin/*.bin) in
  %
  %     measure_integration
  %     metric_space
  %
  %------------------------------------------------------------------------------

  top: THEORY

  BEGIN

    IMPORTING

  % Extras for Metric Space
      bounded_interval_props,
      continuous_on,      % continuity on subsets
      real_intervals_aux, % Bounded Intervals
      real_intervals,     % Often-used intervals
      tends,

  % Extras for analysis
      restriction_integral,  % restrict/extend for analysis Integrals

  % Lebesgue definition
      real_lebesgue_scaf ,   % Old version of lebesgue definition
      lebesgue_def,          % Definition of lebesgue measure (lambda_),
                             %   and measurable sets (cal_M)

  % Riemann-Lebesgue link
      ae_continuous_def,     % definitions of ae continuity
      riemann_scaf,          % link scaffolding
      riemann_link,          % link
      lebesgue_fundamental   % Fundamental Theorem of Calculus for Lebesgue
                             %     (includes integration by parts)

  END top


body:
  %------------------------------------------------------------------------------
  % Extras for analysis library
  %
  %     Author: David Lester, Manchester University
  %
  % (Bored at Houston, after SCAN08 in El Paso)
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  restriction_integral[T1,T2:TYPE FROM real]: THEORY

  BEGIN

    ASSUMING

      connected_domain_T1 : ASSUMPTION
          FORALL (x, y : T1), (z : real) :
              x <= z AND z <= y IMPLIES T1_pred(z)

      connected_domain_T2 : ASSUMPTION
          FORALL (x, y : T2), (z : real) :
              x <= z AND z <= y IMPLIES T2_pred(z)

      not_one_element_T1 : ASSUMPTION
          FORALL (x : T1) : EXISTS (y : T1) : x /= y

      not_one_element_T2 : ASSUMPTION
          FORALL (x : T2) : EXISTS (y : T2) : x /= y

      sub_domain : ASSUMPTION
          FORALL (x : T1) : EXISTS (y : T2) : x = y

    ENDASSUMING

    IMPORTING analysis@integral_def

    a,b: VAR T1
    c:   VAR real
    f:   VAR [T2 -> real]
    g:   VAR [T1 -> real]

    restrict_Integrable: LEMMA Integrable?[T2](a,b,f) <=>
                               Integrable?[T1](a,b,restrict[T2,T1,real](f))

    restrict_Integral:   LEMMA Integrable?[T2](a,b,f) =>
                Integral[T2](a,b,f) = Integral[T1](a,b,restrict[T2,T1,real](f))

    extend_Integrable:   LEMMA Integrable?[T1](a,b,g) <=>
                               Integrable?[T2](a,b,extend[T2,T1,real,c](g))

    extend_Integral:     LEMMA Integrable?[T1](a,b,g) =>
                Integral[T1](a,b,g) = Integral[T2](a,b,extend[T2,T1,real,c](g))

  END restriction_integral

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

  % Subtype TCC generated (at line 43, column 45) for  a
      % expected type  T2
  restrict_Integrable_TCC1: OBLIGATION FORALL (a: T1): T2_pred(a);

  % Assuming TCC generated (at line 14, column 6) for
      % analysis@integral_def[T2]
      % generated from assumption integral_def.connected_domain
  restrict_Integrable_TCC2: OBLIGATION connected?[T2];

  % Assuming TCC generated (at line 17, column 6) for
      % analysis@integral_def[T2]
      % generated from assumption integral_def.not_one_element
  restrict_Integrable_TCC3: OBLIGATION not_one_element?[T2];

  % Assuming TCC generated (at line 14, column 6) for
      % analysis@integral_def[T1]
      % generated from assumption integral_def.connected_domain
  restrict_Integrable_TCC4: OBLIGATION connected?[T1];

  % Assuming TCC generated (at line 17, column 6) for
      % analysis@integral_def[T1]
      % generated from assumption integral_def.not_one_element
  restrict_Integrable_TCC5: OBLIGATION not_one_element?[T1];

  % Subtype TCC generated (at line 47, column 29) for  b
      % expected type  T2
  restrict_Integral_TCC1: OBLIGATION
    FORALL (a, b: T1, f: [T2 -> real]):
      Integrable?[T2](a, b, f) IMPLIES T2_pred(b);

  % Subtype TCC generated (at line 43, column 41) for  x
      % expected type  T2
  restrict_Integral_TCC2: OBLIGATION
    FORALL (a, b: T1, f: [T2 -> real]):
      Integrable?[T2](a, b, f) IMPLIES (FORALL (x: T1): T2_pred(x));

  % Subtype TCC generated (at line 47, column 53) for
      % restrict[T2, T1, real](f)
      % expected type  Integrable_funs[T1](a, b)
  restrict_Integral_TCC3: OBLIGATION
    FORALL (a, b: T1, f: [T2 -> real]):
      Integrable?[T2](a, b, f) IMPLIES
       Integrable?[T1](a, b, restrict[T2, T1, real](f));

  % Subtype TCC generated (at line 53, column 51) for  b
      % expected type  T2
  extend_Integral_TCC1: OBLIGATION
    FORALL (a, b: T1, g: [T1 -> real]):
      Integrable?[T1](a, b, g) IMPLIES T2_pred(b);

  % Subtype TCC generated (at line 43, column 41) for  x
      % expected type  T2
  extend_Integral_TCC2: OBLIGATION
    FORALL (a, b: T1, g: [T1 -> real]):
      Integrable?[T1](a, b, g) IMPLIES (FORALL (x: T1): T2_pred(x));

  % Subtype TCC generated (at line 53, column 53) for
      % extend[T2, T1, real, c](g)
      % expected type  Integrable_funs[T2](a, b)
  extend_Integral_TCC3: OBLIGATION
    FORALL (a, b: T1, c: real, g: [T1 -> real]):
      Integrable?[T1](a, b, g) IMPLIES
       Integrable?[T2](a, b, extend[T2, T1, real, c](g));


body:
  %------------------------------------------------------------------------------
  % Continuity on subtypes of real
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  continuous_on[T:TYPE FROM real]: THEORY

  BEGIN

    IMPORTING metric_space@real_topology,
              topology@continuity_def[real,metric_induced_topology,
                                      real,metric_induced_topology]

    f: VAR [real -> real]
    x: VAR T

    continuous_on?(f):bool = FORALL x: continuous_at?(f,x)

    continuous_on: TYPE = (continuous_on?)

  END continuous_on


body:
  %------------------------------------------------------------------------------
  % Properties of real intervals
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  real_intervals_aux: THEORY

  BEGIN

    IMPORTING metric_space@real_topology,
              reals@bounded_reals
    
    X,A: VAR set[real]
    b: VAR bounded_interval
    u: VAR unbounded_interval
    n: VAR nat
    r: VAR posreal
    nnr: VAR nnreal
    a,x: VAR real

    closed_interval?(A):bool       = interval?(A) and metric_closed?(A)
    open_interval?(A):bool         = interval?(A) and metric_open?(A)

    bounded_open_interval_def: LEMMA bounded_open_interval?(A) <=>
                                     empty?(A) OR EXISTS x,r: A = ball(x,r)

    unbounded_open_interval_def: LEMMA
       (unbounded?(A) AND open_interval?(A)) <=>
       (A = fullset[real] OR
        (EXISTS a: A = open_inf(a)) OR
        (EXISTS a: A = inf_open(a)))

    length(b):nnreal = IF empty?[real](b) THEN 0 ELSE sup(b)-inf(b) ENDIF % 2.1.1

    length_closed: LEMMA nonempty?[real](b) =>
                         length(b) = length({x | inf(b) <= x AND x <= sup(b)})
    length_open:   LEMMA nonempty?[real](b) =>
                         length(b) = length({x | inf(b) <  x AND x <  sup(b)})

    length_empty_rew:  LEMMA length(emptyset[real]) = 0
    length_closed_rew: LEMMA FORALL (b:{x|a<=x}):
                             length({x | a <= x AND x <= b}) = b-a
    length_open_rew:   LEMMA FORALL (b:{x|a<=x}):
                             length({x | a < x AND x < b})   = b-a



    left_closed_right_open_interval?(A):bool
      = nonempty?(A) AND
        interval?(A) AND
        (above_bounded(A) => NOT A(sup(A))) AND
        (below_bounded(A) => A(inf(A)))

    left_closed_right_open_interval: TYPE+ = (left_closed_right_open_interval?)
                                             CONTAINING fullset[real]

    nonempty_interval?(A):bool = nonempty?(A) AND interval?(A)
    nonempty_interval: TYPE+ = (nonempty_interval?) CONTAINING fullset[real]

  END real_intervals_aux

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

  % Subtype TCC generated (at line 36, column 56) for  b
      % expected type  Su: sup_set[real]
  length_TCC1: OBLIGATION
    FORALL (b: bounded_interval):
      NOT empty?[real](b) IMPLIES
       nonempty?[real](b) AND above_bounded[real](b);

  % Subtype TCC generated (at line 36, column 63) for  b
      % expected type  Sl: inf_set[real]
  length_TCC2: OBLIGATION
    FORALL (b: bounded_interval):
      NOT empty?[real](b) IMPLIES
       nonempty?[real](b) AND below_bounded[real](b);

  % Subtype TCC generated (at line 36, column 52) for  sup(b) - inf(b)
      % expected type  nnreal
  length_TCC3: OBLIGATION
    FORALL (b: bounded_interval):
      NOT empty?[real](b) IMPLIES sup[real](b) - inf[real](b) >= 0;

  % Subtype TCC generated (at line 39, column 51) for  b
      % expected type  Sl: inf_set[real]
  length_closed_TCC1: OBLIGATION
    FORALL (b: bounded_interval):
      nonempty?[real](b) IMPLIES below_bounded[real](b);

  % Subtype TCC generated (at line 39, column 72) for  b
      % expected type  Su: sup_set[real]
  length_closed_TCC2: OBLIGATION
    FORALL (b: bounded_interval):
      nonempty?[real](b) IMPLIES
       (FORALL (x: real): inf(b) <= x IMPLIES above_bounded[real](b));

  % Subtype TCC generated (at line 39, column 42) for
      % {x | inf(b) <= x AND x <= sup(b)}
      % expected type  bounded_interval
  length_closed_TCC3: OBLIGATION
    FORALL (b: bounded_interval):
      nonempty?[real](b) IMPLIES
       bounded_interval?({x | inf[real](b) <= x AND x <= sup[real](b)});

  % Subtype TCC generated (at line 41, column 72) for  b
      % expected type  Su: sup_set[real]
  length_open_TCC1: OBLIGATION
    FORALL (b: bounded_interval):
      nonempty?[real](b) IMPLIES
       (FORALL (x: real): inf(b) < x IMPLIES above_bounded[real](b));

  % Subtype TCC generated (at line 41, column 42) for
      % {x | inf(b) < x AND x < sup(b)}
      % expected type  bounded_interval
  length_open_TCC2: OBLIGATION
    FORALL (b: bounded_interval):
      nonempty?[real](b) IMPLIES
       bounded_interval?({x | inf[real](b) < x AND x < sup[real](b)});

  % Subtype TCC generated (at line 43, column 34) for  emptyset[real]
      % expected type  bounded_interval
  length_empty_rew_TCC1: OBLIGATION bounded_interval?(emptyset[real]);

  % Subtype TCC generated (at line 45, column 34) for  {x | a <= x AND x <= b}
      % expected type  bounded_interval
  length_closed_rew_TCC1: OBLIGATION
    FORALL (a: real, b: {x | a <= x}):
      bounded_interval?({x | a <= x AND x <= b});

  % Subtype TCC generated (at line 47, column 34) for  {x | a < x AND x < b}
      % expected type  bounded_interval
  length_open_rew_TCC1: OBLIGATION
    FORALL (a: real, b: {x | a <= x}):
      bounded_interval?({x | a < x AND x < b});

  % Subtype TCC generated (at line 58, column 54) for  fullset[real]
      % expected type  left_closed_right_open_interval
  left_closed_right_open_interval_TCC1: OBLIGATION
    left_closed_right_open_interval?(fullset[real]);

  % Subtype TCC generated (at line 61, column 61) for  fullset[real]
      % expected type  nonempty_interval
  nonempty_interval_TCC1: OBLIGATION nonempty_interval?(fullset[real]);


body:
  %------------------------------------------------------------------------------
  % Real Intervals
  %
  %     Author: David Lester, Manchester University
  %
  % A neater way to express the usual sets over which we integrate
  %
  % In particular, with proper definition of the display functions we
  % get
  %        integral(open_inf(a),f)
  % as
  %        $\int_{(a,\inf)} f$
  %
  % Also, the great counter-example integral(rationals,f)
  % as     $\int_{\mathbb Q} f$
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  real_intervals: THEORY

  BEGIN

    IMPORTING metric_space@real_topology

    x: VAR real

    IMPORTING
      measure_integration@hausdorff_borel[real,metric_induced_topology],
      sets_aux@countable_image, % Proof Only
      power@rational_props_aux  % Proof Only

    rationals:borel = {x | rational_pred(x)}

  END real_intervals

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

  % Subtype TCC generated (at line 33, column 20) for  {x | rational_pred(x)}
      % expected type  borel[real, metric_induced_topology]
  rationals_TCC1: OBLIGATION
    borel?[real, metric_induced_topology]({x | rational_pred(x)});


body:
  %------------------------------------------------------------------------------
  % Scaffold Definitions for Lebesgue inetgration
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  real_lebesgue_scaf: THEORY

  BEGIN

    IMPORTING metric_space@real_topology,
              reals@bounded_reals,
              real_intervals,
              real_intervals_aux,
              sigma_set@absconv_series_aux,
              extended_nnreal@extended_nnreal,
              measure_integration@outer_measure_def[real],
              reals@sqrt % Proof only

    limit: MACRO [convergent->real] = convergence_sequences.limit

    A: VAR set[real]

    b: VAR bounded_interval
    u: VAR unbounded_interval
    i: VAR open_interval
    I: VAR sequence[bounded_open_interval]
    z: VAR extended_nnreal
    n: VAR nat
    r: VAR posreal
    nnr: VAR nnreal
    a,x: VAR real

    x_length(i:interval):extended_nnreal
      = IF bounded_interval?(i) THEN (TRUE,length(i)) ELSE (FALSE,0) ENDIF

    lebesgue_outer_measure: outer_measure                                 % 2.1.6
      = lambda A: x_inf({z | EXISTS I: x_le(x_sum(x_length o I),z) AND
                                       subset?[real](A,IUnion(I))})

    IMPORTING
      measure_integration@outer_measure_props[real,lebesgue_outer_measure]

    lebesgue_outer_measure_singleton: LEMMA                               % 2.1.6
       x_eq(lebesgue_outer_measure(singleton[real](x)),(TRUE,0))

    lebesgue_outer_measure_closed_open: LEMMA nonempty?[real](b) =>       % 2.1.6
       x_eq(lebesgue_outer_measure({x | inf(b) <= x AND x <= sup(b)}),
            lebesgue_outer_measure({x | inf(b) <  x AND x <  sup(b)}))

    lebesgue_outer_measure_closed_open_rew: LEMMA FORALL (b:{x|a<=x}):
       x_eq(lebesgue_outer_measure({x | a <= x AND x <= b}),
            lebesgue_outer_measure({x | a <  x AND x <  b}))

    lebesgue_outer_measure_closed: LEMMA nonempty?[real](b) =>            % 2.1.6
       x_eq(lebesgue_outer_measure(b),
            lebesgue_outer_measure({x | inf(b) <= x AND x <= sup(b)}))

    lebesgue_outer_measure_open: LEMMA nonempty?[real](b) =>              % 2.1.6
       x_eq(lebesgue_outer_measure(b),
            lebesgue_outer_measure({x | inf(b) < x AND x < sup(b)}))

    lebesgue_outer_measure_le_length: LEMMA                               % 2.1.6
       x_le(lebesgue_outer_measure(b),x_length(b))

    IMPORTING metric_space@heine_borel, % Proof Only
              sigma_set@sigma_countable  % Proof Only

    lebesgue_outer_measure_eq_length: LEMMA                               % 2.1.6
       x_eq(lebesgue_outer_measure(b),x_length(b))

    lebesgue_outer_measure_bounded_interval: LEMMA
                     lebesgue_outer_measure(b) = (TRUE,length(b))         % 2.1.6

    lebesgue_outer_measure_unbounded_interval: LEMMA
                     NOT lebesgue_outer_measure(u)`1                      % 2.1.8

    IMPORTING measure_integration@real_borel

    outer_measurable_open_semi_infinite: LEMMA outer_measurable?({x | x < a})
                                                                          % 2.2.1

    lebesgue_measurable:sigma_algebra[real] = fullset[(outer_measurable?)]

    open_interval_is_lebesgue_measurable:
                         JUDGEMENT open_interval   SUBTYPE_OF outer_measurable

    borel_is_lebesgue_measurable: JUDGEMENT borel  SUBTYPE_OF outer_measurable
                                                                          % 2.4.6
    closed_interval_is_lebesgue_measurable:
                         JUDGEMENT closed_interval SUBTYPE_OF outer_measurable

    IMPORTING measure_integration@measure_def[real,lebesgue_measurable]

    lebesgue_measure: complete_sigma_finite[real,lebesgue_measurable]
      = induced_measure

  END real_lebesgue_scaf

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

  % Subtype TCC generated (at line 25, column 36) for
      % convergence_sequences.limit
      % expected type  [convergent[real, (metric_induced_topology)] -> real]
  limit_TCC1: OBLIGATION
    FORALL (x: sequence[real]):
      convergent?(x) IFF
       convergent?
           [real,
            (metric_induced_topology
                 [real, (LAMBDA (x, y: real): abs(x - y))])]
           (x);

  % Subtype TCC generated (at line 43, column 59) for  I
      % expected type  [nat -> interval]
  lebesgue_outer_measure_TCC1: OBLIGATION
    FORALL (I): FORALL (x1: nat): interval?(I(x1));

  % Subtype TCC generated (at line 43, column 6) for
      % LAMBDA A:
      %   x_inf({z |
      %            EXISTS I:
      %              x_le(x_sum(x_length o I), z) AND
      %               subset?[real](A, IUnion(I))})
      % expected type  outer_measure[real]
  lebesgue_outer_measure_TCC2: OBLIGATION
    outer_measure?[real]
        (LAMBDA A:
           x_inf({z |
                    EXISTS I:
                      x_le(x_sum(o[nat, interval, extended_nnreal]
                                     (x_length, I)),
                           z)
                       AND subset?[real](A, IUnion[nat, real](I))}));

  % Subtype TCC generated (at line 53, column 42) for  b
      % expected type  Sl: inf_set[real]
  lebesgue_outer_measure_closed_open_TCC1: OBLIGATION
    FORALL (b: bounded_interval):
      nonempty?[real](b) IMPLIES below_bounded[real](b);

  % Subtype TCC generated (at line 53, column 63) for  b
      % expected type  Su: sup_set[real]
  lebesgue_outer_measure_closed_open_TCC2: OBLIGATION
    FORALL (b: bounded_interval):
      nonempty?[real](b) IMPLIES
       (FORALL (x: real): inf(b) <= x IMPLIES above_bounded[real](b));

  % Subtype TCC generated (at line 54, column 63) for  b
      % expected type  Su: sup_set[real]
  lebesgue_outer_measure_closed_open_TCC3: OBLIGATION
    FORALL (b: bounded_interval):
      nonempty?[real](b) IMPLIES
       (FORALL (x: real): inf(b) < x IMPLIES above_bounded[real](b));

  % Subtype TCC generated (at line 69, column 45) for  b
      % expected type  interval
  lebesgue_outer_measure_le_length_TCC1: OBLIGATION
    FORALL (b: bounded_interval): interval?(b);

  % Subtype TCC generated (at line 88, column 44) for
      % extend
      %     [setof[real], (outer_measurable?[real, lebesgue_outer_measure]),
      %      bool, FALSE]
      %     (fullset[(outer_measurable?)])
      % expected type  sigma_algebra[real]
  lebesgue_measurable_TCC1: OBLIGATION
    sigma_algebra?[real]
        (extend
             [setof[real], (outer_measurable?[real, lebesgue_outer_measure]),
              bool, FALSE]
             (fullset[(outer_measurable?[real, lebesgue_outer_measure])]));

  % Judgement subtype TCC generated (at line 91, column 33) for  x
      % expected type  outer_measurable[real, lebesgue_outer_measure]
  open_interval_is_lebesgue_measurable: OBLIGATION
    FORALL (x: open_interval):
      outer_measurable?[real, lebesgue_outer_measure](x);

  % Judgement subtype TCC generated (at line 93, column 42) for  x
      % expected type  outer_measurable[real, lebesgue_outer_measure]
  borel_is_lebesgue_measurable: OBLIGATION
    FORALL (x: borel): outer_measurable?[real, lebesgue_outer_measure](x);

  % Subtype TCC generated (at line 101, column 6) for  induced_measure
      % expected type  complete_sigma_finite[real, lebesgue_measurable]
  lebesgue_measure_TCC1: OBLIGATION
    (FORALL (x: setof[real]):
       induced_sigma_algebra[real, lebesgue_outer_measure](x) IFF
        lebesgue_measurable(x))
     AND
     complete_sigma_finite?[real, lebesgue_measurable]
         (induced_measure[real, lebesgue_outer_measure]);


body:
  %------------------------------------------------------------------------------
  % Definitions for Lebesgue inetgration
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  % cal_M is the sigma-algebra of Lebesgue-measurable sets of real.
  % lambda_ is the associated Lebesgue-measure
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  lebesgue_def: THEORY

  BEGIN

    IMPORTING real_lebesgue_scaf,
              measure_integration@real_borel

    i,A,B: VAR interval
    X:     VAR sequence[interval]
    n:     VAR nat

    cal_M:sigma_algebra = lebesgue_measurable          % Lebesgue Measurable sets

    a,x: VAR real
    r:   VAR posreal
    nnr: VAR nnreal

    open_semi_infinite_is_cal_M: LEMMA member({x | x < a},cal_M)          % 2.2.1
    borel_is_cal_M:              LEMMA subset?(borel?,cal_M)
    open_interval_is_cal_M:      LEMMA subset?(open_interval?,cal_M)
    closed_interval_is_cal_M:    LEMMA subset?(closed_interval?,cal_M)
    singleton_is_cal_M:          LEMMA member(singleton[real](x),cal_M)
    ball_is_cal_M:               LEMMA member(ball(x,r),cal_M)
    closed_ball_is_cal_M:        LEMMA member(closed_ball(x,nnr),cal_M)   % 2.4.6

    IMPORTING measure_integration@measure_def[real,cal_M]

    lambda_: complete_sigma_finite[real,cal_M] = lebesgue_measure
                                                               % Lebesgue Measure

    lambda_singleton:   LEMMA lambda_(singleton[real](x)) = (TRUE, 0)
    lambda_ball:        LEMMA lambda_(ball(x,r))          = (TRUE, 2*r)
    lambda_closed_ball: LEMMA lambda_(closed_ball(x,nnr)) = (TRUE, 2*nnr)

    IMPORTING measure_integration@measure_space_def[real,cal_M]

    IMPORTING
      measure_integration@complete_measure_theory[real,cal_M,lambda_],
      measure_integration@complete_integral[real,cal_M,lambda_]

    integrable_phi_open:   LEMMA FORALL (a:real,b:{x | a < x}):
                                 integrable?(phi(open(a,b)))
    integrable_phi_closed: LEMMA FORALL (a:real,b:{x | a <= x}):
                                 integrable?(phi(closed(a,b)))
    integral_phi_open:   LEMMA FORALL (a:real,b:{x | a < x}):
                               integral(phi(open(a,b)))   = b-a
    integral_phi_closed: LEMMA FORALL (a:real,b:{x | a <= x}):
                               integral(phi(closed(a,b))) = b-a

    IMPORTING
      topology@identity_continuity[real,metric_induced_topology]

    I_is_measurable:          JUDGEMENT I[real]    HAS_TYPE   measurable_function
    continuous_is_measurable: JUDGEMENT continuous SUBTYPE_OF measurable_function

    X: VAR finite_set[real]
    C: VAR countable_set[real]

    singleton_is_measurable:
                          JUDGEMENT singleton[real](x)    HAS_TYPE measurable_set
    open_is_measurable:   JUDGEMENT
                            open(a:real,b:{x | a < x})    HAS_TYPE measurable_set
    closed_is_measurable: JUDGEMENT
                            closed(a:real,b:{x | a <= x}) HAS_TYPE measurable_set
    finite_is_measurable: JUDGEMENT finite_set[real]    SUBTYPE_OF measurable_set
    countable_is_measurable:
                          JUDGEMENT countable_set[real] SUBTYPE_OF measurable_set

    singleton_is_null: JUDGEMENT singleton[real](x)    HAS_TYPE null_set
    finite_is_null:    JUDGEMENT finite_set[real]    SUBTYPE_OF null_set
    countable_is_null: JUDGEMENT countable_set[real] SUBTYPE_OF null_set

    integrable_singleton:  LEMMA integrable?(phi(singleton[real](x)))
    integrable_finite:     LEMMA integrable?(phi(X))
    integrable_countable:  LEMMA integrable?(phi(C))

    integral_singleton:  LEMMA integral(phi(singleton[real](x))) = 0
    integral_finite:     LEMMA integral(phi(X)) = 0
    integral_countable:  LEMMA integral(phi(C)) = 0


  % The following lemmas are needed to prove the Riemann-Lebesgue lemmas.
  % Essentially, we show that any bounded measurable set can be approximated
  % by a convergent sequence of bounded open intervals.

    nonempty_bounded_open_interval_prop: LEMMA
       FORALL (b:bounded_open_interval):
              nonempty?[real](b) => EXISTS x,r: b = ball(x,r)

    bounded_open_interval_is_measurable:
       JUDGEMENT bounded_open_interval SUBTYPE_OF measurable_set

    E: VAR (mu_fin?)
    I: VAR sequence[bounded_open_interval]

    lebesgue_measurable_intervals: LEMMA
      EXISTS I: subset?[real](E,IUnion(I)) AND
                mu_fin?(IUnion(I))         AND
                convergence?(lambda n: mu(IUnion(n,I)),mu(IUnion(I))) AND
                mu(IUnion(I)) - mu(E) < r


  END lebesgue_def

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

  % Subtype TCC generated (at line 42, column 47) for  lebesgue_measure
      % expected type  complete_sigma_finite[real, cal_M]
  lambda__TCC1: OBLIGATION
    (FORALL (x: setof[real]): lebesgue_measurable(x) IFF cal_M(x)) AND
     complete_sigma_finite?[real, cal_M](lebesgue_measure);

  % Subtype TCC generated (at line 45, column 36) for  singleton[real](x)
      % expected type  (cal_M)
  lambda_singleton_TCC1: OBLIGATION
    FORALL (x: real): cal_M(singleton[real](x));

  % Subtype TCC generated (at line 46, column 36) for  ball(x, r)
      % expected type  (cal_M)
  lambda_ball_TCC1: OBLIGATION
    FORALL (r: posreal, x1: real):
      cal_M(ball[real, (LAMBDA (x, y: real): abs(x - y))](x1, r));

  % Subtype TCC generated (at line 47, column 36) for  closed_ball(x, nnr)
      % expected type  (cal_M)
  lambda_closed_ball_TCC1: OBLIGATION
    FORALL (nnr: nnreal, x: real): cal_M(closed_ball(x, nnr));

  % Subtype TCC generated (at line 60, column 38) for  phi(open(a, b))
      % expected type  integrable[real, cal_M, lambda_]
  integral_phi_open_TCC1: OBLIGATION
    FORALL (a: real, b: {x | a < x}):
      integrable?[real, cal_M, lambda_](phi[real, cal_M](open(a, b)));

  % Subtype TCC generated (at line 62, column 38) for  phi(closed(a, b))
      % expected type  integrable[real, cal_M, lambda_]
  integral_phi_closed_TCC1: OBLIGATION
    FORALL (a: real, b: {x | a <= x}):
      integrable?[real, cal_M, lambda_](phi[real, cal_M](closed(a, b)));

  % Judgement subtype TCC generated (at line 67, column 38) for  I[real]
      % expected type  measurable_function[real, cal_M]
  I_is_measurable: OBLIGATION measurable_function?[real, cal_M](I[real]);

  % Judgement subtype TCC generated (at line 68, column 38) for  x
      % expected type  measurable_function[real, cal_M]
  continuous_is_measurable: OBLIGATION
    FORALL (x: continuous): measurable_function?[real, cal_M](x);

  % Judgement subtype TCC generated (at line 74, column 34) for
      % singleton[real](x)
      % expected type  measurable_set[real, cal_M]
  singleton_is_measurable: OBLIGATION
    FORALL (x): measurable_set?[real, cal_M](singleton[real](x));

  % Judgement subtype TCC generated (at line 76, column 26) for  open(a, b)
      % expected type  measurable_set[real, cal_M]
  open_is_measurable: OBLIGATION
    FORALL (a: real, b: {x | a < x}):
      measurable_set?[real, cal_M](open(a, b));

  % Judgement subtype TCC generated (at line 78, column 26) for  closed(a, b)
      % expected type  measurable_set[real, cal_M]
  closed_is_measurable: OBLIGATION
    FORALL (a: real, b: {x | a <= x}):
      measurable_set?[real, cal_M](closed(a, b));

  % Judgement subtype TCC generated (at line 79, column 34) for  x
      % expected type  measurable_set[real, cal_M]
  finite_is_measurable: OBLIGATION
    FORALL (x: finite_set[real]): measurable_set?[real, cal_M](x);

  % Judgement subtype TCC generated (at line 81, column 34) for  x
      % expected type  measurable_set[real, cal_M]
  countable_is_measurable: OBLIGATION
    FORALL (x: countable_set[real]): measurable_set?[real, cal_M](x);

  % Judgement subtype TCC generated (at line 83, column 31) for
      % singleton[real](x)
      % expected type  null_set[real, cal_M, lambda_]
  singleton_is_null: OBLIGATION
    FORALL (x): null_set?[real, cal_M, lambda_](singleton[real](x));

  % Judgement subtype TCC generated (at line 84, column 31) for  x
      % expected type  null_set[real, cal_M, lambda_]
  finite_is_null: OBLIGATION
    FORALL (x: finite_set[real]): null_set?[real, cal_M, lambda_](x);

  % Judgement subtype TCC generated (at line 85, column 31) for  x
      % expected type  null_set[real, cal_M, lambda_]
  countable_is_null: OBLIGATION
    FORALL (x: countable_set[real]): null_set?[real, cal_M, lambda_](x);

  % Subtype TCC generated (at line 91, column 38) for  phi(singleton[real](x))
      % expected type  integrable[real, cal_M, lambda_]
  integral_singleton_TCC1: OBLIGATION
    FORALL (x: real):
      integrable?[real, cal_M, lambda_](phi[real, cal_M](singleton[real](x)));

  % Subtype TCC generated (at line 92, column 38) for  phi(X)
      % expected type  integrable[real, cal_M, lambda_]
  integral_finite_TCC1: OBLIGATION
    FORALL (X: finite_set[real]):
      integrable?[real, cal_M, lambda_](phi[real, cal_M](X));

  % Subtype TCC generated (at line 93, column 38) for  phi(C)
      % expected type  integrable[real, cal_M, lambda_]
  integral_countable_TCC1: OBLIGATION
    FORALL (C: countable_set[real]):
      integrable?[real, cal_M, lambda_](phi[real, cal_M](C));

  % Judgement subtype TCC generated (at line 105, column 15) for  x
      % expected type  measurable_set[real, cal_M]
  bounded_open_interval_is_measurable: OBLIGATION
    FORALL (x: bounded_open_interval): measurable_set?[real, cal_M](x);

  % Subtype TCC generated (at line 113, column 40) for  IUnion(n, I)
      % expected type  {m: (cal_M) | mu_fin?(m)}
  lebesgue_measurable_intervals_TCC1: OBLIGATION
    FORALL (E: (mu_fin?), I):
      mu_fin?(IUnion(I)) AND subset?[real](E, IUnion(I)) IMPLIES
       (FORALL (n):
          cal_M(IUnion[real](n, I)) AND
           mu_fin?[real, cal_M, lambda_](IUnion[real](n, I)));

  % Subtype TCC generated (at line 113, column 56) for  IUnion(I)
      % expected type  {m: (cal_M) | mu_fin?(m)}
  lebesgue_measurable_intervals_TCC2: OBLIGATION
    FORALL (E: (mu_fin?), I):
      mu_fin?(IUnion(I)) AND subset?[real](E, IUnion(I)) IMPLIES
       cal_M(IUnion[nat, real](I));

  % Subtype TCC generated (at line 114, column 33) for  E
      % expected type  {m: (cal_M) | mu_fin?(m)}
  lebesgue_measurable_intervals_TCC3: OBLIGATION
    FORALL (E: (mu_fin?), I):
      convergence?(LAMBDA n: mu(IUnion(n, I)), mu(IUnion(I))) AND
       mu_fin?(IUnion(I)) AND subset?[real](E, IUnion(I))
       IMPLIES cal_M(E) AND mu_fin?[real, cal_M, lambda_](E);


body:
  %------------------------------------------------------------------------------
  % Definition of almost everywhere continuity
  %
  %     Author: David Lester, Manchester University
  %
  % References: AJ Weir, "Lebesgue Integration and Measure" CUP, 1973.
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  ae_continuous_def: THEORY

  BEGIN

    IMPORTING
      lebesgue_def,
      measure_integration@indefinite_integral[real,cal_M,lambda_],
      metric_space@real_continuity

    a,b,x: VAR real
    f:     VAR [real->real]

    ae_continuous?(a:real,b:{x | a <= x},f):bool
      = null_set?({x | a < x AND x < b AND NOT continuous_at?(f,x)})

    ae_continuous_def: LEMMA a <= b =>
      (ae_continuous?(a,b,f) <=> ae_continuous?(a,b,phi(closed(a,b))*f))

    continuous_at_is_ae_continuous: LEMMA
      a <= b AND (FORALL x: a < x AND x < b => continuous_at?(f,x)) =>
      ae_continuous?(a,b,f)

    continuous_is_ae_continuous: LEMMA
      a <= b AND continuous?(f) => ae_continuous?(a,b,f)

  END ae_continuous_def


body:
  %------------------------------------------------------------------------------
  % Scaffolding to connect Riemann and Lebesgue Integration
  %
  %     Author: David Lester, Manchester University
  %
  % Using the proof given in AJ Weir, "Lebesgue Integration and Measure"
  % CUP, 1973. Pages 51-53.
  %
  %     Version 1.0            1/5/09   Initial Version
  %------------------------------------------------------------------------------

  riemann_scaf[a:real,b:{x:real | a < x}]: THEORY

  BEGIN

    IMPORTING
      measure_integration@sup_norm[real],
      analysis@integral_def[real],
      analysis@integral_bounded[real],
      analysis@integral_step[real],
      analysis@integral_split_scaf[real],
      analysis@integral[real],
      lebesgue_def,
      measure_integration@indefinite_integral[real,cal_M,lambda_],
      reals@real_fun_orders[real],
      ae_continuous_def,
      sets_aux@countability[real] % Proof Only

    c,l,x,y,z: VAR real
    n,m: VAR nat

    continuous_at?(f:[real->real],x):
       MACRO bool= continuity_def.continuous_at?(f,x)

    zeroed?(f:[real->real]):bool = FORALL (x:real): x < a OR b < x => f(x) = 0
    step?(f:[real->real]):bool = step_function?(a,b,f) AND zeroed?(f)
    zeroed_bounded?(f:[real->real]):bool = sup_norm.bounded?(f) AND zeroed?(f)

    step:    TYPE+ = (step?)           CONTAINING (lambda x: 0)
    bounded: TYPE+ = (zeroed_bounded?) CONTAINING (lambda x: 0)

    IMPORTING
      structures@fun_preds_partial[nat,step,
                        restrict[[real, real], [nat, nat], boolean](reals.<=),
                        (real_fun_orders.<=)]
    P,P1,P2: VAR partition(a,b)
    PS: VAR sequence[partition(a,b)]
    epsilon: VAR posreal
    X:   VAR set[real]
    g:   VAR [real->real]
    f,f1,f2: VAR bounded
    phi,psi: VAR step
    Phi: VAR (increasing?[nat,step,
                          restrict[[real, real], [nat, nat], boolean](reals.<=),
                          (real_fun_orders.<=)])
    Psi: VAR (decreasing?[nat,step,
                          restrict[[real, real], [nat, nat], boolean](reals.<=),
                          (real_fun_orders.<=)])

  % The following converts a partion (as defined in analysis@integral_def)
  % into a finite partition (as defined in integration@isf).

    partition_to_finite_partition(P):finite_partition
      = union(union(singleton({x | x < a}),
                    singleton({x | b < x})),
              union({X | EXISTS (i:below(length(P))): X = singleton(seq(P)(i))},
                    {X | EXISTS (i:below(length(P)-1)):
                           X = {x | seq(P)(i) < x AND x < seq(P)(i+1)}}))

  % Note carefully: the step functions defined in analysis@integral_def
  % are constant over OPEN intervals. They are therefore simple functions
  % (as defined in measure_theory@measure_space).
  %
  % Put simply: step_function? => simple?, but not vice versa.
  %
  %  Consider f = phi(fullset[rational])
  %  Then simple?(phi({x | a <= x AND x <= b})*f), but
  %       NOT step_function?(a,b,f)

    riemann_lebesgue_step_isf: LEMMA
      Integrable?(a,b,phi) AND isf?(phi) AND
      Integral(a,b,phi) = isf_integral(phi)

    riemann_lebesgue_step_integrable: LEMMA                          % A(ii) p51
      Integrable?(a,b,phi) AND integrable?(phi) AND
      Integral(a,b,phi) = integral(phi)

    step_function_is_simple:  JUDGEMENT step SUBTYPE_OF simple
    step_function_is_bounded: JUDGEMENT step SUBTYPE_OF bounded

    lower_step_exists: LEMMA EXISTS phi: phi <= f
    upper_step_exists: LEMMA EXISTS psi: f <= psi

    lower_riemann_integral(f):real
      = sup({z | EXISTS phi: phi <= f AND z = integral(phi)})

    upper_riemann_integral(f):real
      = inf({z | EXISTS psi: f <= psi AND z = integral(psi)})

    lower_riemann_prop1: LEMMA EXISTS phi: phi <= f AND
                                integral(phi) > lower_riemann_integral(f)-epsilon

    upper_riemann_prop1: LEMMA EXISTS psi: f <= psi AND
                                integral(psi) < upper_riemann_integral(f)+epsilon

    lower_riemann_prop2: LEMMA phi <= f =>
                               integral(phi) <= lower_riemann_integral(f)

    upper_riemann_prop2: LEMMA f <= psi =>
                               upper_riemann_integral(f) <= integral(psi)

    lower_upper_riemann_prop: LEMMA                                  % A(i) p51
         lower_riemann_integral(f) <= upper_riemann_integral(f)

    riemann_integrable_def1: LEMMA
         Integrable?(a,b,f) IFF
         lower_riemann_integral(f) = upper_riemann_integral(f)

    riemann_integrable_def2: LEMMA Integrable?(a,b,f) =>
         Integral(a,b,f) = lower_riemann_integral(f)

    ii_of_x(P)(x:{x | a <= x AND x < b}): below(length(P)-1)
      = choose[below(length(P)-1)]({ii:below(length(P)-1) |
                                           seq(P)(ii) <= x AND x < seq(P)(ii+1)})

    ii_of_x_def: LEMMA FORALL (x:{x | a <= x AND x < b},ii:below(length(P)-1)):
        ii_of_x(P)(x) = ii IFF seq(P)(ii) <= x AND x < seq(P)(ii+1)

    ii_of_x_prop: LEMMA FORALL (x,y:{x | a <= x AND x < b}):
        ii_of_x(P)(x) = ii_of_x(P)(y) IFF 
        EXISTS (ii:below(length(P)-1)):
               seq(P)(ii) <= x AND x < seq(P)(ii+1) AND
               seq(P)(ii) <= y AND y < seq(P)(ii+1)

    part_set_of(P)(x:{x | a <= x AND x < b}):(nonempty?[real])
      = {y | seq(P)(ii_of_x(P)(x)) < y AND y < seq(P)(ii_of_x(P)(x)+1)}

    part_set_of_prop: LEMMA a <= x AND x < b AND
                            (NOT EXISTS (ii:below(length(P)-1)): x = seq(P)(ii))
                          =>
                            member[real](x,part_set_of(P)(x))

    lower_step(f,P):step                                              % C p52
      = lambda x: IF x < a OR b < x THEN 0
                  ELSIF in_part?(a,b,P,x) OR x = b THEN f(x)
                  ELSE inf(image(f,part_set_of(P)(x))) ENDIF

    lower_step(f)(P):step = lower_step(f,P)

    upper_step(f,P):step
      = lambda x: IF x < a OR b < x THEN 0
                  ELSIF in_part?(a,b,P,x) OR x = b THEN f(x)
                  ELSE sup(image(f,part_set_of(P)(x))) ENDIF

    upper_step(f)(P):step = upper_step(f,P)

    lower_step_prop: LEMMA lower_step(f,P) <= f
    upper_step_prop: LEMMA f <= upper_step(f,P)

    lower_step_neg: LEMMA lower_step(-f,P) = -upper_step(f,P)

  % Probably not needed..
    lower_step_part: LEMMA step_function_on?(a,b,lower_step(f,P),P)

    riemann_sequence: LEMMA                                           % B p52
         (FORALL n: Phi(n) <= f AND f <= Psi(n)) AND
         convergence?(integral o (Psi-Phi),0)     =>
         EXISTS l: convergence?(integral o Psi, l) AND
                   convergence?(integral o Phi, l) AND
                   Integrable?(a,b,f)              AND
                   Integral(a,b,f) = l

    part_norm(P):posreal = width(a,b,P)

    lower_step_error: LEMMA
      phi = lower_step(f,P1) AND
      psi = lower_step(f,P2) =>
      integral(psi) >= integral(phi) - (length(P1)-2)*2*sup_norm(f)*part_norm(P2)

    darboux: THEOREM                                                  % C p52-3
      convergence?(part_norm o PS,0) =>
      (convergence?(integral o lower_step(f) o PS, lower_riemann_integral(f)) AND
       convergence?(integral o upper_step(f) o PS, upper_riemann_integral(f)))

    part_refines?(P1,P2):bool
      = FORALL (ii:below(length(P1)-1)):
           EXISTS (jj:below(length(P2)-1)):
              seq(P2)(jj) <= seq(P1)(ii) AND seq(P1)(ii+1) <= seq(P2)(jj+1)

    partition_2n(n):partition(a,b) = eq_partition(a,b,2^n+1)

    part_norm_partition_2n: LEMMA part_norm(partition_2n(n)) = (b-a)/2^n
    partion_2n_refines: LEMMA n <= m =>
                              part_refines?(partition_2n(m),partition_2n(n))

    lower_refines: LEMMA part_refines?(P2,P1) =>
                         lower_step(f,P1) <= lower_step(f,P2)
    upper_refines: LEMMA part_refines?(P2,P1) =>
                         upper_step(f,P2) <= upper_step(f,P1)

    continuous_step: LEMMA continuous_at?(f,x) =>
          EXISTS n: LET phi = lower_step(f,partition_2n(n)) IN
                    f(x) - epsilon <= phi(x)

    partition_2n_interior:set[real]
      = {x | a < x AND x < b AND NOT EXISTS n,m: x = ((b-a)*n)/2^m+a}

    partition_2n_exterior:set[real]
      = {x | a <= x AND x <= b AND EXISTS n,m: x = ((b-a)*n)/2^m+a}

    countable_2n_exterior: LEMMA is_countable(partition_2n_exterior)

    partition_2n_ext_int_disjoint: LEMMA
        disjoint?(partition_2n_interior,partition_2n_exterior)

    partition_2n_ext_int_union: LEMMA
        union(partition_2n_interior,partition_2n_exterior) = closed(a,b)

    lower_limit_n(f:bounded,x:(partition_2n_interior))(n):real
      = inf(image(f,part_set_of(partition_2n(n))(x)))

    upper_limit_n(f:bounded,x:(partition_2n_interior))(n):real
      = sup(image(f,part_set_of(partition_2n(n))(x)))

    lower_limit_n_prop: LEMMA partition_2n_interior(x) =>
        lower_limit_n(f,x)(n) = lower_step(f,partition_2n(n))(x)

    upper_limit_n_prop: LEMMA partition_2n_interior(x) =>
        upper_limit_n(f,x)(n) = upper_step(f,partition_2n(n))(x)

    lower_limit(f)(x):real
      = IF NOT partition_2n_interior(x) THEN f(x)
        ELSE sup(image(lower_limit_n(f,x),fullset[nat])) ENDIF

    upper_limit(f)(x):real
      = IF NOT partition_2n_interior(x) THEN f(x)
        ELSE inf(image(upper_limit_n(f,x),fullset[nat])) ENDIF

    lower_limit_prop: LEMMA
        lower_step(f,partition_2n(n))(x) <= lower_limit(f)(x) AND
        lower_limit(f)(x) <= f(x)

    upper_limit_prop: LEMMA
        f(x) <= upper_limit(f)(x) AND
        upper_limit(f)(x) <= upper_step(f,partition_2n(n))(x)

    continuous_at_prop: LEMMA partition_2n_interior(x) =>
        (continuous_at?(f,x) <=> upper_limit(f)(x) = lower_limit(f)(x))

    lower_limit_integrable: LEMMA
        integrable?(lower_limit(f)) AND
        integral(lower_limit(f)) = lower_riemann_integral(f)

    upper_limit_integrable: LEMMA
        integrable?(upper_limit(f)) AND
        integral(upper_limit(f)) = upper_riemann_integral(f)

    ae_continuity_implies_integrable: LEMMA                          % Thm 1, P47
        ae_continuous?(a,b,f) => integrable?(f)

    ae_continuity_implies_Integrable: LEMMA
        ae_continuous?(a,b,f) => Integrable?(a,b,f)

    Integrable_implies_ae_continuity: LEMMA
        Integrable?(a,b,f) => ae_continuous?(a,b,f)

    ae_continuity_implies_integrals: LEMMA
        ae_continuous?(a,b,f) => integral(f) = Integral(a,b,f)

  END riemann_scaf

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

  % Assuming TCC generated (at line 18, column 4) for
      % analysis@integral_def[real]
      % generated from assumption integral_def.connected_domain
  IMP_integral_def_TCC1: OBLIGATION connected?[real];

  % Assuming TCC generated (at line 18, column 4) for
      % analysis@integral_def[real]
      % generated from assumption integral_def.not_one_element
  IMP_integral_def_TCC2: OBLIGATION not_one_element?[real];

  % Subtype TCC generated (at line 39, column 49) for  (LAMBDA x: 0)
      % expected type  step
  step_TCC1: OBLIGATION step?((LAMBDA x: 0));

  % Subtype TCC generated (at line 40, column 49) for  (LAMBDA x: 0)
      % expected type  bounded
  bounded_TCC1: OBLIGATION zeroed_bounded?((LAMBDA x: 0));

  % Subtype TCC generated (at line 45, column 23) for
      % (restrict[[[real -> real], [real -> real]], [step, step], boolean]
      %      ((real_fun_orders.<=)))
      % expected type  (partial_order?[step])
  IMP_fun_preds_partial_TCC1: OBLIGATION
    partial_order?[step]
        ((restrict[[[real -> real], [real -> real]], [step, step], boolean]
              ((real_fun_orders[real].<=))));

  % Subtype TCC generated (at line 68, column 41) for  i
      % expected type  below[P`length]
  partition_to_finite_partition_TCC1: OBLIGATION
    FORALL (P: partition[real](a, b), i: below(length(P) - 1)): i < P`length;

  % Subtype TCC generated (at line 68, column 63) for  i + 1
      % expected type  below[P`length]
  partition_to_finite_partition_TCC2: OBLIGATION
    FORALL (P: partition[real](a, b), i: below(length(P) - 1), x: real):
      seq(P)(i) < x IMPLIES i + 1 < P`length;

  % Subtype TCC generated (at line 64, column 6) for
      % union(union(singleton({x | x < a}), singleton({x | b < x})),
      %       union({X |
      %                EXISTS (i: below(length(P))):
      %                  X = singleton(seq(P)(i))},
      %             {X |
      %                EXISTS (i: below(length(P) - 1)):
      %                  X = ({x | seq(P)(i) < x AND x < seq(P)(i + 1)})}))
      % expected type  finite_partition[real]
  partition_to_finite_partition_TCC3: OBLIGATION
    FORALL (P: partition[real](a, b)):
      finite_partition?[real]
          (union[[real -> bool]]
               (union[[real -> bool]]
                    (singleton[[real -> bool]]({x | x < a}),
                     singleton[[real -> bool]]({x | b < x})),
                union[set[real]]
                    ({X |
                        EXISTS (i: below(length(P))):
                          X =
                           singleton[closed_interval[real](a, b)]
                               (seq(P)(i))},
                     {X |
                        EXISTS (i: below(length(P) - 1)):
                          X = ({x | seq(P)(i) < x AND x < seq(P)(i + 1)})})),
           fullset[real]);

  % Judgement subtype TCC generated (at line 88, column 38) for  x
      % expected type  simple[real, cal_M]
  step_function_is_simple: OBLIGATION
    FORALL (x: step): simple?[real, cal_M](x);

  % Judgement subtype TCC generated (at line 89, column 38) for  x
      % expected type  bounded
  step_function_is_bounded: OBLIGATION FORALL (x: step): zeroed_bounded?(x);

  % Subtype TCC generated (at line 95, column 53) for  phi
      % expected type  integrable[real, cal_M, lambda_]
  lower_riemann_integral_TCC1: OBLIGATION
    FORALL (f: bounded, phi):
      phi <= f IMPLIES integrable?[real, cal_M, lambda_](phi);

  % Subtype TCC generated (at line 95, column 10) for
      % {z | EXISTS phi: phi <= f AND z = integral(phi)}
      % expected type  Su: sup_set[real]
  lower_riemann_integral_TCC2: OBLIGATION
    FORALL (f: bounded):
      nonempty?[real]
          ({z |
              EXISTS phi:
                <=[real](phi, f) AND
                 z = integral[real, cal_M, lambda_](phi)})
       AND
       above_bounded[real]
           ({z |
               EXISTS phi:
                 <=[real](phi, f) AND
                  z = integral[real, cal_M, lambda_](phi)});

  % Subtype TCC generated (at line 98, column 53) for  psi
      % expected type  integrable[real, cal_M, lambda_]
  upper_riemann_integral_TCC1: OBLIGATION
    FORALL (f: bounded, psi):
      f <= psi IMPLIES integrable?[real, cal_M, lambda_](psi);

  % Subtype TCC generated (at line 98, column 10) for
      % {z | EXISTS psi: f <= psi AND z = integral(psi)}
      % expected type  Sl: inf_set[real]
  upper_riemann_integral_TCC2: OBLIGATION
    FORALL (f: bounded):
      nonempty?[real]
          ({z |
              EXISTS psi:
                <=[real](f, psi) AND
                 z = integral[real, cal_M, lambda_](psi)})
       AND
       below_bounded[real]
           ({z |
               EXISTS psi:
                 <=[real](f, psi) AND
                  z = integral[real, cal_M, lambda_](psi)});

  % Subtype TCC generated (at line 122, column 46) for  length(P) - 1
      % expected type  nat
  ii_of_x_TCC1: OBLIGATION FORALL (P): length(P) - 1 >= 0;

  % Subtype TCC generated (at line 124, column 72) for  ii + 1
      % expected type  below[P`length]
  ii_of_x_TCC2: OBLIGATION
    FORALL (P: partition[real](a, b), x: {x | a <= x AND x < b},
            ii: below(length(P) - 1)):
      seq(P)(ii) <= x IMPLIES ii + 1 < P`length;

  % Subtype TCC generated (at line 123, column 33) for
      % {ii: below(length(P) - 1) | seq(P)(ii) <= x AND x < seq(P)(ii + 1)}
      % expected type  p: (nonempty?[below(length(P) - 1)])
  ii_of_x_TCC3: OBLIGATION
    FORALL (P: partition[real](a, b), x: {x | a <= x AND x < b}):
      nonempty?[below(length(P) - 1)]
          ({ii: below(length(P) - 1) |
              seq(P)(ii) <= x AND x < seq(P)(ii + 1)});

  % Subtype TCC generated (at line 136, column 18) for  ii_of_x(P)(x)
      % expected type  below[P`length]
  part_set_of_TCC1: OBLIGATION
    FORALL (P: partition[real](a, b), x: {x | a <= x AND x < b}):
      ii_of_x(P)(x) < P`length;

  % Subtype TCC generated (at line 136, column 52) for  ii_of_x(P)(x) + 1
      % expected type  below[P`length]
  part_set_of_TCC2: OBLIGATION
    FORALL (P: partition[real](a, b), x: {x | a <= x AND x < b}, y: real):
      seq(P)(ii_of_x(P)(x)) < y IMPLIES ii_of_x(P)(x) + 1 < P`length;

  % Subtype TCC generated (at line 136, column 6) for
      % {y | seq(P)(ii_of_x(P)(x)) < y AND y < seq(P)(ii_of_x(P)(x) + 1)}
      % expected type  (nonempty?[real])
  part_set_of_TCC3: OBLIGATION
    FORALL (P: partition[real](a, b), x: {x | a <= x AND x < b}):
      nonempty?[real]
          ({y | seq(P)(ii_of_x(P)(x)) < y AND y < seq(P)(ii_of_x(P)(x) + 1)});

  % Subtype TCC generated (at line 141, column 56) for  x
      % expected type  {x | a <= x AND x < b}
  part_set_of_prop_TCC1: OBLIGATION
    FORALL (P: partition[real](a, b), x: real):
      (NOT (EXISTS (ii: below(length(P) - 1)): x = seq(P)(ii))) AND
       x < b AND a <= x
       IMPLIES a <= x AND x < b;

  % Subtype TCC generated (at line 146, column 48) for  x
      % expected type  {x | a <= x AND x < b}
  lower_step_TCC1: OBLIGATION
    FORALL (P: partition[real](a, b), x):
      NOT (EXISTS (ii: below(length(P) - 1)): x = seq(P)(ii)) AND
       NOT x = b AND NOT x < a AND NOT b < x
       IMPLIES a <= x AND x < b;

  % Subtype TCC generated (at line 146, column 25) for
      % image(f, part_set_of(P)(x))
      % expected type  Sl: inf_set[real]
  lower_step_TCC2: OBLIGATION
    FORALL (f: bounded, P: partition[real](a, b), x):
      NOT (EXISTS (ii: below(length(P) - 1)): x = seq(P)(ii)) AND
       NOT x = b AND NOT x < a AND NOT b < x
       IMPLIES
       nonempty?[real](image[real, real](f, part_set_of(P)(x))) AND
        below_bounded[real](image[real, real](f, part_set_of(P)(x)));

  % Subtype TCC generated (at line 144, column 6) for
      % LAMBDA x:
      %   IF x < a OR b < x THEN 0
      %   ELSIF (EXISTS (ii: below(length(P) - 1)): x = seq(P)(ii)) OR x = b
      %     THEN f(x)
      %   ELSE inf(image(f, part_set_of(P)(x)))
      %   ENDIF
      % expected type  step
  lower_step_TCC3: OBLIGATION
    FORALL (f: bounded, P: partition[real](a, b)):
      step?(LAMBDA x:
              IF x < a OR b < x THEN 0
              ELSIF (EXISTS (ii: below(length(P) - 1)): x = seq(P)(ii)) OR
                     x = b
                THEN f(x)
              ELSE inf[real](image[real, real](f, part_set_of(P)(x)))
              ENDIF);

  % Subtype TCC generated (at line 153, column 25) for
      % image(f, part_set_of(P)(x))
      % expected type  Su: sup_set[real]
  upper_step_TCC1: OBLIGATION
    FORALL (f: bounded, P: partition[real](a, b), x):
      NOT (EXISTS (ii: below(length(P) - 1)): x = seq(P)(ii)) AND
       NOT x = b AND NOT x < a AND NOT b < x
       IMPLIES
       nonempty?[real](image[real, real](f, part_set_of(P)(x))) AND
        above_bounded[real](image[real, real](f, part_set_of(P)(x)));

  % Subtype TCC generated (at line 151, column 6) for
      % LAMBDA x:
      %   IF x < a OR b < x THEN 0
      %   ELSIF (EXISTS (ii: below(length(P) - 1)): x = seq(P)(ii)) OR x = b
      %     THEN f(x)
      %   ELSE sup(image(f, part_set_of(P)(x)))
      %   ENDIF
      % expected type  step
  upper_step_TCC2: OBLIGATION
    FORALL (f: bounded, P: partition[real](a, b)):
      step?(LAMBDA x:
              IF x < a OR b < x THEN 0
              ELSIF (EXISTS (ii: below(length(P) - 1)): x = seq(P)(ii)) OR
                     x = b
                THEN f(x)
              ELSE sup[real](image[real, real](f, part_set_of(P)(x)))
              ENDIF);

  % Subtype TCC generated (at line 160, column 35) for  -f
      % expected type  bounded
  lower_step_neg_TCC1: OBLIGATION FORALL (f: bounded): zeroed_bounded?(-f);

  % Subtype TCC generated (at line 167, column 32) for  (Psi - Phi)
      % expected type  [nat -> integrable[real, cal_M, lambda_]]
  riemann_sequence_TCC1: OBLIGATION
    FORALL (Phi:
              (increasing?
                   [nat, step,
                    restrict[[real, real], [nat, nat], boolean](reals.<=),
                    (restrict
                         [[[real -> real], [real -> real]], [step, step],
                          boolean]
                         ((real_fun_orders.<=)))]),
            Psi:
              (decreasing?
                   [nat, step,
                    restrict[[real, real], [nat, nat], boolean](reals.<=),
                    (restrict
                         [[[real -> real], [real -> real]], [step, step],
                          boolean]
                         ((real_fun_orders.<=)))]),
            f: bounded):
      (FORALL n: Phi(n) <= f AND f <= Psi(n)) IMPLIES
       (FORALL (x1: nat):
          integrable?[real, cal_M, lambda_](((-[real])(Psi, Phi))(x1)));

  % Subtype TCC generated (at line 168, column 41) for  Psi
      % expected type  [nat -> integrable[real, cal_M, lambda_]]
  riemann_sequence_TCC2: OBLIGATION
    FORALL (Phi:
              (increasing?
                   [nat, step,
                    restrict[[real, real], [nat, nat], boolean](reals.<=),
                    (restrict
                         [[[real -> real], [real -> real]], [step, step],
                          boolean]
                         ((real_fun_orders.<=)))]),
            Psi:
              (decreasing?
                   [nat, step,
                    restrict[[real, real], [nat, nat], boolean](reals.<=),
                    (restrict
                         [[[real -> real], [real -> real]], [step, step],
                          boolean]
                         ((real_fun_orders.<=)))]),
            f: bounded):
      (convergence?(integral o (Psi - Phi), 0) AND
        (FORALL n: Phi(n) <= f AND f <= Psi(n)))
       IMPLIES (FORALL (x1: nat): integrable?[real, cal_M, lambda_](Psi(x1)));

  % Subtype TCC generated (at line 169, column 41) for  Phi
      % expected type  [nat -> integrable[real, cal_M, lambda_]]
  riemann_sequence_TCC3: OBLIGATION
    FORALL (Phi:
              (increasing?
                   [nat, step,
                    restrict[[real, real], [nat, nat], boolean](reals.<=),
                    (restrict
                         [[[real -> real], [real -> real]], [step, step],
                          boolean]
                         ((real_fun_orders.<=)))]),
            Psi:
              (decreasing?
                   [nat, step,
                    restrict[[real, real], [nat, nat], boolean](reals.<=),
                    (restrict
                         [[[real -> real], [real -> real]], [step, step],
                          boolean]
                         ((real_fun_orders.<=)))]),
            f: bounded):
      (convergence?(integral o (Psi - Phi), 0) AND
        (FORALL n: Phi(n) <= f AND f <= Psi(n)))
       IMPLIES
       (FORALL (l):
          convergence?(integral o Psi, l) IMPLIES
           (FORALL (x1: nat): integrable?[real, cal_M, lambda_](Phi(x1))));

  % Subtype TCC generated (at line 178, column 13) for  psi
      % expected type  integrable[real, cal_M, lambda_]
  lower_step_error_TCC1: OBLIGATION
    FORALL (P1, P2: partition[real](a, b), f: bounded, phi, psi: step):
      psi = lower_step(f, P2) AND phi = lower_step(f, P1) IMPLIES
       integrable?[real, cal_M, lambda_](psi);

  % Subtype TCC generated (at line 178, column 30) for  phi
      % expected type  integrable[real, cal_M, lambda_]
  lower_step_error_TCC2: OBLIGATION
    FORALL (P1, P2: partition[real](a, b), f: bounded, phi, psi: step):
      psi = lower_step(f, P2) AND phi = lower_step(f, P1) IMPLIES
       integrable?[real, cal_M, lambda_](phi);

  % Subtype TCC generated (at line 178, column 63) for  f
      % expected type  bounded[real]
  lower_step_error_TCC3: OBLIGATION
    FORALL (P1, P2: partition[real](a, b), f: bounded, phi, psi: step):
      psi = lower_step(f, P2) AND phi = lower_step(f, P1) IMPLIES
       bounded?[real](f);

  % Subtype TCC generated (at line 39, column 33) for  0
      % expected type  below[fs`length]
  darboux_TCC1: OBLIGATION
    FORALL (fs: finite_sequence[closed_interval[real](a, b)]):
      length(fs) > 1 IMPLIES 0 < fs`length;

  % Subtype TCC generated (at line 39, column 47) for  length(fs) - 1
      % expected type  below[fs`length]
  darboux_TCC2: OBLIGATION
    FORALL (fs: finite_sequence[closed_interval[real](a, b)]):
      seq(fs)(0) = a AND length(fs) > 1 IMPLIES
       length(fs) - 1 >= 0 AND length(fs) - 1 < fs`length;

  % Subtype TCC generated (at line 40, column 29) for  ii
      % expected type  below[fs`length]
  darboux_TCC3: OBLIGATION
    FORALL (fs: finite_sequence[closed_interval[real](a, b)]):
      seq(fs)(length(fs) - 1) = b AND seq(fs)(0) = a AND length(fs) > 1
       IMPLIES (FORALL (ii: below(length(fs) - 1)): ii < fs`length);

  % Subtype TCC generated (at line 39, column 24) for  1 + ii
      % expected type  below[fs`length]
  darboux_TCC4: OBLIGATION
    FORALL (fs: finite_sequence[closed_interval[real](a, b)]):
      seq(fs)(length(fs) - 1) = b AND seq(fs)(0) = a AND length(fs) > 1
       IMPLIES (FORALL (ii: below(length(fs) - 1)): 1 + ii < fs`length);

  % Subtype TCC generated (at line 182, column 29) for  lower_step(f)
      % expected type  [partition[real](a, b) ->
                     %    integrable[real, cal_M, lambda_]]
  darboux_TCC5: OBLIGATION
    FORALL (PS: sequence[partition(a, b)], f: bounded):
      convergence?(part_norm o PS, 0) IMPLIES
       (FORALL (x1: partition[real](a, b)):
          integrable?[real, cal_M, lambda_](lower_step(f)(x1)));

  % Subtype TCC generated (at line 183, column 29) for  upper_step(f)
      % expected type  [partition[real](a, b) ->
                     %    integrable[real, cal_M, lambda_]]
  darboux_TCC6: OBLIGATION
    FORALL (PS: sequence[partition(a, b)], f: bounded):
      convergence?(part_norm o PS, 0) AND
       convergence?(integral o lower_step(f) o PS, lower_riemann_integral(f))
       IMPLIES
       (FORALL (x1: partition[real](a, b)):
          integrable?[real, cal_M, lambda_](upper_step(f)(x1)));

  % Subtype TCC generated (at line 188, column 20) for  jj
      % expected type  below[P2`length]
  part_refines?_TCC1: OBLIGATION
    FORALL (P1: partition[real](a, b), P2: partition[real](a, b),
            ii: below(length(P1) - 1), jj: below(length(P2) - 1)):
      jj < P2`length;

  % Subtype TCC generated (at line 188, column 51) for  ii + 1
      % expected type  below[P1`length]
  part_refines?_TCC2: OBLIGATION
    FORALL (P1: partition[real](a, b), P2: partition[real](a, b),
            ii: below(length(P1) - 1), jj: below(length(P2) - 1)):
      seq(P2)(jj) <= seq(P1)(ii) IMPLIES ii + 1 < P1`length;

  % Subtype TCC generated (at line 188, column 68) for  jj + 1
      % expected type  below[P2`length]
  part_refines?_TCC3: OBLIGATION
    FORALL (P1: partition[real](a, b), P2: partition[real](a, b),
            ii: below(length(P1) - 1), jj: below(length(P2) - 1)):
      seq(P2)(jj) <= seq(P1)(ii) IMPLIES jj + 1 < P2`length;

  % Subtype TCC generated (at line 190, column 52) for  2 ^ n + 1
      % expected type  above(1)
  partition_2n_TCC1: OBLIGATION
    FORALL (n: nat):
      rational_pred(2 ^ n + 1) AND integer_pred(2 ^ n + 1) AND 2 ^ n + 1 > 1;

  % Subtype TCC generated (at line 192, column 67) for  2 ^ n
      % expected type  nznum
  part_norm_partition_2n_TCC1: OBLIGATION FORALL (n: nat): 2 ^ n /= 0;

  % Subtype TCC generated (at line 217, column 68) for  b
      % expected type  {x | a <= x}
  partition_2n_ext_int_union_TCC1: OBLIGATION a <= b;

  % Subtype TCC generated (at line 220, column 47) for  x
      % expected type  {x | a <= x AND x < b}
  lower_limit_n_TCC1: OBLIGATION
    FORALL (x: (partition_2n_interior)): a <= x AND x < b;

  % Subtype TCC generated (at line 220, column 10) for
      % image(f, part_set_of(partition_2n(n))(x))
      % expected type  Sl: inf_set[real]
  lower_limit_n_TCC2: OBLIGATION
    FORALL (f: bounded, x: (partition_2n_interior), n: nat):
      nonempty?[real](image[real, real](f, part_set_of(partition_2n(n))(x)))
       AND
       below_bounded[real]
           (image[real, real](f, part_set_of(partition_2n(n))(x)));

  % Subtype TCC generated (at line 223, column 10) for
      % image(f, part_set_of(partition_2n(n))(x))
      % expected type  Su: sup_set[real]
  upper_limit_n_TCC1: OBLIGATION
    FORALL (f: bounded, x: (partition_2n_interior), n: nat):
      nonempty?[real](image[real, real](f, part_set_of(partition_2n(n))(x)))
       AND
       above_bounded[real]
           (image[real, real](f, part_set_of(partition_2n(n))(x)));

  % Subtype TCC generated (at line 233, column 15) for
      % image(lower_limit_n(f, x), fullset[nat])
      % expected type  Su: sup_set[real]
  lower_limit_TCC1: OBLIGATION
    FORALL (f: bounded, x: real):
      partition_2n_interior(x) IMPLIES
       nonempty?[real](image[nat, real](lower_limit_n(f, x), fullset[nat]))
        AND
        above_bounded[real]
            (image[nat, real](lower_limit_n(f, x), fullset[nat]));

  % Subtype TCC generated (at line 237, column 15) for
      % image(upper_limit_n(f, x), fullset[nat])
      % expected type  Sl: inf_set[real]
  upper_limit_TCC1: OBLIGATION
    FORALL (f: bounded, x: real):
      partition_2n_interior(x) IMPLIES
       nonempty?[real](image[nat, real](upper_limit_n(f, x), fullset[nat]))
        AND
        below_bounded[real]
            (image[nat, real](upper_limit_n(f, x), fullset[nat]));

  % Subtype TCC generated (at line 268, column 40) for  f
      % expected type  integrable[real, cal_M, lambda_]
  ae_continuity_implies_integrals_TCC1: OBLIGATION
    FORALL (f: bounded):
      ae_continuous?(a, b, f) IMPLIES integrable?[real, cal_M, lambda_](f);

  % Subtype TCC generated (at line 268, column 58) for  f
      % expected type  Integrable_funs[real](a, b)
  ae_continuity_implies_integrals_TCC2: OBLIGATION
    FORALL (f: bounded):
      ae_continuous?(a, b, f) IMPLIES Integrable?[real](a, b, f);


body:
  %------------------------------------------------------------------------------
  % The Lebesgue criterion for Riemann Integrability
  %
  %     Author: David Lester, Manchester University
  %
  % References: AJ Weir, "Lebesgue Integration and Measure" CUP, 1973.
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  riemann_link: THEORY

  BEGIN

    IMPORTING
      riemann_scaf,
      analysis@integral_def[real],
      analysis@integral_bounded[real],
      analysis@integral_cont[real],
      metric_space@continuity_link[real]


    a,b,x: VAR real
    f:     VAR [real->real]

    continuous_at?(f,x): MACRO bool = continuity_def.continuous_at?(f,x)
    continuous?(f):      MACRO bool = continuity_def.continuous?(f)

    bounded_on_def: LEMMA FORALL (a:real,b:{x | a < x},f):
      bounded_on?(a,b,f) <=> zeroed_bounded?[a,b](phi(closed(a,b))*f)

    riemann_integrable_def: LEMMA a <= b =>
      (Integrable?(a,b,f) <=> bounded_on?(a,b,f) AND ae_continuous?(a,b,f))

    riemann_lebesgue_integrable: LEMMA
      a <= b AND Integrable?(a,b,f) => integrable?(closed(a,b))(f)

    riemann_lebesgue_integral: LEMMA
      a <= b AND Integrable?(a,b,f) => Integral(a,b,f) = integral(closed(a,b),f)

    bounded_ae_continuous_integrable: LEMMA
      a <= b AND bounded_on?(a,b,f) AND ae_continuous?(a,b,f) =>
      integrable?(closed(a,b))(f)

    continuous_is_Integrable: LEMMA
      a <= b AND continuous?(f) => Integrable?(a,b,f)

    continuous_is_integrable: LEMMA
      a <= b AND continuous?(f) => integrable?(closed(a,b))(f)

    continuous_at_is_bounded: LEMMA
      a <= b AND (FORALL x: a <= x AND x <= b => continuous_at?(f,x)) =>
      bounded_on?(a,b,f)

  END riemann_link

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

  % Subtype TCC generated (at line 30, column 61) for  b
      % expected type  {x | a <= x}
  bounded_on_def_TCC1: OBLIGATION FORALL (a: real, b: {x | a < x}): a <= b;

  % Subtype TCC generated (at line 39, column 76) for  f
      % expected type  (integrable?(closed(a, b)))
  riemann_lebesgue_integral_TCC1: OBLIGATION
    FORALL (a, b: real, f: [real -> real]):
      Integrable?(a, b, f) AND a <= b IMPLIES
       integrable?[real, cal_M, lambda_](closed(a, b))(f);


body:
  %------------------------------------------------------------------------------
  % The Fundamental Theorem of Calculus for Lebesgue Integrals
  %
  %     Author: David Lester, Manchester University
  %
  % References: AJ Weir, "Lebesgue Integration and Measure" CUP, 1973.
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  lebesgue_fundamental[a:real,b:{x:real | a<x}]: THEORY

  BEGIN

    IMPORTING
      riemann_link,
      analysis@fundamental_theorem[(closed(a,b))],
      analysis@derivative_props[(closed(a,b))],
      continuous_on[(closed(a,b))],
      restriction_integral[(closed(a,b)),real]

    F,G: VAR deriv_fun[(closed(a,b))]
    f,g: VAR continuous_on
    x:   VAR real

  ;
    *(f:[(closed(a,b))->real],g:[real->real]): MACRO [real->real]
        = lambda x: extend[real,(closed(a,b)),real,0](f)(x) * g(x);

    fundamental_lebesgue: THEOREM                        % AJW 3.4 Theorem 2, p57
      deriv(F) = f => integrable?(closed(a,b))(f) AND
                      integral(closed(a,b),f) = F(b) - F(a)

    integration_by_parts: THEOREM                     % AJW 3.4 Proposition 1 p58
      (deriv(F) = f AND deriv(G) = g) =>
      (integrable?(closed(a,b))(F*g) AND
       integrable?(closed(a,b))(G*f) AND
       integral(closed(a,b),F*g) = F(b)*G(b)-F(a)*G(a)-integral(closed(a,b),G*f))

  END lebesgue_fundamental

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

  % Subtype TCC generated (at line 17, column 43) for  b
      % expected type  {x | a <= x}
  IMP_fundamental_theorem_TCC1: OBLIGATION a <= b;

  % Assuming TCC generated (at line 17, column 4) for
      % analysis@fundamental_theorem[(closed(a, b))]
      % generated from assumption fundamental_theorem.connected_domain
  IMP_fundamental_theorem_TCC2: OBLIGATION connected?[(closed(a, b))];

  % Assuming TCC generated (at line 17, column 4) for
      % analysis@fundamental_theorem[(closed(a, b))]
      % generated from assumption fundamental_theorem.not_one_element
  IMP_fundamental_theorem_TCC3: OBLIGATION not_one_element?[(closed(a, b))];

  % Existence TCC generated (at line 17, column 4) for
      % analysis@fundamental_theorem[(closed(a, b))]
  IMP_fundamental_theorem_TCC4: OBLIGATION EXISTS (x: (closed(a, b))): TRUE;

  % Assuming TCC generated (at line 20, column 4) for
      % restriction_integral[(closed(a, b)), real]
      % generated from assumption restriction_integral.connected_domain_T1
  IMP_restriction_integral_TCC1: OBLIGATION
    FORALL (x, y: (closed(a, b))), (z: real):
      x <= z AND z <= y IMPLIES closed(a, b)(z);

  % Assuming TCC generated (at line 20, column 4) for
      % restriction_integral[(closed(a, b)), real]
      % generated from assumption restriction_integral.connected_domain_T2
  IMP_restriction_integral_TCC2: OBLIGATION
    FORALL (x, y: real), (z: real): TRUE;

  % Assuming TCC generated (at line 20, column 4) for
      % restriction_integral[(closed(a, b)), real]
      % generated from assumption restriction_integral.not_one_element_T1
  IMP_restriction_integral_TCC3: OBLIGATION
    FORALL (x: (closed(a, b))): EXISTS (y: (closed(a, b))): x /= y;

  % Assuming TCC generated (at line 20, column 4) for
      % restriction_integral[(closed(a, b)), real]
      % generated from assumption restriction_integral.not_one_element_T2
  IMP_restriction_integral_TCC4: OBLIGATION
    FORALL (x: real): EXISTS (y: real): x /= y;

  % Assuming TCC generated (at line 20, column 4) for
      % restriction_integral[(closed(a, b)), real]
      % generated from assumption restriction_integral.sub_domain
  IMP_restriction_integral_TCC5: OBLIGATION
    FORALL (x: (closed(a, b))): EXISTS (y: real): x = y;

  % Assuming TCC generated (at line 22, column 11) for
      % deriv_fun[(closed(a, b))]
      % generated from assumption derivatives.deriv_domain
  F_TCC1: OBLIGATION deriv_domain?[(closed(a, b))];

  % Subtype TCC generated (at line 32, column 48) for  b
      % expected type  (closed(a, b))
  fundamental_lebesgue_TCC1: OBLIGATION
    FORALL (F: deriv_fun[(closed(a, b))], f: continuous_on[(closed(a, b))]):
      deriv(F) = restrict[real, (closed(a, b)), real](f) AND
       integrable?(closed(a, b))(f)
       IMPLIES closed(a, b)(b);

  % Subtype TCC generated (at line 32, column 55) for  a
      % expected type  (closed(a, b))
  fundamental_lebesgue_TCC2: OBLIGATION
    FORALL (F: deriv_fun[(closed(a, b))], f: continuous_on[(closed(a, b))]):
      deriv(F) = restrict[real, (closed(a, b)), real](f) AND
       integrable?(closed(a, b))(f)
       IMPLIES closed(a, b)(a);

  % Subtype TCC generated (at line 38, column 35) for  b
      % expected type  (closed(a, b))
  integration_by_parts_TCC1: OBLIGATION
    FORALL (F, G: deriv_fun[(closed(a, b))],
            f, g: continuous_on[(closed(a, b))]):
      deriv(G) = restrict[real, (closed(a, b)), real](g) AND
       deriv(F) = restrict[real, (closed(a, b)), real](f) AND
        integrable?(closed(a, b))
                   (LAMBDA (x):
                      extend[real, (closed(a, b)), real, 0](F)(x) * g(x))
         AND
         integrable?(closed(a, b))
                    (LAMBDA (x):
                       extend[real, (closed(a, b)), real, 0](G)(x) * f(x))
       IMPLIES closed(a, b)(b);

  % Subtype TCC generated (at line 38, column 45) for  a
      % expected type  (closed(a, b))
  integration_by_parts_TCC2: OBLIGATION
    FORALL (F, G: deriv_fun[(closed(a, b))],
            f, g: continuous_on[(closed(a, b))]):
      deriv(G) = restrict[real, (closed(a, b)), real](g) AND
       deriv(F) = restrict[real, (closed(a, b)), real](f) AND
        integrable?(closed(a, b))
                   (LAMBDA (x):
                      extend[real, (closed(a, b)), real, 0](F)(x) * g(x))
         AND
         integrable?(closed(a, b))
                    (LAMBDA (x):
                       extend[real, (closed(a, b)), real, 0](G)(x) * f(x))
       IMPLIES closed(a, b)(a);


body:
  %------------------------------------------------------------------------------
  % Generalized Convergence
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------

  tends: THEORY

  BEGIN

    epsilon: VAR posreal
    x,y:     VAR nnreal
    c:       VAR real
    f:       VAR [nnreal->real]

    tends_to?(f,c):bool
      = FORALL epsilon: EXISTS x: FORALL y: y >= x => abs(f(y)-c) < epsilon


  END tends


body:
  %------------------------------------------------------------------------------
  % Properties of bounded intervals
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            26/2/10   Initial Version
  %------------------------------------------------------------------------------
  bounded_interval_props: THEORY

  BEGIN

    IMPORTING real_intervals_aux

    A,B: VAR bounded_interval
    a,b: VAR real

    bounded_interval1: LEMMA A(a) => inf(A) <= a AND a <= sup(A)
    bounded_interval2: LEMMA nonempty?[real](A) AND inf(A) < a AND a < sup(A)
                             => A(a)
    bounded_interval3: LEMMA nonempty?[real](A) => inf(A) <= sup(A)
    bounded_interval4: LEMMA disjoint?[real](A,B) AND A(a) AND B(b) AND a <= b =>
                             sup(A) <= inf(B)
    bounded_interval5: LEMMA disjoint?[real](A,B) AND A(a) AND B(b) AND a <= b =>
                             FORALL (x:(A),y:(B)): x < y

    bounded_interval_disjoint_union1:
       LEMMA disjoint?[real](A,B) AND bounded_interval?(union[real](A,B)) AND
             A(a) AND B(b) AND a <= b =>
             sup(A) = inf(B)

    bounded_interval_disjoint_union2:
       LEMMA disjoint?[real](A,B) AND bounded_interval?(union[real](A,B)) AND
             A(a) AND B(b) AND a <= b =>
             (A(sup(A)) OR B(inf(B)))

    bounded_interval_disjoint_union3:
       LEMMA disjoint?[real](A,B) AND bounded_interval?(union[real](A,B)) AND
             A(a) AND B(b) AND a <= b =>
             inf(union[real](A,B)) = inf(A)

    bounded_interval_disjoint_union4:
       LEMMA disjoint?[real](A,B) AND bounded_interval?(union[real](A,B)) AND
             A(a) AND B(b) AND a <= b =>
             sup(union[real](A,B)) = sup(B)

  END bounded_interval_props

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

  % Subtype TCC generated (at line 17, column 39) for  A
      % expected type  Sl: inf_set[real]
  bounded_interval1_TCC1: OBLIGATION
    FORALL (A: bounded_interval, a: real):
      A(a) IMPLIES nonempty?[real](A) AND below_bounded[real](A);

  % Subtype TCC generated (at line 17, column 60) for  A
      % expected type  Su: sup_set[real]
  bounded_interval1_TCC2: OBLIGATION
    FORALL (A: bounded_interval, a: real):
      A(a) AND inf(A) <= a IMPLIES
       nonempty?[real](A) AND above_bounded[real](A);

  % Subtype TCC generated (at line 18, column 54) for  A
      % expected type  Sl: inf_set[real]
  bounded_interval2_TCC1: OBLIGATION
    FORALL (A: bounded_interval):
      nonempty?[real](A) IMPLIES below_bounded[real](A);

  % Subtype TCC generated (at line 18, column 73) for  A
      % expected type  Su: sup_set[real]
  bounded_interval2_TCC2: OBLIGATION
    FORALL (A: bounded_interval, a: real):
      nonempty?[real](A) AND inf(A) < a IMPLIES above_bounded[real](A);

  % Subtype TCC generated (at line 20, column 63) for  A
      % expected type  Su: sup_set[real]
  bounded_interval3_TCC1: OBLIGATION
    FORALL (A: bounded_interval):
      nonempty?[real](A) IMPLIES above_bounded[real](A);

  % Subtype TCC generated (at line 22, column 31) for  A
      % expected type  Su: sup_set[real]
  bounded_interval4_TCC1: OBLIGATION
    FORALL (A, B: bounded_interval, a, b: real):
      a <= b AND B(b) AND A(a) AND disjoint?[real](A, B) IMPLIES
       nonempty?[real](A) AND above_bounded[real](A);

  % Subtype TCC generated (at line 22, column 41) for  B
      % expected type  Sl: inf_set[real]
  bounded_interval4_TCC2: OBLIGATION
    FORALL (A, B: bounded_interval, a, b: real):
      a <= b AND B(b) AND A(a) AND disjoint?[real](A, B) IMPLIES
       nonempty?[real](B) AND below_bounded[real](B);

  % Subtype TCC generated (at line 39, column 15) for  union[real](A, B)
      % expected type  Sl: inf_set[real]
  bounded_interval_disjoint_union3_TCC1: OBLIGATION
    FORALL (A, B: bounded_interval, a, b: real):
           a <= b AND B(b) AND A(a) AND bounded_interval?(union[real](A, B))
       AND disjoint?[real](A, B)
       IMPLIES
       nonempty?[real](union[real](A, B)) AND
        below_bounded[real](union[real](A, B));

  % Subtype TCC generated (at line 44, column 15) for  union[real](A, B)
      % expected type  Su: sup_set[real]
  bounded_interval_disjoint_union4_TCC1: OBLIGATION
    FORALL (A, B: bounded_interval, a, b: real):
           a <= b AND B(b) AND A(a) AND bounded_interval?(union[real](A, B))
       AND disjoint?[real](A, B)
       IMPLIES
       nonempty?[real](union[real](A, B)) AND
        above_bounded[real](union[real](A, B));

  % Subtype TCC generated (at line 44, column 39) for  B
      % expected type  Su: sup_set[real]
  bounded_interval_disjoint_union4_TCC2: OBLIGATION
    FORALL (A, B: bounded_interval, a, b: real):
           a <= b AND B(b) AND A(a) AND bounded_interval?(union[real](A, B))
       AND disjoint?[real](A, B)
       IMPLIES nonempty?[real](B) AND above_bounded[real](B);


body:
  %------------------------------------------------------------------------
  %  Top of linear algebra theory   05/12/2013
  %------------------------------------------------------------------------
  %   
  %      Index:
  %      ------
  %
  %	sigma_lemmas		-- lemmas about sums
  %
  %	linear_map		-- definitions about maps
  %	sigma_vector		-- summation of vector valued functions
  %	linear_map_def		-- definitions and lemmas about linear maps
  %
  %	vect_of_vect		-- definition of vector of vectors
  %	matrices		-- theory about matrices
  %	matrix_operator		-- bijection between matrices and linear maps
  %	matrix_lemmas		-- basic lemmas about matrices
  %	block_matrices		-- theory about block vectors and block matrices
  %
  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013
  %------------------------------------------------------------------------


  top: THEORY


  BEGIN

   IMPORTING	sigma_lemmas,

  		linear_map,
   		sigma_vector,
              	linear_map_def,

  		vect_of_vect,
  		matrices,
              	matrix_operator,
  		matrix_lemmas,
  		block_matrices


  END top


body:
  sigma_lemmas: THEORY

  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013

   BEGIN

   IMPORTING vectors@vectors



  %------------------------------------------------------------
  % Lemmas about sums
  %------------------------------------------------------------

  % These lemmas go from more specific to more general
  % There are three kinds of lemmas:
  % 1. Restricting the domain of the function
  % 2. Shifting the domain of the function
  % 3. Changing the notation of the domain of the function (although it remains the same)



   sigma_restrict_dom: LEMMA FORALL (j: posnat, m: posnat, F: [below[m] -> real],G: [below[m+1] -> real]): (FORALL (i: below[m]): F(i) = G(i)) IMPLIES (j <= m IMPLIES sigma[below[m]](0,j - 1,F) = sigma[below[m+1]](0,j-1,G))

   sigma_restrict_dom2:  LEMMA FORALL (j: posnat, m: posnat, F: [below[m] -> real],G: [below[m+1] -> real]): (FORALL (i: below[m]): F(i) = G(i)) IMPLIES (j < m IMPLIES sigma[below[m]](1,j,F) = sigma[below[m+1]](1,j,G))



   sigma_below_shift: LEMMA FORALL (m: posnat, F:[below[m + 1] -> real]):  sigma(1, m, LAMBDA (i: below[1 + m]): F(i)) =  sigma(0, m - 1, LAMBDA (i: below[m]): F(i + 1))



   sigma_eq_index: LEMMA FORALL (m,n: posnat, F: [below[m] -> real],G: [below[n] -> real]): (m = n AND FORALL (i: below[m]): F(i) = G(i)) IMPLIES sigma(0,m - 1,LAMBDA(i: Index[m]): F(i)) = sigma(0,n - 1,LAMBDA(i: Index[n]): G(i))


   aux_sigma: LEMMA FORALL (m: posnat,n: nat, F: [below[m] -> real],G: [below[m + n] -> real]): (n = 0 AND FORALL (i: below[m]): F(i) = G(i)) IMPLIES sigma(0,m - 1,LAMBDA(i: below[m]): F(i)) = sigma(0,m + n - 1,LAMBDA(i: below[m + n]): G(i))


   aux_sigma2: LEMMA FORALL (m,j: posnat,n: nat, F: [below[m] -> real],G: [below[m + n] -> real]): (n = 0 AND j <= m AND FORALL (i: below[m]): F(i) = G(i)) IMPLIES sigma(0,j - 1,LAMBDA(i: below[m]): F(i)) = sigma(0,j + n - 1,LAMBDA(i: below[m + n]): G(i))


   sigma_restrict_gen: LEMMA FORALL (j: posnat, m,n: posnat, F: [below[m] -> real],G: [below[m + n] -> real]): (FORALL (i: below[m]): F(i) = G(i)) IMPLIES (j <= m IMPLIES sigma[below[m]](0,j - 1,F) = sigma[below[m + n]](0,j-1,G))



   sigma_eq_index2: LEMMA FORALL (m,n,j: posnat, F: [below[m] -> real],G: [below[n] -> real]): (m = n AND j <= m AND FORALL (i: below[m]): F(i) = G(i)) IMPLIES sigma(0,j - 1,LAMBDA(i: Index[m]): F(i)) = sigma(0,j - 1,LAMBDA(i: Index[n]): G(i))


    sigma_restrict_gen2: LEMMA FORALL (j: posnat,k: nat,m,n: posnat, F: [below[m] -> real],G: [below[m + n] -> real]): (FORALL (i: below[m]): F(i) = G(i)) IMPLIES (j <= m AND k < j IMPLIES sigma[below[m]](k,j - 1,F) = sigma[below[m + n]](k,j-1,G))



   sigma_eq_index3: LEMMA FORALL (m,n,j,k: posnat, F: [below[m] -> real],G: [below[n] -> real]): (m = n AND j <= m AND k < j AND FORALL (i: below[m]): F(i) = G(i)) IMPLIES sigma(k,j - 1,LAMBDA(i: Index[m]): F(i)) = sigma(k,j - 1,LAMBDA(i: Index[n]): G(i))


   sigma_shift_gen: LEMMA FORALL (j: posnat, m,n: posnat,F: [below[m + n] -> real]): (j <= m IMPLIES sigma[below[m]](0,j - 1,LAMBDA (i: below[m]): F(i + n)) = sigma[below[m + n]](n,j - 1 + n, LAMBDA (i: below[m + n]): F(i)))


  END sigma_lemmas

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

  % Subtype TCC generated (at line 28, column 137) for  i
      % expected type  below[m + 1]
  sigma_restrict_dom_TCC1: OBLIGATION
    FORALL (m: posnat, i: below[m]): i < 1 + m;

  % Subtype TCC generated (at line 28, column 181) for  0
      % expected type  T_low[below[m]]
  sigma_restrict_dom_TCC2: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j <= m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       0 >= 0 AND 0 < m OR (EXISTS (j: below[m]): j <= 0);

  % Subtype TCC generated (at line 28, column 183) for  j - 1
      % expected type  T_high[below[m]]
  sigma_restrict_dom_TCC3: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j <= m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       j - 1 >= 0 AND j - 1 < m OR (EXISTS (j_1: below[m]): j - 1 <= j_1);

  % Assuming TCC generated (at line 41, column 5) for  reals@sigma[below[m]]
      % generated from assumption sigma.connected_domain
  sigma_restrict_dom_TCC4: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j <= m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       (FORALL (x, y: below[m]), (z: integer):
          x <= z AND z <= y IMPLIES z >= 0 AND z < m);

  % Subtype TCC generated (at line 28, column 212) for  0
      % expected type  T_low[below[m + 1]]
  sigma_restrict_dom_TCC5: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j <= m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       0 >= 0 AND 0 < 1 + m OR (EXISTS (j: below[1 + m]): j <= 0);

  % Subtype TCC generated (at line 28, column 214) for  j - 1
      % expected type  T_high[below[m + 1]]
  sigma_restrict_dom_TCC6: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j <= m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       j - 1 >= 0 AND j - 1 < 1 + m OR
        (EXISTS (j_1: below[1 + m]): j - 1 <= j_1);

  % Assuming TCC generated (at line 41, column 5) for
      % reals@sigma[below[m + 1]]
      % generated from assumption sigma.connected_domain
  sigma_restrict_dom_TCC7: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j <= m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       (FORALL (x, y: below[1 + m]), (z: integer):
          x <= z AND z <= y IMPLIES z >= 0 AND z < 1 + m);

  % Subtype TCC generated (at line 30, column 182) for  1
      % expected type  T_low[below[m]]
  sigma_restrict_dom2_TCC1: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j < m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       1 >= 0 AND 1 < m OR (EXISTS (j: below[m]): j <= 1);

  % Subtype TCC generated (at line 30, column 184) for  j
      % expected type  T_high[below[m]]
  sigma_restrict_dom2_TCC2: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j < m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       j >= 0 AND j < m OR (EXISTS (j_1: below[m]): j <= j_1);

  % Assuming TCC generated (at line 41, column 5) for  reals@sigma[below[m]]
      % generated from assumption sigma.connected_domain
  sigma_restrict_dom2_TCC3: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j < m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       (FORALL (x, y: below[m]), (z: integer):
          x <= z AND z <= y IMPLIES z >= 0 AND z < m);

  % Subtype TCC generated (at line 30, column 209) for  1
      % expected type  T_low[below[m + 1]]
  sigma_restrict_dom2_TCC4: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j < m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       1 >= 0 AND 1 < 1 + m OR (EXISTS (j: below[1 + m]): j <= 1);

  % Subtype TCC generated (at line 30, column 211) for  j
      % expected type  T_high[below[m + 1]]
  sigma_restrict_dom2_TCC5: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j < m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       j >= 0 AND j < 1 + m OR (EXISTS (j_1: below[1 + m]): j <= j_1);

  % Assuming TCC generated (at line 41, column 5) for
      % reals@sigma[below[m + 1]]
      % generated from assumption sigma.connected_domain
  sigma_restrict_dom2_TCC6: OBLIGATION
    FORALL (j: posnat, m: posnat, F: [below[m] -> real],
            G: [below[m + 1] -> real]):
      j < m AND (FORALL (i: below[m]): F(i) = G(i)) IMPLIES
       (FORALL (x, y: below[1 + m]), (z: integer):
          x <= z AND z <= y IMPLIES z >= 0 AND z < 1 + m);

  % Subtype TCC generated (at line 34, column 79) for  1
      % expected type  T_low[below[1 + m]]
  sigma_below_shift_TCC1: OBLIGATION
    FORALL (m: posnat):
      1 >= 0 AND 1 < 1 + m OR (EXISTS (j: below[1 + m]): j <= 1);

  % Subtype TCC generated (at line 34, column 82) for  m
      % expected type  T_high[below[1 + m]]
  sigma_below_shift_TCC2: OBLIGATION
    FORALL (m: posnat):
      m >= 0 AND m < 1 + m OR (EXISTS (j: below[1 + m]): m <= j);

  % Assuming TCC generated (at line 21, column 12) for
      % reals@sigma[below[1 + m]]
      % generated from assumption sigma.connected_domain
  sigma_below_shift_TCC3: OBLIGATION
    FORALL (m: posnat):
      (FORALL (x, y: below[1 + m]), (z: integer):
         x <= z AND z <= y IMPLIES z >= 0 AND z < 1 + m);

  % Subtype TCC generated (at line 34, column 126) for  0
      % expected type  T_low[below[m]]
  sigma_below_shift_TCC4: OBLIGATION
    FORALL (m: posnat): 0 >= 0 AND 0 < m OR (EXISTS (j: below[m]): j <= 0);

  % Subtype TCC generated (at line 34, column 129) for  m - 1
      % expected type  T_high[below[m]]
  sigma_below_shift_TCC5: OBLIGATION
    FORALL (m: posnat):
      m - 1 >= 0 AND m - 1 < m OR (EXISTS (j: below[m]): m - 1 <= j);

  % Subtype TCC generated (at line 34, column 160) for  i + 1
      % expected type  below[m + 1]
  sigma_below_shift_TCC6: OBLIGATION
    FORALL (m: posnat, i: below[m]): i + 1 < 1 + m;

  % Assuming TCC generated (at line 21, column 12) for  reals@sigma[below[m]]
      % generated from assumption sigma.connected_domain
  sigma_below_shift_TCC7: OBLIGATION
    FORALL (m: posnat):
      (FORALL (x, y: below[m]), (z: integer):
         x <= z AND z <= y IMPLIES z >= 0 AND z < m);

  % Subtype TCC generated (at line 38, column 132) for  i
      % expected type  below[n]
  sigma_eq_index_TCC1: OBLIGATION
    FORALL (m, n: posnat): m = n IMPLIES (FORALL (i: below[m]): i < n);

  % Subtype TCC generated (at line 38, column 193) for  0
      % expected type  T_low[Index[n]]
  sigma_eq_index_TCC2: OBLIGATION
    FORALL (m, n: posnat, F: [below[m] -> real], G: [below[n] -> real]):
      (m = n AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       0 >= 0 AND 0 < n OR (EXISTS (j: Index[n]): j <= 0);

  % Subtype TCC generated (at line 38, column 195) for  n - 1
      % expected type  T_high[Index[n]]
  sigma_eq_index_TCC3: OBLIGATION
    FORALL (m, n: posnat, F: [below[m] -> real], G: [below[n] -> real]):
      (m = n AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       n - 1 >= 0 AND n - 1 < n OR (EXISTS (j: Index[n]): n - 1 <= j);

  % Subtype TCC generated (at line 41, column 136) for  i
      % expected type  below[m + n]
  aux_sigma_TCC1: OBLIGATION
    FORALL (m: posnat, n: nat):
      n = 0 IMPLIES (FORALL (i: below[m]): i < m + n);

  % Subtype TCC generated (at line 41, column 197) for  0
      % expected type  T_low[below[m + n]]
  aux_sigma_TCC2: OBLIGATION
    FORALL (m: posnat, n: nat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (n = 0 AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       0 >= 0 AND 0 < m + n OR (EXISTS (j: below[m + n]): j <= 0);

  % Subtype TCC generated (at line 41, column 199) for  m + n - 1
      % expected type  T_high[below[m + n]]
  aux_sigma_TCC3: OBLIGATION
    FORALL (m: posnat, n: nat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (n = 0 AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       m + n - 1 >= 0 AND m + n - 1 < m + n OR
        (EXISTS (j: below[m + n]): m + n - 1 <= j);

  % Subtype TCC generated (at line 44, column 170) for  j - 1
      % expected type  T_high[below[m]]
  aux_sigma2_TCC1: OBLIGATION
    FORALL (m, j: posnat, n: nat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (n = 0 AND j <= m AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       j - 1 >= 0 AND j - 1 < m OR (EXISTS (j_1: below[m]): j - 1 <= j_1);

  % Subtype TCC generated (at line 44, column 213) for  j + n - 1
      % expected type  T_high[below[m + n]]
  aux_sigma2_TCC2: OBLIGATION
    FORALL (m, j: posnat, n: nat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (n = 0 AND j <= m AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       j + n - 1 >= 0 AND j + n - 1 < m + n OR
        (EXISTS (j_1: below[m + n]): j + n - 1 <= j_1);

  % Subtype TCC generated (at line 47, column 141) for  i
      % expected type  below[m + n]
  sigma_restrict_gen_TCC1: OBLIGATION
    FORALL (m, n: posnat, i: below[m]): i < m + n;

  % Subtype TCC generated (at line 47, column 187) for  j - 1
      % expected type  T_high[below[m]]
  sigma_restrict_gen_TCC2: OBLIGATION
    FORALL (j: posnat, m, n: posnat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (j <= m AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       j - 1 >= 0 AND j - 1 < m OR (EXISTS (j_1: below[m]): j - 1 <= j_1);

  % Subtype TCC generated (at line 47, column 218) for  0
      % expected type  T_low[below[m + n]]
  sigma_restrict_gen_TCC3: OBLIGATION
    FORALL (j: posnat, m, n: posnat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (j <= m AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       0 >= 0 AND 0 < m + n OR (EXISTS (j: below[m + n]): j <= 0);

  % Subtype TCC generated (at line 47, column 220) for  j - 1
      % expected type  T_high[below[m + n]]
  sigma_restrict_gen_TCC4: OBLIGATION
    FORALL (j: posnat, m, n: posnat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (j <= m AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       j - 1 >= 0 AND j - 1 < m + n OR
        (EXISTS (j_1: below[m + n]): j - 1 <= j_1);

  % Subtype TCC generated (at line 51, column 166) for  j - 1
      % expected type  T_high[Index[m]]
  sigma_eq_index2_TCC1: OBLIGATION
    FORALL (m, n, j: posnat, F: [below[m] -> real], G: [below[n] -> real]):
      (m = n AND j <= m AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       j - 1 >= 0 AND j - 1 < m OR (EXISTS (j_1: Index[m]): j - 1 <= j_1);

  % Subtype TCC generated (at line 51, column 209) for  j - 1
      % expected type  T_high[Index[n]]
  sigma_eq_index2_TCC2: OBLIGATION
    FORALL (m, n, j: posnat, F: [below[m] -> real], G: [below[n] -> real]):
      (m = n AND j <= m AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       j - 1 >= 0 AND j - 1 < n OR (EXISTS (j_1: Index[n]): j - 1 <= j_1);

  % Subtype TCC generated (at line 54, column 203) for  k
      % expected type  T_low[below[m]]
  sigma_restrict_gen2_TCC1: OBLIGATION
    FORALL (j: posnat, k: nat, m, n: posnat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (j <= m AND k < j AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       k >= 0 AND k < m OR (EXISTS (j: below[m]): j <= k);

  % Subtype TCC generated (at line 54, column 236) for  k
      % expected type  T_low[below[m + n]]
  sigma_restrict_gen2_TCC2: OBLIGATION
    FORALL (j: posnat, k: nat, m, n: posnat, F: [below[m] -> real],
            G: [below[m + n] -> real]):
      (j <= m AND k < j AND (FORALL (i: below[m]): F(i) = G(i))) IMPLIES
       k >= 0 AND k < m + n OR (EXISTS (j: below[m + n]): j <= k);

  % Subtype TCC generated (at line 58, column 176) for  k
      % expected type  T_low[Index[m]]
  sigma_eq_index3_TCC1: OBLIGATION
    FORALL (m, n, j, k: posnat, F: [below[m] -> real],
            G: [below[n] -> real]):
      (m = n AND j <= m AND k < j AND (FORALL (i: below[m]): F(i) = G(i)))
       IMPLIES k >= 0 AND k < m OR (EXISTS (j_1: Index[m]): j_1 <= k);

  % Subtype TCC generated (at line 58, column 219) for  k
      % expected type  T_low[Index[n]]
  sigma_eq_index3_TCC2: OBLIGATION
    FORALL (m, n, j, k: posnat, F: [below[m] -> real],
            G: [below[n] -> real]):
      (m = n AND j <= m AND k < j AND (FORALL (i: below[m]): F(i) = G(i)))
       IMPLIES k >= 0 AND k < n OR (EXISTS (j_1: Index[n]): j_1 <= k);

  % Subtype TCC generated (at line 61, column 117) for  j - 1
      % expected type  T_high[below[m]]
  sigma_shift_gen_TCC1: OBLIGATION
    FORALL (j: posnat, m, n: posnat):
      j <= m IMPLIES
       j - 1 >= 0 AND j - 1 < m OR (EXISTS (j_1: below[m]): j - 1 <= j_1);

  % Subtype TCC generated (at line 61, column 147) for  i + n
      % expected type  below[m + n]
  sigma_shift_gen_TCC2: OBLIGATION
    FORALL (j: posnat, m, n: posnat):
      j <= m IMPLIES (FORALL (i: below[m]): i + n < m + n);

  % Subtype TCC generated (at line 61, column 177) for  n
      % expected type  T_low[below[m + n]]
  sigma_shift_gen_TCC3: OBLIGATION
    FORALL (j: posnat, m, n: posnat):
      j <= m IMPLIES
       n >= 0 AND n < m + n OR (EXISTS (j: below[m + n]): j <= n);

  % Subtype TCC generated (at line 61, column 179) for  j - 1 + n
      % expected type  T_high[below[m + n]]
  sigma_shift_gen_TCC4: OBLIGATION
    FORALL (j: posnat, m, n: posnat):
      j <= m IMPLIES
       j - 1 + n >= 0 AND j - 1 + n < m + n OR
        (EXISTS (j_1: below[m + n]): j - 1 + n <= j_1);


body:
  % This theory just defines a vector of vectors as a listed family of vectors, 
  % this is, a vector in which each component is also a vector.

  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013

  vect_of_vect[n,m: posnat]: THEORY

   BEGIN
   
   IMPORTING vectors@vectors
   
   Vector_of_Vectors: TYPE = [below(m) -> Vector[n]]

   END vect_of_vect


body:
  matrices: THEORY

  BEGIN

   IMPORTING vect_of_vect

   conversion- b2n

   n, m,e: VAR nat
   pn, pm: VAR posnat
   c, r, s: VAR real


  %------------------------------------------------------------------
  % Matrix definition
  % We define matrices as records, giving the number or rows,
  % of columns, and the elements
  %------------------------------------------------------------------

   Matrix: TYPE = [# rows: posnat, cols: posnat,
                     matrix: [below(rows), below(cols) -> real] #]

   Mat(m, n): TYPE = {M: Matrix | M`rows = m and M`cols = n}

   M, N, P: VAR Matrix



  % We can consider the rows or the columns of a matrix as vectors

   rowV(M)(i: below(M`rows)): Vector[M`cols] =
     lambda (j: below(M`cols)): M`matrix(i, j)

   colV(M)(j: below(M`cols)): Vector[M`rows] =
     lambda (i: below(M`rows)): M`matrix(i, j)



  % We can also consider the rows or the columns of a matrix as
  % matrices with just one column or just one row

   rowM(M)(i: below(M`rows)): Matrix =
     (# rows := 1, cols := M`cols,
        matrix := lambda (k: below(1), j: below(M`cols)): M`matrix(i, j) #)

   colM(M)(j: below(M`cols)): Matrix =
     (# rows := M`rows, cols := 1,
        matrix := lambda (i: below(M`rows), k: below(1)): M`matrix(i, j) #)



  % A matrix 1xn or nx1 can be seen as a vector

   Mr2V(M: Matrix | M`rows = 1): Vector[M`cols] =
     lambda (j: below(M`cols)): M`matrix(0, j)

   Mc2V(M: Matrix | M`cols = 1): Vector[M`rows] =
     lambda (j: below(M`rows)): M`matrix(j, 0)



  % There are direct transformations between matrices and vectors of vectors

   cols(M): Vector_of_Vectors[M`rows, M`cols] =
     lambda (i: below(M`cols)):
       lambda (j: below(M`rows)): M`matrix(j, i)

   rows(M): Vector_of_Vectors[M`cols, M`rows] =
     lambda (i: below(M`rows)):
       lambda (j: below(M`cols)): M`matrix(i, j)

   vectors2matrix(pn, pm)(V2: Vector_of_Vectors[pn, pm]): Matrix = 
     (# cols := pm, rows := pn,
        matrix := lambda (i: below(pn), j: below(pm)): V2(j)(i) #)

   conversion+ vectors2matrix, cols



  % Transpose matrix
  	
   transpose(M): Matrix =
     (# rows := M`cols, cols := M`rows,
        matrix := lambda (i: below(M`cols), j: below(M`rows)): M`matrix(j, i) #)


   transpose2: LEMMA transpose(transpose(M)) = M



  % Definition of square matrices

   square?(M): bool = M`rows = M`cols

   Square: TYPE = (square?)

   squareMat?(n: posnat)(M: Square): bool = M`rows = n

   SquareMat(n: posnat): TYPE = (squareMat?(n))



  % Definition of zero and nonzero matrix

   zero?(M): bool =
     FORALL (i: below(M`rows), j: below(M`cols)): M`matrix(i, j) = 0

   nonzero?(M): bool = not zero?(M)

   Zero: TYPE = (zero?)



  % Definition of identity matrix

   delta(i, j: nat): MACRO nat = if i = j then 1 else 0 endif

   identity?(M: Matrix): bool =
     square?(M) and
     FORALL (i, j: below(M`rows)):
       M`matrix(i, j) = delta(i, j)

   I(n: posnat): (identity?)
      = (# rows := n, cols := n,
           matrix := lambda (i, j: below(n)): delta(i, j) #)


   ident_trans:LEMMA transpose(I(pn))=I(pn)



  % Definition of triangular and diagonal matrices

   upper_triangular?(M): bool = square?(M)
     AND FORALL (i, j: below(M`rows)): i > j => M`matrix(i,j) = 0

   lower_triangular?(M): bool = square?(M)
     AND FORALL (i, j: below(M`rows)): i < j => M`matrix(i,j) = 0

   diagonal?(M): bool = square?(M)
     AND FORALL (i, j: below(M`rows)): i /= j => M`matrix(i,j) = 0;



  % Definition of opposite matrix

   -(M): Matrix =
      M WITH [`matrix := LAMBDA (i: below(M`rows), j: below(M`cols)): -M`matrix(i, j)]






  %---------------------------------------------------------------------
  % Sum and substraction of matrices
  % To be able to operate with two matrices they must have same_dim?
  %---------------------------------------------------------------------
   
   same_dim?(M, N): macro bool = M`rows = N`rows AND M`cols = N`cols

   same_dim?(M)(N): macro bool = M`rows = N`rows AND M`cols = N`cols;


   +(M, (N: (same_dim?(M)))): Matrix =
     M WITH [ `matrix := LAMBDA (i: below(M`rows), j: below(M`cols)):
                         M`matrix(i, j) + N`matrix(i, j) ];

   -(M, (N: (same_dim?(M)))): Matrix =
     M WITH [ `matrix := LAMBDA (i: below(M`rows), j: below(M`cols)):
                         M`matrix(i, j) - N`matrix(i, j) ];


  % associative properties
   plus_assoc: LEMMA
     FORALL (M, (N, P: (same_dim?(M)))): M + (N + P) = (M + N) + P;

   plus_comm: LEMMA
     FORALL (M, (N: (same_dim?(M)))): M + N = N + M;


  % adding zero matrix
   zero_left_ident: LEMMA
     FORALL (Z: Zero, M: (same_dim?(Z))): Z + M = M;

   zero_right_ident: LEMMA
     FORALL (Z: Zero, M: (same_dim?(Z))): M + Z = M;



  % Multiplying a matrix by an scalar

   *(r, M): Matrix =
      M WITH [`matrix := LAMBDA (i: below(M`rows), j: below(M`cols)):
                          r * M`matrix(i, j)];

   *(M, r): Matrix = r * M;



  %-----------------------------------------------------------------------
  % Product of matrices and product of a matrix and a vector
  %-----------------------------------------------------------------------

   *(M, (N: Matrix | M`cols = N`rows)): Matrix =
     (# rows := M`rows, cols := N`cols,
        matrix := lambda (i: below(M`rows), j: below(N`cols)):
                    sigma[below(M`cols)](0, M`cols-1, lambda (k: below(M`cols)):
                                       M`matrix(i, k) * N`matrix(k, j)) #);

   *(M, (v:Vector[M`cols])): Vector[M`rows] = lambda (i: below(M`rows)):
                    sigma[below(M`cols)](0, M`cols-1, lambda (k: below(M`cols)):
                                       M`matrix(i, k) * v(k)); 



  % Multiplying by the zero matrix  
   zero_times_left: LEMMA
     FORALL (M, (Z: Zero | Z`cols = M`rows)): zero?(Z * M)

   zero_times_right: LEMMA
     FORALL (Z: Zero, (M | M`cols = Z`rows)): zero?(M * Z)



   sigma_lem: LEMMA % This lemma is just to make other proofs easier
     FORALL (n: posnat, j: below(n), r: real):
      sigma[below(n)](0, n - 1, (lambda (k: below(n)): 0) WITH [(j) := r]) = r


  % Multiplying by the identity matrix
   right_mult_ident: LEMMA
     FORALL (M, (I: Matrix | identity?(I) AND M`cols = I`rows)):
                 M * I = M

   left_mult_ident: LEMMA
     FORALL (M, (I: Matrix | identity?(I) AND M`rows = I`cols)):
                 I * M = M

   ident_vect:LEMMA FORALL (I:Matrix|identity?(I)): FORALL (x:Vector[I`cols]): I*x=x 



  % Technical sigma lemmas  
   sigma_prop: LEMMA
     FORALL (m, n: posint, f: [below(m) -> real], g: [below(m), below(n) -> real]):
      sigma[below(m)](0, m-1, lambda (i: below(m)):
                      f(i) * sigma[below(n)](0, n-1, lambda (j: below(n)): g(i,j)))
       = sigma[below(m)](0, m-1, lambda (i: below(m)):
                         sigma[below(n)](0, n-1, lambda(j: below(n)): f(i) * g(i,j)))

   sigma_comm: LEMMA
     FORALL (m, n: posnat, f: [below(m), below(n) -> real]):
       sigma[below(m)](0, m-1, lambda (i: below(m)):
                       sigma[below(n)](0, n-1, lambda (j: below(n)): f(i, j)))
        = sigma[below(n)](0, n-1, lambda (j: below(n)):
                       sigma[below(m)](0, m-1, lambda (i: below(m)): f(i, j)))



  % Associative properties
   mult_assoc: LEMMA
     FORALL (M, (N | M`cols = N`rows), (P | N`cols = P`rows)):
      M * (N * P) = (M * N) * P

   mult_assoc_vect: LEMMA FORALL (M, (N | M`cols = N`rows), V:Vector[N`cols]): (M * N) * V = M * (N * V)



  % Distributive properties
   left_distributive: LEMMA
     FORALL (M, (N | M`cols = N`rows), (P: (same_dim?(N)))):
      M * (N + P) = (M * N) + (M * P)

   right_distributive: LEMMA
     FORALL (M, (N: (same_dim?(M))), (P | M`cols = P`rows)):
      (M + N) * P = (M * P) + (N * P)

   left_distributive_vect:  LEMMA FORALL (M, (v1, v2:Vector[M`cols])):  M * v1 - M * v2 = M * (v1 - v2)



  % Relationship  between product and transposes
   transpose_product: LEMMA
     FORALL (M, (N | M`cols = N`rows)):
      transpose(M * N) = transpose(N) * transpose(M)

   trans_mat_scal: LEMMA FORALL (A:Matrix, x:Vector[A`rows], y:Vector[A`cols]): x * (A * y) = (transpose(A) * x) * y   



  %---------------------------------------------------------------------
  % Definition of inverse and invertible matrix
  %--------------------------------------------------------------------

   inverse?(M: Square)(N: Square | N`rows = M`rows): bool =
     M * N = I(M`rows) and N * M = I(M`rows)

   invertible?(M: Square): bool = EXISTS (N: (inverse?(M))): inverse?(M)(N)

   inverse_unique: lemma
     FORALL (M: (invertible?), N, P: (inverse?(M))): N = P

   inverse(M: (invertible?)): {N: Square | N`rows = M`rows}
     = the! (N: Square | N`rows = M`rows): inverse?(M)(N)



  % The product of invertible matrices is also invertible
   invertible_product: lemma
     FORALL (M: (invertible?), N: (invertible?) | N`rows = M`rows):
       invertible?(M * N)


  % Relationship between product and inverse
   product_inverse: lemma
     FORALL (M: (invertible?), N: (invertible?) | N`rows = M`rows):
       inverse(M * N) = inverse(N) * inverse(M)



  % Trace of a matrix

   trace(M: Square): real = sigma[below(M`rows)](0, M`rows-1, lambda (k: below(M`rows)): M`matrix(k, k))



  % About symmetric and skew-symmetric matrices

   symmetric?(M): bool = square?(M) AND transpose(M) = M

   skew_symmetric?(M): bool = square?(M) AND transpose(M) = -M 

   symmetric_part(M: Square): (symmetric?) =
     1/2 * (M + transpose(M))

   skew_symmetric_part(M: Square): (skew_symmetric?) =
     1/2 * (M - transpose(M))

   square_decomp: LEMMA
     FORALL (M: Square): M = symmetric_part(M) + skew_symmetric_part(M)



  % Matrix induction

   square_matrix_induct: LEMMA
     forall (p: pred[Square]):
      (forall (M: Square):
        (forall (N: Square): N`rows < M`rows implies p(N)) implies p(M))
      implies (forall (M: Square): p(M))



  % Positive semidefinite and definite matrices

   semidef_pos?(A: (square?)): bool = FORALL (x: Vector[A`rows]): x*(A*x) >= 0
   
   def_pos?(A: (square?)): bool = FORALL (x: Vector[A`rows]): x /= zero[A`rows] IMPLIES x*(A*x) > 0


  END matrices

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

  % Subtype TCC generated (at line 55, column 39) for  0
      % expected type  below(M`rows)
  Mr2V_TCC1: OBLIGATION
    FORALL (M: Matrix | M`rows = 1, j: below(M`cols)): 0 < M`rows;

  % Subtype TCC generated (at line 58, column 42) for  0
      % expected type  below(M`cols)
  Mc2V_TCC1: OBLIGATION
    FORALL (M: Matrix | M`cols = 1, j: below(M`rows)): 0 < M`cols;

  % Subtype TCC generated (at line 121, column 17) for  j
      % expected type  below(M`cols)
  identity?_TCC1: OBLIGATION
    FORALL (M: Matrix):
      square?(M) IMPLIES (FORALL (i, j: below(M`rows)): j < M`cols);

  % Subtype TCC generated (at line 124, column 6) for
      % (# rows := n,
      %    cols := n,
      %    matrix := LAMBDA (i, j: below(n)): IF i = j THEN 1 ELSE 0 ENDIF #)
      % expected type  (identity?)
  I_TCC1: OBLIGATION
    FORALL (n: posnat):
      identity?((# rows := n,
                   cols := n,
                   matrix
                     := LAMBDA (i, j: below(n)):
                          IF i = j THEN 1 ELSE 0 ENDIF #));

  % Subtype TCC generated (at line 167, column 49) for  i
      % expected type  below(N`rows)
  plus_TCC1: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)),
            i: below(M`rows), j: below(M`cols)):
      i < N`rows;

  % Subtype TCC generated (at line 167, column 52) for  j
      % expected type  below(N`cols)
  plus_TCC2: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)),
            i: below(M`rows), j: below(M`cols)):
      j < N`cols;

  % Subtype TCC generated (at line 176, column 48) for  P
      % expected type  (LAMBDA (N_1: Matrix):
                     %    N`rows = N_1`rows AND N`cols = N_1`cols)
  plus_assoc_TCC1: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)),
            (P:
               (LAMBDA (N_1: Matrix):
                  M`rows = N_1`rows AND M`cols = N_1`cols))):
      N`rows = P`rows AND N`cols = P`cols;

  % Subtype TCC generated (at line 176, column 44) for  (N + P)
      % expected type  (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)
  plus_assoc_TCC2: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)),
            (P:
               (LAMBDA (N_1: Matrix):
                  M`rows = N_1`rows AND M`cols = N_1`cols))):
      M`rows = (N + P)`rows AND M`cols = (N + P)`cols;

  % Subtype TCC generated (at line 176, column 63) for  P
      % expected type  (LAMBDA (N_1: Matrix):
                     %    (M + N)`rows = N_1`rows AND (M + N)`cols = N_1`cols)
  plus_assoc_TCC3: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)),
            (P:
               (LAMBDA (N_1: Matrix):
                  M`rows = N_1`rows AND M`cols = N_1`cols))):
      (M + N)`rows = P`rows AND (M + N)`cols = P`cols;

  % Subtype TCC generated (at line 179, column 48) for  M
      % expected type  (LAMBDA (N_1: Matrix):
                     %    N`rows = N_1`rows AND N`cols = N_1`cols)
  plus_comm_TCC1: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols))):
      N`rows = M`rows AND N`cols = M`cols;

  % Subtype TCC generated (at line 187, column 44) for  Z
      % expected type  (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)
  zero_right_ident_TCC1: OBLIGATION
    FORALL (Z: Zero, M: (LAMBDA (N): Z`rows = N`rows AND Z`cols = N`cols)):
      M`rows = Z`rows AND M`cols = Z`cols;

  % Subtype TCC generated (at line 208, column 39) for  0
      % expected type  T_low[below(M`cols)]
  times_TCC1: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows), i: below(M`rows),
            j: below(N`cols)):
      0 >= 0 AND 0 < M`cols OR (EXISTS (j: below(M`cols)): j <= 0);

  % Subtype TCC generated (at line 208, column 42) for  M`cols - 1
      % expected type  T_high[below(M`cols)]
  times_TCC2: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows), i: below(M`rows),
            j: below(N`cols)):
      M`cols - 1 >= 0 AND M`cols - 1 < M`cols OR
       (EXISTS (j: below(M`cols)): M`cols - 1 <= j);

  % Subtype TCC generated (at line 209, column 63) for  k
      % expected type  below(N`rows)
  times_TCC3: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows), i: below(M`rows),
            j: below(N`cols), k: below(M`cols)):
      k < N`rows;

  % Assuming TCC generated (at line 41, column 5) for
      % reals@sigma[below(M`cols)]
      % generated from assumption sigma.connected_domain
  times_TCC4: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows), i: below(M`rows),
            j: below(N`cols)):
      FORALL (x, y: below(M`cols)), (z: integer):
        x <= z AND z <= y IMPLIES z >= 0 AND z < M`cols;

  % Subtype TCC generated (at line 212, column 39) for  0
      % expected type  T_low[below(M`cols)]
  times_TCC5: OBLIGATION
    FORALL (M: Matrix, i: below(M`rows)):
      0 >= 0 AND 0 < M`cols OR (EXISTS (j: below(M`cols)): j <= 0);

  % Subtype TCC generated (at line 212, column 42) for  M`cols - 1
      % expected type  T_high[below(M`cols)]
  times_TCC6: OBLIGATION
    FORALL (M: Matrix, i: below(M`rows)):
      M`cols - 1 >= 0 AND M`cols - 1 < M`cols OR
       (EXISTS (j: below(M`cols)): M`cols - 1 <= j);

  % Subtype TCC generated (at line 219, column 54) for  M
      % expected type  {N: Matrix | Z`cols = N`rows}
  zero_times_left_TCC1: OBLIGATION
    FORALL (M: Matrix, (Z: Zero | Z`cols = M`rows)): Z`cols = M`rows;

  % Subtype TCC generated (at line 222, column 54) for  Z
      % expected type  {N: Matrix | M`cols = N`rows}
  zero_times_right_TCC1: OBLIGATION
    FORALL (Z: Zero, (M: Matrix | M`cols = Z`rows)): M`cols = Z`rows;

  % Subtype TCC generated (at line 228, column 20) for  0
      % expected type  T_low[below(n)]
  sigma_lem_TCC1: OBLIGATION
    FORALL (n: posnat, j: below(n)):
      0 >= 0 AND 0 < n OR (EXISTS (j: below(n)): j <= 0);

  % Subtype TCC generated (at line 228, column 23) for  n - 1
      % expected type  T_high[below(n)]
  sigma_lem_TCC2: OBLIGATION
    FORALL (n: posnat, j: below(n)):
      n - 1 >= 0 AND n - 1 < n OR (EXISTS (j: below(n)): n - 1 <= j);

  % Assuming TCC generated (at line 41, column 5) for  reals@sigma[below(n)]
      % generated from assumption sigma.connected_domain
  sigma_lem_TCC3: OBLIGATION
    FORALL (n: posnat, j: below(n)):
      (FORALL (x, y: below(n)), (z: integer):
         x <= z AND z <= y IMPLIES z >= 0 AND z < n);

  % Subtype TCC generated (at line 238, column 19) for  M
      % expected type  {N: Matrix | I`cols = N`rows}
  left_mult_ident_TCC1: OBLIGATION
    FORALL (M: Matrix, (I: Matrix | identity?(I) AND M`rows = I`cols)):
      I`cols = M`rows;

  % Subtype TCC generated (at line 240, column 81) for  x
      % expected type  Vector[I`rows]
  ident_vect_TCC1: OBLIGATION
    FORALL (I: Matrix | identity?(I)):
      FORALL (x2: nat): x2 < I`cols IFF x2 < I`rows;

  % Subtype TCC generated (at line 247, column 20) for  0
      % expected type  T_low[below(m)]
  sigma_prop_TCC1: OBLIGATION
    FORALL (m, n: posint): 0 >= 0 AND 0 < m OR (EXISTS (j: below(m)): j <= 0);

  % Subtype TCC generated (at line 247, column 23) for  m - 1
      % expected type  T_high[below(m)]
  sigma_prop_TCC2: OBLIGATION
    FORALL (m, n: posint):
      m - 1 >= 0 AND m - 1 < m OR (EXISTS (j: below(m)): m - 1 <= j);

  % Subtype TCC generated (at line 248, column 43) for  0
      % expected type  T_low[below(n)]
  sigma_prop_TCC3: OBLIGATION
    FORALL (m, n: posint, i: below(m)):
      0 >= 0 AND 0 < n OR (EXISTS (j: below(n)): j <= 0);

  % Subtype TCC generated (at line 248, column 46) for  n - 1
      % expected type  T_high[below(n)]
  sigma_prop_TCC4: OBLIGATION
    FORALL (m, n: posint, i: below(m)):
      n - 1 >= 0 AND n - 1 < n OR (EXISTS (j: below(n)): n - 1 <= j);

  % Subtype TCC generated (at line 256, column 24) for  0
      % expected type  T_low[below(n)]
  sigma_comm_TCC1: OBLIGATION
    FORALL (m, n: posnat): 0 >= 0 AND 0 < n OR (EXISTS (j: below(n)): j <= 0);

  % Subtype TCC generated (at line 256, column 27) for  n - 1
      % expected type  T_high[below(n)]
  sigma_comm_TCC2: OBLIGATION
    FORALL (m, n: posnat):
      n - 1 >= 0 AND n - 1 < n OR (EXISTS (j: below(n)): n - 1 <= j);

  % Subtype TCC generated (at line 264, column 9) for  (N * P)
      % expected type  {N: Matrix | M`cols = N`rows}
  mult_assoc_TCC1: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows),
            (P: Matrix | N`cols = P`rows)):
      M`cols = (N * P)`rows;

  % Subtype TCC generated (at line 264, column 28) for  P
      % expected type  {N_1: Matrix | (M * N)`cols = N_1`rows}
  mult_assoc_TCC2: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows),
            (P: Matrix | N`cols = P`rows)):
      (M * N)`cols = P`rows;

  % Subtype TCC generated (at line 266, column 87) for  V
      % expected type  Vector[(M * N)`cols]
  mult_assoc_vect_TCC1: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows)):
      FORALL (x: nat): x < N`cols IFF x < (M * N)`cols;

  % Subtype TCC generated (at line 266, column 96) for  (N * V)
      % expected type  Vector[M`cols]
  mult_assoc_vect_TCC2: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows)):
      FORALL (x: nat): x < N`rows IFF x < M`cols;

  % Subtype TCC generated (at line 266, column 91) for  M * (N * V)
      % expected type  Vector[(M * N)`rows]
  mult_assoc_vect_TCC3: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows)):
      FORALL (x: nat): x < M`rows IFF x < (M * N)`rows;

  % Subtype TCC generated (at line 273, column 9) for  (N + P)
      % expected type  {N: Matrix | M`cols = N`rows}
  left_distributive_TCC1: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows),
            (P:
               (LAMBDA (N_1: Matrix):
                  N`rows = N_1`rows AND N`cols = N_1`cols))):
      M`cols = (N + P)`rows;

  % Subtype TCC generated (at line 273, column 33) for  P
      % expected type  {N: Matrix | M`cols = N`rows}
  left_distributive_TCC2: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows),
            (P:
               (LAMBDA (N_1: Matrix):
                  N`rows = N_1`rows AND N`cols = N_1`cols))):
      M`cols = P`rows;

  % Subtype TCC generated (at line 273, column 29) for  (M * P)
      % expected type  (LAMBDA (N_1: Matrix):
                     %    (M * N)`rows = N_1`rows AND (M * N)`cols = N_1`cols)
  left_distributive_TCC3: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows),
            (P:
               (LAMBDA (N_1: Matrix):
                  N`rows = N_1`rows AND N`cols = N_1`cols))):
      (M * N)`rows = (M * P)`rows AND (M * N)`cols = (M * P)`cols;

  % Subtype TCC generated (at line 277, column 14) for  P
      % expected type  {N_1: Matrix | (M + N)`cols = N_1`rows}
  right_distributive_TCC1: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)),
            (P: Matrix | M`cols = P`rows)):
      (M + N)`cols = P`rows;

  % Subtype TCC generated (at line 277, column 33) for  P
      % expected type  {N_1: Matrix | N`cols = N_1`rows}
  right_distributive_TCC2: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)),
            (P: Matrix | M`cols = P`rows)):
      N`cols = P`rows;

  % Subtype TCC generated (at line 277, column 29) for  (N * P)
      % expected type  (LAMBDA (N):
                     %    (M * P)`rows = N`rows AND (M * P)`cols = N`cols)
  right_distributive_TCC3: OBLIGATION
    FORALL (M: Matrix,
            (N: (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)),
            (P: Matrix | M`cols = P`rows)):
      (M * P)`rows = (N * P)`rows AND (M * P)`cols = (N * P)`cols;

  % Subtype TCC generated (at line 286, column 38) for  transpose(M)
      % expected type  {N_1: Matrix | transpose(N)`cols = N_1`rows}
  transpose_product_TCC1: OBLIGATION
    FORALL (M: Matrix, (N: Matrix | M`cols = N`rows)):
      transpose(N)`cols = transpose(M)`rows;

  % Subtype TCC generated (at line 288, column 108) for  x
      % expected type  Vector[transpose(A)`cols]
  trans_mat_scal_TCC1: OBLIGATION
    FORALL (A: Matrix):
      FORALL (x2: nat): x2 < A`rows IFF x2 < transpose(A)`cols;

  % Subtype TCC generated (at line 288, column 113) for  y
      % expected type  Vector[transpose(A)`rows]
  trans_mat_scal_TCC2: OBLIGATION
    FORALL (A: Matrix):
      FORALL (x2: nat): x2 < A`cols IFF x2 < transpose(A)`rows;

  % Subtype TCC generated (at line 297, column 7) for  N
      % expected type  {N: Matrix | M`cols = N`rows}
  inverse?_TCC1: OBLIGATION
    FORALL (M: Square, N: Square | N`rows = M`rows): M`cols = N`rows;

  % Subtype TCC generated (at line 297, column 29) for  M
      % expected type  {N_1: Matrix | N`cols = N_1`rows}
  inverse?_TCC2: OBLIGATION
    FORALL (M: Square, N: Square | N`rows = M`rows):
      M * N = I(M`rows) IMPLIES N`cols = M`rows;

  % Subtype TCC generated for
      % LAMBDA (N: Square | N`rows = M`rows): inverse?(M)(N)
      % expected type  p: (singleton?[{N: Square | N`rows = M`rows}])
  inverse_TCC1: OBLIGATION
    FORALL (M: (invertible?)):
      singleton?[{N: Square | N`rows = M`rows}]
          (LAMBDA (N: Square | N`rows = M`rows): inverse?(M)(N));

  % Subtype TCC generated (at line 312, column 17) for  M * N
      % expected type  Square
  invertible_product_TCC1: OBLIGATION
    FORALL (M: (invertible?), N: (invertible?) | N`rows = M`rows):
      square?(M * N);

  % Subtype TCC generated (at line 318, column 13) for  M * N
      % expected type  M: (invertible?)
  product_inverse_TCC1: OBLIGATION
    FORALL (M: (invertible?), N: (invertible?) | N`rows = M`rows):
      square?(M * N) AND invertible?(M * N);

  % Subtype TCC generated (at line 318, column 35) for  inverse(M)
      % expected type  {N_1: Matrix | inverse(N)`cols = N_1`rows}
  product_inverse_TCC2: OBLIGATION
    FORALL (M: (invertible?), N: (invertible?) | N`rows = M`rows):
      inverse(N)`cols = inverse(M)`rows;

  % Subtype TCC generated (at line 324, column 47) for  0
      % expected type  T_low[below(M`rows)]
  trace_TCC1: OBLIGATION
    FORALL (M: Square):
      0 >= 0 AND 0 < M`rows OR (EXISTS (j: below(M`rows)): j <= 0);

  % Subtype TCC generated (at line 324, column 50) for  M`rows - 1
      % expected type  T_high[below(M`rows)]
  trace_TCC2: OBLIGATION
    FORALL (M: Square):
      M`rows - 1 >= 0 AND M`rows - 1 < M`rows OR
       (EXISTS (j: below(M`rows)): M`rows - 1 <= j);

  % Subtype TCC generated (at line 324, column 99) for  k
      % expected type  below(M`cols)
  trace_TCC3: OBLIGATION FORALL (M: Square, k: below(M`rows)): k < M`cols;

  % Subtype TCC generated (at line 335, column 14) for  transpose(M)
      % expected type  (LAMBDA (N): M`rows = N`rows AND M`cols = N`cols)
  symmetric_part_TCC1: OBLIGATION
    FORALL (M: Square):
      M`rows = transpose(M)`rows AND M`cols = transpose(M)`cols;

  % Subtype TCC generated (at line 335, column 3) for
      % 1 / 2 * (M + transpose(M))
      % expected type  (symmetric?)
  symmetric_part_TCC2: OBLIGATION
    FORALL (M: Square): symmetric?(1 / 2 * (M + transpose(M)));

  % Subtype TCC generated (at line 338, column 3) for
      % 1 / 2 * (M - transpose(M))
      % expected type  (skew_symmetric?)
  skew_symmetric_part_TCC1: OBLIGATION
    FORALL (M: Square): skew_symmetric?(1 / 2 * (M - transpose(M)));

  % Subtype TCC generated (at line 341, column 47) for  skew_symmetric_part(M)
      % expected type  (LAMBDA (N):
                     %    symmetric_part(M)`rows = N`rows AND
                     %     symmetric_part(M)`cols = N`cols)
  square_decomp_TCC1: OBLIGATION
    FORALL (M: Square):
      symmetric_part(M)`rows = skew_symmetric_part(M)`rows AND
       symmetric_part(M)`cols = skew_symmetric_part(M)`cols;

  % Subtype TCC generated (at line 357, column 69) for  x
      % expected type  Vector[A`cols]
  semidef_pos?_TCC1: OBLIGATION
    FORALL (A: (square?)): FORALL (x2: nat): x2 < A`rows IFF x2 < A`cols;


body:
  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013

  % This file gives the construction and properties of block vectors and block matrices

  block_matrices: THEORY

   BEGIN

   IMPORTING matrices,sigma_lemmas


   m,n,p,q: VAR posnat



  %------------------------------------------------------------
  % Definition of Block Matrices
  %------------------------------------------------------------
  % We define matrices of 2x2 blocks.

   Block_Matrix: TYPE = [# rows1: posnat,rows2: posnat,cols1: posnat,cols2: posnat,matrix: [below(rows1 + rows2), below(cols1 + cols2) -> real] #]

   
   M,N: VAR Block_Matrix



  %------------------------------------------------------------
  % Matrix Conversions
  %------------------------------------------------------------

  %Given a Block Matrix, we obtain the Matrix given by it
   Block2M(M): Matrix = (# rows := M`rows1 + M`rows2, cols := M`cols1 + M`cols2,matrix := LAMBDA (i: below(M`rows1 + M`rows2), j: below(M`cols1 + M`cols2)): M`matrix(i,j) #)


   conversion Block2M


  %Given a Block Matrix, we obtain the four Matrices given by its blocks
   Block2M1(M): Matrix = (# rows := M`rows1, cols := M`cols1,matrix := LAMBDA (i: below(M`rows1), j: below(M`cols1)): M`matrix(i,j) #) %upper left block

   Block2M2(M): Matrix = (# rows := M`rows2, cols := M`cols1,matrix := LAMBDA (i: below(M`rows2), j: below(M`cols1)): M`matrix(i + M`rows1,j) #) %lower left block

   Block2M3(M): Matrix = (# rows := M`rows1, cols := M`cols2,matrix := LAMBDA (i: below(M`rows1), j: below(M`cols2)): M`matrix(i,j + M`cols1) #) %upper right block

   Block2M4(M): Matrix = (# rows := M`rows2, cols := M`cols2,matrix := LAMBDA (i: below(M`rows2), j: below(M`cols2)): M`matrix(i + M`rows1,j + M`cols1) #) %lower right block


  % Given four Matrices and its Dimensions we obtain the Block Matrix composed by them, which has the following form:
  % (A C)
  % (B D)
   M2Block(m,n,p,q)(A: Mat(m,p),B: Mat(n,p),C: Mat(m,q),D: Mat(n,q)): Block_Matrix =  (# rows1 := A`rows,rows2 := B`rows,cols1 := A`cols,cols2 := C`cols,matrix := 
   	    LAMBDA (i: below(A`rows + B`rows), j: below(A`cols + C`cols)): 
  	    IF i < A`rows THEN 
  	       	 IF j < A`cols THEN A`matrix(i,j)
  	       	    ELSE C`matrix(i,j - A`cols) 
  		 ENDIF

  	       	 ELSE IF j < A`cols THEN B`matrix (i - A`rows,j)
  		    ELSE D`matrix(i - A`rows,j - A`cols)
  		 ENDIF
  	    ENDIF  
  	    #)



  %------------------------------------------------------------
  % Definition of Block Vectors
  %------------------------------------------------------------

   Block_Vector: TYPE = [# comp1: posnat,comp2: posnat,vector: [below(comp1 + comp2) -> real] #]

   Block_Vector2: TYPE = [# comp1: posnat,comp2: posnat,vector1: [below(comp1) -> real],vector2: [below(comp2) -> real] #]

   Block_Vect(m,n): TYPE = {V: Block_Vector | V`comp1 = m AND V`comp2 = n}


   V: Var Block_Vector



  %------------------------------------------------------------
  % Vector Conversions
  %------------------------------------------------------------

   BV1toBV2(V): Block_Vector2 = (# comp1 := V`comp1, comp2 := V`comp2, vector1 := LAMBDA (i: below(V`comp1)): V`vector(i),vector2 := LAMBDA (i: below(V`comp2)): V`vector(i + V`comp1)#)

   BV2toBV1(V: Block_Vector2): Block_Vector = (# comp1 := V`comp1, comp2 := V`comp2, vector := LAMBDA (i: below(V`comp1 + V`comp2)): IF i < V`comp1 THEN V`vector1(i) ELSE V`vector2(i - V`comp1) ENDIF #)


   Block2V(V): Vector[V`comp1 + V`comp2] = LAMBDA (i: below[V`comp1 + V`comp2]): V`vector(i)

   Block2V1(V): Vector[V`comp1] = LAMBDA (i: below[V`comp1]): V`vector(i)

   Block2V2(V): Vector[V`comp2] = LAMBDA (i: below[V`comp2]): V`vector(i + V`comp1)

   
   V2Block(m,n: posnat)(x: Vector[m],y: Vector[n]): Block_Vector = (# comp1 := m,comp2 := n,vector := 
   	    LAMBDA (i: below(m + n)): 
  	    IF i < m THEN x(i)
  	    ELSE y(i - m) ENDIF  
  	    #);


   Vec2Block(m,n: posnat)(x: Vector[m + n]): Block_Vector = (# comp1 := m,comp2 := n,vector := LAMBDA (i: below(m + n)): x(i) #);


   conversion BV1toBV2,BV2toBV1



  %------------------------------------------------------------
  % Definitions involving Block Matrices
  %------------------------------------------------------------

   Btranspose(M): Block_Matrix =  (# rows1 := M`cols1,rows2 := M`cols2,cols1 := M`rows1,cols2 := M`rows2,matrix := LAMBDA (i: below(M`cols1 + M`cols2), j: below(M`rows1 + M`rows2)): M`matrix(j,i) #)

   Bsquare?(M): bool = square?(M)

   Bdiag_square?(M): bool = square?(Block2M1(M)) AND square?(Block2M4(M))

   Bsymmetric?(M): bool = symmetric?(M)

   same_Bdim?(M)(N): bool = M`rows1 = N`rows1 AND M`rows2 = N`rows2 AND M`cols1 = N`cols1 AND M`cols2 = N`cols2;



  %------------------------------------------------------------
  % Block Operations
  %------------------------------------------------------------

   *(V, (W: Block_Vect(V`comp1,V`comp2))): real = Block2V1(V)*Block2V1(W) + Block2V2(V)*Block2V2(W);

   *(M: (Bdiag_square?),V: Block_Vect(M`cols1,M`cols2)): Block_Vector2 = (# comp1 := M`rows1, comp2 := M`rows2,vector1 := Block2M1(M)*Block2V1(V) + Block2M3(M)*Block2V2(V), vector2 := Block2M2(M)*Block2V1(V) + Block2M4(M)*Block2V2(V)#);

   +(M: Block_Matrix,N: (same_Bdim?(M))): Block_Matrix = (# rows1 := M`rows1,rows2 := M`rows2,cols1 := M`cols1 ,cols2 := M`cols2,matrix := LAMBDA (i: below(M`rows1 + M`rows2),j: below(M`cols1 + M`cols2)): M`matrix(i,j) + N`matrix(i,j) #);

   *(r: real, M: Block_Matrix): Block_Matrix = M WITH [`matrix := LAMBDA (i: below(M`rows1 + M`rows2), j: below(M`cols1 + M`cols2)): r * M`matrix(i, j)];
   


  %------------------------------------------------------------
  % Generic Lemmas about Blocks
  %------------------------------------------------------------

   conv_transp: LEMMA FORALL (M: Block_Matrix): Btranspose(M) = M2Block(M`cols1,M`cols2,M`rows1,M`rows2)(transpose(Block2M1(M)),transpose(Block2M3(M)),transpose(Block2M2(M)),transpose(Block2M4(M)))

   block_square: LEMMA FORALL (M: Block_Matrix): Bdiag_square?(M) IMPLIES Bsquare?(M)
   
   block_symmetric: LEMMA FORALL (M: Block_Matrix): symmetric?(Block2M1(M)) AND symmetric?(Block2M4(M)) AND transpose(Block2M2(M)) = Block2M3(M) IMPLIES Bsymmetric?(M);

   block_symmetric2: LEMMA FORALL (M: Block_Matrix): Bsymmetric?(M) AND square?(Block2M1(M)) AND square?(Block2M4(M)) IMPLIES symmetric?(Block2M1(M)) AND symmetric?(Block2M4(M)) AND transpose(Block2M2(M)) = Block2M3(M)



  %------------------------------------------------------------
  % Lemmas about Equalities and Operations withs Blocks
  %------------------------------------------------------------

   blockV_equal: LEMMA FORALL (W: Block_Vect(V`comp1,V`comp2)): V = W IFF Block2V(V) = Block2V(W) 



   VtoBlocktoV1: LEMMA FORALL (x: Vector[m],y: Vector[n]): Block2V1(V2Block(m,n)(x,y)) = x

   VtoBlocktoV2: LEMMA FORALL (x: Vector[m],y: Vector[n]): Block2V2(V2Block(m,n)(x,y)) = y

   VtoBlocktoV: LEMMA FORALL (x: Vector[m],y: Vector[n],i: below[m + n]): Block2V(V2Block(m,n)(x,y))(i) = IF i < m THEN x(i) ELSE y(i - m) ENDIF

   Vec_block_Vec: LEMMA FORALL (m,n: posnat, V: Vector[m + n]): Block2V(Vec2Block(m, n)(V)) = V

   block_Vec_block: LEMMA FORALL (V: Block_Vector): Vec2Block(V`comp1, V`comp2)(Block2V(V)) = V



   block_product: LEMMA FORALL (M: (Bdiag_square?),V: Block_Vect(M`cols1,M`cols2)): Block2V(M*V) = Block2M(M)*Block2V(V)

   Block2V_product: LEMMA FORALL (W: Block_Vect(V`comp1,V`comp2)): V*W = Block2V(V)*Block2V(W) 


  END block_matrices

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

  % Subtype TCC generated (at line 46, column 125) for  i
      % expected type  below(M`rows1 + M`rows2)
  Block2M1_TCC1: OBLIGATION
    FORALL (M: Block_Matrix, i: below(M`rows1), j: below(M`cols1)):
      i < M`rows1 + M`rows2;

  % Subtype TCC generated (at line 46, column 127) for  j
      % expected type  below(M`cols1 + M`cols2)
  Block2M1_TCC2: OBLIGATION
    FORALL (M: Block_Matrix, i: below(M`rows1), j: below(M`cols1)):
      j < M`cols1 + M`cols2;

  % Subtype TCC generated (at line 48, column 125) for  i + M`rows1
      % expected type  below(M`rows1 + M`rows2)
  Block2M2_TCC1: OBLIGATION
    FORALL (M: Block_Matrix, i: below(M`rows2), j: below(M`cols1)):
      i + M`rows1 < M`rows1 + M`rows2;

  % Subtype TCC generated (at line 48, column 137) for  j
      % expected type  below(M`cols1 + M`cols2)
  Block2M2_TCC2: OBLIGATION
    FORALL (M: Block_Matrix, i: below(M`rows2), j: below(M`cols1)):
      j < M`cols1 + M`cols2;

  % Subtype TCC generated (at line 50, column 125) for  i
      % expected type  below(M`rows1 + M`rows2)
  Block2M3_TCC1: OBLIGATION
    FORALL (M: Block_Matrix, i: below(M`rows1), j: below(M`cols2)):
      i < M`rows1 + M`rows2;

  % Subtype TCC generated (at line 50, column 127) for  j + M`cols1
      % expected type  below(M`cols1 + M`cols2)
  Block2M3_TCC2: OBLIGATION
    FORALL (M: Block_Matrix, i: below(M`rows1), j: below(M`cols2)):
      j + M`cols1 < M`cols1 + M`cols2;

  % Subtype TCC generated (at line 52, column 125) for  i + M`rows1
      % expected type  below(M`rows1 + M`rows2)
  Block2M4_TCC1: OBLIGATION
    FORALL (M: Block_Matrix, i: below(M`rows2), j: below(M`cols2)):
      i + M`rows1 < M`rows1 + M`rows2;

  % Subtype TCC generated (at line 52, column 137) for  j + M`cols1
      % expected type  below(M`cols1 + M`cols2)
  Block2M4_TCC2: OBLIGATION
    FORALL (M: Block_Matrix, i: below(M`rows2), j: below(M`cols2)):
      j + M`cols1 < M`cols1 + M`cols2;

  % Subtype TCC generated (at line 62, column 27) for  i
      % expected type  below(C`rows)
  M2Block_TCC1: OBLIGATION
    FORALL (m: posnat, n: posnat, p: posnat, q: posnat, A: Mat(m, p),
            B: Mat(n, p), C: Mat(m, q), D: Mat(n, q),
            i: below(A`rows + B`rows), j: below(A`cols + C`cols)):
      NOT j < A`cols AND i < A`rows IMPLIES i < C`rows;

  % Subtype TCC generated (at line 62, column 29) for  j - A`cols
      % expected type  below(C`cols)
  M2Block_TCC2: OBLIGATION
    FORALL (m: posnat, n: posnat, p: posnat, q: posnat, A: Mat(m, p),
            B: Mat(n, p), C: Mat(m, q), D: Mat(n, q),
            i: below(A`rows + B`rows), j: below(A`cols + C`cols)):
      NOT j < A`cols AND i < A`rows IMPLIES
       j - A`cols >= 0 AND j - A`cols < C`cols;

  % Subtype TCC generated (at line 65, column 44) for  i - A`rows
      % expected type  below(B`rows)
  M2Block_TCC3: OBLIGATION
    FORALL (m: posnat, n: posnat, p: posnat, q: posnat, A: Mat(m, p),
            B: Mat(n, p), C: Mat(m, q), D: Mat(n, q),
            i: below(A`rows + B`rows), j: below(A`cols + C`cols)):
      j < A`cols AND NOT i < A`rows IMPLIES
       i - A`rows >= 0 AND i - A`rows < B`rows;

  % Subtype TCC generated (at line 65, column 55) for  j
      % expected type  below(B`cols)
  M2Block_TCC4: OBLIGATION
    FORALL (m: posnat, n: posnat, p: posnat, q: posnat, A: Mat(m, p),
            B: Mat(n, p), C: Mat(m, q), D: Mat(n, q),
            i: below(A`rows + B`rows), j: below(A`cols + C`cols)):
      j < A`cols AND NOT i < A`rows IMPLIES j < B`cols;

  % Subtype TCC generated (at line 66, column 20) for  i - A`rows
      % expected type  below(D`rows)
  M2Block_TCC5: OBLIGATION
    FORALL (m: posnat, n: posnat, p: posnat, q: posnat, A: Mat(m, p),
            B: Mat(n, p), C: Mat(m, q), D: Mat(n, q),
            i: below(A`rows + B`rows), j: below(A`cols + C`cols)):
      NOT j < A`cols AND NOT i < A`rows IMPLIES
       i - A`rows >= 0 AND i - A`rows < D`rows;

  % Subtype TCC generated (at line 66, column 31) for  j - A`cols
      % expected type  below(D`cols)
  M2Block_TCC6: OBLIGATION
    FORALL (m: posnat, n: posnat, p: posnat, q: posnat, A: Mat(m, p),
            B: Mat(n, p), C: Mat(m, q), D: Mat(n, q),
            i: below(A`rows + B`rows), j: below(A`cols + C`cols)):
      NOT j < A`cols AND NOT i < A`rows IMPLIES
       j - A`cols >= 0 AND j - A`cols < D`cols;

  % Subtype TCC generated (at line 92, column 117) for  i
      % expected type  below(V`comp1 + V`comp2)
  BV1toBV2_TCC1: OBLIGATION
    FORALL (V: Block_Vector, i: below(V`comp1)): i < V`comp1 + V`comp2;

  % Subtype TCC generated (at line 92, column 168) for  i + V`comp1
      % expected type  below(V`comp1 + V`comp2)
  BV1toBV2_TCC2: OBLIGATION
    FORALL (V: Block_Vector, i: below(V`comp2)):
      i + V`comp1 < V`comp1 + V`comp2;

  % Subtype TCC generated (at line 94, column 179) for  i - V`comp1
      % expected type  below(V`comp2)
  BV2toBV1_TCC1: OBLIGATION
    FORALL (V: Block_Vector2, i: below(V`comp1 + V`comp2)):
      NOT i < V`comp1 IMPLIES i - V`comp1 >= 0 AND i - V`comp1 < V`comp2;

  % Subtype TCC generated (at line 107, column 12) for  i - m
      % expected type  Index[n]
  V2Block_TCC1: OBLIGATION
    FORALL (m, n: posnat, i: below(m + n)):
      NOT i < m IMPLIES i - m >= 0 AND i - m < n;

  % Subtype TCC generated (at line 138, column 60) for  Block2V1(W)
      % expected type  Vector[V`comp1]
  times_TCC1: OBLIGATION
    FORALL (V: Block_Vector, (W: Block_Vect(V`comp1, V`comp2))):
      FORALL (x: nat): x < W`comp1 IFF x < V`comp1;

  % Subtype TCC generated (at line 138, column 86) for  Block2V2(W)
      % expected type  Vector[V`comp2]
  times_TCC2: OBLIGATION
    FORALL (V: Block_Vector, (W: Block_Vect(V`comp1, V`comp2))):
      FORALL (x: nat): x < W`comp2 IFF x < V`comp2;

  % Subtype TCC generated (at line 140, column 132) for  Block2V1(V)
      % expected type  Vector[Block2M1(M)`cols]
  times_TCC3: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < V`comp1 IFF x < Block2M1(M)`cols;

  % Subtype TCC generated (at line 140, column 158) for  Block2V2(V)
      % expected type  Vector[Block2M3(M)`cols]
  times_TCC4: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < V`comp2 IFF x < Block2M3(M)`cols;

  % Subtype TCC generated (at line 140, column 146) for
      % Block2M3(M) * Block2V2(V)
      % expected type  Vector[Block2M1(M)`rows]
  times_TCC5: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < Block2M3(M)`rows IFF x < Block2M1(M)`rows;

  % Subtype TCC generated (at line 140, column 120) for
      % Block2M1(M) * Block2V1(V) + Block2M3(M) * Block2V2(V)
      % expected type  [below(M`rows1) -> real]
  times_TCC6: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < Block2M1(M)`rows IFF x < M`rows1;

  % Subtype TCC generated (at line 140, column 194) for  Block2V1(V)
      % expected type  Vector[Block2M2(M)`cols]
  times_TCC7: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < V`comp1 IFF x < Block2M2(M)`cols;

  % Subtype TCC generated (at line 140, column 220) for  Block2V2(V)
      % expected type  Vector[Block2M4(M)`cols]
  times_TCC8: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < V`comp2 IFF x < Block2M4(M)`cols;

  % Subtype TCC generated (at line 140, column 208) for
      % Block2M4(M) * Block2V2(V)
      % expected type  Vector[Block2M2(M)`rows]
  times_TCC9: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < Block2M4(M)`rows IFF x < Block2M2(M)`rows;

  % Subtype TCC generated (at line 140, column 182) for
      % Block2M2(M) * Block2V1(V) + Block2M4(M) * Block2V2(V)
      % expected type  [below(M`rows2) -> real]
  times_TCC10: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < Block2M2(M)`rows IFF x < M`rows2;

  % Subtype TCC generated (at line 142, column 228) for  i
      % expected type  below(N`rows1 + N`rows2)
  plus_TCC1: OBLIGATION
    FORALL (M: Block_Matrix, N: (same_Bdim?(M)), i: below(M`rows1 + M`rows2),
            j: below(M`cols1 + M`cols2)):
      i < N`rows1 + N`rows2;

  % Subtype TCC generated (at line 142, column 230) for  j
      % expected type  below(N`cols1 + N`cols2)
  plus_TCC2: OBLIGATION
    FORALL (M: Block_Matrix, N: (same_Bdim?(M)), i: below(M`rows1 + M`rows2),
            j: below(M`cols1 + M`cols2)):
      j < N`cols1 + N`cols2;

  % Subtype TCC generated (at line 152, column 103) for
      % transpose(Block2M1(M))
      % expected type  Mat(M`cols1, M`rows1)
  conv_transp_TCC1: OBLIGATION
    FORALL (M: Block_Matrix):
      transpose(Block2M1(M))`rows = M`cols1 AND
       transpose(Block2M1(M))`cols = M`rows1;

  % Subtype TCC generated (at line 152, column 126) for
      % transpose(Block2M3(M))
      % expected type  Mat(M`cols2, M`rows1)
  conv_transp_TCC2: OBLIGATION
    FORALL (M: Block_Matrix):
      transpose(Block2M3(M))`rows = M`cols2 AND
       transpose(Block2M3(M))`cols = M`rows1;

  % Subtype TCC generated (at line 152, column 149) for
      % transpose(Block2M2(M))
      % expected type  Mat(M`cols1, M`rows2)
  conv_transp_TCC3: OBLIGATION
    FORALL (M: Block_Matrix):
      transpose(Block2M2(M))`rows = M`cols1 AND
       transpose(Block2M2(M))`cols = M`rows2;

  % Subtype TCC generated (at line 152, column 172) for
      % transpose(Block2M4(M))
      % expected type  Mat(M`cols2, M`rows2)
  conv_transp_TCC4: OBLIGATION
    FORALL (M: Block_Matrix):
      transpose(Block2M4(M))`rows = M`cols2 AND
       transpose(Block2M4(M))`cols = M`rows2;

  % Subtype TCC generated (at line 166, column 85) for  Block2V(W)
      % expected type  Vector[V`comp1 + V`comp2]
  blockV_equal_TCC1: OBLIGATION
    FORALL (V: Block_Vector, W: Block_Vect(V`comp1, V`comp2)):
      FORALL (x: nat): x < W`comp1 + W`comp2 IFF x < V`comp1 + V`comp2;

  % Subtype TCC generated (at line 170, column 87) for  x
      % expected type  Vector[V2Block(m, n)(x, y)`comp1]
  VtoBlocktoV1_TCC1: OBLIGATION
    FORALL (m, n: posnat, x: Vector[m], y: Vector[n]):
      FORALL (x2: nat): x2 < m IFF x2 < V2Block(m, n)(x, y)`comp1;

  % Subtype TCC generated (at line 172, column 87) for  y
      % expected type  Vector[V2Block(m, n)(x, y)`comp2]
  VtoBlocktoV2_TCC1: OBLIGATION
    FORALL (m, n: posnat, x: Vector[m], y: Vector[n]):
      FORALL (x2: nat): x2 < n IFF x2 < V2Block(m, n)(x, y)`comp2;

  % Subtype TCC generated (at line 174, column 99) for  i
      % expected type  Index
                     %     [V2Block(m, n)(x, y)`comp1 +
                     %       V2Block(m, n)(x, y)`comp2]
  VtoBlocktoV_TCC1: OBLIGATION
    FORALL (m, n: posnat, x: Vector[m], y: Vector[n], i: below[m + n]):
      i < V2Block(m, n)(x, y)`comp1 + V2Block(m, n)(x, y)`comp2;

  % Subtype TCC generated (at line 176, column 92) for  V
      % expected type  Vector
                     %     [Vec2Block(m, n)(V)`comp1 +
                     %       Vec2Block(m, n)(V)`comp2]
  Vec_block_Vec_TCC1: OBLIGATION
    FORALL (m, n: posnat, V: Vector[m + n]):
      FORALL (x: nat):
        x < m + n IFF x < Vec2Block(m, n)(V)`comp1 + Vec2Block(m, n)(V)`comp2;

  % Subtype TCC generated (at line 182, column 108) for  Block2V(V)
      % expected type  Vector[Block2M(M)`cols]
  block_product_TCC1: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat): x < V`comp1 + V`comp2 IFF x < Block2M(M)`cols;

  % Subtype TCC generated (at line 182, column 97) for
      % Block2M(M) * Block2V(V)
      % expected type  Vector[BV2toBV1(M * V)`comp1 + BV2toBV1(M * V)`comp2]
  block_product_TCC2: OBLIGATION
    FORALL (M: (Bdiag_square?), V: Block_Vect(M`cols1, M`cols2)):
      FORALL (x: nat):
        x < Block2M(M)`rows IFF
         x < BV2toBV1(M * V)`comp1 + BV2toBV1(M * V)`comp2;


body:
  % --------------------------------------------------------------
  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013
  % ----------------------------------------------------------------
  %   This theory defines the map operator.   
  % 
  % --------------------------------------------------------------
  %  This file is a single component of a library of linear 
  %  algebra theories. 
  %  --------------------------------------------------------------
  %  For the most part, we follow the treatmet in the following texts
  %
  % [FIS] Linear Algebra, S. Friedburg, A.  Insel, and L. Spense, 3rd edition, Prentice-Hall.
  %
  % [SA]  Linear Algebra Done Right,  S. Axler. 2nd Edition. Springer-Verlag. 
  %
  %   [D]  Topology,  J. Dungundji, Allen and Bacon Co.
  %
  %   [K]  Introductory Functional Analysis,  Kreysizg, Wiley.
  %
  %   [R]  Convex Analysis, R. Rockafellar, Princeton University Press.   
  %
  %   [J]   A Lecture or the S-Procedure, U. Jonsson.
  %
  %
  %
  %-------------------------------------------------------------


  linear_map: theory

   BEGIN


   IMPORTING vectors@vectors

   n,m :VAR posnat 



  %------------------------------------------------------------------------
  % A map from an n dimensional vector space to an m dimensional vector
  % space takes a n-dimensional vector to an m-dimensional vector.
  % It is defined as a record given by: the dimension of the domain, the
  % dimension of the codomain, and the function from the domain to the
  % codomain
  %------------------------------------------------------------------------

   Maping: TYPE = [#dom: posnat,codom: posnat,mp: [Vector[dom]->Vector[codom]]#]

   Map(n,m): TYPE = {f: Maping | f`dom = n and f`codom = m}



  %-----------------------------------------------------------------------------
  % Next we define operations with mappings.
  % same_dim? and same? provide the restrictions relating to the domain and
  % codomain which allow us to define the sum and the composition, respectively
  %-----------------------------------------------------------------------------

   same_dim?(f: Maping)(g: Maping):bool = f`dom = g`dom and f`codom = g`codom;

   same?(f: Maping)(g: Maping): bool = f`dom = g`codom; 


   +(f: Maping,(g: (same_dim?(f)))): Maping = f WITH [`mp:= lambda(x: Vector[f`dom]): f`mp(x) + g`mp(x)];	

   *(a: real, f: Maping): Maping = f WITH [`mp:= lambda(x: Vector[f`dom]): a*f`mp(x)];

   o(f: Maping,(g: (same?(f)))): Maping = (#dom:= g`dom,codom:= f`codom,mp:= f`mp o g`mp#)	



  %------------------------------------------------------------------------------------
  % Finally we define the concepts of bijective map and inverse mapping, which are 
  % given through the same definitions relating to functions, and we also define
  % the identity mapping
  %------------------------------------------------------------------------------------

   bijective?(n)(f: Map(n,n)): bool = bijective?[Vector[n],Vector[n]](f`mp);

   inverse(n)(f: Map(n,n)): Maping = (#dom:= n,codom:= n,mp:= inverse[Vector[n],Vector[n]](f`mp)#)

   id(n): Maping = (#dom:= n,codom:= n,mp:= lambda(x: Vector[n]): x#)



  end linear_map

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

  % Subtype TCC generated (at line 70, column 99) for  x
      % expected type  Vector[g`dom]
  plus_TCC1: OBLIGATION
    FORALL (f: Maping, (g: (same_dim?(f)))):
      FORALL (x2: nat): x2 < f`dom IFF x2 < g`dom;

  % Subtype TCC generated (at line 70, column 94) for  g`mp(x)
      % expected type  Vector[f`codom]
  plus_TCC2: OBLIGATION
    FORALL (f: Maping, (g: (same_dim?(f)))):
      FORALL (x2: nat): x2 < g`codom IFF x2 < f`codom;

  % Subtype TCC generated (at line 74, column 82) for  g`mp
      % expected type  [Vector[g`dom] -> Vector[f`dom]]
  oh_TCC1: OBLIGATION
    FORALL (f: Maping, (g: (same?(f)))):
      FORALL (x1: Vector[g`dom], x: nat): x < g`codom IFF x < f`dom;

  % Subtype TCC generated (at line 84, column 68) for  f`mp
      % expected type  [Vector[n] -> Vector[n]]
  bijective?_TCC1: OBLIGATION
    FORALL (n: posnat, f: Map(n, n)):
      (FORALL (x: nat): x < f`dom IFF x < n) AND
       (FORALL (x1: Vector[f`dom], x: nat): x < f`codom IFF x < n);


body:
  % --------------------------------------------------------------
  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013
  % ---------------------------------------------------------------
  % This is the top level file of a linear algebra library for PVS.
  % 
  % 
  % --------------------------------------------------------------
  %  This file is a single component of a library of linear 
  %  algebra theories. The NASA vector libraries are used.
  %

  % ---------------------------------------------------------------

  %  --------------------------------------------------------------
  %  For the most part, we follow the treatmet in the following texts
  %
  % [FIS] Linear Algebra, S. Friedburg, A.  Insel, and L. Spense, 3rd edition, Prentice-Hall.
  %
  % [SA]  Linear Algebra Done Right,  S. Axler. 2nd Edition. Springer-Verlag. 
  %
  %   [D]  Topology,  J. Dungundji, Allen and Bacon Co.
  %
  %   [K]  Introductory Functional Analysis,  Kreysizg, Wiley.
  %
  %   [R]  Convex Analysis, R. Rockafellar, Princeton University Press
  %
  %   [J]   A Lecture or the S-Procedure, U. Jonsson
  %
  %-------------------------------------------------------------------

  %-------------------------------------------------------------------
  % This theory introduces and defines properties of the summation of 
  % vector valued functions, F: T -> Rn
  %
  %  		                high
  %		                ----
  %  (SigmaV(low, high, F))(i) =  \     (F(j))(i)
  %		                /
  %		                ----
  %		               j = low
  %
  %------------------------------------------------------------------


  sigma_vector[T: type from int,n: posnat]: THEORY


   BEGIN

   ASSUMING
   
      connected_domain: ASSUMPTION (FORALL (x, y: T), (z: integer): 
                                       x <= z AND z <= y IMPLIES T_pred(z))
   ENDASSUMING


   IMPORTING  linear_map



   F: VAR FUNCTION [T -> Vector[n]]
   d: VAR FUNCTION [T -> real]
   low: VAR T_low[T]
   high: VAR T_high[T] 
   a: VAR real
   


  %--------------------------------------------------------------------------------------------
  % Defines the vector given by the summation of a vector valued function  over a given range
  % -------------------------------------------------------------------------------------------

   SigmaV(low,high,F): Vector[n] = (lambda(i: below[n]): sigma(low,high,lambda(j: T): F(j)(i)));



  %---------------------------------------------------------------------------
  % Defines multiplication of a scalar real by a vector valued function
  % --------------------------------------------------------------------------

   *: [real,function[T -> Vector[n]] -> function[T -> Vector[n]]] = LAMBDA(a,F): LAMBDA(i: T): a*F(i);


  % --------------------------------------------------------------------------
  % Defines the multiplication of a vector by a vector valued function 
  % --------------------------------------------------------------------------
   
   *: [function[T -> real],function[T -> Vector[n]] -> function[T -> Vector[n]]] = LAMBDA(d,F): LAMBDA(i: T): d(i)*F(i);


  % --------------------------------------------------------------------------
  % Defines the compositon of a map and a vector valued function. 
  % --------------------------------------------------------------------------

   o: [Map(n,n),function[T -> Vector[n]] -> function[T -> Vector[n]]] = LAMBDA(h: Map(n,n),F): LAMBDA(i: T): h`mp(F(i));



  %---------------------------------------------------------------------------
  % This lemma allow us to isolate the last term of the sum
  %---------------------------------------------------------------------------

   SigmaV_last: THEOREM high >= low IMPLIES SigmaV(low, high, F) = SigmaV(low, high-1, F) + F(high);	



  %---------------------------------------------------------------------------
  % This lemma allow us to extract an scalar from the sum
  %---------------------------------------------------------------------------

   SigmaV_scal: LEMMA FORALL (a: real, m,p: T,F: [T -> Vector[n]]): SigmaV(p,m,a*F) = a*SigmaV(p,m,F)


  END sigma_vector

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

  % Assuming TCC generated (at line 69, column 10) for  T_low[T]
      % generated from assumption sigma.connected_domain
  low_TCC1: OBLIGATION
    (FORALL (x, y: T), (z: integer): x <= z AND z <= y IMPLIES T_pred(z));

  % Subtype TCC generated (at line 101, column 112) for  F(i)
      % expected type  Vector[h`dom]
  oh_TCC1: OBLIGATION
    FORALL (h: Map(n, n), i: T): FORALL (x: nat): x < n IFF x < h`dom;

  % Subtype TCC generated (at line 101, column 107) for  h`mp(F(i))
      % expected type  Vector[n]
  oh_TCC2: OBLIGATION
    FORALL (h: Map(n, n), i: T): FORALL (x: nat): x < h`codom IFF x < n;

  % Subtype TCC generated (at line 109, column 77) for  high - 1
      % expected type  T_high[T]
  SigmaV_last_TCC1: OBLIGATION
    FORALL (high: T_high[T], low: T_low[T]):
      high >= low IMPLIES T_pred(high - 1) OR (EXISTS (j: T): high - 1 <= j);

  % Subtype TCC generated (at line 109, column 92) for  high
      % expected type  T
  SigmaV_last_TCC2: OBLIGATION
    FORALL (high: T_high[T], low: T_low[T]): high >= low IMPLIES T_pred(high);


body:
  % --------------------------------------------------------------
  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013
  % ---------------------------------------------------------------
  % This PVS theory defines a linear map on vector spaces. See [SA] Chapter 3 and 
  %  Chapter 2 of [FIS] for an a detailed account of the concepts.  
  % 
  % --------------------------------------------------------------
  %  This file is a single component of a library of linear 
  %  algebra theories. 
  %

  % ------------------------------------------------------------  

  %  --------------------------------------------------------------
  %  For the most part, we follow the treatmet in the following texts
  %
  % [FIS] Linear Algebra, S. Friedburg, A.  Insel, and L. Spense, 3rd edition, Prentice-Hall.
  %
  % [SA]  Linear Algebra Done Right,  S. Axler. 2nd Edition. Springer-Verlag. 
  %
  %   [D]  Topology,  J. Dungundji, Allen and Bacon Co.
  %
  %   [K]  Introductory Functional Analysis,  Kreysizg, Wiley.
  %
  %   [R]  Convex Analysis, R. Rockafellar, Princeton University Press
  %
  %   [J]   A Lecture or the S-Procedure, U. Jonsson
  %
  %-------------------------------------------------------------


  linear_map_def: theory

   BEGIN


   IMPORTING sigma_vector,sigma_lemmas

   f,g,h,k: VAR Maping
   n,m,l,p: VAR posnat



  % -------------------------------------------------------------------------------
  % We define a base of an n-dimensionan vector space as a set of n vector which
  % are unitary, orthogonal and which generate the whole vector space
  % -------------------------------------------------------------------------------

   unit?(n)(e: [below[n] -> Vector[n]]): bool = FORALL (i: below[n]): e(i)*e(i)=1

   ortho?(n)(e: [below[n] -> Vector[n]]): bool = FORALL (i,j: below[n]): (i /= j IMPLIES e(i)*e(j)=0)

   vec_expan?(n)(e: [below[n] -> Vector[n]]): bool = FORALL (x: Vector[n]): x = SigmaV(0,n-1,x*e)


   base?(n)(e: [below[n] -> Vector[n]]): bool = unit?(n)(e) and ortho?(n)(e) and vec_expan?(n)(e)



  % -------------------------------------------------------------------------------
  % We now define the base of an n-dimensional vector space as the "standard 
  % base", that is, each ith element of the base is a row of 0s with the exception
  % that the ith entry is 1.
  % So base e(i)(i) = 1 and e(i)(j) =0 if i /= j.
  %
  % We also prove that this is indeed a base, according to the previous definition.
  % In order to do this we use the lemma which states that a vector can be 
  % represented as a combination of itself and the "standar base"
  % -------------------------------------------------------------------------------

   e(n): [below[n]->Vector[n]] = LAMBDA(j: below[n]): LAMBDA(i: below[n]): IF (i=j) THEN 1 ELSE 0 ENDIF

   vec_repre_bases: LEMMA FORALL (x: Vector[n]): x = SigmaV(0,n-1,x*e(n))

   cano_base:LEMMA base?(n)(e(n))




  %---------------------------------------------------------------------------
  % Definition of linear maps, which is given with two different notations
  %---------------------------------------------------------------------------
   
   linear_map_e?(h,l,n,m): bool = h`dom = n and h`codom = m and FORALL (x: Vector[l],F: [below[l]->Vector[n]]): 
   h`mp(SigmaV[below[l],n](0,l-1,x*F)) = SigmaV[below[l],m](0,l - 1,x*(h`mp o F));


   linear_map_e?(n,m)(h): bool = FORALL (l): linear_map_e?(h,l,n,m)


   Map_linear(n,m): TYPE = {h: Map(n,m) | linear_map_e?(n,m)(h)}



  % ------------------------------------------------------------------------------------------- 
  % If f and g are linear maps, then their compositon is a linear map.  
  % -------------------------------------------------------------------------------------------  

   linear_map_e_comp: LEMMA FORALL (f: Map(m,p),g: Map(n,m)): linear_map_e?(m,p)(f)  AND linear_map_e?(n,m)(g) 
                        IMPLIES linear_map_e?(n,p)(f o g)



  % --------------------------------------------------------------------------
  % If functions k and j are equal and h is bijective, then k is bijective. 
  % --------------------------------------------------------------------------
   
   bijecti_fun_equa: LEMMA FORALL (k,h:Map(n,n)):k=h AND bijective?(n)(h) 
                    IMPLIES 
                    bijective?(n)(k)



  % --------------------------------------------------------------------------
  % If two linear maps, h and k, coincide when applying them to the standard
  % base, the maps are equal
  % --------------------------------------------------------------------------

   equa_basis_n: LEMMA FORALL (h,k: Map_linear(n,m)): h`mp o e(n) = k`mp o e(n) 
                      IMPLIES h = k



  %------------------------------------------------------------
  % Classic linear map definition
  %------------------------------------------------------------

   additive?(f): bool = FORALL (x,y: Vector[f`dom]): f`mp(x + y) = f`mp(x) + f`mp(y)

   homogeneous?(f): bool = FORALL (a: real, x: Vector[f`dom]): f`mp(a*x) = a*f`mp(x)

   linear_map?(f): bool = additive?(f) AND homogeneous?(f);



  %------------------------------------------------------------
  % Equivalence between the two linear map definitions
  %------------------------------------------------------------

   linear_map_characterization: LEMMA FORALL (f: Map(n,n)): linear_map?(f) IFF linear_map_e?(n,n)(f);


  end linear_map_def

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

  % Subtype TCC generated (at line 59, column 85) for  0
      % expected type  T_low[Index[n]]
  vec_expan?_TCC1: OBLIGATION
    FORALL (n: posnat): 0 >= 0 AND 0 < n OR (EXISTS (j: Index[n]): j <= 0);

  % Subtype TCC generated (at line 59, column 87) for  n - 1
      % expected type  T_high[Index[n]]
  vec_expan?_TCC2: OBLIGATION
    FORALL (n: posnat):
      n - 1 >= 0 AND n - 1 < n OR (EXISTS (j: Index[n]): n - 1 <= j);

  % Assuming TCC generated (at line 43, column 11) for
      % sigma_vector[Index[n], n]
      % generated from assumption sigma_vector.connected_domain
  vec_expan?_TCC3: OBLIGATION
    FORALL (n: posnat):
      FORALL (x, y: Index[n]), (z: integer):
        x <= z AND z <= y IMPLIES z >= 0 AND z < n;

  % Subtype TCC generated (at line 91, column 25) for  0
      % expected type  T_low[below[l]]
  linear_map_e?_TCC1: OBLIGATION
    FORALL (h: Maping, l: posnat, n: posnat, m: posnat):
      h`codom = m AND h`dom = n IMPLIES
       0 >= 0 AND 0 < l OR (EXISTS (j: below[l]): j <= 0);

  % Subtype TCC generated (at line 91, column 27) for  l - 1
      % expected type  T_high[below[l]]
  linear_map_e?_TCC2: OBLIGATION
    FORALL (h: Maping, l: posnat, n: posnat, m: posnat):
      h`codom = m AND h`dom = n IMPLIES
       l - 1 >= 0 AND l - 1 < l OR (EXISTS (j: below[l]): l - 1 <= j);

  % Assuming TCC generated (at line 43, column 11) for
      % sigma_vector[Index[l], n]
      % generated from assumption sigma_vector.connected_domain
  linear_map_e?_TCC3: OBLIGATION
    FORALL (h: Maping, l: posnat, n: posnat, m: posnat):
      h`codom = m AND h`dom = n IMPLIES
       (FORALL (x, y: Index[l]), (z: integer):
          x <= z AND z <= y IMPLIES z >= 0 AND z < l);

  % Subtype TCC generated (at line 91, column 6) for
      % SigmaV[below[l], n](0, l - 1, x * F)
      % expected type  Vector[h`dom]
  linear_map_e?_TCC4: OBLIGATION
    FORALL (h: Maping, n: posnat, m: posnat):
      h`codom = m AND h`dom = n IMPLIES
       (FORALL (x2: nat): x2 < n IFF x2 < h`dom);

  % Subtype TCC generated (at line 91, column 66) for  x * (h`mp o F)
      % expected type  [below[l] -> Vector[m]]
  linear_map_e?_TCC5: OBLIGATION
    FORALL (h: Maping, l: posnat, n: posnat, m: posnat):
      h`codom = m AND h`dom = n IMPLIES
       (FORALL (x1: Index[l], x3: nat): x3 < h`codom IFF x3 < m);

  % Subtype TCC generated (at line 91, column 39) for
      % SigmaV[below[l], m](0, l - 1, x * (h`mp o F))
      % expected type  Vector[h`codom]
  linear_map_e?_TCC6: OBLIGATION
    FORALL (h: Maping, n: posnat, m: posnat):
      h`codom = m AND h`dom = n IMPLIES
       (FORALL (x2: nat): x2 < m IFF x2 < h`codom);

  % Subtype TCC generated (at line 106, column 53) for  g
      % expected type  (same?(f))
  linear_map_e_comp_TCC1: OBLIGATION
    FORALL (m, n, p: posnat, f: Map(m, p), g: Map(n, m)):
      linear_map_e?(m, p)(f) AND linear_map_e?(n, m)(g) IMPLIES same?(f)(g);

  % Subtype TCC generated (at line 125, column 59) for  e(n)
      % expected type  [below[n] -> Vector[h`dom]]
  equa_basis_n_TCC1: OBLIGATION
    FORALL (m, n: posnat, h, k: Map_linear(n, m)):
      FORALL (x1: below[n], x: nat): x < n IFF x < h`dom;

  % Subtype TCC generated (at line 125, column 73) for  e(n)
      % expected type  [below[n] -> Vector[k`dom]]
  equa_basis_n_TCC2: OBLIGATION
    FORALL (m, n: posnat, h, k: Map_linear(n, m)):
      FORALL (x1: below[n], x: nat): x < n IFF x < k`dom;

  % Subtype TCC generated (at line 125, column 66) for  k`mp o e(n)
      % expected type  [below[n] -> Vector[h`codom]]
  equa_basis_n_TCC3: OBLIGATION
    FORALL (m, n: posnat, h, k: Map_linear(n, m)):
      FORALL (x1: below[n], x: nat): x < k`codom IFF x < h`codom;


body:
  % --------------------------------------------------------------
  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013
  % ---------------------------------------------------------------
  %
  %       File Contents
  %-----------------------------------------------------------------------------
  % This theory gives a one to one relation between maps and matrices
  % The inverse of a matrix is defined using the inverse of the associated map
  % This theory gives basic properties of the inverse of a matrix
  %
  % ----------------------------------------------------------------------------
  %  This file is a single component of a library of linear 
  %  algebra theories. 
  %  ---------------------------------------------------------------------------
  %  For the most part, we follow the treatmet in the following texts
  %
  % [FIS] Linear Algebra, S. Friedburg, A.  Insel, and L. Spense, 3rd edition, Prentice-Hall.
  % 
  % [SA]  Linear Algebra Done Right,  S. Axler. 2nd Edition. Springer-Verlag. 
  %
  %   [D]  Topology,  J. Dungundji, Allen and Bacon Co.
  %
  %   [K]  Introductory Functional Analysis,  Kreysizg, Wiley.
  %
  %   [R]  Convex Analysis, R. Rockafellar, Princeton University Press.   
  %
  %   [J]   A Lecture or the S-Procedure, U. Jonsson.
  %
  % --------------------------------------------------------------



  matrix_operator: theory

   BEGIN

   IMPORTING matrices,linear_map_def

   A,B: VAR Matrix
   M:VAR Square
   n,m,l,p: VAR posnat




  % ------------------------------------------------------------------------------------------  
  % Preliminary lemmas
  % ------------------------------------------------------------------------------------------

  % Given a linear bijective map, its inverse is also linear
   linear_inverse_map_n: LEMMA  FORALL (f: Map_linear(n,n)): bijective?(n)(f)  IMPLIES linear_map_e?(n,n)(inverse(n)(f))


  % The composition of linear maps is also linear
   linear_comp: LEMMA FORALL (n,m,l: posnat,g: Map_linear(n,m),f: Map_linear(m,l)):
                     linear_map_e?(n,l)(f o g)


   linear_matrix: LEMMA FORALL (A: Mat(n,m),F: [below[l] -> [Vector[m]]]): A*SigmaV(0,l-1,F) = SigmaV(0,l-1,lambda(i: below[l]):A*F(i))


  % The inverse of a map is unique
   equa_inv:LEMMA FORALL(f,g,h: Map(n,n)):(f o g)`mp = id(n)`mp and (h o f)`mp = id(n)`mp
                 IMPLIES
                 bijective?(n)(f)                     

   inv_uni:LEMMA FORALL(f,g,h: Map(n,n)): (f o g)`mp = id(n)`mp and (h o f)`mp = id(n)`mp
                 IMPLIES
                 inverse(n)(f) = g and inverse(n)(f) = h 




  % ------------------------------------------------------------------------------------------  
  % Defines an operator L which associates a Matrix to a linear map f,
  % See pg 74[FIS].
  % ------------------------------------------------------------------------------------------  

   L(n,m): [Map_linear(n,m) -> Mat(m,n)] = (lambda(f: Map_linear(n,m)): 
                   (#rows:= m,cols:= n,matrix:= lambda(j: below[m],i: below[n]): f`mp(e(n)(i))(j)#))



  % ------------------------------------------------------------------------------------------- 
  % Defines a operator T that given an n x n square matrix A produces a linear map on the n
  % dimensional vector space. 
  % -------------------------------------------------------------------------------------------
   
  T(n,m): [Mat(m,n) -> Map_linear(n,m)]=(lambda(A: Mat(m,n)): (#dom:= n,codom:= m,mp:= lambda(x: Vector[n]): lambda(j: below[m]): 
                                                              sigma(0,A`cols-1,lambda(i: below[A`cols]): A`matrix(j,i)*x(i))#))  



  % -------------------------------------------------------------------------------------------
  % The operator T is just multiplying by the matrix
  % -------------------------------------------------------------------------------------------  

   T_matr: LEMMA FORALL (A: Mat(m,n),x: Vector[n]): (T(n,m)(A))`mp(x) = A*x; 



  % -------------------------------------------------------------------------------------------  
  % The map produced by T is a linear map. 
  % -------------------------------------------------------------------------------------------  
   
   linear_map_T: LEMMA  FORALL (A: Mat(m,n)): linear_map_e?(n,m)(T(n,m)(A));
   


  % -------------------------------------------------------------------------------------------  
  % There is bijection between L and T.  
  % -------------------------------------------------------------------------------------------  

   map_matrix_bij: LEMMA FORALL (A: Mat(m,n)): L(n,m)(T(n,m)(A)) = A



  % -------------------------------------------------------------------------------------------  
  % If f and g are equal, then  the matrices produced by applying L to them are also 
  % equal.
  % -------------------------------------------------------------------------------------------  

   operator: LEMMA FORALL (f,g: Map_linear(n,m)): f = g 
                  IMPLIES 
                  L(f`dom,f`codom)(f) = L(g`dom,g`codom)(g)              



  % -------------------------------------------------------------------------------------------  
  %  The operator L is bijective 
  % -------------------------------------------------------------------------------------------  

   Iso: LEMMA  bijective?(L(n,m))



  % -------------------------------------------------------------------------------------------  
  % Given a linear map f, applying L and then T yields f
  % -------------------------------------------------------------------------------------------  

   iso_map: LEMMA FORALL (f: Map_linear(n,m)):
                 T(n,m)(L(n,m)(f)) = f 

     

  % -------------------------------------------------------------------------------------------  
  %  The inverse of L is T 
  % -------------------------------------------------------------------------------------------

   L_inverse: LEMMA inverse(L(n,m)) = T(n,m)



  % -------------------------------------------------------------------------------------------  
  %  The operator T is bijective 
  % -------------------------------------------------------------------------------------------

   Iso_T : LEMMA bijective?(T(n,m))



  % -------------------------------------------------------------------------------------------  
  % T takes products of matrices to compositions of maps.
  % L takes compositions of maps to products of matrices
  % -------------------------------------------------------------------------------------------

   mult_comp: LEMMA FORALL (A: Mat(p,m),B: Mat(m,n)): T(n,p)(A*B) = T(m,p)(A) o T(n,m)(B)

   comp_mult:   LEMMA FORALL (g: Map_linear(n,m),f: Map_linear(m,p)): 
                        L(n,p)(f o g) = L(m,p)(f)*L(n,m)(g)



  % -------------------------------------------------------------------------------------------  
  % Applying L to the indetiy map yields the identiy matrix.
  % Applying T to the idenity matrix yields the identity map
  % -------------------------------------------------------------------------------------------  

  iso_ide_L: LEMMA  L(n,n)(id(n)) = I(n)

  iso_ide_T: LEMMA T(n,n)(I(n)) = id(n)



  % -------------------------------------------------------------------------------------------  
  % Defines the set of all square  matrices where the T operator applied to them is bijective.
  % These will be the set of invertible matrices
  % -------------------------------------------------------------------------------------------  

  Matrix_inv(n):type= {A: Square | squareMat?(n)(A) and bijective?(n)(T(n,n)(A))}



  % ------------------------------------------------------------------------------------------- 
  % Defines the inverse of an invertable matrix A  by  applying L to the inverse of the
  % map produced by T(A).  See page 94 of [FIS]
  % -------------------------------------------------------------------------------------------  

   inverse_invertible: LEMMA 
   		     
  		     square?(A) AND 
  		     squareMat?(n)(A) AND 
                       bijective?(n)(T(n,n)(A)) 
                      
  		    IMPLIES 
  		    
  		    squareMat?(n)(L(n, n)(inverse(n)(T(n, n)(A)))) AND
                      bijective?(n)(T(n, n)(L(n, n)(inverse(n)(T(n, n)(A)))))

   % Definition of the inverse matrix
   inv(n): [Matrix_inv(n) -> Matrix_inv(n)] = (lambda (A: Matrix_inv(n)): L(n,n)(inverse(n)(T(n,n)(A))))






  % -------------------------------------------------------------------------------------------  
  % The product of the  inverse of a matrix A and A is the identity matrix. 
  % See Page 94 of [FIS]
  % -------------------------------------------------------------------------------------------  

   iso_inv: LEMMA  squareMat?(n)(M) AND bijective?(n)(T(n,n)(M))  
                   IMPLIES  
                   inv(n)(M)*M  = I(n) AND M*inv(n)(M) = I(n)



  % -------------------------------------------------------------------------------------------  
  % The matrix given by "inv" is in fact the inverse
  % ------------------------------------------------------------------------------------------- 

   inv: LEMMA squareMat?(n)(M) AND  
                        bijective?(n)(T(n,n)(M)) 
                        IMPLIES    
                        inverse?(M)(inv(n)(M))



  % Technical lemma
   bijec_prod: LEMMA square?(A) AND squareMat?(n)(A) AND bijective?(n)(T(n,n)(A)) AND
                    square?(M) AND squareMat?(n)(M) AND bijective?(n)(T(n,n)(M)) 
                    IMPLIES 
                    bijective?(n)(T(n,n)(A*M))



  %--------------------------------------------------------------------------------------------
  % The operator T commutes with the inverse
  %--------------------------------------------------------------------------------------------
   map_matrix_bij_inv: LEMMA FORALL (A: Matrix_inv(n)): inverse(n)(T(n,n)(A)) = T(n,n)(inv(n)(A))



  % Technical lemma
   tran_inv: LEMMA square?(A) and squareMat?(n)(A) and bijective?(n)(T(n,n)(A))
             IMPLIES 
             inverse?(transpose(A))(transpose(inv(n)(A)))  
    


  %----------------------------------------------------------------------------------------------
  % The inverse of a transpose matrix is the transpose of the inverse matrix
  %----------------------------------------------------------------------------------------------             

  bijec_transpose: LEMMA square?(A) AND squareMat?(n)(A) AND 
                         bijective?(n)(T(n,n)(A)) 
                         IMPLIES 
                         bijective?(n)(T(n,n)(transpose(A)))


  tran_inv_oper: LEMMA square?(A) and squareMat?(n)(A) and bijective?(n)(T(n,n)(A))
                 IMPLIES 
                  inv(n)(transpose(A))=transpose(inv(n)(A))



  %----------------------------------------------------------------------------------------------
  % The inverse of a product of matrices, is the product of the inverses (in the opposite order)
  %----------------------------------------------------------------------------------------------

  prod_inv:LEMMA square?(A) and squareMat?(n)(A) and bijective?(n)(T(n,n)(A)) AND
                 square?(B) and squareMat?(n)(B) and bijective?(n)(T(n,n)(B))
                 IMPLIES 
                 inverse?(A*B)(inv(n)(B)*inv(n)(A))


  prod_inv_oper:LEMMA square?(A) and squareMat?(n)(A) and bijective?(n)(T(n,n)(A)) AND
                 square?(B) and squareMat?(n)(B) and bijective?(n)(T(n,n)(B))
                 IMPLIES 
                 inv(n)(A*B)=inv(n)(B)*inv(n)(A)



  % Technical lemma, to prove the ellipsoid theorem

  equa_sol: LEMMA FORALL(x,y,b:Vector[n]): square?(M) AND 
                  squareMat?(n)(M) and 
                  y=M*x+b and 
                  bijective?(n)(T(n,n)(M)) 
                  IMPLIES 
                  x=inv(n)(M)*(y-b) 


  end matrix_operator

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

  % Subtype TCC generated (at line 63, column 42) for  g
      % expected type  (same?(f))
  linear_comp_TCC1: OBLIGATION
    FORALL (n, m, l: posnat, g: Map_linear(n, m), f: Map_linear(m, l)):
      same?(f)(g);

  % Subtype TCC generated (at line 66, column 82) for  0
      % expected type  T_low[below[l]]
  linear_matrix_TCC1: OBLIGATION
    FORALL (l, m, n: posnat, A: Mat(n, m)):
      0 >= 0 AND 0 < l OR (EXISTS (j: below[l]): j <= 0);

  % Subtype TCC generated (at line 66, column 84) for  l - 1
      % expected type  T_high[below[l]]
  linear_matrix_TCC2: OBLIGATION
    FORALL (l, m, n: posnat, A: Mat(n, m)):
      l - 1 >= 0 AND l - 1 < l OR (EXISTS (j: below[l]): l - 1 <= j);

  % Assuming TCC generated (at line 43, column 11) for
      % sigma_vector[below[l], m]
      % generated from assumption sigma_vector.connected_domain
  linear_matrix_TCC3: OBLIGATION
    FORALL (l, m, n: posnat, A: Mat(n, m)):
      FORALL (x, y: below[l]), (z: integer):
        x <= z AND z <= y IMPLIES z >= 0 AND z < l;

  % Subtype TCC generated (at line 66, column 75) for  SigmaV(0, l - 1, F)
      % expected type  Vector[A`cols]
  linear_matrix_TCC4: OBLIGATION
    FORALL (m, n: posnat, A: Mat(n, m)):
      FORALL (x: nat): x < m IFF x < A`cols;

  % Subtype TCC generated (at line 70, column 45) for  g
      % expected type  (same?(f))
  equa_inv_TCC1: OBLIGATION
    FORALL (n: posnat, f, g, h: Map(n, n)): same?(f)(g);

  % Subtype TCC generated (at line 70, column 53) for  id(n)`mp
      % expected type  [Vector[(f o g)`dom] -> Vector[(f o g)`codom]]
  equa_inv_TCC2: OBLIGATION
    FORALL (n: posnat, f, g, h: Map(n, n)):
      (FORALL (x: nat): x < id(n)`dom IFF x < (f o g)`dom) AND
       (FORALL (x1: Vector[id(n)`dom], x: nat):
          x < id(n)`codom IFF x < (f o g)`codom);

  % Subtype TCC generated (at line 70, column 71) for  f
      % expected type  (same?(h))
  equa_inv_TCC3: OBLIGATION
    FORALL (n: posnat, f, g, h: Map(n, n)):
      (f o g)`mp = id(n)`mp IMPLIES same?(h)(f);

  % Subtype TCC generated (at line 70, column 79) for  id(n)`mp
      % expected type  [Vector[(h o f)`dom] -> Vector[(h o f)`codom]]
  equa_inv_TCC4: OBLIGATION
    FORALL (n: posnat, f, g, h: Map(n, n)):
      (f o g)`mp = id(n)`mp IMPLIES
       (FORALL (x: nat): x < id(n)`dom IFF x < (h o f)`dom) AND
        (FORALL (x1: Vector[id(n)`dom], x: nat):
           x < id(n)`codom IFF x < (h o f)`codom);

  % Subtype TCC generated (at line 87, column 93) for  j
      % expected type  Index[f`codom]
  L_TCC1: OBLIGATION
    FORALL (n: posnat, m: posnat, f: Map_linear(n, m), j: below[m],
            i: below[n]):
      j < f`codom;

  % Subtype TCC generated (at line 87, column 84) for  e(n)(i)
      % expected type  Vector[f`dom]
  L_TCC2: OBLIGATION
    FORALL (n: posnat, m: posnat, f: Map_linear(n, m), j: below[m],
            i: below[n]):
      FORALL (x: nat): x < n IFF x < f`dom;

  % Subtype TCC generated (at line 97, column 66) for  0
      % expected type  T_low[below[A`cols]]
  T_TCC1: OBLIGATION
    FORALL (n: posnat, m: posnat, A: Mat(m, n), j: below[m]):
      0 >= 0 AND 0 < A`cols OR (EXISTS (j: below[A`cols]): j <= 0);

  % Subtype TCC generated (at line 97, column 68) for  A`cols - 1
      % expected type  T_high[below[A`cols]]
  T_TCC2: OBLIGATION
    FORALL (n: posnat, m: posnat, A: Mat(m, n), j: below[m]):
      A`cols - 1 >= 0 AND A`cols - 1 < A`cols OR
       (EXISTS (j: below[A`cols]): A`cols - 1 <= j);

  % Subtype TCC generated (at line 97, column 112) for  j
      % expected type  below(A`rows)
  T_TCC3: OBLIGATION
    FORALL (n: posnat, m: posnat, A: Mat(m, n), j: below[m],
            i: below[A`cols]):
      j < A`rows;

  % Subtype TCC generated (at line 97, column 119) for  i
      % expected type  Index[n]
  T_TCC4: OBLIGATION
    FORALL (n: posnat, m: posnat, A: Mat(m, n), j: below[m],
            i: below[A`cols]):
      i < n;

  % Assuming TCC generated (at line 21, column 12) for
      % reals@sigma[below[A`cols]]
      % generated from assumption sigma.connected_domain
  T_TCC5: OBLIGATION
    FORALL (n: posnat, m: posnat, A: Mat(m, n), j: below[m]):
      FORALL (x, y: below[A`cols]), (z: integer):
        x <= z AND z <= y IMPLIES z >= 0 AND z < A`cols;

  % Subtype TCC generated (at line 96, column 60) for
      % (# dom := n,
      %    codom := m,
      %    mp
      %      := LAMBDA (x: Vector[n]):
      %           LAMBDA (j: below[m]):
      %             sigma(0, A`cols - 1,
      %                   LAMBDA (i: below[A`cols]): A`matrix(j, i) * x(i)) #)
      % expected type  Map_linear(n, m)
  T_TCC6: OBLIGATION
    FORALL (n: posnat, m: posnat, A: Mat(m, n)):
      linear_map_e?(n, m)
                   ((# dom := n,
                       codom := m,
                       mp
                         := LAMBDA (x: Vector[n]):
                              LAMBDA (j: below[m]):
                                sigma[below[A`cols]]
                                    (0, A`cols - 1,
                                     LAMBDA (i: below[A`cols]):
                                       A`matrix(j, i) * x(i)) #));

  % Subtype TCC generated (at line 105, column 65) for  x
      % expected type  Vector[(T(n, m)(A))`dom]
  T_matr_TCC1: OBLIGATION
    FORALL (m, n: posnat, A: Mat(m, n)):
      FORALL (x2: nat): x2 < n IFF x2 < (T(n, m)(A))`dom;

  % Subtype TCC generated (at line 105, column 72) for  x
      % expected type  Vector[A`cols]
  T_matr_TCC2: OBLIGATION
    FORALL (m, n: posnat, A: Mat(m, n)):
      FORALL (x2: nat): x2 < n IFF x2 < A`cols;

  % Subtype TCC generated (at line 105, column 70) for  A * x
      % expected type  Vector[(T(n, m)(A))`codom]
  T_matr_TCC3: OBLIGATION
    FORALL (m, n: posnat, A: Mat(m, n)):
      FORALL (x2: nat): x2 < A`rows IFF x2 < (T(n, m)(A))`codom;

  % Subtype TCC generated (at line 132, column 33) for  f
      % expected type  Map_linear(f`dom, f`codom)
  operator_TCC1: OBLIGATION
    FORALL (m, n: posnat, f, g: Map_linear(n, m)):
      f = g IMPLIES linear_map_e?(f`dom, f`codom)(f);

  % Subtype TCC generated (at line 132, column 55) for  g
      % expected type  Map_linear(g`dom, g`codom)
  operator_TCC2: OBLIGATION
    FORALL (m, n: posnat, f, g: Map_linear(n, m)):
      f = g IMPLIES linear_map_e?(g`dom, g`codom)(g);

  % Existence TCC generated (at line 157, column 18) for  inverse
  L_inverse_TCC1: OBLIGATION
    FORALL (m, n: posnat): EXISTS (x: Map_linear(n, m)): TRUE;

  % Subtype TCC generated (at line 174, column 61) for  B
      % expected type  {N: Matrix | A`cols = N`rows}
  mult_comp_TCC1: OBLIGATION
    FORALL (m, n, p: posnat, A: Mat(p, m), B: Mat(m, n)): A`cols = B`rows;

  % Subtype TCC generated (at line 174, column 59) for  A * B
      % expected type  Mat(p, n)
  mult_comp_TCC2: OBLIGATION
    FORALL (m, n, p: posnat, A: Mat(p, m), B: Mat(m, n)):
      (A * B)`rows = p AND (A * B)`cols = n;

  % Subtype TCC generated (at line 174, column 78) for  T(n, m)(B)
      % expected type  (same?(T(m, p)(A)))
  mult_comp_TCC3: OBLIGATION
    FORALL (m, n, p: posnat, A: Mat(p, m), B: Mat(m, n)):
      same?(T(m, p)(A))(T(n, m)(B));

  % Subtype TCC generated (at line 177, column 29) for  f o g
      % expected type  Map_linear(n, p)
  comp_mult_TCC1: OBLIGATION
    FORALL (m, n, p: posnat, g: Map_linear(n, m), f: Map_linear(m, p)):
      ((f o g)`dom = n AND (f o g)`codom = p) AND linear_map_e?(n, p)(f o g);

  % Subtype TCC generated (at line 177, column 48) for  L(n, m)(g)
      % expected type  {N: Matrix | L(m, p)(f)`cols = N`rows}
  comp_mult_TCC2: OBLIGATION
    FORALL (m, n, p: posnat, g: Map_linear(n, m), f: Map_linear(m, p)):
      L(m, p)(f)`cols = L(n, m)(g)`rows;

  % Subtype TCC generated (at line 186, column 25) for  id(n)
      % expected type  Map_linear(n, n)
  iso_ide_L_TCC1: OBLIGATION
    FORALL (n: posnat):
      (id(n)`dom = n AND id(n)`codom = n) AND linear_map_e?(n, n)(id(n));

  % Subtype TCC generated (at line 188, column 24) for  I(n)
      % expected type  Mat(n, n)
  iso_ide_T_TCC1: OBLIGATION
    FORALL (n: posnat): I(n)`rows = n AND I(n)`cols = n;

  % Subtype TCC generated (at line 197, column 75) for  A
      % expected type  Mat(n, n)
  Matrix_inv_TCC1: OBLIGATION
    FORALL (n: posnat, A: Square):
      squareMat?(n)(A) IMPLIES A`rows = n AND A`cols = n;

  % Subtype TCC generated (at line 210, column 42) for  A
      % expected type  Mat(n, n)
  inverse_invertible_TCC1: OBLIGATION
    FORALL (A: Matrix, n: posnat):
      square?(A) AND squareMat?(n)(A) IMPLIES A`rows = n AND A`cols = n;

  % Subtype TCC generated (at line 214, column 28) for  inverse(n)(T(n, n)(A))
      % expected type  Map_linear(n, n)
  inverse_invertible_TCC2: OBLIGATION
    FORALL (A: Matrix, n: posnat):
      bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A) IMPLIES
       (inverse(n)(T(n, n)(A))`dom = n AND inverse(n)(T(n, n)(A))`codom = n)
        AND linear_map_e?(n, n)(inverse(n)(T(n, n)(A)));

  % Subtype TCC generated (at line 214, column 20) for
      % L(n, n)(inverse(n)(T(n, n)(A)))
      % expected type  Square
  inverse_invertible_TCC3: OBLIGATION
    FORALL (A: Matrix, n: posnat):
      bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A) IMPLIES
       square?(L(n, n)(inverse(n)(T(n, n)(A))));

  % Subtype TCC generated (at line 218, column 97) for  A
      % expected type  Mat(n, n)
  inv_TCC1: OBLIGATION
    FORALL (n: posnat, A: Matrix_inv(n)): A`rows = n AND A`cols = n;

  % Subtype TCC generated (at line 218, column 79) for  inverse(n)(T(n, n)(A))
      % expected type  Map_linear(n, n)
  inv_TCC2: OBLIGATION
    FORALL (n: posnat, A: Matrix_inv(n)):
      (inverse(n)(T(n, n)(A))`dom = n AND inverse(n)(T(n, n)(A))`codom = n)
       AND linear_map_e?(n, n)(inverse(n)(T(n, n)(A)));

  % Subtype TCC generated (at line 218, column 72) for
      % L(n, n)(inverse(n)(T(n, n)(A)))
      % expected type  Matrix_inv(n)
  inv_TCC3: OBLIGATION
    FORALL (n: posnat, A: Matrix_inv(n)):
      square?(L(n, n)(inverse(n)(T(n, n)(A)))) AND
       squareMat?(n)(L(n, n)(inverse(n)(T(n, n)(A)))) AND
        bijective?(n)(T(n, n)(L(n, n)(inverse(n)(T(n, n)(A)))));

  % Subtype TCC generated (at line 232, column 24) for  M
      % expected type  Matrix_inv(n)
  iso_inv_TCC1: OBLIGATION
    FORALL (M: Square, n: posnat):
      bijective?(n)(T(n, n)(M)) AND squareMat?(n)(M) IMPLIES
       squareMat?(n)(M) AND bijective?(n)(T(n, n)(M));

  % Subtype TCC generated (at line 232, column 27) for  M
      % expected type  {N: Matrix | inv(n)(M)`cols = N`rows}
  iso_inv_TCC2: OBLIGATION
    FORALL (M: Square, n: posnat):
      bijective?(n)(T(n, n)(M)) AND squareMat?(n)(M) IMPLIES
       inv(n)(M)`cols = M`rows;

  % Subtype TCC generated (at line 232, column 43) for  inv(n)(M)
      % expected type  {N: Matrix | M`cols = N`rows}
  iso_inv_TCC3: OBLIGATION
    FORALL (M: Square, n: posnat):
      bijective?(n)(T(n, n)(M)) AND squareMat?(n)(M) AND inv(n)(M) * M = I(n)
       IMPLIES M`cols = inv(n)(M)`rows;

  % Subtype TCC generated (at line 243, column 34) for  inv(n)(M)
      % expected type  {N: Square | N`rows = M`rows}
  inv_TCC4: OBLIGATION
    FORALL (M: Square, n: posnat):
      bijective?(n)(T(n, n)(M)) AND squareMat?(n)(M) IMPLIES
       inv(n)(M)`rows = M`rows;

  % Subtype TCC generated (at line 251, column 41) for  M
      % expected type  {N: Matrix | A`cols = N`rows}
  bijec_prod_TCC1: OBLIGATION
    FORALL (A: Matrix, M: Square, n: posnat):
           bijective?(n)(T(n, n)(M)) AND squareMat?(n)(M) AND square?(M)
       AND bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A)
       IMPLIES A`cols = M`rows;

  % Subtype TCC generated (at line 251, column 39) for  A * M
      % expected type  Mat(n, n)
  bijec_prod_TCC2: OBLIGATION
    FORALL (A: Matrix, M: Square, n: posnat):
           bijective?(n)(T(n, n)(M)) AND squareMat?(n)(M) AND square?(M)
       AND bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A)
       IMPLIES (A * M)`rows = n AND (A * M)`cols = n;

  % Subtype TCC generated (at line 258, column 85) for  inv(n)(A)
      % expected type  Mat(n, n)
  map_matrix_bij_inv_TCC1: OBLIGATION
    FORALL (n: posnat, A: Matrix_inv(n)):
      inv(n)(A)`rows = n AND inv(n)(A)`cols = n;

  % Subtype TCC generated (at line 265, column 51) for  A
      % expected type  Matrix_inv(n)
  tran_inv_TCC1: OBLIGATION
    FORALL (A: Matrix, n: posnat):
      bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A) IMPLIES
       squareMat?(n)(A) AND bijective?(n)(T(n, n)(A));

  % Subtype TCC generated (at line 265, column 34) for  transpose(inv(n)(A))
      % expected type  {N: Square | N`rows = transpose(A)`rows}
  tran_inv_TCC2: OBLIGATION
    FORALL (A: Matrix, n: posnat):
      bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A) IMPLIES
       square?(transpose(inv(n)(A))) AND
        transpose(inv(n)(A))`rows = transpose(A)`rows;

  % Subtype TCC generated (at line 265, column 20) for  transpose(A)
      % expected type  M: Square
  tran_inv_TCC3: OBLIGATION
    FORALL (A: Matrix, n: posnat):
      bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A) IMPLIES
       square?(transpose(A));

  % Subtype TCC generated (at line 276, column 44) for  transpose(A)
      % expected type  Mat(n, n)
  bijec_transpose_TCC1: OBLIGATION
    FORALL (A: Matrix, n: posnat):
      bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A) IMPLIES
       transpose(A)`rows = n AND transpose(A)`cols = n;

  % Subtype TCC generated (at line 281, column 23) for  transpose(A)
      % expected type  Matrix_inv(n)
  tran_inv_oper_TCC1: OBLIGATION
    FORALL (A: Matrix, n: posnat):
      bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A) IMPLIES
       square?(transpose(A)) AND
        squareMat?(n)(transpose(A)) AND bijective?(n)(T(n, n)(transpose(A)));

  % Subtype TCC generated (at line 290, column 72) for  B
      % expected type  Mat(n, n)
  prod_inv_TCC1: OBLIGATION
    FORALL (A, B: Matrix, n: posnat):
           square?(A) AND squareMat?(n)(A) AND bijective?(n)(T(n, n)(A))
       AND square?(B) AND squareMat?(n)(B)
       IMPLIES B`rows = n AND B`cols = n;

  % Subtype TCC generated (at line 292, column 36) for  B
      % expected type  Matrix_inv(n)
  prod_inv_TCC2: OBLIGATION
    FORALL (A, B: Matrix, n: posnat):
           bijective?(n)(T(n, n)(B)) AND squareMat?(n)(B) AND square?(B)
       AND bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A)
       IMPLIES squareMat?(n)(B) AND bijective?(n)(T(n, n)(B));

  % Subtype TCC generated (at line 292, column 39) for  inv(n)(A)
      % expected type  {N: Matrix | inv(n)(B)`cols = N`rows}
  prod_inv_TCC3: OBLIGATION
    FORALL (A, B: Matrix, n: posnat):
           bijective?(n)(T(n, n)(B)) AND squareMat?(n)(B) AND square?(B)
       AND bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A)
       IMPLIES inv(n)(B)`cols = inv(n)(A)`rows;

  % Subtype TCC generated (at line 292, column 29) for  inv(n)(B) * inv(n)(A)
      % expected type  {N: Square | N`rows = (A * B)`rows}
  prod_inv_TCC4: OBLIGATION
    FORALL (A, B: Matrix, n: posnat):
           bijective?(n)(T(n, n)(B)) AND squareMat?(n)(B) AND square?(B)
       AND bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A)
       IMPLIES
       square?(inv(n)(B) * inv(n)(A)) AND
        (inv(n)(B) * inv(n)(A))`rows = (A * B)`rows;

  % Subtype TCC generated (at line 292, column 26) for  B
      % expected type  {N: Matrix | A`cols = N`rows}
  prod_inv_TCC5: OBLIGATION
    FORALL (A, B: Matrix, n: posnat):
           bijective?(n)(T(n, n)(B)) AND squareMat?(n)(B) AND square?(B)
       AND bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A)
       IMPLIES A`cols = B`rows;

  % Subtype TCC generated (at line 292, column 24) for  A * B
      % expected type  M: Square
  prod_inv_TCC6: OBLIGATION
    FORALL (A, B: Matrix, n: posnat):
           bijective?(n)(T(n, n)(B)) AND squareMat?(n)(B) AND square?(B)
       AND bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A)
       IMPLIES square?(A * B);

  % Subtype TCC generated (at line 298, column 22) for  A * B
      % expected type  Matrix_inv(n)
  prod_inv_oper_TCC1: OBLIGATION
    FORALL (A, B: Matrix, n: posnat):
           bijective?(n)(T(n, n)(B)) AND squareMat?(n)(B) AND square?(B)
       AND bijective?(n)(T(n, n)(A)) AND squareMat?(n)(A) AND square?(A)
       IMPLIES
       square?(A * B) AND
        squareMat?(n)(A * B) AND bijective?(n)(T(n, n)(A * B));

  % Subtype TCC generated (at line 306, column 20) for  x
      % expected type  Vector[M`cols]
  equa_sol_TCC1: OBLIGATION
    FORALL (M: Square, n: posnat):
      squareMat?(n)(M) AND square?(M) IMPLIES
       (FORALL (x2: nat): x2 < n IFF x2 < M`cols);

  % Subtype TCC generated (at line 306, column 22) for  b
      % expected type  Vector[M`rows]
  equa_sol_TCC2: OBLIGATION
    FORALL (M: Square, n: posnat):
      squareMat?(n)(M) AND square?(M) IMPLIES
       (FORALL (x2: nat): x2 < n IFF x2 < M`rows);

  % Subtype TCC generated (at line 306, column 18) for  M * x + b
      % expected type  Vector[n]
  equa_sol_TCC3: OBLIGATION
    FORALL (M: Square, n: posnat):
      squareMat?(n)(M) AND square?(M) IMPLIES
       (FORALL (x2: nat): x2 < M`rows IFF x2 < n);

  % Subtype TCC generated (at line 309, column 29) for  (y - b)
      % expected type  Vector[inv(n)(M)`cols]
  equa_sol_TCC4: OBLIGATION
    FORALL (M: Square, n: posnat, x, y, b: Vector[n]):
      square?(M) AND
       squareMat?(n)(M) AND y = M * x + b AND bijective?(n)(T(n, n)(M))
       IMPLIES (FORALL (x2: nat): x2 < n IFF x2 < inv(n)(M)`cols);

  % Subtype TCC generated (at line 309, column 18) for  inv(n)(M) * (y - b)
      % expected type  Vector[n]
  equa_sol_TCC5: OBLIGATION
    FORALL (M: Square, n: posnat, x, y, b: Vector[n]):
      square?(M) AND
       squareMat?(n)(M) AND y = M * x + b AND bijective?(n)(T(n, n)(M))
       IMPLIES (FORALL (x2: nat): x2 < inv(n)(M)`rows IFF x2 < n);


body:
  matrix_lemmas: THEORY

  % Linear Algebra library
  % Heber Herencia-Zapana NIA
  % Gilberto Pérez        University of Coruña Spain
  % Pablo Ascariz         University of Coruña Spain
  % Felicidad Aguado      University of Coruña Spain
  % Date: December, 2013

   BEGIN

   IMPORTING matrix_operator


  %--------------------------------------------------------------------------------------
  %--------------------------------------------------------------------------------------
  % Matrix Lemmas
  %--------------------------------------------------------------------------------------
  %--------------------------------------------------------------------------------------


  %--------------------------------------------------------------------------------------
  % Multiplying a matrix and the zero vector yields the zero vector
  %--------------------------------------------------------------------------------------

   matrix_prod_zero: LEMMA FORALL (A:Matrix): A * zero[A`cols] = zero[A`rows]



  %--------------------------------------------------------------------------------------
  % Rows and cols of a subtraction of matrices
  %--------------------------------------------------------------------------------------

   minus_rows: LEMMA FORALL (A:Matrix,B: (same_dim?(A))): (A - B)`rows = A`rows

   minus_cols: LEMMA FORALL (A:Matrix,B: (same_dim?(A))): (A - B)`cols = A`cols
   


  %--------------------------------------------------------------------------------------
  % Rows and cols of the transpose matrix
  %--------------------------------------------------------------------------------------

   transpose_rows: LEMMA FORALL (A: Matrix): transpose(A)`rows = A`cols

   transpose_cols: LEMMA FORALL (A: Matrix): transpose(A)`cols = A`rows



  %--------------------------------------------------------------------------------------
  % Rows and cols of a product of matrices
  %--------------------------------------------------------------------------------------

   product_rows: LEMMA FORALL (A: Matrix,(B: Matrix | B`rows = A`cols)): (A * B)`rows = A`rows

   product_cols: LEMMA FORALL (A: Matrix,(B: Matrix | B`rows = A`cols)): (A * B)`cols = B`cols



   product_rows2: LEMMA FORALL (A: Matrix,(B: Matrix | B`rows = A`cols),(C: Matrix | C`rows = B`cols)): (A * B * C)`rows = A`rows

   product_cols2: LEMMA FORALL (A: Matrix,(B: Matrix | B`rows = A`cols),(C: Matrix | C`rows = B`cols)): (A * B * C)`cols = C`cols



   product_rows3: LEMMA FORALL (A: Matrix,(B: Matrix | B`rows = A`cols),(C: Matrix | C`rows = B`cols),(D: Matrix | D`rows = C`cols)): (A * B * C * D)`rows = A`rows

   product_cols3: LEMMA FORALL (A: Matrix,(B: Matrix | B`rows = A`cols),(C: Matrix | C`rows = B`cols),(D: Matrix | D`rows = C`cols)): (A * B * C * D)`cols = D`cols



   product_rows4: LEMMA FORALL (A: Matrix,(B: Matrix | B`rows = A`cols),(C: Matrix | C`rows = B`cols),(D: Matrix | D`rows = C`cols),(E: Matrix | E`rows = D`cols)): (A * B * C * D * E)`rows = A`rows

   product_cols4: LEMMA FORALL (A: Matrix,(B: Matrix | B`rows = A`cols),(C: Matrix | C`rows = B`cols),(D: Matrix | D`rows = C`cols),(E: Matrix | E`rows = D`cols)): (A * B * C * D * E)`cols = E`cols



  %--------------------------------------------------------------------------------------
  % Multiplying a matrix by its inverse yields the identity matrix
  %--------------------------------------------------------------------------------------

   inverse_ident: LEMMA FORALL (N: (invertible?)): inverse(N) * N = I(N`rows)

   ident_inverse: LEMMA FORALL (N: (invertible?)): N * (inverse(N)) = I(N`rows)



  %--------------------------------------------------------------------------------------
  % Multiplying the identity matrix by a vector yields the vector
  %--------------------------------------------------------------------------------------

   ident_mat_prod: LEMMA FORALL (n: posnat, x: Vector[n]): matrices.I(n) * x = x



  %--------------------------------------------------------------------------------------
  % Rows and cols of the inverse matrix
  %--------------------------------------------------------------------------------------

   inverse_rows: LEMMA FORALL (N: (invertible?)): (inverse(N))`rows = N`rows

   inverse_cols: LEMMA FORALL (N: (invertible?)): (inverse(N))`cols = N`cols



  %--------------------------------------------------------------------------------------
  % The transpose of the identity matrix is the identity matrix
  %--------------------------------------------------------------------------------------

   transp_ident: LEMMA FORALL (n: posnat): transpose(I(n)) = I(n)



  %--------------------------------------------------------------------------------------
  % Transpose and inverse "commute"
  %--------------------------------------------------------------------------------------

   transp_inv: LEMMA FORALL (M: (invertible?)):
                  transpose(inverse(M))=inverse((transpose(M)))



  %--------------------------------------------------------------------------------------
  % Auxiliary lemmas to make further calculations eaiser with no other interest
  %--------------------------------------------------------------------------------------

   invar_inverse: LEMMA FORALL (A: Matrix, (N: (invertible?) | A`cols = N`rows)):
       A * (inverse(N) * N) = A

   invar_inverse_left: LEMMA FORALL (B: Matrix, (N: (invertible?) | B`rows = N`cols)):
       N * (inverse(N)) * B = B



   simply1_mat_vect: LEMMA FORALL (A: Matrix, (N: (invertible?) | A`cols = N`rows), y: Vector[A`rows], x: Vector[A`cols]):
       y * ((A * (inverse(N) * N)) * x) = y * (A * x)

   simply2_mat_vect: LEMMA FORALL (B: Matrix, (N: (invertible?) | B`rows = N`rows), y: Vector[B`rows], x: Vector[B`cols]):
       y * (N * (inverse(N)) * B * x) = y * (B * x)



  %--------------------------------------------------------------------------------------
  % Distributive rules for matrices and vectors
  %--------------------------------------------------------------------------------------

   distr_mat_vect: LEMMA FORALL (A: Matrix, (B: (same_dim?(A))), y: Vector[A`cols]):
      (A + B) * y = A * y + B * y

   distr_vect_mat: LEMMA FORALL (A: Matrix, x, y: Vector[A`cols]):
      A * x + A * y = A * (x + y)



  %--------------------------------------------------------------------------------------
  % Technical lemmas about applying "minus" to matrices
  %--------------------------------------------------------------------------------------

   matrix_sum_minus: LEMMA FORALL (A: Matrix, (B: (same_dim?(A)))): A - B = A + (-B)

   matrix_prod_minus: LEMMA FORALL (A: Matrix, x: Vector[A`cols]): -(A * x) = (-A) * x



  %--------------------------------------------------------------------------------------
  % Some more distributive rules for matrices and vectors
  %--------------------------------------------------------------------------------------

   distr_esc_add: LEMMA FORALL (A: Matrix, (B: (same_dim?(A))), x:Vector[A`rows], y:Vector[A`cols]):
      x * ((A + B) * y) = x * (A * y) + x * (B * y)

   distr_esc_dif: LEMMA FORALL (A: Matrix, (B: (same_dim?(A))), x:Vector[A`rows], y:Vector[A`cols]):
      x * ((A - B) * y) = x * (A * y) - x * (B * y)

   distr_add_esc: LEMMA FORALL (A: (square?), x:Vector[A`cols], y:Vector[A`cols]):
      (x + y) * (A  * (x + y)) = x * (A * x) + x * (A * y) + y * (A * x) + y * (A * y)
   


  %--------------------------------------------------------------------------------------
  % Auxiliary lemma to make further calculations easier (aimed at Schur formula)
  %--------------------------------------------------------------------------------------

   conv_prod_int:  LEMMA FORALL (B: Matrix, (A: Matrix | B`cols = A`rows), (C: Matrix | A`cols = C`rows),  x: Vector[B`rows], y: Vector[C`cols]):
      x*((B*(A*C))*y) = (transpose(B)*x)*(A*(C*y)) 


  END matrix_lemmas

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

  % Subtype TCC generated (at line 54, column 76) for  B
      % expected type  {N: Matrix | A`cols = N`rows}
  product_rows_TCC1: OBLIGATION
    FORALL (A: Matrix, (B: Matrix | B`rows = A`cols)): A`cols = B`rows;

  % Subtype TCC generated (at line 60, column 111) for  C
      % expected type  {N: Matrix | (A * B)`cols = N`rows}
  product_rows2_TCC1: OBLIGATION
    FORALL (A: Matrix, (B: Matrix | B`rows = A`cols),
            (C: Matrix | C`rows = B`cols)):
      (A * B)`cols = C`rows;

  % Subtype TCC generated (at line 66, column 145) for  D
      % expected type  {N: Matrix | (A * B * C)`cols = N`rows}
  product_rows3_TCC1: OBLIGATION
    FORALL (A: Matrix, (B: Matrix | B`rows = A`cols),
            (C: Matrix | C`rows = B`cols), (D: Matrix | D`rows = C`cols)):
      (A * B * C)`cols = D`rows;

  % Subtype TCC generated (at line 72, column 179) for  E
      % expected type  {N: Matrix | (A * B * C * D)`cols = N`rows}
  product_rows4_TCC1: OBLIGATION
    FORALL (A: Matrix, (B: Matrix | B`rows = A`cols),
            (C: Matrix | C`rows = B`cols), (D: Matrix | D`rows = C`cols),
            (E: Matrix | E`rows = D`cols)):
      (A * B * C * D)`cols = E`rows;

  % Subtype TCC generated (at line 82, column 62) for  N
      % expected type  {N_1: Matrix | inverse(N)`cols = N_1`rows}
  inverse_ident_TCC1: OBLIGATION
    FORALL (N: (invertible?)): inverse(N)`cols = N`rows;

  % Subtype TCC generated (at line 84, column 54) for  (inverse(N))
      % expected type  {N_1: Matrix | N`cols = N_1`rows}
  ident_inverse_TCC1: OBLIGATION
    FORALL (N: (invertible?)): N`cols = (inverse(N))`rows;

  % Subtype TCC generated (at line 92, column 73) for  x
      % expected type  Vector[matrices.I(n)`cols]
  ident_mat_prod_TCC1: OBLIGATION
    FORALL (n: posnat): FORALL (x2: nat): x2 < n IFF x2 < matrices.I(n)`cols;

  % Subtype TCC generated (at line 92, column 77) for  x
      % expected type  Vector[matrices.I(n)`rows]
  ident_mat_prod_TCC2: OBLIGATION
    FORALL (n: posnat): FORALL (x2: nat): x2 < n IFF x2 < matrices.I(n)`rows;

  % Subtype TCC generated (at line 119, column 47) for  (transpose(M))
      % expected type  M: (invertible?)
  transp_inv_TCC1: OBLIGATION
    FORALL (M: (invertible?)):
      square?((transpose(M))) AND invertible?((transpose(M)));

  % Subtype TCC generated (at line 128, column 10) for  (inverse(N) * N)
      % expected type  {N: Matrix | A`cols = N`rows}
  invar_inverse_TCC1: OBLIGATION
    FORALL (A: Matrix, (N: (invertible?) | A`cols = N`rows)):
      A`cols = (inverse(N) * N)`rows;

  % Subtype TCC generated (at line 131, column 24) for  B
      % expected type  {N_1: Matrix | (N * (inverse(N)))`cols = N_1`rows}
  invar_inverse_left_TCC1: OBLIGATION
    FORALL (B: Matrix, (N: (invertible?) | B`rows = N`cols)):
      (N * (inverse(N)))`cols = B`rows;

  % Subtype TCC generated (at line 136, column 35) for  x
      % expected type  Vector[(A * (inverse(N) * N))`cols]
  simply1_mat_vect_TCC1: OBLIGATION
    FORALL (A: Matrix, (N: (invertible?) | A`cols = N`rows)):
      FORALL (x2: nat): x2 < A`cols IFF x2 < (A * (inverse(N) * N))`cols;

  % Subtype TCC generated (at line 136, column 10) for
      % ((A * (inverse(N) * N)) * x)
      % expected type  Vector[A`rows]
  simply1_mat_vect_TCC2: OBLIGATION
    FORALL (A: Matrix, (N: (invertible?) | A`cols = N`rows)):
      FORALL (x2: nat): x2 < (A * (inverse(N) * N))`rows IFF x2 < A`rows;

  % Subtype TCC generated (at line 139, column 29) for  B
      % expected type  {N_1: Matrix | (N * (inverse(N)))`cols = N_1`rows}
  simply2_mat_vect_TCC1: OBLIGATION
    FORALL (B: Matrix, (N: (invertible?) | B`rows = N`rows)):
      (N * (inverse(N)))`cols = B`rows;

  % Subtype TCC generated (at line 139, column 33) for  x
      % expected type  Vector[(N * (inverse(N)) * B)`cols]
  simply2_mat_vect_TCC2: OBLIGATION
    FORALL (B: Matrix, (N: (invertible?) | B`rows = N`rows)):
      FORALL (x2: nat): x2 < B`cols IFF x2 < (N * (inverse(N)) * B)`cols;

  % Subtype TCC generated (at line 139, column 10) for
      % (N * (inverse(N)) * B * x)
      % expected type  Vector[B`rows]
  simply2_mat_vect_TCC3: OBLIGATION
    FORALL (B: Matrix, (N: (invertible?) | B`rows = N`rows)):
      FORALL (x2: nat): x2 < (N * (inverse(N)) * B)`rows IFF x2 < B`rows;

  % Subtype TCC generated (at line 148, column 14) for  y
      % expected type  Vector[(A + B)`cols]
  distr_mat_vect_TCC1: OBLIGATION
    FORALL (A: Matrix,
            (B: (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols))):
      FORALL (x: nat): x < A`cols IFF x < (A + B)`cols;

  % Subtype TCC generated (at line 148, column 30) for  y
      % expected type  Vector[B`cols]
  distr_mat_vect_TCC2: OBLIGATION
    FORALL (A: Matrix,
            (B: (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols))):
      FORALL (x: nat): x < A`cols IFF x < B`cols;

  % Subtype TCC generated (at line 148, column 26) for  B * y
      % expected type  Vector[A`rows]
  distr_mat_vect_TCC3: OBLIGATION
    FORALL (A: Matrix,
            (B: (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols))):
      FORALL (x: nat): x < B`rows IFF x < A`rows;

  % Subtype TCC generated (at line 148, column 18) for  A * y + B * y
      % expected type  Vector[(A + B)`rows]
  distr_mat_vect_TCC4: OBLIGATION
    FORALL (A: Matrix,
            (B: (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols))):
      FORALL (x: nat): x < A`rows IFF x < (A + B)`rows;

  % Subtype TCC generated (at line 159, column 79) for  (-B)
      % expected type  (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols)
  matrix_sum_minus_TCC1: OBLIGATION
    FORALL (A: Matrix,
            (B: (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols))):
      A`rows = (-B)`rows AND A`cols = (-B)`cols;

  % Subtype TCC generated (at line 161, column 83) for  x
      % expected type  Vector[(-A)`cols]
  matrix_prod_minus_TCC1: OBLIGATION
    FORALL (A: Matrix): FORALL (x2: nat): x2 < A`cols IFF x2 < (-A)`cols;

  % Subtype TCC generated (at line 161, column 76) for  (-A) * x
      % expected type  Vector[A`rows]
  matrix_prod_minus_TCC2: OBLIGATION
    FORALL (A: Matrix): FORALL (x2: nat): x2 < (-A)`rows IFF x2 < A`rows;

  % Subtype TCC generated (at line 170, column 9) for  ((A + B) * y)
      % expected type  Vector[A`rows]
  distr_esc_add_TCC1: OBLIGATION
    FORALL (A: Matrix,
            (B: (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols))):
      FORALL (x2: nat): x2 < (A + B)`rows IFF x2 < A`rows;

  % Subtype TCC generated (at line 173, column 19) for  y
      % expected type  Vector[(A - B)`cols]
  distr_esc_dif_TCC1: OBLIGATION
    FORALL (A: Matrix,
            (B: (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols))):
      FORALL (x2: nat): x2 < A`cols IFF x2 < (A - B)`cols;

  % Subtype TCC generated (at line 173, column 9) for  ((A - B) * y)
      % expected type  Vector[A`rows]
  distr_esc_dif_TCC2: OBLIGATION
    FORALL (A: Matrix,
            (B: (LAMBDA (N): A`rows = N`rows AND A`cols = N`cols))):
      FORALL (x2: nat): x2 < (A - B)`rows IFF x2 < A`rows;

  % Subtype TCC generated (at line 176, column 15) for  (A * (x + y))
      % expected type  Vector[A`cols]
  distr_add_esc_TCC1: OBLIGATION
    FORALL (A: (square?)): FORALL (x2: nat): x2 < A`rows IFF x2 < A`cols;

  % Subtype TCC generated (at line 185, column 11) for  (A * C)
      % expected type  {N: Matrix | B`cols = N`rows}
  conv_prod_int_TCC1: OBLIGATION
    FORALL (B: Matrix, (A: Matrix | B`cols = A`rows),
            (C: Matrix | A`cols = C`rows)):
      B`cols = (A * C)`rows;

  % Subtype TCC generated (at line 185, column 17) for  y
      % expected type  Vector[(B * (A * C))`cols]
  conv_prod_int_TCC2: OBLIGATION
    FORALL (B: Matrix, (A: Matrix | B`cols = A`rows),
            (C: Matrix | A`cols = C`rows)):
      FORALL (x2: nat): x2 < C`cols IFF x2 < (B * (A * C))`cols;

  % Subtype TCC generated (at line 185, column 7) for  ((B * (A * C)) * y)
      % expected type  Vector[B`rows]
  conv_prod_int_TCC3: OBLIGATION
    FORALL (B: Matrix, (A: Matrix | B`cols = A`rows),
            (C: Matrix | A`cols = C`rows)):
      FORALL (x2: nat): x2 < (B * (A * C))`rows IFF x2 < B`rows;

  % Subtype TCC generated (at line 185, column 36) for  x
      % expected type  Vector[transpose(B)`cols]
  conv_prod_int_TCC4: OBLIGATION
    FORALL (B: Matrix, (A: Matrix | B`cols = A`rows),
            (C: Matrix | A`cols = C`rows)):
      FORALL (x2: nat): x2 < B`rows IFF x2 < transpose(B)`cols;

  % Subtype TCC generated (at line 185, column 43) for  (C * y)
      % expected type  Vector[A`cols]
  conv_prod_int_TCC5: OBLIGATION
    FORALL (B: Matrix, (A: Matrix | B`cols = A`rows),
            (C: Matrix | A`cols = C`rows)):
      FORALL (x2: nat): x2 < C`rows IFF x2 < A`cols;

  % Subtype TCC generated (at line 185, column 40) for  (A * (C * y))
      % expected type  Vector[transpose(B)`rows]
  conv_prod_int_TCC6: OBLIGATION
    FORALL (B: Matrix, (A: Matrix | B`cols = A`rows),
            (C: Matrix | A`cols = C`rows)):
      FORALL (x2: nat): x2 < A`rows IFF x2 < transpose(B)`rows;


body:
  top: THEORY
  %------------------------------------------------------------------------
  %   Axiomatic Version of Logarithm and Exponential functions (lnexp)
  %
  %   Version 1.0    4/15/05 
  %
  %   Authors:  Ricky W. Butler              NASA Langley Research Center
  %             David Lester                 Manchester University
  %
  %------------------------------------------------------------------------------
  BEGIN
      IMPORTING ln_exp,              % Foundational definitions
                expt,                % a^x where x real and a >= 0
                hyperbolic,          % e.g. sinh cosh functions
                exp_series,          % exp as infinite series
                ln_series,           % ln  as taylor series
                exp_approx,          % exp approximation
                ln_approx,           % ln aproximation
                ln_exp_series_alt,   % alternate ln/exp series formulation
                ln_exp_ineq          % inequalities involving ln/exp

  END top


body:
  ln_exp: THEORY
  %------------------------------------------------------------------------
  %   Definition of Logarithm and Exponential functions
  %
  %   Author:  Ricky W. Butler              NASA Langley Research Center
  %------------------------------------------------------------------------
  BEGIN

     x,y,a: VAR real
     i: VAR integer
     px,py,p1,p2: VAR posreal


  %   IMPORTING analysis@integral, 
  %             analysis@fundamental_theorem, 
  %             analysis@chain_rule, 
  %             analysis@derivatives_more

      IMPORTING reals@real_fun_ops, reals@real_fun_preds

  %   one_over_t_cont: LEMMA continuous((LAMBDA (t: posreal): 1 / t))

  %   ln_prep: LEMMA FORALL (x: posreal):
  %         Integrable?[posreal](1, x, (LAMBDA (t: posreal): 1 / t));


     ln(x: posreal): real % = Integral(1,x, (LAMBDA (t: posreal): 1/t))

  %   ln_derivable   : LEMMA derivable(ln) AND
  %                       deriv(ln) = (LAMBDA (t: posreal): 1/t)

  %   ln_continuous  : LEMMA continuous(ln)
   
     ln_1           : AXIOM ln(1) = 0

     ln_mult        : AXIOM ln(px*py) = ln(px) + ln(py)
     ln_div         : LEMMA ln(px/py) = ln(px) - ln(py)
     ln_expt        : LEMMA ln(px^i)  = i*ln(px) 

     ln_strict_increasing: AXIOM strict_increasing?(ln)
    
     ln_increasing  : LEMMA increasing?(ln)

     ln_image_all   : AXIOM EXISTS (px: posreal): ln(px) = y

     ln_bij         : LEMMA bijective?[posreal, real](ln)

     large_ln       : LEMMA (FORALL a: EXISTS px: a < ln(px))

     ln_eq_0        : LEMMA ln(px) = 0 IMPLIES px = 1

     ln_ge_0        : LEMMA px >= 1 IMPLIES ln(px) >= 0

     ln_gt_0        : LEMMA px > 1 IMPLIES ln(px) > 0

     exp(x): { py | x = ln(py)}

     e: posreal = exp(1)

     exp_def        : LEMMA exp = inverse(ln)

     exp_bij        : LEMMA bijective?[real,posreal](exp)

     ln_exp         : LEMMA ln(exp(x)) = x

     exp_ln         : LEMMA exp(ln(py)) = py

     ln_e           : LEMMA ln(e) = 1

     ln_2_bnds      : AXIOM 1/2 <= ln(2) AND ln(2) <= 1

     exp_int        : LEMMA exp(i) = e^i

     exp_sum        : LEMMA exp(x+y) = exp(x)*exp(y) 

     exp_diff       : LEMMA exp(x-y) = exp(x)/exp(y) 

     exp_scal       : LEMMA exp(i*x) = exp(x)^i

     exp_0          : LEMMA exp(0) = 1

     exp_1          : LEMMA exp(1) = e

     exp_neg        : LEMMA exp(-x) = 1/exp(x)

     expt_alt_def   : LEMMA x > 0 IMPLIES x^i = exp(i*ln(x))

     exp_strict_increasing : LEMMA strict_increasing?(exp)

     exp_increasing : LEMMA increasing?(exp)

  %   exp_continuous : LEMMA continuous(exp)

  %   IMPORTING analysis@derivative_inverse

  %   exp_deriv      : LEMMA derivable(exp) AND deriv(exp) = exp

     e_bnds         : LEMMA 2 <= e AND e <= 4

     large_exp      : LEMMA (FORALL a: EXISTS x: a < exp(x))

     small_exp      : LEMMA (FORALL px: EXISTS x: exp(x) < px)

     AUTO_REWRITE+ exp_0
     AUTO_REWRITE+ exp_1
     AUTO_REWRITE+ ln_1
     AUTO_REWRITE+ ln_e

  END ln_exp

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

  % Subtype TCC generated (at line 38, column 32) for  i
      % expected type  {i: int | px /= 0 OR i >= 0}
  ln_expt_TCC1: OBLIGATION
    FORALL (i: integer, px: posreal): px /= 0 OR i >= 0;

  % Existence TCC generated (at line 56, column 3) for
      % exp(x): {py | x = ln(py)}
  exp_TCC1: OBLIGATION EXISTS (x1: [x: real -> {py | x = ln(py)}]): TRUE;

  % Subtype TCC generated (at line 72, column 37) for  i
      % expected type  {i: int | e /= 0 OR i >= 0}
  exp_int_TCC1: OBLIGATION FORALL (i: integer): e /= 0 OR i >= 0;

  % Subtype TCC generated (at line 78, column 44) for  i
      % expected type  {i: int | exp(x) /= 0 OR i >= 0}
  exp_scal_TCC1: OBLIGATION
    FORALL (i: integer, x: real): exp(x) /= 0 OR i >= 0;

  % Subtype TCC generated (at line 86, column 42) for  i
      % expected type  {i: int | x /= 0 OR i >= 0}
  expt_alt_def_TCC1: OBLIGATION
    FORALL (i: integer, x: real): x > 0 IMPLIES x /= 0 OR i >= 0;

  % Subtype TCC generated (at line 86, column 55) for  x
      % expected type  posreal
  expt_alt_def_TCC2: OBLIGATION FORALL (x: real): x > 0 IMPLIES x >= 0;


body:
  ln_exp_series_alt: THEORY
  %------------------------------------------------------------------------------
  %
  % Alternate means of establishing infinite series for ln and exp
  %
  % Author: David Lester
  %
  % 
  %------------------------------------------------------------------------------
  BEGIN

     real_gtm1_le1: NONEMPTY_TYPE = {x:real | -1 < x AND x <= 1} CONTAINING 0

     x:    VAR real
     px:   VAR posreal
     xgm1: VAR {x:real | x > -1}
     nzx:  VAR nzreal
     z:    VAR real_gtm1_le1
     n:    VAR nat

     IMPORTING ln_exp, 
  %             analysis@derivative_inverse,
  %             series@nth_derivatives, series@taylors, series@series,
  %             analysis@integral, 
               reals@sqrt, reals@sigma_nat, reals@factorial, taylor_help

  %    nderiv_ln: LEMMA derivable_n_times[posreal](ln,n)

  %    ln_nderiv      : LEMMA nderiv[posreal](n,ln) = IF n = 0 THEN ln ELSE 
  %                         (LAMBDA (x:posreal): -factorial(n-1)/(-x)^n) ENDIF

     ln_estimate(x:real,n:nat):real
           = sigma(0,n,(LAMBDA (nn:nat): IF nn=0 THEN 0 ELSE -(-x)^nn/nn ENDIF))

  %    ln_estimate_scaf1: LEMMA continuous((LAMBDA (t: posreal): (1-t)^n/t))

  %    ln_estimate_scaf2: LEMMA FORALL (x:posreal):
  %                      Integrable?[posreal](1,x,(LAMBDA (t: posreal): (1-t)^n/t))

  %    ln_estimate_scaf3: LEMMA FORALL (x:posreal):
  %                             ln(x) = Integral(1,x,LAMBDA (t:posreal): (1-t)^0/t)

     ln_estimate_scaf4: LEMMA x /= 1 IMPLIES
             1/(1-x) = sigma(0,n,(LAMBDA (i:nat): x^i)) + x^(n+1)/(1-x)

     ln_estimate_scaf5: LEMMA
             1/nzx = sigma(0,n,(LAMBDA (i:nat): (1-nzx)^i)) + (1-nzx)^(n+1)/nzx

  %    ln_estimate_scaf6: LEMMA derivable[posreal](LAMBDA px: ln_estimate(px-1, n))

  %    ln_estimate_scaf7: LEMMA deriv[posreal](LAMBDA px: ln_estimate(px-1, n+1))
  %                 = (LAMBDA px: sigma(0,n,(LAMBDA (i:nat): (1-px)^i)))

  %    ln_estimate_scaf8: LEMMA
  %          ln(px) = ln_estimate(px-1,n+1) +
  %                       Integral(1,px,LAMBDA (t:posreal): (1-t)^(n+1)/t)

  %    ln_estimate_scaf9: LEMMA
  %          ln(px) = ln_estimate(px-1,n) +
  %                       Integral(1,px,LAMBDA (t:posreal): (1-t)^n/t)

  %    ln_estimate_scaf10: LEMMA 1 <= px AND px <= 2 IMPLIES
  %            abs(Integral(1,px,LAMBDA (t:posreal): (1-t)^n/t))
  %                                         <= (px-1)^(n+1)/(n+1)

  %    ln_estimate_scaf11: LEMMA px < 1 IMPLIES
  %            abs(Integral(1,px,LAMBDA (t:posreal): (1-t)^n/t))
  %                                         <= (1-px)^(n+1)/((n+1)*px)

     ln_estimate_bnd: AXIOM abs(ln(1+z) - ln_estimate(z,n)) <=
                        abs(z)^(n+1)/(IF z < 0 THEN 1+z ELSE 1 ENDIF*(n+1))

     lnT(x:real_gtm1_le1)(n:nat):real_gtm1_le1 = -(-x)^(n+1)/(n+1)

  %    lnT_convergence: LEMMA convergence(series(lnT(z)),ln(1+z))

  %    lnT_convergent: LEMMA convergent(series(lnT(z)))

  %    ln_series_def: LEMMA ln(1+z) = inf_sum(lnT(z))

     ln_taylors:     AXIOM EXISTS (c: between[{x:real | x > -1}](1,1+xgm1)):
                       ln(xgm1+1) = ln_estimate(xgm1,n) -(xgm1/-c)^(n+1)/(n+1)

  %  Properties of exp

  %    nderiv_exp: LEMMA derivable_n_times(exp, n)
  %                      AND nderiv(n, exp) = exp

     expT(x)(n):real = IF n = 0 THEN 1 ELSE x^n / factorial(n) ENDIF

     exp_estimate(x,n):real = sigma(0,n,expT(x))

     exp_taylors:     AXIOM EXISTS (c:between[real](0,x)):
                       exp(x) = exp_estimate(x,n) + exp(c)*x^(n+1)/factorial(n+1)

     exp_estimate_bnd:  LEMMA abs(exp(x)-exp_estimate(x,n)) 
                                  <= max(exp(x),1)*abs(x)^(n+1)/factorial(n+1)

  %    exp_series_scaf2: LEMMA sqrt(n)^(2*n) <= factorial(2*n)

  %    exp_series_scaf3: LEMMA sqrt(n)^(2*n+1) <= factorial(2*n+1)

  %    expT_convergence: LEMMA convergence(series(expT(x)),exp(x))

  %    expT_convergent: LEMMA convergent(series(expT(x)))

  %    exp_series: LEMMA exp(x) = inf_sum(expT(x))

  END ln_exp_series_alt

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

  % Subtype TCC generated (at line 33, column 19) for  n
      % expected type  T_high[nat]
  ln_estimate_TCC1: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 33, column 65) for  nn
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  ln_estimate_TCC2: OBLIGATION
    FORALL (x: real, nn: nat): NOT nn = 0 IMPLIES (-x) /= 0 OR nn >= 0;

  % Subtype TCC generated (at line 33, column 68) for  nn
      % expected type  nznum
  ln_estimate_TCC3: OBLIGATION FORALL (nn: nat): NOT nn = 0 IMPLIES nn /= 0;

  % Subtype TCC generated (at line 44, column 14) for  (1 - x)
      % expected type  nznum
  ln_estimate_scaf4_TCC1: OBLIGATION
    FORALL (x: real): x /= 1 IMPLIES (1 - x) /= 0;

  % Subtype TCC generated (at line 44, column 50) for  i
      % expected type  {i: int | x /= 0 OR i >= 0}
  ln_estimate_scaf4_TCC2: OBLIGATION
    FORALL (x: real): x /= 1 IMPLIES (FORALL (i: nat): x /= 0 OR i >= 0);

  % Subtype TCC generated (at line 44, column 59) for  (n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  ln_estimate_scaf4_TCC3: OBLIGATION
    FORALL (n: nat, x: real): x /= 1 IMPLIES x /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 47, column 54) for  i
      % expected type  {i: int | (1 - nzx) /= 0 OR i >= 0}
  ln_estimate_scaf5_TCC1: OBLIGATION
    FORALL (nzx: nzreal, i: nat): (1 - nzx) /= 0 OR i >= 0;

  % Subtype TCC generated (at line 47, column 69) for  (n + 1)
      % expected type  {i: int | (1 - nzx) /= 0 OR i >= 0}
  ln_estimate_scaf5_TCC2: OBLIGATION
    FORALL (n: nat, nzx: nzreal): (1 - nzx) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 70, column 33) for  1 + z
      % expected type  posreal
  ln_estimate_bnd_TCC1: OBLIGATION
    FORALL (z: real_gtm1_le1): 1 + z >= 0 AND 1 + z > 0;

  % Subtype TCC generated (at line 71, column 30) for  (n + 1)
      % expected type  {i: int | abs(z) /= 0 OR i >= 0}
  ln_estimate_bnd_TCC2: OBLIGATION
    FORALL (n: nat, z: real_gtm1_le1): abs(z) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 71, column 36) for
      % (IF z < 0 THEN 1 + z ELSE 1 ENDIF * (n + 1))
      % expected type  nznum
  ln_estimate_bnd_TCC3: OBLIGATION
    FORALL (n: nat, z: real_gtm1_le1):
      (IF z < 0 THEN 1 + z ELSE 1 ENDIF * (n + 1)) /= 0;

  % Subtype TCC generated (at line 73, column 54) for  (n + 1)
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  lnT_TCC1: OBLIGATION
    FORALL (x: real_gtm1_le1, n: nat): (-x) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 73, column 47) for
      % -(-x) ^ (n + 1) / (n + 1)
      % expected type  real_gtm1_le1
  lnT_TCC2: OBLIGATION
    FORALL (x: real_gtm1_le1, n: nat):
      -1 < -(-x) ^ (n + 1) / (n + 1) AND -(-x) ^ (n + 1) / (n + 1) <= 1;

  % Subtype TCC generated (at line 82, column 24) for  xgm1 + 1
      % expected type  posreal
  ln_taylors_TCC1: OBLIGATION
    FORALL (xgm1: {x: real | x > -1},
            c: between[{x: real | x > -1}](1, 1 + xgm1)):
      xgm1 + 1 >= 0 AND xgm1 + 1 > 0;

  % Subtype TCC generated (at line 82, column 61) for  -c
      % expected type  nznum
  ln_taylors_TCC2: OBLIGATION
    FORALL (xgm1: {x: real | x > -1},
            c: between[{x: real | x > -1}](1, 1 + xgm1)):
      -c /= 0;

  % Subtype TCC generated (at line 82, column 66) for  (n + 1)
      % expected type  {i: int | (xgm1 / -c) /= 0 OR i >= 0}
  ln_taylors_TCC3: OBLIGATION
    FORALL (n: nat, xgm1: {x: real | x > -1},
            c: between[{x: real | x > -1}](1, 1 + xgm1)):
      (xgm1 / -c) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 89, column 44) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  expT_TCC1: OBLIGATION
    FORALL (x: real, n: nat): NOT n = 0 IMPLIES x /= 0 OR n >= 0;

  % Subtype TCC generated (at line 94, column 60) for  (n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  exp_taylors_TCC1: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)): x /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 97, column 57) for  (n + 1)
      % expected type  {i: int | abs(x) /= 0 OR i >= 0}
  exp_estimate_bnd_TCC1: OBLIGATION
    FORALL (n: nat, x: real): abs(x) /= 0 OR (n + 1) >= 0;


body:
  ln_exp_ineq: THEORY
  %------------------------------------------------------------------------------

  % Inequalities involving ln and exp
  %
  % Author: David Lester
  %
  % 
  %------------------------------------------------------------------------------

    BEGIN

    IMPORTING ln_exp, 
  %            analysis@derivative_props, analysis@chain_rule,
              ln_exp_series_alt

    nzreal_gt_m1: NONEMPTY_TYPE = {x:nzreal | x > -1}          CONTAINING  1
    nzreal_lt1:   NONEMPTY_TYPE = {x:nzreal | x < 1 }          CONTAINING -1
    real_abs_lt1: NONEMPTY_TYPE = {x:real   | -1 < x & x < 1 } CONTAINING  0

    xgtm1: VAR nzreal_gt_m1
    xlt1:  VAR nzreal_lt1
    px:    VAR posreal
    nzx:   VAR nzreal
    pn:    VAR posnat
    xalt1: VAR real_abs_lt1

    ln_ineq1:  AXIOM xgtm1/(1+xgtm1) < ln(1+xgtm1) AND
                     ln(1+xgtm1) < xgtm1                                 % 4.1.33

    ln_ineq2:  LEMMA xlt1 < -ln(1-xlt1) AND -ln(1-xlt1) < xlt1/(1-xlt1)  % 4.1.34

    ln_ineq3:  AXIOM px <= 5828/10000 IMPLIES abs(ln(1-px)) < 3*px/2     % 4.1.35

    ln_ineq4:  LEMMA ln(px) <= px-1                                      % 4.1.36

    ln_ineq5:  LEMMA ln(px) <= pn*(exp(ln(px)/pn)-1)                     % 4.1.37

    ln_ineq6:  LEMMA abs(ln(1+xalt1)) <= -ln(1-abs(xalt1))               % 4.1.38

    exp_ineq1: LEMMA exp(-xlt1/(1-xlt1)) < 1-xlt1 AND
                     1-xlt1 < exp(-xlt1)                                 % 4.2.29

    exp_ineq2: LEMMA nzx+1 < exp(nzx)                                    % 4.2.30

    exp_ineq3: LEMMA exp(xlt1) < 1/(1-xlt1)                              % 4.2.31

    END ln_exp_ineq

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

  % Subtype TCC generated (at line 28, column 26) for  (1 + xgtm1)
      % expected type  nznum
  ln_ineq1_TCC1: OBLIGATION FORALL (xgtm1: nzreal_gt_m1): (1 + xgtm1) /= 0;

  % Subtype TCC generated (at line 28, column 40) for  1 + xgtm1
      % expected type  posreal
  ln_ineq1_TCC2: OBLIGATION
    FORALL (xgtm1: nzreal_gt_m1): 1 + xgtm1 >= 0 AND 1 + xgtm1 > 0;

  % Subtype TCC generated (at line 31, column 30) for  1 - xlt1
      % expected type  posreal
  ln_ineq2_TCC1: OBLIGATION
    FORALL (xlt1: nzreal_lt1): 1 - xlt1 >= 0 AND 1 - xlt1 > 0;

  % Subtype TCC generated (at line 31, column 62) for  (1 - xlt1)
      % expected type  nznum
  ln_ineq2_TCC2: OBLIGATION
    FORALL (xlt1: nzreal_lt1): xlt1 < -ln(1 - xlt1) IMPLIES (1 - xlt1) /= 0;

  % Subtype TCC generated (at line 33, column 51) for  1 - px
      % expected type  posreal
  ln_ineq3_TCC1: OBLIGATION
    FORALL (px: posreal):
      px <= 5828 / 10000 IMPLIES 1 - px >= 0 AND 1 - px > 0;

  % Subtype TCC generated (at line 39, column 26) for  1 + xalt1
      % expected type  posreal
  ln_ineq6_TCC1: OBLIGATION
    FORALL (xalt1: real_abs_lt1): 1 + xalt1 >= 0 AND 1 + xalt1 > 0;

  % Subtype TCC generated (at line 39, column 43) for  1 - abs(xalt1)
      % expected type  posreal
  ln_ineq6_TCC2: OBLIGATION
    FORALL (xalt1: real_abs_lt1): 1 - abs(xalt1) >= 0 AND 1 - abs(xalt1) > 0;

  % Subtype TCC generated (at line 41, column 30) for  (1 - xlt1)
      % expected type  nznum
  exp_ineq1_TCC1: OBLIGATION FORALL (xlt1: nzreal_lt1): (1 - xlt1) /= 0;


body:
  ln_series: THEORY
  %----------------------------------------------------------------------------
  %
  %  Series Expansion for Natural Logarithm Function
  %
  %  Author: Ricky W. Butler              NASA Langley Research Center
  %
  %  Note.  See ln_exp_series_alt for an alternate formulation
  %----------------------------------------------------------------------------
  BEGIN
     IMPORTING  ln_exp
  %              series@taylor_series, 
  %              convergence_special

     IMPORTING reals@sigma_nat

     x: VAR real
     px: VAR posreal
     n,m: VAR nat
     a: VAR sequence[real]
     l,t: VAR real


  %    nderiv_ln  : LEMMA derivable_n_times[posreal](ln, n)

  %    ln_nderiv  : LEMMA nderiv[posreal](n,ln) = IF n = 0 THEN ln ELSE 
  %                         (LAMBDA (x:posreal): -factorial(n-1)/(-x)^n) ENDIF


     abslt1: TYPE = {x: real | abs(x) < 1}


  %   IMPORTING series@taylor_series[abslt1] 

     IMPORTING taylor_help

     Gt_m1: TYPE = {x:real | x > -1}
     xgm1:  VAR Gt_m1

     ln_estimate(x:real,n:nat):real = 
           sigma(0,n,(LAMBDA (nn:nat): IF nn=0 THEN 0 ELSE -(-x)^nn/nn ENDIF))

     ln_taylors:  AXIOM EXISTS (c: between[{x:real | x > -1}](1,1+xgm1)):
                       ln(xgm1+1) = ln_estimate(xgm1,n) -(xgm1/-c)^(n+1)/(n+1)

  %   --- Series for log(1+x) follows from term-by-term integration
  %   --- of 1/(1+x) = 1 - x + x^2 - x^3.  Using term-by-term
  %   --- in power_series_integ, we can use proof in Rosenlicht
  %   --- page 155 or Salas-Hille pg 466 to get log(1+x) series for abs(x) < 1
  %   --- Also use corollary 3 on pg 128 of Rosenlicht to establish that
  %   --- ln(1+x) = integral(1,1+x,1/t) = integral(0,x,1/(1+t))
  %

  %   IMPORTING analysis@integral_chg_var,
  %             analysis@abs_props,
  %             analysis@integral_diff_doms


     x1: VAR abslt1

  %    lnp1: LEMMA ln(1+x1) = Integral(1,1+x1,(LAMBDA (t: posreal): 1/t)) 


  %    lnp1_prep: LEMMA  Integrable?(0,x1,(LAMBDA (u: Gt_m1): 1/(u+1))) AND
  %                        Integral(1,1+x1,(LAMBDA (t: posreal): 1/t)) = 
  %                        Integral(0,x1,(LAMBDA (u: Gt_m1): 1/(u+1)))


  %     geom_neg: LEMMA abs(x) < 1 IMPLIES 
  %                                convergent(series(LAMBDA n: (-x) ^ n))  AND
  %                                1/(1+x) = inf_sum((LAMBDA n: (-x)^n))

      lnp1(x: abslt1): real = ln(1+x)

      lnp1_seq(n): real = IF n = 0 THEN 0 ELSE (-1)^(n+1)/n ENDIF


  %    IMPORTING series@power_series_integ

  %    lnp1_conv: LEMMA conv_powerseries?[abslt1](lnp1_seq)

  %    int_geo_prep: LEMMA Integrable?(0,x1,(LAMBDA (u: abslt1): 1 / (1 + u)))

  %   ----- ln(1 + x) = x - x^2/2 + x^3/3 - x^4/4 + .... if |x| < 1 -----

  %   int_geo_neg: LEMMA conv_powerseries?[abslt1](lnp1_seq) AND
  %                      Integral(0,x1,(LAMBDA (u: {x:real | x > -1}): 1/(u+1))) 
  %                          = Inf_sum(lnp1_seq)(x1)  % inf Sum - (-1)^n/n x^n


  END ln_series

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

  % Subtype TCC generated (at line 41, column 17) for  n
      % expected type  T_high[nat]
  ln_estimate_TCC1: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 41, column 63) for  nn
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  ln_estimate_TCC2: OBLIGATION
    FORALL (x: real, nn: nat): NOT nn = 0 IMPLIES (-x) /= 0 OR nn >= 0;

  % Subtype TCC generated (at line 41, column 66) for  nn
      % expected type  nznum
  ln_estimate_TCC3: OBLIGATION FORALL (nn: nat): NOT nn = 0 IMPLIES nn /= 0;

  % Subtype TCC generated (at line 44, column 24) for  xgm1 + 1
      % expected type  posreal
  ln_taylors_TCC1: OBLIGATION
    FORALL (xgm1: Gt_m1, c: between[{x: real | x > -1}](1, 1 + xgm1)):
      xgm1 + 1 >= 0 AND xgm1 + 1 > 0;

  % Subtype TCC generated (at line 44, column 61) for  -c
      % expected type  nznum
  ln_taylors_TCC2: OBLIGATION
    FORALL (xgm1: Gt_m1, c: between[{x: real | x > -1}](1, 1 + xgm1)):
      -c /= 0;

  % Subtype TCC generated (at line 44, column 66) for  (n + 1)
      % expected type  {i: int | (xgm1 / -c) /= 0 OR i >= 0}
  ln_taylors_TCC3: OBLIGATION
    FORALL (n: nat, xgm1: Gt_m1,
            c: between[{x: real | x > -1}](1, 1 + xgm1)):
      (xgm1 / -c) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 73, column 31) for  1 + x
      % expected type  posreal
  lnp1_TCC1: OBLIGATION FORALL (x: abslt1): 1 + x >= 0 AND 1 + x > 0;


body:
  ln_approx: THEORY
  %-----------------------------------------------------------------------------
  %      ln_approx by David Lester  Manchester Univ
  %                   Cesar Munoz   NIA
  %      ---------
  %      Defines upper and lower bounds on ln:
  %           - ln_lb(a,n) <= ln(a) <= ln_ub(a,n)
  %-----------------------------------------------------------------------------

  BEGIN

    IMPORTING ln_series,reals@log_nat

    n:    VAR nat
    x:    VAR real
    px:   VAR posreal
    pn:   VAR posnat
    xgt1: VAR {x:posreal | x > 1}

    ln_le2_lb(n,x): real = if x = 0 then 0 else ln_estimate(x,2*n)   endif
    ln_le2_ub(n,x): real = if x = 0 then 0 else ln_estimate(x,2*n+1) endif

    ln_le2_bounds: LEMMA 0 < x AND x <= 1 IMPLIES
         (ln_le2_lb(n,x) < ln(x+1) AND ln(x+1) < ln_le2_ub(n,x))

    ln2_lb(n): MACRO real = ln_le2_lb(n,1)
    ln2_ub(n): MACRO real = ln_le2_ub(n,1)

    ln_gt1_lb(n,xgt1): real = 
      let (m,y) = log_nat(xgt1,2) in
        m*ln2_lb(n)+ln_le2_lb(n,y-1) 

    ln_gt1_ub(n,xgt1): real = 
      let (m,y) = log_nat(xgt1,2) in
         m*ln2_ub(n)+ln_le2_ub(n,y-1) 

    ln_gt1_bounds: LEMMA 1 < x IMPLIES
         (ln_gt1_lb(n,x) < ln(x) AND ln(x) < ln_gt1_ub(n,x))

    ln_lb(px,n): real = IF    px < 1 THEN -ln_gt1_ub(n,1/px)
                        ELSIF px = 1 THEN 0
                                     ELSE ln_gt1_lb(n,px)    ENDIF

    ln_ub(px,n): real = IF    px < 1 THEN -ln_gt1_lb(n,1/px)
                        ELSIF px = 1 THEN 0
                                     ELSE ln_gt1_ub(n,px)    ENDIF

    ln_bounds: LEMMA ln_lb(px,n) <= ln(px) AND ln(px) <= ln_ub(px,n)

  END ln_approx

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

  % Subtype TCC generated (at line 24, column 28) for  x + 1
      % expected type  posreal
  ln_le2_bounds_TCC1: OBLIGATION
    FORALL (x: real): x <= 1 AND 0 < x IMPLIES x + 1 >= 0 AND x + 1 > 0;

  % Subtype TCC generated (at line 30, column 24) for  xgt1
      % expected type  {x: real | x >= 1}
  ln_gt1_lb_TCC1: OBLIGATION FORALL (xgt1: {x: posreal | x > 1}): xgt1 >= 1;

  % Subtype TCC generated (at line 38, column 20) for  x
      % expected type  {x: posreal | x > 1}
  ln_gt1_bounds_TCC1: OBLIGATION
    FORALL (x: real): 1 < x IMPLIES x >= 0 AND x > 0 AND x > 1;

  % Subtype TCC generated (at line 38, column 28) for  x
      % expected type  posreal
  ln_gt1_bounds_TCC2: OBLIGATION
    FORALL (x: real): 1 < x IMPLIES x >= 0 AND x > 0;

  % Subtype TCC generated (at line 40, column 53) for  1 / px
      % expected type  {x: posreal | x > 1}
  ln_lb_TCC1: OBLIGATION FORALL (px: posreal): px < 1 IMPLIES 1 / px > 1;

  % Subtype TCC generated (at line 42, column 52) for  px
      % expected type  {x: posreal | x > 1}
  ln_lb_TCC2: OBLIGATION
    FORALL (px: posreal): NOT px = 1 AND NOT px < 1 IMPLIES px > 1;


body:
  exp_series: THEORY
  %----------------------------------------------------------------------------
  %
  %  Series expansion for Exponential Function
  %
  %  Author: Ricky W. Butler              NASA Langley Research Center
  %
  %  Note.  See ln_exp_series_alt for an alternate formulation
  %----------------------------------------------------------------------------
  BEGIN
     IMPORTING  ln_exp
  %              series@taylor_series[real], 
  %              convergence_special

     IMPORTING reals@sigma_nat, reals@factorial, taylor_help

     x: VAR real
     n,m: VAR nat
     a: VAR sequence[real]
     l,t: VAR real


     exp_seq(n): real = 1/factorial(n)

  %   nderiv_exp: LEMMA derivable_n_times(exp, n)
  %                     AND nderiv(n, exp) = exp

  %   exp_inf_deriv: LEMMA inf_deriv_fun?[real](exp)

  %   exp_series_prep: LEMMA 
  %                     convergence(LAMBDA n: Taylor_rem(n,exp,0,x,
  %                                           GET_C(exp,x,n)),0)

  %   conv_exp: LEMMA conv_powerseries?[real](exp_seq)

  %   exp_series: THEOREM exp = Inf_sum(exp_seq)  % lim n->inf  Sum  x^n/n!


     exp_estimate(x:real,n:nat):real = 
                  1 + sigma(1,n,(LAMBDA (nn:nat): x^nn/factorial(nn)))


     exp_taylors: AXIOM EXISTS (c: between[real](0,x)):
                             exp(x) = exp_estimate(x,n)
                                          + exp(c)*x^(n+1)/factorial(n+1)

     exp_taylors_err: LEMMA abs(exp(x)-exp_estimate(x,n)) 
                                  <= max(exp(x),1)*abs(x)^(n+1)/factorial(n+1)


  END exp_series

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

  % Subtype TCC generated (at line 40, column 28) for  n
      % expected type  T_high[nat]
  exp_estimate_TCC1: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 40, column 50) for  nn
      % expected type  {i: int | x /= 0 OR i >= 0}
  exp_estimate_TCC2: OBLIGATION FORALL (x: real, nn: nat): x /= 0 OR nn >= 0;

  % Subtype TCC generated (at line 45, column 52) for  (n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  exp_taylors_TCC1: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)): x /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 48, column 57) for  (n + 1)
      % expected type  {i: int | abs(x) /= 0 OR i >= 0}
  exp_taylors_err_TCC1: OBLIGATION
    FORALL (n: nat, x: real): abs(x) /= 0 OR (n + 1) >= 0;


body:
  exp_approx: THEORY
  %-----------------------------------------------------------------------------
  %   Approximation of Exponential Function
  %   -------------------------------------
  %
  %      Defines upper and lower bounds on exp:
  %           - exp_lb(a,n) <= exp(a) <= exp_ub(a,n)
  %           - e_lb(n)     <= e      <= e_ub(n)
  %
  %  Author: David Lester             Manchester University
  %-----------------------------------------------------------------------------

    BEGIN

    IMPORTING exp_series
    IMPORTING reals@quad_minmax % For proof only

    n:  VAR nat
    pn: VAR posnat
    x:  VAR real
    nx: VAR negreal

    exp_neg_le1_ub(n,x): real = exp_estimate(x,2*n)

    exp_neg_le1_lb(n,x): real = exp_estimate(x,2*n+1)

    exp_neg_le1_bounds: LEMMA -1 <= x AND x < 0 IMPLIES
      (exp_neg_le1_lb(n,x) < exp(x) AND exp(x) < exp_neg_le1_ub(n,x))

    exp_neg_le1_ub_strict_decreasing_n: LEMMA -1 <= x AND x < 0 IMPLIES
        strict_decreasing?(LAMBDA (n:nat): exp_neg_le1_ub(n,x))

    exp_neg_le1_lb_strict_increasing_n: LEMMA -1 <= x AND x < 0 IMPLIES
        strict_increasing?(LAMBDA (n:nat): exp_neg_le1_lb(n,x))

    exp_neg_le1_lb_pos: LEMMA -1 <= x AND x < 0 IMPLIES exp_neg_le1_lb(pn,x) > 0

    exp_neg_ub(n,nx):posreal = LET pn= -floor(nx) IN exp_neg_le1_ub(n+1,nx/pn)^pn

    exp_neg_lb(n,nx):posreal = LET pn= -floor(nx) IN exp_neg_le1_lb(n+1,nx/pn)^pn

    exp_neg_bounds: LEMMA exp_neg_lb(n,nx) < exp(nx) & exp(nx) < exp_neg_ub(n,nx)

    exp_ub(x,n): posreal = IF    x < 0 THEN exp_neg_ub(n,x)
                           ELSIF x = 0 THEN 1
                                       ELSE 1/exp_neg_lb(n,-x) ENDIF

    exp_lb(x,n): posreal = IF    x < 0 THEN exp_neg_lb(n,x)
                           ELSIF x = 0 THEN 1
                                       ELSE 1/exp_neg_ub(n,-x) ENDIF

    exp_bounds: LEMMA exp_lb(x,n) <= exp(x) AND exp(x) <= exp_ub(x,n)

    e_lb(n) : posreal = exp_lb(1,n)

    e_ub(n) : posreal = exp_ub(1,n)

    e_bounds: LEMMA e_lb(n) <= e & e <= e_ub(n)

    e_LB : MACRO posreal = 2718281828/1000000000

    e_UB : MACRO posreal = 2718281829/1000000000

    e_bounds2: LEMMA e_LB < e & e < e_UB

    e_lb    : posreal = 271/100

    e_ub    : posreal = 272/100

    e_bound : JUDGEMENT e HAS_TYPE {x:posreal| e_lb < e AND e < e_ub}

    END exp_approx

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

  % Subtype TCC generated (at line 38, column 73) for  pn
      % expected type  nznum
  exp_neg_ub_TCC1: OBLIGATION
    FORALL (nx: negreal, pn: int): pn = -floor(nx) IMPLIES pn /= 0;

  % Subtype TCC generated (at line 38, column 77) for  pn
      % expected type  {i: int |
                     %          NOT exp_neg_le1_ub(1 + n, nx / pn) = 0 OR
                     %           i >= 0}
  exp_neg_ub_TCC2: OBLIGATION
    FORALL (n: nat, nx: negreal, pn: int):
      pn = -floor(nx) IMPLIES
       NOT exp_neg_le1_ub(1 + n, nx / pn) = 0 OR pn >= 0;

  % Subtype TCC generated (at line 38, column 51) for
      % exp_neg_le1_ub(n + 1, nx / pn) ^ pn
      % expected type  posreal
  exp_neg_ub_TCC3: OBLIGATION
    FORALL (n: nat, nx: negreal, pn: int):
      pn = -floor(nx) IMPLIES
       exp_neg_le1_ub(n + 1, nx / pn) ^ pn >= 0 AND
        exp_neg_le1_ub(n + 1, nx / pn) ^ pn > 0;

  % Subtype TCC generated (at line 40, column 77) for  pn
      % expected type  {i: int |
                     %          NOT exp_neg_le1_lb(1 + n, nx / pn) = 0 OR
                     %           i >= 0}
  exp_neg_lb_TCC1: OBLIGATION
    FORALL (n: nat, nx: negreal, pn: int):
      pn = -floor(nx) IMPLIES
       NOT exp_neg_le1_lb(1 + n, nx / pn) = 0 OR pn >= 0;

  % Subtype TCC generated (at line 40, column 51) for
      % exp_neg_le1_lb(n + 1, nx / pn) ^ pn
      % expected type  posreal
  exp_neg_lb_TCC2: OBLIGATION
    FORALL (n: nat, nx: negreal, pn: int):
      pn = -floor(nx) IMPLIES
       exp_neg_le1_lb(n + 1, nx / pn) ^ pn >= 0 AND
        exp_neg_le1_lb(n + 1, nx / pn) ^ pn > 0;

  % Subtype TCC generated (at line 44, column 55) for  x
      % expected type  negreal
  exp_ub_TCC1: OBLIGATION FORALL (x: real): x < 0 IMPLIES x <= 0;

  % Subtype TCC generated (at line 46, column 57) for  -x
      % expected type  negreal
  exp_ub_TCC2: OBLIGATION
    FORALL (x: real): NOT x = 0 AND NOT x < 0 IMPLIES -x <= 0 AND -x < 0;

  % Judgement subtype TCC generated (at line 70, column 22) for  e
      % expected type  {x: posreal | e_lb < e AND e < e_ub}
  e_bound: OBLIGATION e_lb < e AND e < e_ub;


body:
  hyperbolic: THEORY
  %------------------------------------------------------------------------
  %   Definition of Hyperbolic Trig Functions
  %
  %   Version 1.0    12/3/03 
  %   Version 1.1    8/25/04  
  %   Version 1.2    10/27/04        added exp_approx, ln_approx
  %
  %   Author:  David Lester
  %
  %   Formula labels are from Handbook of Mathematical Functions
  %                           by Abramowitz and Stegun
  %------------------------------------------------------------------------
  BEGIN

    IMPORTING reals@sq, reals@sqrt,
              ln_exp,  %% RWB
              reals@binomial

    IMPORTING taylor_help, reals@polynomials

    posreal_ge1:  NONEMPTY_TYPE = {x:real    | x >= 1         } CONTAINING 1
    posreal_gt1:  NONEMPTY_TYPE = {x:real    | x >  1         } CONTAINING 2
    posreal_le1:  NONEMPTY_TYPE = {x:posreal | x <= 1         } CONTAINING 1/2
    real_abs_lt1: NONEMPTY_TYPE = {x:real    | -1 < x &  x < 1} CONTAINING 0
    real_abs_gt1: NONEMPTY_TYPE = {x:real    | x < -1 OR 1 < x} CONTAINING 2

    x,y:     VAR real
    pxle1:   VAR posreal_le1
    pxge1:   VAR posreal_ge1
    xalt1:   VAR real_abs_lt1
    n0x,n0y: VAR nzreal
    n,m:     VAR nat

  % A&S Section 4.5 Hyperbolic Functions

    sinh(x:  real)  :real         = (exp(x)-exp(-x))/2                   % 4.5.1
    cosh(x:  real)  :posreal_ge1  = (exp(x)+exp(-x))/2                   % 4.5.2
    tanh(x:  real)  :real_abs_lt1 = sinh(x)/cosh(x)                      % 4.5.3
    csch(n0x:nzreal):real         = 1/sinh(n0x)                          % 4.5.4
    sech(x  :real)  :posreal_le1  = 1/cosh(x)                            % 4.5.5
    coth(n0x:nzreal):real_abs_gt1 = 1/tanh(n0x)                          % 4.5.6

  % Restrictions for Branch Properties

    nnreal_cosh (nnx:nnreal):posreal_ge1  = cosh(nnx)
    posreal_csch(px:posreal):posreal      = csch(px)
    nnreal_sech (nnx:nnreal):posreal_le1  = sech(nnx)
    posreal_coth(px:posreal):posreal_gt1  = coth(px)

  % Monotonicity Properties

    sinh_strict_increasing: LEMMA strict_increasing?(sinh)  
    cosh_strict_increasing: LEMMA strict_increasing?(nnreal_cosh)
    tanh_strict_increasing: LEMMA strict_increasing?(tanh)
    csch_strict_decreasing: LEMMA strict_decreasing?(posreal_csch)
    sech_strict_decreasing: LEMMA strict_decreasing?(nnreal_sech)
    coth_strict_decreasing: LEMMA strict_decreasing?(posreal_coth)

  % Special Values of the Hyperbolic Functions

    sinh_0: LEMMA sinh(0) = 0                                            % 4.5.61
    cosh_0: LEMMA cosh(0) = 1                                            % 4.5.61
    tanh_0: LEMMA tanh(0) = 0                                            % 4.5.61
    sech_0: LEMMA sech(0) = 1                                            % 4.5.61

  % Relations between Hyperbolic Functions

    cosh_sinh_one:   LEMMA sq(cosh(x))   - sq(sinh(x))   = 1             % 4.5.16
    tanh_sech_one:   LEMMA sq(tanh(x))   + sq(sech(x))   = 1             % 4.5.17
    coth_csch_one:   LEMMA sq(coth(n0x)) - sq(csch(n0x)) = 1             % 4.5.18
    cosh_plus_sinh:  LEMMA cosh(x)       + sinh(x)       = exp(x)        % 4.5.19
    cosh_minus_sinh: LEMMA cosh(x)       - sinh(x)       = exp(-x)       % 4.5.20

  % Negative Angle FormulasMA FORALL (k:{i:nat| i<n}): C(n,k+1) = C(n,k)*((n-k)/(k+1))


    sinh_neg: LEMMA sinh(-x)   = -sinh(x)                                % 4.5.21
    cosh_neg: LEMMA cosh(-x)   = cosh(x)                                 % 4.5.22
    tanh_neg: LEMMA tanh(-x)   = -tanh(x)                                % 4.5.23
    csch_neg: LEMMA csch(-n0x) = -csch(n0x)
    sech_neg: LEMMA sech(-x)   = sech(x)
    coth_neg: LEMMA coth(-n0x) = -coth(n0x)

  % Addition Formulas

    sinh_sum:  LEMMA sinh(x+y) = sinh(x)*cosh(y) + cosh(x)*sinh(y)       % 4.5.24
    sinh_diff: LEMMA sinh(x-y) = sinh(x)*cosh(y) - cosh(x)*sinh(y)
    cosh_sum:  LEMMA cosh(x+y) = cosh(x)*cosh(y) + sinh(x)*sinh(y)       % 4.5.25
    cosh_diff: LEMMA cosh(x-y) = cosh(x)*cosh(y) - sinh(x)*sinh(y)
    tanh_sum:  LEMMA tanh(x+y) = (tanh(x)+tanh(y))/(1+tanh(x)*tanh(y))   % 4.5.26
    coth_sum:  LEMMA n0x+n0y /= 0 IMPLIES                                % 4.5.27
                     coth(n0x+n0y)
                               = (1+coth(n0x)*coth(n0y))/(coth(n0x)+coth(n0y))

  % Half-angle Formulas

    sinh_half:  LEMMA sinh(x/2) = LET y = sqrt((cosh(x)-1)/2) IN         % 4.5.28
                                  IF x >= 0 THEN y ELSE -y ENDIF
    cosh_half:  LEMMA cosh(x/2) = sqrt((cosh(x)+1)/2)                    % 4.5.29
    tanh_half1: LEMMA tanh(x/2) = LET y = sqrt((cosh(x)-1)/(cosh(x)+1))  % 4.5.30
                                  IN IF x >= 0 THEN y ELSE -y ENDIF
    tanh_half2: LEMMA tanh(n0x/2) = (cosh(n0x)-1)/sinh(n0x)              % 4.5.30
    tanh_half3: LEMMA tanh(x/2) = sinh(x)/(cosh(x)+1)                    % 4.5.30

  % Multiple-angle Formulas

    sinh2x:     LEMMA sinh(2*x) = 2*sinh(x)*cosh(x)                      % 4.5.31
    sinh2x_B:   LEMMA sinh(2*x) = 2*tanh(x)/(1-sq(tanh(x)))              % 4.5.31
    cosh2x:     LEMMA cosh(2*x) = 2*sq(cosh(x))-1                        % 4.5.32
    cosh2x_B:   LEMMA cosh(2*x) = 2*sq(sinh(x))+1                        % 4.5.32
    cosh2x_C:   LEMMA cosh(2*x) = sq(cosh(x)) + sq(sinh(x))              % 4.5.32
    tanh2x:     LEMMA tanh(2*x) = 2*tanh(x)/(1+sq(tanh(x)))              % 4.5.33
    sinh3x:     LEMMA sinh(3*x) = 3*sinh(x) + 4*sinh(x)^3                % 4.5.34
    cosh3x:     LEMMA cosh(3*x) = 4*cosh(x)^3-3*cosh(x)                  % 4.5.35
    sinh4x:     LEMMA sinh(4*x)                                          % 4.5.36
                                = 4*sinh(x)*cosh(x)*(sq(sinh(x)) + sq(cosh(x)))
    cosh4x:     LEMMA cosh(4*x)                                          % 4.5.37
                                = cosh(x)^4+6*sq(sinh(x)*cosh(x))+sinh(x)^4

  % Products

    sinh_times_sinh: LEMMA sinh(x)*sinh(y) = (cosh(x+y)-cosh(x-y))/2     % 4.5.38
    cosh_times_cosh: LEMMA cosh(x)*cosh(y) = (cosh(x+y)+cosh(x-y))/2     % 4.5.39
    sinh_times_cosh: LEMMA sinh(x)*cosh(y) = (sinh(x+y)+sinh(x-y))/2     % 4.5.40

  % Addition and Subtraction

    sum_sinh:   LEMMA sinh(x)+sinh(y) = 2*sinh((x+y)/2)*cosh((x-y)/2)    % 4.5.41
    diff_sinh:  LEMMA sinh(x)-sinh(y) = 2*cosh((x+y)/2)*sinh((x-y)/2)    % 4.5.42
    sum_cosh:   LEMMA cosh(x)+cosh(y) = 2*cosh((x+y)/2)*cosh((x-y)/2)    % 4.5.43
    diff_cosh:  LEMMA cosh(x)-cosh(y) = 2*sinh((x+y)/2)*sinh((x-y)/2)    % 4.5.44
    sum_tanh:   LEMMA tanh(x)+tanh(y) = sinh(x+y)/(cosh(x)*cosh(y))      % 4.5.45
    sum_coth:   LEMMA coth(n0x)+coth(n0y)                                % 4.5.46
                                      = sinh(n0x+n0y)/(sinh(n0x)*sinh(n0y))

  % Relations between squares of hyperbolic sines and cosines

    diff_sinh_sq: LEMMA sq(sinh(x))-sq(sinh(y)) = sinh(x+y)*sinh(x-y)    % 4.5.47
    diff_cosh_sq: LEMMA sq(cosh(x))-sq(cosh(y)) = sinh(x+y)*sinh(x-y)    % 4.5.47
    sum_cosh_sinh_sq: LEMMA sq(sinh(x))+sq(cosh(y))                      % 4.5.48
                                                = cosh(x+y)*cosh(x-y)

  % De Moivre's Theorem

    hyperbolic_deMoivre: LEMMA (cosh(x)+sinh(x))^n = cosh(n*x)+sinh(n*x) % 4.5.53


  % Series expansions

    sinh_series_n(x:real,n:nat):real
      = sigma(0,n,LAMBDA (i:nat): x^(2*i+1)/factorial(2*i+1))

    sinh_taylors: AXIOM EXISTS (c: between[real](0,x)):                  % 4.5.62
               sinh(x) = sinh_series_n(x,n) + cosh(c)*x^(2*n+3)/factorial(2*n+3)


  % Logarithmic representations of inverse hyperbolics

    asinh(x:real):       real   = ln(x+sqrt(sq(x)+1))                    % 4.6.20
    acosh(x:posreal_ge1):nnreal = ln(x+sqrt(sq(x)-1))                    % 4.6.21
    atanh(x:real_abs_lt1):real  = ln((1+x)/(1-x))/2                      % 4.6.22
     
  % Bijection relations

    sinh_bij: LEMMA bijective?[real,real](sinh)
    cosh_bij: LEMMA bijective?[nnreal,posreal_ge1](nnreal_cosh)
    tanh_bij: LEMMA bijective?[real,real_abs_lt1](tanh)
    csch_bij: LEMMA bijective?[posreal,posreal](posreal_csch)
    sech_bij: LEMMA bijective?[nnreal,posreal_le1](nnreal_sech)
    coth_bij: LEMMA bijective?[posreal,posreal_gt1](posreal_coth)

    asinh_alt_def: LEMMA asinh(x) = inverse(sinh)(x)

    asinh_sinh:              LEMMA asinh(sinh(x)) = x
    sinh_asinh:              LEMMA sinh(asinh(x)) = x
    asinh_strict_increasing: LEMMA strict_increasing?(asinh)
    asinh_bij:               LEMMA bijective?[real,real](asinh)



  % Taylor Series for atanh

    z:  VAR real_abs_lt1
    pn: VAR posnat

    atanhF(n:nat)(i:nat):int
      = IF i > 2*n OR odd?(i) THEN 0 ELSE factorial(2*n)*C(2*n+1,i) ENDIF

    atanhD(n:nat)(x:real):real = (1-sq(x))^(2*n+1)

    atanhN(n:nat):[real->real] = polynomial(atanhF(n),2*n)

  %  atanh_taylors_prep1: LEMMA
  %    derivable_n_times(atanhN(n),m) AND derivable_n_times(atanhD(n),m)

  %   atanh_taylors_prep2: LEMMA
  %     deriv(atanhN(n))
  %       = IF n = 0 THEN const_fun(0)
  %                  ELSE polynomial(LAMBDA (i:nat): (i+1)*atanhF(n)(i+1),2*n-1)
  %         ENDIF

  %   atanh_taylors_prep3: LEMMA
  %     deriv(atanhD(n)) = (LAMBDA (z:real): -(4*n+2)*z*
  %                     IF n = 0 THEN 1 ELSE (1-sq(z))*atanhD(n-1)(z) ENDIF)

  %   atanh_taylors_prep4: LEMMA
  %     deriv(deriv(atanhN(n)))
  %       = IF n = 0 THEN const_fun(0)
  %                  ELSE polynomial(LAMBDA (i:nat): (i+2)*(i+1)*atanhF(n)(i+2),2*n-2)
  %         ENDIF

  %   atanh_taylors_prep5: LEMMA FORALL (f:[real_abs_lt1->real],
  %                                      g:[real_abs_lt1->nzreal]):
  %     derivable[real_abs_lt1](f) AND derivable[real_abs_lt1](g) IMPLIES
  %        derivable[real_abs_lt1](f/g^pn) AND
  %        deriv[real_abs_lt1](f/g^pn)
  %           = (deriv[real_abs_lt1](f)*g-pn*f*deriv[real_abs_lt1](g))/(g^(pn+1))

    atanhND(n:nat):[real_abs_lt1->real]
        = (LAMBDA (x:real_abs_lt1): atanhN(n)(x)/atanhD(n)(x))

  %   atanh_taylors_prep6: LEMMA       %% Proof streamlined by Ben Di Vito %%
  %     nderiv[real_abs_lt1](2,LAMBDA (x:real_abs_lt1): atanhN(n)(x)/atanhD(n)(x))
  %       = (LAMBDA (x:real_abs_lt1): atanhN(n+1)(x)/atanhD(n+1)(x))

  %   atanh_taylors_prep7: LEMMA
  %     derivable_n_times[real_abs_lt1](atanhND(n),2*m)

  %   atanh_taylors_prep8: LEMMA nderiv[real_abs_lt1](2*m,atanhND(n))=atanhND(n+m)

  %   atanh_nderiv: LEMMA
  %     nderiv[real_abs_lt1](n,atanh)
  %       = IF    n = 0    THEN atanh
  %         ELSIF even?(n) THEN deriv[real_abs_lt1](atanhND(n/2-1))
  %                        ELSE atanhND((n-1)/2) ENDIF

  %   atanh_nderiv_0: LEMMA
  %     nderiv[real_abs_lt1](n,atanh)(0)
  %       = IF even?(n) THEN 0 ELSE factorial(n-1) ENDIF

  %   atanh_n_times_derivable: LEMMA derivable_n_times[real_abs_lt1](atanh,n)

    atanh_series_term(z:real_abs_lt1):[nat->real]
        = (LAMBDA (n:nat): z^(2*n+1)/(2*n+1))
    atanh_series_n(z:real_abs_lt1,n:nat):real = sigma(0,n,atanh_series_term(z))

  %   atanh_series_eqv: LEMMA
  %    atanh_series_n(z,n) = sigma(0,2*n+2,
  %       LAMBDA (nn:nat): IF nn > 2*n+2 OR nn = 0 THEN 0 ELSE
  %                          nderiv[real_abs_lt1](nn,atanh)(0)*
  %                                                      z^nn/factorial(nn) ENDIF)

  %   atanh_taylors: LEMMA (EXISTS (c: between[real_abs_lt1](0,z)): 
  %                atanh(z) = atanh_series_n(z,n) + 
  %                                  nderiv[real_abs_lt1](2*n+3,atanh)(c)*
  %                                                     z^(2*n+3)/factorial(2*n+3))

    atanh_series: AXIOM abs(atanh(z)-atanh_series_n(z,n)) <=
                     ((1+z)^(2*n+3)+(1-z)^(2*n+3))/(2*(2*n+3)*(1-sq(z))^(2*n+3))

  END hyperbolic

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

  % Subtype TCC generated (at line 38, column 34) for  (exp(x) + exp(-x)) / 2
      % expected type  posreal_ge1
  cosh_TCC1: OBLIGATION FORALL (x: real): (exp(x) + exp(-x)) / 2 >= 1;

  % Subtype TCC generated (at line 39, column 42) for  cosh(x)
      % expected type  nznum
  tanh_TCC1: OBLIGATION FORALL (x: real): cosh(x) /= 0;

  % Subtype TCC generated (at line 39, column 34) for  sinh(x) / cosh(x)
      % expected type  real_abs_lt1
  tanh_TCC2: OBLIGATION
    FORALL (x: real): -1 < sinh(x) / cosh(x) & sinh(x) / cosh(x) < 1;

  % Subtype TCC generated (at line 40, column 36) for  sinh(n0x)
      % expected type  nznum
  csch_TCC1: OBLIGATION FORALL (n0x: nzreal): sinh(n0x) /= 0;

  % Subtype TCC generated (at line 41, column 34) for  1 / cosh(x)
      % expected type  posreal_le1
  sech_TCC1: OBLIGATION
    FORALL (x: real):
      1 / cosh(x) >= 0 AND 1 / cosh(x) > 0 AND 1 / cosh(x) <= 1;

  % Subtype TCC generated (at line 42, column 36) for  tanh(n0x)
      % expected type  nznum
  coth_TCC1: OBLIGATION FORALL (n0x: nzreal): tanh(n0x) /= 0;

  % Subtype TCC generated (at line 42, column 34) for  1 / tanh(n0x)
      % expected type  real_abs_gt1
  coth_TCC2: OBLIGATION
    FORALL (n0x: nzreal): 1 / tanh(n0x) < -1 OR 1 < 1 / tanh(n0x);

  % Subtype TCC generated (at line 47, column 42) for  csch(px)
      % expected type  posreal
  posreal_csch_TCC1: OBLIGATION
    FORALL (px: posreal): csch(px) >= 0 AND csch(px) > 0;

  % Subtype TCC generated (at line 49, column 42) for  coth(px)
      % expected type  posreal_gt1
  posreal_coth_TCC1: OBLIGATION FORALL (px: posreal): coth(px) > 1;

  % Subtype TCC generated (at line 91, column 50) for  (1 + tanh(x) * tanh(y))
      % expected type  nznum
  tanh_sum_TCC1: OBLIGATION FORALL (x, y: real): (1 + tanh(x) * tanh(y)) /= 0;

  % Subtype TCC generated (at line 94, column 56) for  (coth(n0x) + coth(n0y))
      % expected type  nznum
  coth_sum_TCC1: OBLIGATION
    FORALL (n0x, n0y: nzreal):
      n0x + n0y /= 0 IMPLIES (coth(n0x) + coth(n0y)) /= 0;

  % Subtype TCC generated (at line 98, column 45) for  (cosh(x) - 1) / 2
      % expected type  nnx: nonneg_real
  sinh_half_TCC1: OBLIGATION FORALL (x: real): (cosh(x) - 1) / 2 >= 0;

  % Subtype TCC generated (at line 100, column 37) for  (cosh(x) + 1) / 2
      % expected type  nnx: nonneg_real
  cosh_half_TCC1: OBLIGATION FORALL (x: real): (cosh(x) + 1) / 2 >= 0;

  % Subtype TCC generated (at line 101, column 58) for  (cosh(x) + 1)
      % expected type  nznum
  tanh_half1_TCC1: OBLIGATION FORALL (x: real): (cosh(x) + 1) /= 0;

  % Subtype TCC generated (at line 101, column 45) for
      % (cosh(x) - 1) / (cosh(x) + 1)
      % expected type  nnx: nonneg_real
  tanh_half1_TCC2: OBLIGATION
    FORALL (x: real): (cosh(x) - 1) / (cosh(x) + 1) >= 0;

  % Subtype TCC generated (at line 109, column 43) for  (1 - sq(tanh(x)))
      % expected type  nznum
  sinh2x_B_TCC1: OBLIGATION FORALL (x: real): (1 - sq(tanh(x))) /= 0;

  % Subtype TCC generated (at line 114, column 54) for  3
      % expected type  {i: int | sinh(x) /= 0 OR i >= 0}
  sinh3x_TCC1: OBLIGATION FORALL (x: real): sinh(x) /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 119, column 72) for  4
      % expected type  {i: int | sinh(x) /= 0 OR i >= 0}
  cosh4x_TCC1: OBLIGATION FORALL (x: real): sinh(x) /= 0 OR 4 >= 0;

  % Subtype TCC generated (at line 133, column 49) for  (cosh(x) * cosh(y))
      % expected type  nznum
  sum_tanh_TCC1: OBLIGATION FORALL (x, y: real): (cosh(x) * cosh(y)) /= 0;

  % Subtype TCC generated (at line 135, column 53) for
      % (sinh(n0x) * sinh(n0y))
      % expected type  nznum
  sum_coth_TCC1: OBLIGATION
    FORALL (n0x, n0y: nzreal): (sinh(n0x) * sinh(n0y)) /= 0;

  % Subtype TCC generated (at line 146, column 47) for  n
      % expected type  {i: int | (cosh(x) + sinh(x)) /= 0 OR i >= 0}
  hyperbolic_deMoivre_TCC1: OBLIGATION
    FORALL (n: nat, x: real): (cosh(x) + sinh(x)) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 152, column 14) for  n
      % expected type  T_high[nat]
  sinh_series_n_TCC1: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 152, column 35) for  (2 * i + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  sinh_series_n_TCC2: OBLIGATION
    FORALL (x: real, i: nat): x /= 0 OR (2 * i + 1) >= 0;

  % Subtype TCC generated (at line 155, column 55) for  (2 * n + 3)
      % expected type  {i: int | x /= 0 OR i >= 0}
  sinh_taylors_TCC1: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)):
      x /= 0 OR (2 * n + 3) >= 0;

  % Subtype TCC generated (at line 160, column 35) for  x + sqrt(sq(x) + 1)
      % expected type  posreal
  asinh_TCC1: OBLIGATION
    FORALL (x: real): x + sqrt(sq(x) + 1) >= 0 AND x + sqrt(sq(x) + 1) > 0;

  % Subtype TCC generated (at line 161, column 42) for  sq(x) - 1
      % expected type  nnx: nonneg_real
  acosh_TCC1: OBLIGATION FORALL (x: posreal_ge1): sq(x) - 1 >= 0;

  % Subtype TCC generated (at line 161, column 35) for  x + sqrt(sq(x) - 1)
      % expected type  posreal
  acosh_TCC2: OBLIGATION
    FORALL (x: posreal_ge1):
      x + sqrt(sq(x) - 1) >= 0 AND x + sqrt(sq(x) - 1) > 0;

  % Subtype TCC generated (at line 161, column 32) for
      % ln(x + sqrt(sq(x) - 1))
      % expected type  nnreal
  acosh_TCC3: OBLIGATION
    FORALL (x: posreal_ge1): ln(x + sqrt(sq(x) - 1)) >= 0;

  % Subtype TCC generated (at line 162, column 42) for  (1 - x)
      % expected type  nznum
  atanh_TCC1: OBLIGATION FORALL (x: real_abs_lt1): (1 - x) /= 0;

  % Subtype TCC generated (at line 162, column 35) for  (1 + x) / (1 - x)
      % expected type  posreal
  atanh_TCC2: OBLIGATION
    FORALL (x: real_abs_lt1):
      (1 + x) / (1 - x) >= 0 AND (1 + x) / (1 - x) > 0;

  % Subtype TCC generated (at line 188, column 63) for  i
      % expected type  {i: nat | i <= 1 + 2 * n}
  atanhF_TCC1: OBLIGATION
    FORALL (n, i: nat): NOT i > 2 * n AND NOT odd?(i) IMPLIES i <= 1 + 2 * n;

  % Subtype TCC generated (at line 190, column 42) for  (2 * n + 1)
      % expected type  {i: int | (1 - sq(x)) /= 0 OR i >= 0}
  atanhD_TCC1: OBLIGATION
    FORALL (n: nat, x: real): (1 - sq(x)) /= 0 OR (2 * n + 1) >= 0;

  % Subtype TCC generated (at line 221, column 47) for  atanhD(n)(x)
      % expected type  nznum
  atanhND_TCC1: OBLIGATION
    FORALL (n: nat, x: real_abs_lt1): atanhD(n)(x) /= 0;

  % Subtype TCC generated (at line 245, column 28) for  (2 * n + 1)
      % expected type  {i: int | z /= 0 OR i >= 0}
  atanh_series_term_TCC1: OBLIGATION
    FORALL (z: real_abs_lt1, n: nat): z /= 0 OR (2 * n + 1) >= 0;

  % Subtype TCC generated (at line 260, column 27) for  (2 * n + 3)
      % expected type  {i: int | (1 + z) /= 0 OR i >= 0}
  atanh_series_TCC1: OBLIGATION
    FORALL (n: nat, z: real_abs_lt1): (1 + z) /= 0 OR (2 * n + 3) >= 0;

  % Subtype TCC generated (at line 260, column 71) for  (2 * n + 3)
      % expected type  {i: int | (1 - sq(z)) /= 0 OR i >= 0}
  atanh_series_TCC2: OBLIGATION
    FORALL (n: nat, z: real_abs_lt1): (1 - sq(z)) /= 0 OR (2 * n + 3) >= 0;

  % Subtype TCC generated (at line 260, column 50) for
      % (2 * (2 * n + 3) * (1 - sq(z)) ^ (2 * n + 3))
      % expected type  nznum
  atanh_series_TCC3: OBLIGATION
    FORALL (n: nat, z: real_abs_lt1):
      (2 * (2 * n + 3) * (1 - sq(z)) ^ (2 * n + 3)) /= 0;


body:
  expt: THEORY
  %----------------------------------------------------------------------------
  %
  %  Exponentiation: a^x where both a and x are real-valued
  %
  %  Author:  Rick Butler     NASA Langely Research Center
  %
  %  Version 1.0              8/27/04
  %
  %----------------------------------------------------------------------------
  BEGIN

     IMPORTING ln_exp 

     k,n,m: VAR nat
     x,t: VAR real

     epsilon: VAR posreal


     ^^(a: nnreal,x: {r:real | a /= 0 OR r /= 0}): nnreal = IF a = 0 THEN 0
                                                            ELSE exp(x*ln(a))
                                                            ENDIF
   
     a,b: VAR posreal
     px:  VAR posreal
     nzx: VAR nzreal


     hathat_sum   : LEMMA a^^(n + m) = (a^^n)*(a^^m) 
     hathat_diff  : LEMMA a^^(n - m) = (a^^n)/(a^^m) 

     hathat_to_0  : LEMMA px^^0 = 1

     hathat_to_1  : LEMMA a^^1 = a

     hathat_0     : LEMMA 0^^nzx = 0

     hathat_1     : LEMMA 1^^x = 1

     hathat_nat   : LEMMA a^^n = a^n 

     hathat_lt_cross: LEMMA a^^(1/px) < b IMPLIES a < b^^px

     hathat_gt_cross: LEMMA a^^(1/px) > b IMPLIES a > b^^px

     hathat_eq_0  : LEMMA a^^nzx = 0 IFF a = 0

     hathat_eq_1  : LEMMA px^^x = 1 IFF (x = 0 OR px = 1)

     hathat_div   : LEMMA (a/px)^^x = a^^x/px^^x

     hathat_abs   : LEMMA abs(a^^x) = abs(a)^^x

  %   hathat_cont  : LEMMA continuous(LAMBDA x: a^^x)

  %  hathat_cont_nn : LEMMA continuous(LAMBDA (x: posreal): x^^t)

  %  hathat_cont_nnpos : LEMMA continuous(LAMBDA (x: nnreal): x^^a)

     AUTO_REWRITE+ hathat_to_0 
     AUTO_REWRITE+ hathat_to_1 
     AUTO_REWRITE+ hathat_0    
     AUTO_REWRITE+ hathat_1    

  %  There are now multiple versions of f(x) = a^x
  %  available in PVS.  The prelude provides a version for a^n where n is natural
  %  This theory provides a definition for non-negative a and x real
  %  The complex library provides exp(z) for complex z, from which
  %  we could defined another ^ (not yet done).

  %  I am not happy with naming the lemmas "hathat" but I can't think
  %  of a better name.  One could explore the use of theory interpretations
  %  to create an axiomatic version of ^ which is more general than
  %  the current version in the prelude and use these other theories 
  %  to show that this axiomatic version is consistent.

  END expt

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

  % Subtype TCC generated (at line 22, column 72) for  a
      % expected type  posreal
  doublecaret_TCC1: OBLIGATION
    FORALL (a: nnreal, x: {r: real | a /= 0 OR r /= 0}):
      NOT a = 0 IMPLIES a > 0;

  % Subtype TCC generated (at line 30, column 28) for  (n + m)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_sum_TCC1: OBLIGATION
    FORALL (a: posreal, m, n: nat): a /= 0 OR (n + m) /= 0;

  % Subtype TCC generated (at line 30, column 41) for  n
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_sum_TCC2: OBLIGATION FORALL (a: posreal, n: nat): a /= 0 OR n /= 0;

  % Subtype TCC generated (at line 31, column 28) for  (n - m)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_diff_TCC1: OBLIGATION
    FORALL (a: posreal, m, n: nat): a /= 0 OR (n - m) /= 0;

  % Subtype TCC generated (at line 31, column 45) for  (a ^^ m)
      % expected type  nznum
  hathat_diff_TCC2: OBLIGATION FORALL (a: posreal, m: nat): (a ^^ m) /= 0;

  % Subtype TCC generated (at line 33, column 28) for  0
      % expected type  {r: real | px /= 0 OR r /= 0}
  hathat_to_0_TCC1: OBLIGATION FORALL (px: posreal): px /= 0 OR 0 /= 0;

  % Subtype TCC generated (at line 35, column 27) for  1
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_to_1_TCC1: OBLIGATION FORALL (a: posreal): a /= 0 OR 1 /= 0;

  % Subtype TCC generated (at line 41, column 33) for  n
      % expected type  {i: int | a /= 0 OR i >= 0}
  hathat_nat_TCC1: OBLIGATION FORALL (a: posreal, n: nat): a /= 0 OR n >= 0;

  % Subtype TCC generated (at line 43, column 30) for  (1 / px)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_lt_cross_TCC1: OBLIGATION
    FORALL (a, px: posreal): a /= 0 OR (1 / px) /= 0;

  % Subtype TCC generated (at line 43, column 55) for  px
      % expected type  {r: real | b /= 0 OR r /= 0}
  hathat_lt_cross_TCC2: OBLIGATION
    FORALL (a, b, px: posreal): a ^^ (1 / px) < b IMPLIES b /= 0 OR px /= 0;

  % Subtype TCC generated (at line 45, column 55) for  px
      % expected type  {r: real | b /= 0 OR r /= 0}
  hathat_gt_cross_TCC1: OBLIGATION
    FORALL (a, b, px: posreal): a ^^ (1 / px) > b IMPLIES b /= 0 OR px /= 0;

  % Subtype TCC generated (at line 47, column 27) for  nzx
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_eq_0_TCC1: OBLIGATION
    FORALL (a: posreal, nzx: nzreal): a /= 0 OR nzx /= 0;

  % Subtype TCC generated (at line 49, column 28) for  x
      % expected type  {r: real | px /= 0 OR r /= 0}
  hathat_eq_1_TCC1: OBLIGATION
    FORALL (px: posreal, x: real): px /= 0 OR x /= 0;

  % Subtype TCC generated (at line 51, column 32) for  x
      % expected type  {r: real | (a / px) /= 0 OR r /= 0}
  hathat_div_TCC1: OBLIGATION
    FORALL (a, px: posreal, x: real): (a / px) /= 0 OR x /= 0;

  % Subtype TCC generated (at line 51, column 41) for  px ^^ x
      % expected type  nznum
  hathat_div_TCC2: OBLIGATION FORALL (px: posreal, x: real): px ^^ x /= 0;

  % Subtype TCC generated (at line 53, column 44) for  x
      % expected type  {r: real | abs(a) /= 0 OR r /= 0}
  hathat_abs_TCC1: OBLIGATION
    FORALL (a: posreal, x: real): abs(a) /= 0 OR x /= 0;


body:
  top: THEORY
  %------------------------------------------------------------------------
  %   Definition of Logarithm and Exponential functions (lnexp_fnd)
  %
  %   Version 1.0    12/3/03 
  %   Version 1.1    8/25/04  
  %   Version 1.2    10/27/04        added exp_approx, ln_approx
  %   Version 1.3    3/29/05         infinite series for ln completed
  %   Version 1.4    4/10/05         ln_exp_series_alt, ln_exp_ineq added
  %
  %   Authors:  Ricky W. Butler              NASA Langley Research Center
  %             David Lester                 Manchester University
  %
  %------------------------------------------------------------------------------
  BEGIN
      IMPORTING ln_exp,              % Foundational definitions
                expt,                % a^x where x real and a >= 0
                hyperbolic,          % e.g. sinh cosh functions
                exp_series,          % exp as infinite series
                ln_series,           % ln  as taylor series
                exp_approx,          % exp approximation
                ln_approx,           % ln aproximation
                ln_exp_series_alt,   % alternate ln/exp series formulation
                ln_exp_ineq          % inequalities involving ln/exp

  END top


body:
  ln_exp: THEORY
  %------------------------------------------------------------------------
  %   Definition of Logarithm and Exponential functions
  %
  %   Author:  Ricky W. Butler              NASA Langley Research Center
  %------------------------------------------------------------------------
  BEGIN

     x,y,a: VAR real
     i: VAR integer
     px,py,p1,p2: VAR posreal


     IMPORTING analysis@integral, 
               analysis@indefinite_integral, 
               analysis@chain_rule, 
               analysis@derivative_props, analysis@deriv_domains

     conn_posreal: LEMMA connected?[posreal]

     AUTO_REWRITE+ conn_posreal

     one_over_t_cont: LEMMA continuous?((LAMBDA (t: posreal): 1 / t))

     ln_prep: LEMMA FORALL (x: posreal):
           Integrable?[posreal](1, x, (LAMBDA (t: posreal): 1 / t));


     ln(x: posreal): real = Integral(1,x, (LAMBDA (t: posreal): 1/t))

     ln_derivable   : LEMMA derivable?(ln) AND
                         deriv(ln) = (LAMBDA (t: posreal): 1/t)

     ln_continuous  : LEMMA continuous?(ln)
   
     ln_1           : LEMMA ln(1) = 0

     ln_mult        : LEMMA ln(px*py) = ln(px) + ln(py)
     ln_div         : LEMMA ln(px/py) = ln(px) - ln(py)
     ln_expt        : LEMMA ln(px^i)  = i*ln(px) 

     ln_strict_increasing: LEMMA strict_increasing?(ln)
    
     ln_increasing  : LEMMA increasing?(ln)

     ln_image_all   : LEMMA EXISTS (px: posreal): ln(px) = y

     ln_bij         : LEMMA bijective?[posreal, real](ln)

     large_ln       : LEMMA (FORALL a: EXISTS px: a < ln(px))

     ln_eq_0        : LEMMA ln(px) = 0 IMPLIES px = 1

     ln_ge_0        : LEMMA px >= 1 IMPLIES ln(px) >= 0

     ln_gt_0        : LEMMA px > 1 IMPLIES ln(px) > 0

     exp(x): { py | x = ln(py)}

     e: posreal = exp(1)

     exp_def        : LEMMA exp = inverse(ln)

     exp_bij        : LEMMA bijective?[real,posreal](exp)

     ln_exp         : LEMMA ln(exp(x)) = x

     exp_ln         : LEMMA exp(ln(py)) = py

     ln_e           : LEMMA ln(e) = 1

     ln_2_bnds      : LEMMA 1/2 <= ln(2) AND ln(2) <= 1

     exp_int        : LEMMA exp(i) = e^i

     exp_sum        : LEMMA exp(x+y) = exp(x)*exp(y) 

     exp_diff       : LEMMA exp(x-y) = exp(x)/exp(y) 

     exp_scal       : LEMMA exp(i*x) = exp(x)^i

     exp_0          : LEMMA exp(0) = 1

     exp_1          : LEMMA exp(1) = e

     exp_neg        : LEMMA exp(-x) = 1/exp(x)

     expt_alt_def   : LEMMA x > 0 IMPLIES x^i = exp(i*ln(x))

     exp_strict_increasing : LEMMA strict_increasing?(exp)

     exp_increasing : LEMMA increasing?(exp)

     exp_continuous : LEMMA continuous?(exp)

     IMPORTING analysis@derivative_inverse

     exp_deriv      : LEMMA derivable?(exp) AND deriv(exp) = exp

     e_bnds         : LEMMA 2 <= e AND e <= 4

     large_exp      : LEMMA (FORALL a: EXISTS x: a < exp(x))

     small_exp      : LEMMA (FORALL px: EXISTS x: exp(x) < px)

     AUTO_REWRITE+ exp_0
     AUTO_REWRITE+ exp_1
     AUTO_REWRITE+ ln_1
     AUTO_REWRITE+ ln_e

  END ln_exp

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

  % Assuming TCC generated (at line 14, column 6) for
      % analysis@integral_def[posreal]
      % generated from assumption integral_def.connected_domain
  ln_prep_TCC1: OBLIGATION connected?[posreal];

  % Assuming TCC generated (at line 17, column 6) for
      % analysis@integral_def[posreal]
      % generated from assumption integral_def.not_one_element
  ln_prep_TCC2: OBLIGATION not_one_element?[posreal];

  % Subtype TCC generated (at line 29, column 41) for
      % (LAMBDA (t: posreal): 1 / t)
      % expected type  Integrable_funs[posreal](1, x)
  ln_TCC1: OBLIGATION
    FORALL (x: posreal):
      Integrable?[posreal](1, x, (LAMBDA (t: posreal): 1 / t));

  % Assuming TCC generated (at line 14, column 12) for
      % analysis@derivatives[posreal]
      % generated from assumption derivatives.deriv_domain
  ln_derivable_TCC1: OBLIGATION deriv_domain?[posreal];

  % Subtype TCC generated (at line 40, column 32) for  i
      % expected type  {i: int | px /= 0 OR i >= 0}
  ln_expt_TCC1: OBLIGATION
    FORALL (i: integer, px: posreal): px /= 0 OR i >= 0;

  % Existence TCC generated (at line 58, column 3) for
      % exp(x): {py | x = ln(py)}
  exp_TCC1: OBLIGATION EXISTS (x1: [x: real -> {py | x = ln(py)}]): TRUE;

  % Subtype TCC generated (at line 74, column 37) for  i
      % expected type  {i: int | e /= 0 OR i >= 0}
  exp_int_TCC1: OBLIGATION FORALL (i: integer): e /= 0 OR i >= 0;

  % Subtype TCC generated (at line 80, column 44) for  i
      % expected type  {i: int | exp(x) /= 0 OR i >= 0}
  exp_scal_TCC1: OBLIGATION
    FORALL (i: integer, x: real): exp(x) /= 0 OR i >= 0;

  % Subtype TCC generated (at line 88, column 42) for  i
      % expected type  {i: int | x /= 0 OR i >= 0}
  expt_alt_def_TCC1: OBLIGATION
    FORALL (i: integer, x: real): x > 0 IMPLIES x /= 0 OR i >= 0;

  % Subtype TCC generated (at line 88, column 55) for  x
      % expected type  posreal
  expt_alt_def_TCC2: OBLIGATION FORALL (x: real): x > 0 IMPLIES x >= 0;

  % Assuming TCC generated (at line 14, column 12) for
      % analysis@derivatives[real]
      % generated from assumption derivatives.deriv_domain
  exp_deriv_TCC1: OBLIGATION deriv_domain?[real];

  % Assuming TCC generated (at line 14, column 12) for
      % analysis@derivatives[real]
      % generated from assumption derivatives.not_one_element
  exp_deriv_TCC2: OBLIGATION not_one_element?[real];


body:
  ln_exp_series_alt: THEORY
  %------------------------------------------------------------------------------
  %
  % Alternate means of establishing infinite series for ln and exp
  %
  % Author: David Lester
  %
  % 
  %------------------------------------------------------------------------------
  BEGIN

     real_gtm1_le1: NONEMPTY_TYPE = {x:real | -1 < x AND x <= 1} CONTAINING 0

     x:    VAR real
     px:   VAR posreal
     xgm1: VAR {x:real | x > -1}
     nzx:  VAR nzreal
     z:    VAR real_gtm1_le1
     n:    VAR nat


     IMPORTING ln_exp, analysis@derivative_inverse,
               analysis@nth_derivatives, analysis@taylors, series@series,
               analysis@integral, analysis@indefinite_integral, reals@sqrt

     noa_posreal      : LEMMA not_one_element?[posreal]
     conn_posreal     : LEMMA connected?[posreal]
     noa_gt_m1        : LEMMA not_one_element?[{x: real | x > -1}]
     conn_gt_m1       : LEMMA connected?[{x: real | x > -1}]
     deriv_domain_gtm1: LEMMA deriv_domain?[{x: real | x > -1}]

     AUTO_REWRITE+ noa_gt_m1 
     AUTO_REWRITE+ conn_gt_m1
     AUTO_REWRITE+ deriv_domain_gtm1
     AUTO_REWRITE+ noa_posreal
     AUTO_REWRITE+ conn_posreal
     AUTO_REWRITE+ deriv_domain_posreal


     AUTO_REWRITE+ sigma_0_neg

     nderiv_ln: LEMMA derivable_n_times?[posreal](ln,n)

     ln_nderiv      : LEMMA nderiv[posreal](n,ln) = IF n = 0 THEN ln ELSE 
                          (LAMBDA (x:posreal): -factorial(n-1)/(-x)^n) ENDIF

     ln_estimate(x:real,n:nat):real
           = sigma(0,n,(LAMBDA (nn:nat): IF nn=0 THEN 0 ELSE -(-x)^nn/nn ENDIF))

     ln_estimate_scaf1: LEMMA continuous?((LAMBDA (t: posreal): (1-t)^n/t))

     ln_estimate_scaf2: LEMMA FORALL (x:posreal):
                       Integrable?[posreal](1,x,(LAMBDA (t: posreal): (1-t)^n/t))

     ln_estimate_scaf3: LEMMA FORALL (x:posreal):
                              ln(x) = Integral(1,x,LAMBDA (t:posreal): (1-t)^0/t)

     ln_estimate_scaf4: LEMMA x /= 1 IMPLIES
             1/(1-x) = sigma(0,n,(LAMBDA (i:nat): x^i)) + x^(n+1)/(1-x)

     ln_estimate_scaf5: LEMMA
             1/nzx = sigma(0,n,(LAMBDA (i:nat): (1-nzx)^i)) + (1-nzx)^(n+1)/nzx

     ln_estimate_scaf6: LEMMA derivable?[posreal](LAMBDA px: ln_estimate(px-1, n))

     ln_estimate_scaf7: LEMMA deriv[posreal](LAMBDA px: ln_estimate(px-1, n+1))
                  = (LAMBDA px: sigma(0,n,(LAMBDA (i:nat): (1-px)^i)))

     ln_estimate_scaf8: LEMMA
           ln(px) = ln_estimate(px-1,n+1) +
                        Integral(1,px,LAMBDA (t:posreal): (1-t)^(n+1)/t)

     ln_estimate_scaf9: LEMMA
           ln(px) = ln_estimate(px-1,n) +
                        Integral(1,px,LAMBDA (t:posreal): (1-t)^n/t)

     ln_estimate_scaf10: LEMMA 1 <= px AND px <= 2 IMPLIES
             abs(Integral(1,px,LAMBDA (t:posreal): (1-t)^n/t))
                                          <= (px-1)^(n+1)/(n+1)

     ln_estimate_scaf11: LEMMA px < 1 IMPLIES
             abs(Integral(1,px,LAMBDA (t:posreal): (1-t)^n/t))
                                          <= (1-px)^(n+1)/((n+1)*px)

     ln_estimate_bnd: LEMMA abs(ln(1+z) - ln_estimate(z,n)) <=
                        abs(z)^(n+1)/(IF z < 0 THEN 1+z ELSE 1 ENDIF*(n+1))

     lnT(x:real_gtm1_le1)(n:nat):real_gtm1_le1 = -(-x)^(n+1)/(n+1)

     lnT_convergence: LEMMA convergence(series(lnT(z)),ln(1+z))

     lnT_convergent: LEMMA convergent?(series(lnT(z)))

     ln_series_def: LEMMA ln(1+z) = inf_sum(lnT(z))

     ln_taylors:     LEMMA EXISTS (c: between[{x:real | x > -1}](1,1+xgm1)):
                       ln(xgm1+1) = ln_estimate(xgm1,n) -(xgm1/-c)^(n+1)/(n+1)

  %  Properties of exp

     nderiv_exp: LEMMA derivable_n_times?(exp, n)
                       AND nderiv(n, exp) = exp

     expT(x)(n):real = IF n = 0 THEN 1 ELSE x^n / factorial(n) ENDIF

     exp_estimate(x,n):real = sigma(0,n,expT(x))

     exp_taylors:     LEMMA EXISTS (c:between[real](0,x)):
                       exp(x) = exp_estimate(x,n) + exp(c)*x^(n+1)/factorial(n+1)

     exp_estimate_bnd:      LEMMA abs(exp(x)-exp_estimate(x,n)) 
                                  <= max(exp(x),1)*abs(x)^(n+1)/factorial(n+1)

     exp_series_scaf2: LEMMA sqrt(n)^(2*n) <= factorial(2*n)

     exp_series_scaf3: LEMMA sqrt(n)^(2*n+1) <= factorial(2*n+1)

     expT_convergence: LEMMA convergence(series(expT(x)),exp(x))

     expT_convergent: LEMMA convergent?(series(expT(x)))

     exp_series: LEMMA exp(x) = inf_sum(expT(x))

  END ln_exp_series_alt

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

  % Assuming TCC generated (at line 22, column 3) for
      % analysis@nth_derivatives[posreal]
      % generated from assumption nth_derivatives.deriv_domain
  nderiv_ln_TCC1: OBLIGATION deriv_domain?[posreal];

  % Assuming TCC generated (at line 24, column 3) for
      % analysis@nth_derivatives[posreal]
      % generated from assumption nth_derivatives.not_one_element
  nderiv_ln_TCC2: OBLIGATION not_one_element?[posreal];

  % Subtype TCC generated (at line 44, column 44) for  ln
      % expected type  nderiv_fun[posreal](n)
  ln_nderiv_TCC1: OBLIGATION
    FORALL (n: nat): derivable_n_times?[posreal](ln, n);

  % Subtype TCC generated (at line 45, column 56) for  n - 1
      % expected type  nat
  ln_nderiv_TCC2: OBLIGATION FORALL (n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Subtype TCC generated (at line 45, column 66) for  n
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  ln_nderiv_TCC3: OBLIGATION
    FORALL (n: nat):
      NOT n = 0 IMPLIES (FORALL (x: posreal): (-x) /= 0 OR n >= 0);

  % Subtype TCC generated (at line 48, column 17) for  0
      % expected type  T_low[nat]
  ln_estimate_TCC1: OBLIGATION 0 >= 0 OR (EXISTS (j: nat): j <= 0);

  % Subtype TCC generated (at line 48, column 19) for  n
      % expected type  T_high[nat]
  ln_estimate_TCC2: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 48, column 65) for  nn
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  ln_estimate_TCC3: OBLIGATION
    FORALL (x: real, nn: nat): NOT nn = 0 IMPLIES (-x) /= 0 OR nn >= 0;

  % Subtype TCC generated (at line 48, column 68) for  nn
      % expected type  nznum
  ln_estimate_TCC4: OBLIGATION FORALL (nn: nat): NOT nn = 0 IMPLIES nn /= 0;

  % Subtype TCC generated (at line 50, column 68) for  n
      % expected type  {i: int | (1 - t) /= 0 OR i >= 0}
  ln_estimate_scaf1_TCC1: OBLIGATION
    FORALL (n: nat, t: posreal): (1 - t) /= 0 OR n >= 0;

  % Assuming TCC generated (at line 14, column 6) for
      % analysis@integral_def[posreal]
      % generated from assumption integral_def.connected_domain
  ln_estimate_scaf2_TCC1: OBLIGATION connected?[posreal];

  % Subtype TCC generated (at line 56, column 75) for  0
      % expected type  {i: int | (1 - t) /= 0 OR i >= 0}
  ln_estimate_scaf3_TCC1: OBLIGATION
    FORALL (t: posreal): (1 - t) /= 0 OR 0 >= 0;

  % Subtype TCC generated (at line 56, column 49) for
      % LAMBDA (t: posreal): (1 - t) ^ 0 / t
      % expected type  Integrable_funs[posreal](1, x)
  ln_estimate_scaf3_TCC2: OBLIGATION
    FORALL (x: posreal):
      Integrable?[posreal](1, x, LAMBDA (t: posreal): (1 - t) ^ 0 / t);

  % Subtype TCC generated (at line 59, column 14) for  (1 - x)
      % expected type  nznum
  ln_estimate_scaf4_TCC1: OBLIGATION
    FORALL (x: real): x /= 1 IMPLIES (1 - x) /= 0;

  % Subtype TCC generated (at line 59, column 50) for  i
      % expected type  {i: int | x /= 0 OR i >= 0}
  ln_estimate_scaf4_TCC2: OBLIGATION
    FORALL (x: real): x /= 1 IMPLIES (FORALL (i: nat): x /= 0 OR i >= 0);

  % Subtype TCC generated (at line 59, column 59) for  (n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  ln_estimate_scaf4_TCC3: OBLIGATION
    FORALL (n: nat, x: real): x /= 1 IMPLIES x /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 62, column 54) for  i
      % expected type  {i: int | (1 - nzx) /= 0 OR i >= 0}
  ln_estimate_scaf5_TCC1: OBLIGATION
    FORALL (nzx: nzreal, i: nat): (1 - nzx) /= 0 OR i >= 0;

  % Subtype TCC generated (at line 62, column 69) for  (n + 1)
      % expected type  {i: int | (1 - nzx) /= 0 OR i >= 0}
  ln_estimate_scaf5_TCC2: OBLIGATION
    FORALL (n: nat, nzx: nzreal): (1 - nzx) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 66, column 43) for
      % LAMBDA px: ln_estimate(px - 1, n + 1)
      % expected type  deriv_fun[posreal]
  ln_estimate_scaf7_TCC1: OBLIGATION
    FORALL (n: nat):
      derivable?[posreal](LAMBDA px: ln_estimate(px - 1, n + 1));

  % Subtype TCC generated (at line 71, column 63) for  (n + 1)
      % expected type  {i: int | (1 - t) /= 0 OR i >= 0}
  ln_estimate_scaf8_TCC1: OBLIGATION
    FORALL (n: nat, t: posreal): (1 - t) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 71, column 36) for
      % LAMBDA (t: posreal): (1 - t) ^ (n + 1) / t
      % expected type  Integrable_funs[posreal](1, px)
  ln_estimate_scaf8_TCC2: OBLIGATION
    FORALL (n: nat, px: posreal):
      Integrable?[posreal](1, px, LAMBDA (t: posreal): (1 - t) ^ (n + 1) / t);

  % Subtype TCC generated (at line 75, column 36) for
      % LAMBDA (t: posreal): (1 - t) ^ n / t
      % expected type  Integrable_funs[posreal](1, px)
  ln_estimate_scaf9_TCC1: OBLIGATION
    FORALL (n: nat, px: posreal):
      Integrable?[posreal](1, px, LAMBDA (t: posreal): (1 - t) ^ n / t);

  % Subtype TCC generated (at line 79, column 51) for  (n + 1)
      % expected type  {i: int | (px - 1) /= 0 OR i >= 0}
  ln_estimate_scaf10_TCC1: OBLIGATION
    FORALL (n: nat, px: posreal):
      px <= 2 AND 1 <= px IMPLIES (px - 1) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 85, column 33) for  1 + z
      % expected type  posreal
  ln_estimate_bnd_TCC1: OBLIGATION
    FORALL (z: real_gtm1_le1): 1 + z >= 0 AND 1 + z > 0;

  % Subtype TCC generated (at line 86, column 30) for  (n + 1)
      % expected type  {i: int | abs(z) /= 0 OR i >= 0}
  ln_estimate_bnd_TCC2: OBLIGATION
    FORALL (n: nat, z: real_gtm1_le1): abs(z) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 86, column 36) for
      % (IF z < 0 THEN 1 + z ELSE 1 ENDIF * (n + 1))
      % expected type  nznum
  ln_estimate_bnd_TCC3: OBLIGATION
    FORALL (n: nat, z: real_gtm1_le1):
      (IF z < 0 THEN 1 + z ELSE 1 ENDIF * (n + 1)) /= 0;

  % Subtype TCC generated (at line 88, column 54) for  (n + 1)
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  lnT_TCC1: OBLIGATION
    FORALL (x: real_gtm1_le1, n: nat): (-x) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 88, column 47) for
      % -(-x) ^ (n + 1) / (n + 1)
      % expected type  real_gtm1_le1
  lnT_TCC2: OBLIGATION
    FORALL (x: real_gtm1_le1, n: nat):
      -1 < -(-x) ^ (n + 1) / (n + 1) AND -(-x) ^ (n + 1) / (n + 1) <= 1;

  % Subtype TCC generated (at line 94, column 42) for  lnT(z)
      % expected type  (conv_series?)
  ln_series_def_TCC1: OBLIGATION
    FORALL (z: real_gtm1_le1): conv_series?(lnT(z));

  % Assuming TCC generated (at line 19, column 5) for
      % analysis@taylors[{x: real | x > -1}]
      % generated from assumption taylors.connected_domain
  ln_taylors_TCC1: OBLIGATION connected?[{x: real | x > -1}];

  % Assuming TCC generated (at line 21, column 5) for
      % analysis@taylors[{x: real | x > -1}]
      % generated from assumption taylors.not_one_element
  ln_taylors_TCC2: OBLIGATION not_one_element?[{x: real | x > -1}];

  % Subtype TCC generated (at line 97, column 24) for  xgm1 + 1
      % expected type  posreal
  ln_taylors_TCC3: OBLIGATION
    FORALL (xgm1: {x: real | x > -1},
            c: between[{x: real | x > -1}](1, 1 + xgm1)):
      xgm1 + 1 >= 0 AND xgm1 + 1 > 0;

  % Subtype TCC generated (at line 97, column 61) for  -c
      % expected type  nznum
  ln_taylors_TCC4: OBLIGATION
    FORALL (xgm1: {x: real | x > -1},
            c: between[{x: real | x > -1}](1, 1 + xgm1)):
      -c /= 0;

  % Subtype TCC generated (at line 97, column 66) for  (n + 1)
      % expected type  {i: int | (xgm1 / -c) /= 0 OR i >= 0}
  ln_taylors_TCC5: OBLIGATION
    FORALL (n: nat, xgm1: {x: real | x > -1},
            c: between[{x: real | x > -1}](1, 1 + xgm1)):
      (xgm1 / -c) /= 0 OR (n + 1) >= 0;

  % Assuming TCC generated (at line 23, column 13) for
      % analysis@nth_derivatives[real]
      % generated from assumption nth_derivatives.deriv_domain
  nderiv_exp_TCC1: OBLIGATION deriv_domain?[real];

  % Assuming TCC generated (at line 23, column 13) for
      % analysis@nth_derivatives[real]
      % generated from assumption nth_derivatives.not_one_element
  nderiv_exp_TCC2: OBLIGATION not_one_element?[real];

  % Subtype TCC generated (at line 104, column 44) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  expT_TCC1: OBLIGATION
    FORALL (x: real, n: nat): NOT n = 0 IMPLIES x /= 0 OR n >= 0;

  % Assuming TCC generated (at line 19, column 5) for  analysis@taylors[real]
      % generated from assumption taylors.connected_domain
  exp_taylors_TCC1: OBLIGATION connected?[real];

  % Subtype TCC generated (at line 109, column 60) for  (n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  exp_taylors_TCC2: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)): x /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 112, column 57) for  (n + 1)
      % expected type  {i: int | abs(x) /= 0 OR i >= 0}
  exp_estimate_bnd_TCC1: OBLIGATION
    FORALL (n: nat, x: real): abs(x) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 114, column 36) for  (2 * n)
      % expected type  {i: int | sqrt(n) /= 0 OR i >= 0}
  exp_series_scaf2_TCC1: OBLIGATION
    FORALL (n: nat): sqrt(n) /= 0 OR (2 * n) >= 0;

  % Subtype TCC generated (at line 116, column 36) for  (2 * n + 1)
      % expected type  {i: int | sqrt(n) /= 0 OR i >= 0}
  exp_series_scaf3_TCC1: OBLIGATION
    FORALL (n: nat): sqrt(n) /= 0 OR (2 * n + 1) >= 0;

  % Subtype TCC generated (at line 122, column 38) for  expT(x)
      % expected type  (conv_series?)
  exp_series_TCC1: OBLIGATION FORALL (x: real): conv_series?(expT(x));


body:
  ln_exp_ineq: THEORY
  %------------------------------------------------------------------------------

  % Inequalities involving ln and exp
  %
  % Author: David Lester
  %
  % 
  %------------------------------------------------------------------------------

    BEGIN

    IMPORTING ln_exp, analysis@derivative_props, analysis@chain_rule,
  %            ln_series, exp_series
              ln_exp_series_alt

    nzreal_gt_m1: NONEMPTY_TYPE = {x:nzreal | x > -1}          CONTAINING  1
    nzreal_lt1:   NONEMPTY_TYPE = {x:nzreal | x < 1 }          CONTAINING -1
    real_abs_lt1: NONEMPTY_TYPE = {x:real   | -1 < x & x < 1 } CONTAINING  0


     noa_posreal : LEMMA not_one_element?[posreal]
     conn_posreal: LEMMA connected?[posreal]

     AUTO_REWRITE+ noa_posreal
     AUTO_REWRITE+ conn_posreal
     AUTO_REWRITE+ deriv_domain_posreal


    xgtm1: VAR nzreal_gt_m1
    xlt1:  VAR nzreal_lt1
    px:    VAR posreal
    nzx:   VAR nzreal
    pn:    VAR posnat
    xalt1: VAR real_abs_lt1

    ln_ineq1:  LEMMA xgtm1/(1+xgtm1) < ln(1+xgtm1) AND
                     ln(1+xgtm1) < xgtm1                                 % 4.1.33

    ln_ineq2:  LEMMA xlt1 < -ln(1-xlt1) AND -ln(1-xlt1) < xlt1/(1-xlt1)  % 4.1.34

    ln_ineq3:  LEMMA px <= 5828/10000 IMPLIES abs(ln(1-px)) < 3*px/2     % 4.1.35

    ln_ineq4:  LEMMA ln(px) <= px-1                                      % 4.1.36

    ln_ineq5:  LEMMA ln(px) <= pn*(exp(ln(px)/pn)-1)                     % 4.1.37

    ln_ineq6:  LEMMA abs(ln(1+xalt1)) <= -ln(1-abs(xalt1))               % 4.1.38

    exp_ineq1: LEMMA exp(-xlt1/(1-xlt1)) < 1-xlt1 AND
                     1-xlt1 < exp(-xlt1)                                 % 4.2.29

    exp_ineq2: LEMMA nzx+1 < exp(nzx)                                    % 4.2.30

    exp_ineq3: LEMMA exp(xlt1) < 1/(1-xlt1)                              % 4.2.31

    END ln_exp_ineq

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

  % Subtype TCC generated (at line 37, column 26) for  (1 + xgtm1)
      % expected type  nznum
  ln_ineq1_TCC1: OBLIGATION FORALL (xgtm1: nzreal_gt_m1): (1 + xgtm1) /= 0;

  % Subtype TCC generated (at line 37, column 40) for  1 + xgtm1
      % expected type  posreal
  ln_ineq1_TCC2: OBLIGATION
    FORALL (xgtm1: nzreal_gt_m1): 1 + xgtm1 >= 0 AND 1 + xgtm1 > 0;

  % Subtype TCC generated (at line 40, column 30) for  1 - xlt1
      % expected type  posreal
  ln_ineq2_TCC1: OBLIGATION
    FORALL (xlt1: nzreal_lt1): 1 - xlt1 >= 0 AND 1 - xlt1 > 0;

  % Subtype TCC generated (at line 40, column 62) for  (1 - xlt1)
      % expected type  nznum
  ln_ineq2_TCC2: OBLIGATION
    FORALL (xlt1: nzreal_lt1): xlt1 < -ln(1 - xlt1) IMPLIES (1 - xlt1) /= 0;

  % Subtype TCC generated (at line 42, column 51) for  1 - px
      % expected type  posreal
  ln_ineq3_TCC1: OBLIGATION
    FORALL (px: posreal):
      px <= 5828 / 10000 IMPLIES 1 - px >= 0 AND 1 - px > 0;

  % Subtype TCC generated (at line 48, column 26) for  1 + xalt1
      % expected type  posreal
  ln_ineq6_TCC1: OBLIGATION
    FORALL (xalt1: real_abs_lt1): 1 + xalt1 >= 0 AND 1 + xalt1 > 0;

  % Subtype TCC generated (at line 48, column 43) for  1 - abs(xalt1)
      % expected type  posreal
  ln_ineq6_TCC2: OBLIGATION
    FORALL (xalt1: real_abs_lt1): 1 - abs(xalt1) >= 0 AND 1 - abs(xalt1) > 0;

  % Subtype TCC generated (at line 50, column 30) for  (1 - xlt1)
      % expected type  nznum
  exp_ineq1_TCC1: OBLIGATION FORALL (xlt1: nzreal_lt1): (1 - xlt1) /= 0;


body:
  expt: THEORY
  %----------------------------------------------------------------------------
  %
  %  Exponentiation: a^x where both a and x are real-valued
  %
  %  Author:  Rick Butler     NASA Langley Research Center
  %           Olga Lightfoot, QMUL
  %
  %  Version 1.0              8/27/04
  %
  %----------------------------------------------------------------------------
  BEGIN

     IMPORTING ln_exp 

     k,n,m: VAR nat
     x,t: VAR real

     epsilon: VAR posreal


     ^^(a: nnreal,x: {r:real | a /= 0 OR r /= 0}): nnreal = IF a = 0 THEN 0
                                                            ELSE exp(x*ln(a))
                                                            ENDIF
   
     a,b: VAR posreal
     px,py:  VAR posreal
     nzx: VAR nzreal


     hathat_sum   : LEMMA a^^(n + m) = (a^^n)*(a^^m) 
     hathat_diff  : LEMMA a^^(n - m) = (a^^n)/(a^^m) 

     hathat_to_0  : LEMMA px^^0 = 1

     hathat_to_1  : LEMMA a^^1 = a

     hathat_0     : LEMMA 0^^nzx = 0

     hathat_1     : LEMMA 1^^x = 1

     hathat_nat   : LEMMA a^^n = a^n 

     hathat_lt_cross: LEMMA a^^(1/px) < b IMPLIES a < b^^px

     hathat_gt_cross: LEMMA a^^(1/px) > b IMPLIES a > b^^px

     hathat_eq_0  : LEMMA a^^nzx = 0 IFF a = 0

     hathat_eq_1  : LEMMA px^^x = 1 IFF (x = 0 OR px = 1)

     hathat_cross : LEMMA a^^(1/px)=b IMPLIES a=b^^px

     hathat_mult  : LEMMA (a^^px)^^py=a^^(px*py)

     hathat_div   : LEMMA (a/px)^^x = a^^x/px^^x

     hathat_abs   : LEMMA abs(a^^x) = abs(a)^^x

     hathat_sum_posreal: LEMMA (a^^px)*(a^^py)=a^^(px+py)

     hathat_diff_posreal: LEMMA (a^^px)/(a^^py)=a^^(px-py)


     hathat_cont  : LEMMA continuous?(LAMBDA x: a^^x)

  %  hathat_cont_nn : LEMMA continuous?(LAMBDA (x: posreal): x^^t)

  %  hathat_cont_nnpos : LEMMA continuous?(LAMBDA (x: nnreal): x^^a)

     AUTO_REWRITE+ hathat_to_0 
     AUTO_REWRITE+ hathat_to_1 
     AUTO_REWRITE+ hathat_0    
     AUTO_REWRITE+ hathat_1    

  %  There are now multiple versions of f(x) = a^x
  %  available in PVS.  The prelude provides a version for a^n where n is natural
  %  This theory provides a definition for non-negative a and x real
  %  The complex library provides exp(z) for complex z, from which
  %  we could defined another ^ (not yet done).

  %  I am not happy with naming the lemmas "hathat" but I can't think
  %  of a better name.  One could explore the use of theory interpretations
  %  to create an axiomatic version of ^ which is more general than
  %  the current version in the prelude and use these other theories 
  %  to show that this axiomatic version is consistent.

  END expt

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

  % Subtype TCC generated (at line 23, column 72) for  a
      % expected type  posreal
  doublecaret_TCC1: OBLIGATION
    FORALL (a: nnreal, x: {r: real | a /= 0 OR r /= 0}):
      NOT a = 0 IMPLIES a > 0;

  % Subtype TCC generated (at line 31, column 28) for  (n + m)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_sum_TCC1: OBLIGATION
    FORALL (a: posreal, m, n: nat): a /= 0 OR (n + m) /= 0;

  % Subtype TCC generated (at line 31, column 41) for  n
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_sum_TCC2: OBLIGATION FORALL (a: posreal, n: nat): a /= 0 OR n /= 0;

  % Subtype TCC generated (at line 32, column 28) for  (n - m)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_diff_TCC1: OBLIGATION
    FORALL (a: posreal, m, n: nat): a /= 0 OR (n - m) /= 0;

  % Subtype TCC generated (at line 32, column 45) for  (a ^^ m)
      % expected type  nznum
  hathat_diff_TCC2: OBLIGATION FORALL (a: posreal, m: nat): (a ^^ m) /= 0;

  % Subtype TCC generated (at line 34, column 28) for  0
      % expected type  {r: real | px /= 0 OR r /= 0}
  hathat_to_0_TCC1: OBLIGATION FORALL (px: posreal): px /= 0 OR 0 /= 0;

  % Subtype TCC generated (at line 36, column 27) for  1
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_to_1_TCC1: OBLIGATION FORALL (a: posreal): a /= 0 OR 1 /= 0;

  % Subtype TCC generated (at line 42, column 33) for  n
      % expected type  {i: int | a /= 0 OR i >= 0}
  hathat_nat_TCC1: OBLIGATION FORALL (a: posreal, n: nat): a /= 0 OR n >= 0;

  % Subtype TCC generated (at line 44, column 30) for  (1 / px)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_lt_cross_TCC1: OBLIGATION
    FORALL (a, px: posreal): a /= 0 OR (1 / px) /= 0;

  % Subtype TCC generated (at line 44, column 55) for  px
      % expected type  {r: real | b /= 0 OR r /= 0}
  hathat_lt_cross_TCC2: OBLIGATION
    FORALL (a, b, px: posreal): a ^^ (1 / px) < b IMPLIES b /= 0 OR px /= 0;

  % Subtype TCC generated (at line 46, column 55) for  px
      % expected type  {r: real | b /= 0 OR r /= 0}
  hathat_gt_cross_TCC1: OBLIGATION
    FORALL (a, b, px: posreal): a ^^ (1 / px) > b IMPLIES b /= 0 OR px /= 0;

  % Subtype TCC generated (at line 48, column 27) for  nzx
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_eq_0_TCC1: OBLIGATION
    FORALL (a: posreal, nzx: nzreal): a /= 0 OR nzx /= 0;

  % Subtype TCC generated (at line 50, column 28) for  x
      % expected type  {r: real | px /= 0 OR r /= 0}
  hathat_eq_1_TCC1: OBLIGATION
    FORALL (px: posreal, x: real): px /= 0 OR x /= 0;

  % Subtype TCC generated (at line 52, column 49) for  px
      % expected type  {r: real | b /= 0 OR r /= 0}
  hathat_cross_TCC1: OBLIGATION
    FORALL (a, b, px: posreal): a ^^ (1 / px) = b IMPLIES b /= 0 OR px /= 0;

  % Subtype TCC generated (at line 54, column 28) for  px
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_mult_TCC1: OBLIGATION FORALL (a, px: posreal): a /= 0 OR px /= 0;

  % Subtype TCC generated (at line 54, column 33) for  py
      % expected type  {r: real | (a ^^ px) /= 0 OR r /= 0}
  hathat_mult_TCC2: OBLIGATION
    FORALL (a, px, py: posreal): (a ^^ px) /= 0 OR py /= 0;

  % Subtype TCC generated (at line 54, column 40) for  (px * py)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_mult_TCC3: OBLIGATION
    FORALL (a, px, py: posreal): a /= 0 OR (px * py) /= 0;

  % Subtype TCC generated (at line 56, column 32) for  x
      % expected type  {r: real | (a / px) /= 0 OR r /= 0}
  hathat_div_TCC1: OBLIGATION
    FORALL (a, px: posreal, x: real): (a / px) /= 0 OR x /= 0;

  % Subtype TCC generated (at line 56, column 41) for  px ^^ x
      % expected type  nznum
  hathat_div_TCC2: OBLIGATION FORALL (px: posreal, x: real): px ^^ x /= 0;

  % Subtype TCC generated (at line 58, column 44) for  x
      % expected type  {r: real | abs(a) /= 0 OR r /= 0}
  hathat_abs_TCC1: OBLIGATION
    FORALL (a: posreal, x: real): abs(a) /= 0 OR x /= 0;

  % Subtype TCC generated (at line 60, column 49) for  (px + py)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_sum_posreal_TCC1: OBLIGATION
    FORALL (a, px, py: posreal): a /= 0 OR (px + py) /= 0;

  % Subtype TCC generated (at line 62, column 39) for  (a ^^ py)
      % expected type  nznum
  hathat_diff_posreal_TCC1: OBLIGATION
    FORALL (a, py: posreal): (a ^^ py) /= 0;

  % Subtype TCC generated (at line 62, column 50) for  (px - py)
      % expected type  {r: real | a /= 0 OR r /= 0}
  hathat_diff_posreal_TCC2: OBLIGATION
    FORALL (a, px, py: posreal): a /= 0 OR (px - py) /= 0;


body:
  convergence_special: THEORY
  %
  %  Special sequences that come up over and over
  %
  %  Taken from Salas/Hille  Calculus page 411
  %
  %  Author: Ricky W. Butler    NASA Langley   8/24/04
  %
  %  NOTE:  All of the machinery necessary to prove these is available
  %         in analysis and lnexp libraries
  %
  %  Nothing in the series library depends upon these UNPROVED lemmas
  %
  BEGIN

     IMPORTING expt, ints@factorial, 
               analysis@continuous_functions_more

     n: VAR nat

     x,c: VAR real

     px,pa: VAR posreal

  %   xlt1: VAR {x: real | abs(x) < 1}


     cn: VAR sequence[real]

     f: VAR [real -> real]


  %  --- note use of "n+1" rather than "n" to avoid div by zero ---

     conv_1_div_n        : LEMMA convergence(LAMBDA n: 1 / (n + 1), 0)

     conv_x_to_1_div_n   : LEMMA convergence(LAMBDA n: px^^(1/(n+1)),1)

     conv_x_to_n         : LEMMA abs(x) < 1 IMPLIES 
                                     convergence(LAMBDA n: x^n,0)

     expt_abs_gt         : LEMMA abs(x) ^ n >= x ^ n

     conv_x_to_n_div_fact: LEMMA convergence(LAMBDA n: x^n/factorial(n),0)

  %   conv_1_div_N_to_a   : LEMMA %% UNPROVED
  %                         convergence(LAMBDA n: 1/((n+1)^^pa),0) 

  %   conv_ln_div_n       : LEMMA convergence(LAMBDA n: ln(n+1)/(n+1), 0)

  %   conv_n_to_1_div_n   : LEMMA convergence(LAMBDA n: (n+1)^^(1/(n+1)),1)

  %   conv_n_to_a_div_exp : LEMMA convergence(LAMBDA n: n^^pa/exp(n), 0)

  %   conv_exp_spec       : LEMMA convergence(LAMBDA n: (1 + x/(n+1))^(n+1),exp(x))


  END convergence_special

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

  % Subtype TCC generated (at line 37, column 58) for  (1 / (n + 1))
      % expected type  {r: real | px /= 0 OR r /= 0}
  conv_x_to_1_div_n_TCC1: OBLIGATION
    FORALL (px: posreal, n): px /= 0 OR (1 / (n + 1)) /= 0;

  % Subtype TCC generated (at line 40, column 59) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  conv_x_to_n_TCC1: OBLIGATION
    FORALL (x: real): abs(x) < 1 IMPLIES (FORALL (n): x /= 0 OR n >= 0);

  % Subtype TCC generated (at line 42, column 40) for  n
      % expected type  {i: int | abs(x) /= 0 OR i >= 0}
  expt_abs_gt_TCC1: OBLIGATION
    FORALL (n: nat, x: real): abs(x) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 42, column 49) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  expt_abs_gt_TCC2: OBLIGATION FORALL (n: nat, x: real): x /= 0 OR n >= 0;


body:
  ln_series: THEORY
  %----------------------------------------------------------------------------
  %
  %  Series Expansion for Natural Logarithm Function
  %
  %  Author: Ricky W. Butler              NASA Langley Research Center
  %
  %          September 2012 by Anthony Narkawicz (Series is Increasing)
  %  Note.  See ln_exp_series_alt for an alternate formulation
  %----------------------------------------------------------------------------
  BEGIN
     IMPORTING  ln_exp,
                series@taylor_series, 
                convergence_special

     x,y: VAR real
     n,m: VAR nat
     a: VAR sequence[real]
     l,t: VAR real

     abslt1: TYPE = {x: real | abs(x) < 1}
     absle1: TYPE = {x: real | abs(x) <=1}

     noa_posreal: LEMMA not_one_element?[posreal]
     noa_gt_m1 : LEMMA not_one_element?[{x: real | x > -1}]
     conn_gt_m1: LEMMA connected?[{x: real | x > -1}]
     conn_posreal: LEMMA connected?[posreal]
     conn_abslt1: LEMMA connected?[abslt1]
     noa_abslt1: LEMMA not_one_element?[abslt1]
     deriv_domain_gtm1: LEMMA deriv_domain?[{x: real | x > -1}]

     AUTO_REWRITE+ noa_gt_m1 
     AUTO_REWRITE+ conn_gt_m1
     AUTO_REWRITE+ noa_posreal
     AUTO_REWRITE+ deriv_domain_posreal
     AUTO_REWRITE+ conn_posreal
     AUTO_REWRITE+ deriv_domain_gtm1
     AUTO_REWRITE+ conn_abslt1
     AUTO_REWRITE+ noa_abslt1

     nderiv_ln  : LEMMA derivable_n_times?[posreal](ln, n)

     ln_nderiv  : LEMMA nderiv[posreal](n,ln) = IF n = 0 THEN ln ELSE 
                          (LAMBDA (x:posreal): -factorial(n-1)/(-x)^n) ENDIF

     IMPORTING series@taylor_series[abslt1] 

     Gt_m1: TYPE = {x:real | x > -1}
     xgm1:  VAR Gt_m1

     ln_estimate(x:real,n:nat):real = 
           sigma(0,n,(LAMBDA (nn:nat): IF nn=0 THEN 0 ELSE -(-x)^nn/nn ENDIF))

     ln_taylors:     LEMMA EXISTS (c: between[{x:real | x > -1}](1,1+xgm1)):
                       ln(xgm1+1) = ln_estimate(xgm1,n) -(xgm1/-c)^(n+1)/(n+1)

     ln_estimate_error_bound: LEMMA FORALL (xp:posreal):
       abs(ln(xp+1)-ln_estimate(xp,n)) <= xp ^ (n + 1) / (n + 1)

  %   --- Series for log(1+x) follows from term-by-term integration
  %   --- of 1/(1+x) = 1 - x + x^2 - x^3.  Using term-by-term
  %   --- in power_series_integ, we can use proof in Rosenlicht
  %   --- page 155 or Salas-Hille pg 466 to get log(1+x) series for abs(x) < 1
  %   --- Also use corollary 3 on pg 128 of Rosenlicht to establish that
  %   --- ln(1+x) = integral(1,1+x,1/t) = integral(0,x,1/(1+t))
  %

     IMPORTING analysis@integral_chg_var,
               reals@abs_lems,
               analysis@integral_diff_doms

     x1: VAR abslt1

     lnp1: LEMMA ln(1+x1) = Integral(1,1+x1,(LAMBDA (t: posreal): 1/t)) 

     ln_estimate_increasing_odd: LEMMA FORALL (px,py:real):
       px<=py IMPLIES ln_estimate(px,2*n+1)<=ln_estimate(py,2*n+1)

     ln_estimate_increasing_even: LEMMA FORALL (x1,y1:absle1):
       x1<=y1 IMPLIES ln_estimate(x1,2*n)<=ln_estimate(y1,2*n)

     lnp1_prep: LEMMA  Integrable?(0,x1,(LAMBDA (u: Gt_m1): 1/(u+1))) AND
                         Integral(1,1+x1,(LAMBDA (t: posreal): 1/t)) = 
                         Integral(0,x1,(LAMBDA (u: Gt_m1): 1/(u+1)))

      geom_neg: LEMMA abs(x) < 1 IMPLIES 
                                 convergent?(series(LAMBDA n: (-x) ^ n))  AND
                                 1/(1+x) = inf_sum((LAMBDA n: (-x)^n))

      lnp1(x: abslt1): real = ln(1+x)

      lnp1_seq(n): real = IF n = 0 THEN 0 ELSE (-1)^(n+1)/n ENDIF

      IMPORTING series@power_series_integ

      lnp1_conv: LEMMA conv_powerseries?[abslt1](lnp1_seq)

      int_geo_prep: LEMMA Integrable?(0,x1,(LAMBDA (u: abslt1): 1 / (1 + u)))

  %   ----- ln(1 + x) = x - x^2/2 + x^3/3 - x^4/4 + .... if |x| < 1 -----

      int_geo_neg: LEMMA conv_powerseries?[abslt1](lnp1_seq) AND
                         Integral(0,x1,(LAMBDA (u: {x:real | x > -1}): 1/(u+1))) 
                            = Inf_sum(lnp1_seq)(x1)  % inf Sum - (-1)^n/n x^n


  END ln_series

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

  % Assuming TCC generated (at line 22, column 3) for
      % analysis@nth_derivatives[posreal]
      % generated from assumption nth_derivatives.deriv_domain
  nderiv_ln_TCC1: OBLIGATION deriv_domain?[posreal];

  % Assuming TCC generated (at line 24, column 3) for
      % analysis@nth_derivatives[posreal]
      % generated from assumption nth_derivatives.not_one_element
  nderiv_ln_TCC2: OBLIGATION not_one_element?[posreal];

  % Subtype TCC generated (at line 43, column 40) for  ln
      % expected type  nderiv_fun[posreal](n)
  ln_nderiv_TCC1: OBLIGATION
    FORALL (n: nat): derivable_n_times?[posreal](ln, n);

  % Subtype TCC generated (at line 44, column 56) for  n - 1
      % expected type  nat
  ln_nderiv_TCC2: OBLIGATION FORALL (n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Subtype TCC generated (at line 44, column 66) for  n
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  ln_nderiv_TCC3: OBLIGATION
    FORALL (n: nat):
      NOT n = 0 IMPLIES (FORALL (x: posreal): (-x) /= 0 OR n >= 0);

  % Assuming TCC generated (at line 46, column 13) for
      % series@taylor_series[abslt1]
      % generated from assumption taylor_series.connected_domain
  IMP_taylor_series_TCC1: OBLIGATION connected?[abslt1];

  % Assuming TCC generated (at line 46, column 13) for
      % series@taylor_series[abslt1]
      % generated from assumption taylor_series.not_one_element
  IMP_taylor_series_TCC2: OBLIGATION not_one_element?[abslt1];

  % Assuming TCC generated (at line 46, column 13) for
      % series@taylor_series[abslt1]
      % generated from assumption taylor_series.open
  IMP_taylor_series_TCC3: OBLIGATION
    FORALL (x: abslt1):
      EXISTS (delta: posreal):
        FORALL (y: real): abs(x - y) < delta IMPLIES abs(y) < 1;

  % Assuming TCC generated (at line 46, column 13) for
      % series@taylor_series[abslt1]
      % generated from assumption taylor_series.ball
  IMP_taylor_series_TCC4: OBLIGATION
    FORALL (x: abslt1): abs(x) < 1 IMPLIES abs(-x) < 1;

  % Existence TCC generated (at line 46, column 13) for
      % series@taylor_series[abslt1]
  IMP_taylor_series_TCC5: OBLIGATION EXISTS (x: abslt1): TRUE;

  % Subtype TCC generated (at line 52, column 15) for  0
      % expected type  T_low[nat]
  ln_estimate_TCC1: OBLIGATION 0 >= 0 OR (EXISTS (j: nat): j <= 0);

  % Subtype TCC generated (at line 52, column 17) for  n
      % expected type  T_high[nat]
  ln_estimate_TCC2: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 52, column 63) for  nn
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  ln_estimate_TCC3: OBLIGATION
    FORALL (x: real, nn: nat): NOT nn = 0 IMPLIES (-x) /= 0 OR nn >= 0;

  % Subtype TCC generated (at line 52, column 66) for  nn
      % expected type  nznum
  ln_estimate_TCC4: OBLIGATION FORALL (nn: nat): NOT nn = 0 IMPLIES nn /= 0;

  % Assuming TCC generated (at line 19, column 5) for
      % analysis@taylors[{x: real | x > -1}]
      % generated from assumption taylors.connected_domain
  ln_taylors_TCC1: OBLIGATION connected?[{x: real | x > -1}];

  % Assuming TCC generated (at line 21, column 5) for
      % analysis@taylors[{x: real | x > -1}]
      % generated from assumption taylors.not_one_element
  ln_taylors_TCC2: OBLIGATION not_one_element?[{x: real | x > -1}];

  % Subtype TCC generated (at line 55, column 24) for  xgm1 + 1
      % expected type  posreal
  ln_taylors_TCC3: OBLIGATION
    FORALL (xgm1: Gt_m1, c: between[{x: real | x > -1}](1, 1 + xgm1)):
      xgm1 + 1 >= 0 AND xgm1 + 1 > 0;

  % Subtype TCC generated (at line 55, column 61) for  -c
      % expected type  nznum
  ln_taylors_TCC4: OBLIGATION
    FORALL (xgm1: Gt_m1, c: between[{x: real | x > -1}](1, 1 + xgm1)):
      -c /= 0;

  % Subtype TCC generated (at line 55, column 66) for  (n + 1)
      % expected type  {i: int | (xgm1 / -c) /= 0 OR i >= 0}
  ln_taylors_TCC5: OBLIGATION
    FORALL (n: nat, xgm1: Gt_m1,
            c: between[{x: real | x > -1}](1, 1 + xgm1)):
      (xgm1 / -c) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 58, column 46) for  (n + 1)
      % expected type  {i: int | xp /= 0 OR i >= 0}
  ln_estimate_error_bound_TCC1: OBLIGATION
    FORALL (n: nat, xp: posreal): xp /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 74, column 18) for  1 + x1
      % expected type  posreal
  lnp1_TCC1: OBLIGATION FORALL (x1: abslt1): 1 + x1 >= 0 AND 1 + x1 > 0;

  % Subtype TCC generated (at line 74, column 43) for
      % (LAMBDA (t: posreal): 1 / t)
      % expected type  Integrable_funs[posreal](1, 1 + x1)
  lnp1_TCC2: OBLIGATION
    FORALL (x1: abslt1):
      Integrable?[posreal](1, 1 + x1, (LAMBDA (t: posreal): 1 / t));

  % Assuming TCC generated (at line 26, column 13) for
      % analysis@integral_def[posreal]
      % generated from assumption integral_def.connected_domain
  lnp1_TCC3: OBLIGATION connected?[posreal];

  % Subtype TCC generated (at line 82, column 35) for  x1
      % expected type  Gt_m1
  lnp1_prep_TCC1: OBLIGATION FORALL (x1: abslt1): x1 > -1;

  % Subtype TCC generated (at line 82, column 61) for  (u + 1)
      % expected type  nznum
  lnp1_prep_TCC2: OBLIGATION FORALL (u: Gt_m1): (u + 1) /= 0;

  % Subtype TCC generated (at line 87, column 67) for  n
      % expected type  {i: int | (-x) /= 0 OR i >= 0}
  geom_neg_TCC1: OBLIGATION
    FORALL (x: real): abs(x) < 1 IMPLIES (FORALL (n): (-x) /= 0 OR n >= 0);

  % Subtype TCC generated (at line 88, column 34) for  (1 + x)
      % expected type  nznum
  geom_neg_TCC2: OBLIGATION
    FORALL (x: real):
      abs(x) < 1 AND convergent?(series(LAMBDA n: (-x) ^ n)) IMPLIES
       (1 + x) /= 0;

  % Subtype TCC generated (at line 88, column 50) for  (LAMBDA n: (-x) ^ n)
      % expected type  (conv_series?)
  geom_neg_TCC3: OBLIGATION
    FORALL (x: real):
      abs(x) < 1 AND convergent?(series(LAMBDA n: (-x) ^ n)) IMPLIES
       conv_series?(LAMBDA n: (-x) ^ n);

  % Subtype TCC generated (at line 98, column 36) for  0
      % expected type  abslt1
  int_geo_prep_TCC1: OBLIGATION abs(0) < 1;

  % Subtype TCC generated (at line 98, column 67) for  (1 + u)
      % expected type  nznum
  int_geo_prep_TCC2: OBLIGATION FORALL (u: abslt1): (1 + u) /= 0;

  % Subtype TCC generated (at line 103, column 38) for
      % (LAMBDA (u: {x: real | x > -1}): 1 / (u + 1))
      % expected type  Integrable_funs[{x: real | x > -1}](0, x1)
  int_geo_neg_TCC1: OBLIGATION
    FORALL (x1: abslt1):
      conv_powerseries?[abslt1](lnp1_seq) IMPLIES
       Integrable?[{x: real | x > -1}]
           (0, x1, (LAMBDA (u: {x: real | x > -1}): 1 / (u + 1)));


body:
  ln_approx: THEORY
  %-----------------------------------------------------------------------------
  %      ln_approx by David Lester  Manchester Univ
  %                    Cesar Munoz  NASA
  %	       Anthony Narkawicz  NASA
  %      ---------
  %      Defines upper and lower bounds on ln:
  %           - ln_lb(a,n) <= ln(a) <= ln_ub(a,n)
  %-----------------------------------------------------------------------------

  BEGIN

    IMPORTING ln_series,reals@log_nat

    n:    VAR nat
    x:    VAR real
    px:   VAR posreal
    pn:   VAR posnat
    xgt1,ygt1: VAR {x:posreal | x > 1}

    ln_le2_lb(n,x): real = if x = 0 then 0 else ln_estimate(x,2*n)   endif
    ln_le2_ub(n,x): real = if x = 0 then 0 else ln_estimate(x,2*n+1) endif

    ln_le2_bounds: LEMMA 0 < x AND x <= 1 IMPLIES
         (ln_le2_lb(n,x) < ln(x+1) AND ln(x+1) < ln_le2_ub(n,x))

    ln2_lb(n): MACRO real = ln_le2_lb(n,1)
    ln2_ub(n): MACRO real = ln_le2_ub(n,1)

    ln_gt1_lb(n,xgt1): real = 
      let (m,y) = log_nat(xgt1,2) in
        m*ln2_lb(n)+ln_le2_lb(n,y-1) 

    ln_gt1_ub(n,xgt1): real = 
      let (m,y) = log_nat(xgt1,2) in
         m*ln2_ub(n)+ln_le2_ub(n,y-1)

    ln_gt1_ub_increasing: LEMMA
      xgt1<=ygt1 IMPLIES
      ln_gt1_ub(n,xgt1)<=ln_gt1_ub(n,ygt1)

    ln_gt1_lb_increasing: LEMMA
      xgt1<=ygt1 IMPLIES
      ln_gt1_lb(n,xgt1)<=ln_gt1_lb(n,ygt1)

    ln_gt1_bounds: LEMMA 1 < x IMPLIES
         (ln_gt1_lb(n,x) < ln(x) AND ln(x) < ln_gt1_ub(n,x))

    ln_lb(px,n): real = IF    px < 1 THEN -ln_gt1_ub(n,1/px)
                        ELSIF px = 1 THEN 0
                                     ELSE ln_gt1_lb(n,px)    ENDIF

    ln_ub(px,n): real = IF    px < 1 THEN -ln_gt1_lb(n,1/px)
                        ELSIF px = 1 THEN 0
                                     ELSE ln_gt1_ub(n,px)    ENDIF

    ln_lb_increasing: LEMMA FORALL (px,py:posreal): 
      px <= py IMPLIES ln_lb(px,n) <= ln_lb(py,n)

    ln_ub_increasing: LEMMA FORALL (px,py:posreal): 
      px <= py IMPLIES ln_ub(px,n) <= ln_ub(py,n)

    ln_bounds: LEMMA ln_lb(px,n) <= ln(px) AND ln(px) <= ln_ub(px,n)

    %%% Relationship of floor(ln(px)/ln(py)) to log_nat

    floor_eq_log_nat_ge_1: LEMMA
      FORALL ((xp:real|xp>=1),(np:posnat|np>1)):
      floor(ln(xp)/ln(np)) = log_nat(xp,np)`1

  END ln_approx

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

  % Subtype TCC generated (at line 25, column 28) for  x + 1
      % expected type  posreal
  ln_le2_bounds_TCC1: OBLIGATION
    FORALL (x: real): x <= 1 AND 0 < x IMPLIES x + 1 >= 0 AND x + 1 > 0;

  % Subtype TCC generated (at line 31, column 24) for  xgt1
      % expected type  {x: real | x >= 1}
  ln_gt1_lb_TCC1: OBLIGATION FORALL (xgt1: {x: posreal | x > 1}): xgt1 >= 1;

  % Subtype TCC generated (at line 47, column 20) for  x
      % expected type  {x: posreal | x > 1}
  ln_gt1_bounds_TCC1: OBLIGATION
    FORALL (x: real): 1 < x IMPLIES x >= 0 AND x > 0 AND x > 1;

  % Subtype TCC generated (at line 47, column 28) for  x
      % expected type  posreal
  ln_gt1_bounds_TCC2: OBLIGATION
    FORALL (x: real): 1 < x IMPLIES x >= 0 AND x > 0;

  % Subtype TCC generated (at line 49, column 53) for  1 / px
      % expected type  {x: posreal | x > 1}
  ln_lb_TCC1: OBLIGATION FORALL (px: posreal): px < 1 IMPLIES 1 / px > 1;

  % Subtype TCC generated (at line 51, column 52) for  px
      % expected type  {x: posreal | x > 1}
  ln_lb_TCC2: OBLIGATION
    FORALL (px: posreal): NOT px = 1 AND NOT px < 1 IMPLIES px > 1;

  % Subtype TCC generated (at line 69, column 13) for  xp
      % expected type  posreal
  floor_eq_log_nat_ge_1_TCC1: OBLIGATION
    FORALL ((xp: real | xp >= 1), (np: posnat | np > 1)): xp >= 0 AND xp > 0;

  % Subtype TCC generated (at line 69, column 17) for  ln(np)
      % expected type  nznum
  floor_eq_log_nat_ge_1_TCC2: OBLIGATION
    FORALL ((xp: real | xp >= 1), (np: posnat | np > 1)): ln(np) /= 0;


body:
  exp_series: THEORY
  %----------------------------------------------------------------------------
  %
  %  Series expansion for Exponential Function
  %
  %  Author: Ricky W. Butler              NASA Langley Research Center
  %
  %  Note.  See ln_exp_series_alt for an alternate formulation
  %----------------------------------------------------------------------------
  BEGIN
     IMPORTING  ln_exp,
                series@taylor_series[real], ints@factorial,
                convergence_special,
  	      reals@polynomials

     x,y: VAR real
     n,m: VAR nat
     a: VAR sequence[real]
     l,t: VAR real

     AUTO_REWRITE+ sigma_0_neg


     exp_seq(n): real = 1/factorial(n)

     nderiv_exp: LEMMA derivable_n_times?(exp, n)
                       AND nderiv(n, exp) = exp

     exp_inf_deriv: LEMMA inf_deriv_fun?[real](exp)

     exp_series_prep: LEMMA 
                       convergence(LAMBDA n: Taylor_rem(n,exp,0,x,
                                             GET_C(exp,x,n)),0)

     conv_exp: LEMMA conv_powerseries?[real](exp_seq)

     exp_series: THEOREM exp = Inf_sum(exp_seq)  % lim n->inf  Sum  x^n/n!

     exp_estimate(x:real,n:nat):real = 
                  1 + sigma(1,n,(LAMBDA (nn:nat): x^nn/factorial(nn)))

     exp_taylors: LEMMA EXISTS (c: between[real](0,x)):
                             exp(x) = exp_estimate(x,n)
                                          + exp(c)*x^(n+1)/factorial(n+1)

     exp_taylors_err: LEMMA abs(exp(x)-exp_estimate(x,n)) 
                                  <= max(exp(x),1)*abs(x)^(n+1)/factorial(n+1) 

     exp_estimate_increasing: LEMMA
       -1 <= x AND x<=y IMPLIES
       exp_estimate(x,n) <= exp_estimate(y,n)

     exp_estimate_positive: LEMMA
       n>=2 AND -1 <= x IMPLIES
       exp_estimate(x,n)>0

     exp_estimate_0: LEMMA
       exp_estimate(0,n) = 1


  END exp_series

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

  % Assuming TCC generated (at line 12, column 14) for
      % series@taylor_series[real]
      % generated from assumption taylor_series.connected_domain
  IMP_taylor_series_TCC1: OBLIGATION connected?[real];

  % Assuming TCC generated (at line 12, column 14) for
      % series@taylor_series[real]
      % generated from assumption taylor_series.not_one_element
  IMP_taylor_series_TCC2: OBLIGATION not_one_element?[real];

  % Assuming TCC generated (at line 12, column 14) for
      % series@taylor_series[real]
      % generated from assumption taylor_series.open
  IMP_taylor_series_TCC3: OBLIGATION
    FORALL (x: real): EXISTS (delta: posreal): FORALL (y: real): TRUE;

  % Assuming TCC generated (at line 12, column 14) for
      % series@taylor_series[real]
      % generated from assumption taylor_series.ball
  IMP_taylor_series_TCC4: OBLIGATION FORALL (x: real): TRUE;

  % Assuming TCC generated (at line 27, column 26) for
      % analysis@nth_derivatives[real]
      % generated from assumption nth_derivatives.deriv_domain
  nderiv_exp_TCC1: OBLIGATION deriv_domain?[real];

  % Subtype TCC generated (at line 32, column 56) for  exp
      % expected type  nderiv_fun[real](1 + n)
  exp_series_prep_TCC1: OBLIGATION
    FORALL (n): derivable_n_times?[real](exp, 1 + n);

  % Subtype TCC generated (at line 33, column 49) for  exp
      % expected type  (inf_deriv_fun?[real])
  exp_series_prep_TCC2: OBLIGATION inf_deriv_fun?[real](exp);

  % Subtype TCC generated (at line 37, column 37) for  exp_seq
      % expected type  (conv_powerseries?)
  exp_series_TCC1: OBLIGATION conv_powerseries?[real](exp_seq);

  % Subtype TCC generated (at line 40, column 26) for  1
      % expected type  T_low[nat]
  exp_estimate_TCC1: OBLIGATION 1 >= 0 OR (EXISTS (j: nat): j <= 1);

  % Subtype TCC generated (at line 40, column 28) for  n
      % expected type  T_high[nat]
  exp_estimate_TCC2: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 40, column 50) for  nn
      % expected type  {i: int | x /= 0 OR i >= 0}
  exp_estimate_TCC3: OBLIGATION FORALL (x: real, nn: nat): x /= 0 OR nn >= 0;

  % Subtype TCC generated (at line 44, column 52) for  (n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  exp_taylors_TCC1: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)): x /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 47, column 57) for  (n + 1)
      % expected type  {i: int | abs(x) /= 0 OR i >= 0}
  exp_taylors_err_TCC1: OBLIGATION
    FORALL (n: nat, x: real): abs(x) /= 0 OR (n + 1) >= 0;


body:
  exp_approx: THEORY
  %-----------------------------------------------------------------------------
  %   Approximation of Exponential Function
  %   -------------------------------------
  %
  %      Defines upper and lower bounds on exp:
  %           - exp_lb(a,n) <= exp(a) <= exp_ub(a,n)
  %           - e_lb(n)     <= e      <= e_ub(n)
  %
  %  Author: David Lester             Manchester University
  %-----------------------------------------------------------------------------

    BEGIN

    IMPORTING exp_series
    IMPORTING reals@quad_minmax % For proof only

    n:   VAR nat
    pn:  VAR posnat
    x:   VAR real
    nx:  VAR negreal
    nnx: VAR nnreal

    exp_neg_le1_ub(n,x): real = exp_estimate(x,2*n)

    % old exp_neg_le1_lb1(n,x): real = exp_estimate(x,2*n+1)

    exp_neg_le1_lb(n,x): real = exp_estimate(x,2*n) - 1.000001/factorial(2*n+1)

    exp_neg_le1_bounds: LEMMA -1 <= x AND x < 0 IMPLIES
      (exp_neg_le1_lb(n,x) < exp(x) AND exp(x) < exp_neg_le1_ub(n,x))

    exp_neg_le1_ub_strict_decreasing_n: LEMMA -1 <= x AND x < 0 IMPLIES
        strict_decreasing?(LAMBDA (n:nat): exp_neg_le1_ub(n,x))

    % exp_neg_le1_lb_strict_increasing_n: LEMMA -1 <= x AND x < 0 IMPLIES
    %     strict_increasing?(LAMBDA (n:nat): exp_neg_le1_lb(n,x))

    exp_neg_le1_lb_pos: LEMMA -1 <= x AND x < 0 IMPLIES exp_neg_le1_lb(pn,x) > 0

    exp_neg_ub(n,nx):posreal = LET pn= -floor(nx) IN exp_neg_le1_ub(n+1,nx/pn)^pn

    exp_neg_lb(n,nx):posreal = LET pn= -floor(nx) IN exp_neg_le1_lb(n+1,nx/pn)^pn

    exp_neg_bounds: LEMMA exp_neg_lb(n,nx) < exp(nx) & exp(nx) < exp_neg_ub(n,nx)

    exp_approx_int_cutoff: MACRO posnat = 60
    exp_approx_term_cutoff: MACRO posnat = 30

    exp_ub_n(x,n): posreal = IF    x < 0 AND x>=-exp_approx_int_cutoff
    	       	       	       	       THEN exp_neg_ub(n,x)
  		         ELSIF x<0     THEN exp_neg_ub(n,-exp_approx_int_cutoff)
                           ELSIF x = 0   THEN 1 
  			 ELSIF x<=exp_approx_int_cutoff
  				       THEN 1/exp_neg_lb(n,-x)
  				       ELSE max(1/exp_neg_lb(n,-exp_approx_int_cutoff),4^(floor(x)+1)) ENDIF

    exp_lb_n(x,n): posreal = IF    x < 0 AND x>=-exp_approx_int_cutoff
    	       	       	       	       THEN exp_neg_lb(n,x)
  			 ELSIF x < 0   THEN min(exp_neg_lb(n,-exp_approx_int_cutoff),4^floor(x))
                           ELSIF x = 0   THEN 1
  			 ELSIF x<=exp_approx_int_cutoff
  				       THEN 1/exp_neg_ub(n,-x)
  			 	       ELSE max(1/exp_neg_ub(n,-exp_approx_int_cutoff),2^floor(x)) ENDIF

    exp_ub(x,n): posreal = IF n <= exp_approx_term_cutoff THEN exp_ub_n(x,n)
    	       	         ELSE exp_ub_n(x,exp_approx_term_cutoff) ENDIF

    exp_lb(x,n): posreal = IF n <= exp_approx_term_cutoff THEN exp_lb_n(x,n)
    	       	         ELSE exp_lb_n(x,exp_approx_term_cutoff) ENDIF

    exp_bounds: LEMMA exp_lb(x,n) <= exp(x) AND exp(x) <= exp_ub(x,n)

    exp_range_test: LEMMA FORALL (kk:subrange(1,exp_approx_int_cutoff)):
      FORALL (nn:subrange(1,exp_approx_term_cutoff+1)):
      exp_estimate(-kk/(kk+1),2*nn)^(kk+1) <= exp_estimate(-1,2*nn)^kk

    exp_range_test_lb: LEMMA FORALL (kk:subrange(1,exp_approx_int_cutoff)):
      FORALL (nn:subrange(1,exp_approx_term_cutoff+1)):
      (exp_estimate(-kk/(kk+1),2*nn)- 1.000001/factorial(2*nn+1))^(kk+1) <= (exp_estimate(-1,2*nn)- 1.000001/factorial(2*nn+1))^kk

    exp_neg_ub_increasing: LEMMA
      LET TT = (LAMBDA (xr:negreal): xr >= - exp_approx_int_cutoff)
      IN n<=exp_approx_term_cutoff IMPLIES increasing?(LAMBDA (xr:(TT)): exp_neg_ub(n, xr))

    exp_neg_lb_increasing: LEMMA
      LET TT = (LAMBDA (xr:negreal): xr >= - exp_approx_int_cutoff)
      IN n<=exp_approx_term_cutoff IMPLIES increasing?(LAMBDA (xr:(TT)): exp_neg_lb(n, xr))

    test: LEMMA
      FORALL (ii:below(1000)):
        LET xx = -30*((ii+1)/(1000)), yy = xx + 1/1000000 IN
          exp_neg_lb(1,xx) <= exp_neg_lb(1,yy)

    exp_ub_increasing: LEMMA
      increasing?(LAMBDA (x:real): exp_ub(x,n))

    exp_lb_increasing: LEMMA
      increasing?(LAMBDA (x:real): exp_lb(x,n))

    e_lb(n) : posreal = exp_lb(1,n)

    e_ub(n) : posreal = exp_ub(1,n)

    e_bounds: LEMMA e_lb(n) <= e & e <= e_ub(n)

    e_LB : MACRO posreal = 2718281828/1000000000

    e_UB : MACRO posreal = 2718281829/1000000000

    e_bounds2: LEMMA e_LB < e & e < e_UB

    e_lb    : posreal = 271/100

    e_ub    : posreal = 272/100

    e_bound : JUDGEMENT e HAS_TYPE {x:posreal| e_lb < e AND e < e_ub}

    END exp_approx

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

  % Subtype TCC generated (at line 41, column 73) for  pn
      % expected type  nznum
  exp_neg_ub_TCC1: OBLIGATION
    FORALL (nx: negreal, pn: int): pn = -floor(nx) IMPLIES pn /= 0;

  % Subtype TCC generated (at line 41, column 77) for  pn
      % expected type  {i: int |
                     %          NOT exp_neg_le1_ub(1 + n, nx / pn) = 0 OR
                     %           i >= 0}
  exp_neg_ub_TCC2: OBLIGATION
    FORALL (n: nat, nx: negreal, pn: int):
      pn = -floor(nx) IMPLIES
       NOT exp_neg_le1_ub(1 + n, nx / pn) = 0 OR pn >= 0;

  % Subtype TCC generated (at line 41, column 51) for
      % exp_neg_le1_ub(n + 1, nx / pn) ^ pn
      % expected type  posreal
  exp_neg_ub_TCC3: OBLIGATION
    FORALL (n: nat, nx: negreal, pn: int):
      pn = -floor(nx) IMPLIES
       exp_neg_le1_ub(n + 1, nx / pn) ^ pn >= 0 AND
        exp_neg_le1_ub(n + 1, nx / pn) ^ pn > 0;

  % Subtype TCC generated (at line 43, column 77) for  pn
      % expected type  {i: int |
                     %          NOT exp_neg_le1_lb(1 + n, nx / pn) = 0 OR
                     %           i >= 0}
  exp_neg_lb_TCC1: OBLIGATION
    FORALL (n: nat, nx: negreal, pn: int):
      pn = -floor(nx) IMPLIES
       NOT exp_neg_le1_lb(1 + n, nx / pn) = 0 OR pn >= 0;

  % Subtype TCC generated (at line 43, column 51) for
      % exp_neg_le1_lb(n + 1, nx / pn) ^ pn
      % expected type  posreal
  exp_neg_lb_TCC2: OBLIGATION
    FORALL (n: nat, nx: negreal, pn: int):
      pn = -floor(nx) IMPLIES
       exp_neg_le1_lb(n + 1, nx / pn) ^ pn >= 0 AND
        exp_neg_le1_lb(n + 1, nx / pn) ^ pn > 0;

  % Subtype TCC generated (at line 51, column 52) for  x
      % expected type  negreal
  exp_ub_n_TCC1: OBLIGATION
    FORALL (x: real): x < 0 AND x >= -60 IMPLIES x <= 0;

  % Subtype TCC generated (at line 55, column 31) for  -x
      % expected type  negreal
  exp_ub_n_TCC2: OBLIGATION
    FORALL (x: real):
      x <= 60 AND NOT x = 0 AND NOT x < 0 AND NOT (x < 0 AND x >= -60)
       IMPLIES -x <= 0 AND -x < 0;

  % Subtype TCC generated (at line 76, column 35) for  (kk + 1)
      % expected type  {i: int |
                     %          NOT exp_estimate(-kk / (1 + kk), 2 * nn) = 0
                     %           OR i >= 0}
  exp_range_test_TCC1: OBLIGATION
    FORALL (kk: subrange(1, 60), nn: subrange(1, 30 + 1)):
      NOT exp_estimate(-kk / (1 + kk), 2 * nn) = 0 OR (kk + 1) >= 0;

  % Subtype TCC generated (at line 76, column 66) for  kk
      % expected type  {i: int | exp_estimate(-1, 2 * nn) /= 0 OR i >= 0}
  exp_range_test_TCC2: OBLIGATION
    FORALL (kk: subrange(1, 60), nn: subrange(1, 30 + 1)):
      exp_estimate(-1, 2 * nn) /= 0 OR kk >= 0;

  % Subtype TCC generated (at line 80, column 65) for  (kk + 1)
      % expected type  {i: int |
                     %          NOT (exp_estimate(-kk / (1 + kk), 2 * nn) -
                     %                1000001/1000000
                     %                /
                     %                factorial(1 + 2 * nn))
                     %               = 0
                     %           OR i >= 0}
  exp_range_test_lb_TCC1: OBLIGATION
    FORALL (kk: subrange(1, 60), nn: subrange(1, 30 + 1)):
      NOT (exp_estimate(-kk / (1 + kk), 2 * nn) -
            1000001/1000000 / factorial(1 + 2 * nn))
           = 0
       OR (kk + 1) >= 0;

  % Subtype TCC generated (at line 80, column 126) for  kk
      % expected type  {i: int |
                     %          NOT (exp_estimate(-1, 2 * nn) -
                     %                1000001/1000000
                     %                /
                     %                factorial(1 + 2 * nn))
                     %               = 0
                     %           OR i >= 0}
  exp_range_test_lb_TCC2: OBLIGATION
    FORALL (kk: subrange(1, 60), nn: subrange(1, 30 + 1)):
      NOT (exp_estimate(-1, 2 * nn) -
            1000001/1000000 / factorial(1 + 2 * nn))
           = 0
       OR kk >= 0;

  % Subtype TCC generated (at line 93, column 21) for  xx
      % expected type  negreal
  test_TCC1: OBLIGATION
    FORALL (ii: below(1000), xx: nzrat):
      xx = -30 * ((ii + 1) / (1000)) IMPLIES
       (FORALL (yy: rat): yy = xx + 1 / 1000000 IMPLIES xx <= 0 AND xx < 0);

  % Subtype TCC generated (at line 93, column 41) for  yy
      % expected type  negreal
  test_TCC2: OBLIGATION
    FORALL (ii: below(1000), xx: nzrat):
      xx = -30 * ((ii + 1) / (1000)) IMPLIES
       (FORALL (yy: rat): yy = xx + 1 / 1000000 IMPLIES yy <= 0 AND yy < 0);

  % Judgement subtype TCC generated (at line 117, column 22) for  e
      % expected type  {x: posreal | e_lb < e AND e < e_ub}
  e_bound: OBLIGATION e_lb < e AND e < e_ub;


body:
  hyperbolic: THEORY
  %------------------------------------------------------------------------
  %   Definition of Hyperbolic Trig Functions
  %
  %   Version 1.0    12/3/03 
  %   Version 1.1    8/25/04  
  %   Version 1.2    10/27/04        added exp_approx, ln_approx
  %
  %   Author:  David Lester
  %
  %   Formula labels are from Handbook of Mathematical Functions
  %                           by Abramowitz and Stegun
  %
  %------------------------------------------------------------------------
  BEGIN

    IMPORTING reals@sq, reals@sqrt,
  	    analysis@sqrt_derivative, analysis@restrict2_deriv, analysis@deriv_domains,
              analysis@nth_derivatives, analysis@taylors,
              analysis@polynomial_deriv,
              ln_exp,  %% RWB
              reals@binomial



    posreal_ge1:  NONEMPTY_TYPE = {x:real    | x >= 1         } CONTAINING 1
    posreal_gt1:  NONEMPTY_TYPE = {x:real    | x >  1         } CONTAINING 2
    posreal_le1:  NONEMPTY_TYPE = {x:posreal | x <= 1         } CONTAINING 1/2
    real_abs_lt1: NONEMPTY_TYPE = {x:real    | -1 < x &  x < 1} CONTAINING 0
    real_abs_gt1: NONEMPTY_TYPE = {x:real    | x < -1 OR 1 < x} CONTAINING 2


    noa_abs_lt1         : LEMMA not_one_element?[real_abs_lt1];
    noa_posreal_gt1     : LEMMA not_one_element?[posreal_gt1];
    conn_abs_lt1        : LEMMA connected?[real_abs_lt1];
    conn_real           : LEMMA connected?[real]
    deriv_domain_abs_lt1: LEMMA deriv_domain?[real_abs_lt1]
    deriv_domain_posreal_gt1: LEMMA deriv_domain?[posreal_gt1]

    AUTO_REWRITE+ noa_abs_lt1    
    AUTO_REWRITE+ noa_posreal_gt1
    AUTO_REWRITE+ conn_abs_lt1   
    AUTO_REWRITE+ conn_real
    AUTO_REWRITE+ deriv_domain_abs_lt1
    AUTO_REWRITE+ deriv_domain_posreal_gt1



    x,y:     VAR real
    pxle1:   VAR posreal_le1
    pxge1:   VAR posreal_ge1
    xalt1:   VAR real_abs_lt1
    n0x,n0y: VAR nzreal
    n,m:     VAR nat

  % A&S Section 4.5 Hyperbolic Functions

    sinh(x:  real)  :real         = (exp(x)-exp(-x))/2                   % 4.5.1
    cosh(x:  real)  :posreal_ge1  = (exp(x)+exp(-x))/2                   % 4.5.2
    tanh(x:  real)  :real_abs_lt1 = sinh(x)/cosh(x)                      % 4.5.3
    csch(n0x:nzreal):real         = 1/sinh(n0x)                          % 4.5.4
    sech(x  :real)  :posreal_le1  = 1/cosh(x)                            % 4.5.5
    coth(n0x:nzreal):real_abs_gt1 = 1/tanh(n0x)                          % 4.5.6

  % Restrictions for Branch Properties

    nnreal_cosh (nnx:nnreal):posreal_ge1  = cosh(nnx)
    posreal_csch(px:posreal):posreal      = csch(px)
    nnreal_sech (nnx:nnreal):posreal_le1  = sech(nnx)
    posreal_coth(px:posreal):posreal_gt1  = coth(px)

  % Monotonicity Properties

    sinh_strict_increasing: LEMMA strict_increasing?(sinh)  
    cosh_strict_increasing: LEMMA strict_increasing?(nnreal_cosh)
    tanh_strict_increasing: LEMMA strict_increasing?(tanh)
    csch_strict_decreasing: LEMMA strict_decreasing?(posreal_csch)
    sech_strict_decreasing: LEMMA strict_decreasing?(nnreal_sech)
    coth_strict_decreasing: LEMMA strict_decreasing?(posreal_coth)

  % Special Values of the Hyperbolic Functions

    sinh_0: LEMMA sinh(0) = 0                                            % 4.5.61
    cosh_0: LEMMA cosh(0) = 1                                            % 4.5.61
    tanh_0: LEMMA tanh(0) = 0                                            % 4.5.61
    sech_0: LEMMA sech(0) = 1                                            % 4.5.61

  % Relations between Hyperbolic Functions

    cosh_sinh_one:   LEMMA sq(cosh(x))   - sq(sinh(x))   = 1             % 4.5.16
    tanh_sech_one:   LEMMA sq(tanh(x))   + sq(sech(x))   = 1             % 4.5.17
    coth_csch_one:   LEMMA sq(coth(n0x)) - sq(csch(n0x)) = 1             % 4.5.18
    cosh_plus_sinh:  LEMMA cosh(x)       + sinh(x)       = exp(x)        % 4.5.19
    cosh_minus_sinh: LEMMA cosh(x)       - sinh(x)       = exp(-x)       % 4.5.20

  % Negative Angle FormulasMA FORALL (k:{i:nat| i<n}): C(n,k+1) = C(n,k)*((n-k)/(k+1))


    sinh_neg: LEMMA sinh(-x)   = -sinh(x)                                % 4.5.21
    cosh_neg: LEMMA cosh(-x)   = cosh(x)                                 % 4.5.22
    tanh_neg: LEMMA tanh(-x)   = -tanh(x)                                % 4.5.23
    csch_neg: LEMMA csch(-n0x) = -csch(n0x)
    sech_neg: LEMMA sech(-x)   = sech(x)
    coth_neg: LEMMA coth(-n0x) = -coth(n0x)

  % Addition Formulas

    sinh_sum:  LEMMA sinh(x+y) = sinh(x)*cosh(y) + cosh(x)*sinh(y)       % 4.5.24
    sinh_diff: LEMMA sinh(x-y) = sinh(x)*cosh(y) - cosh(x)*sinh(y)
    cosh_sum:  LEMMA cosh(x+y) = cosh(x)*cosh(y) + sinh(x)*sinh(y)       % 4.5.25
    cosh_diff: LEMMA cosh(x-y) = cosh(x)*cosh(y) - sinh(x)*sinh(y)
    tanh_sum:  LEMMA tanh(x+y) = (tanh(x)+tanh(y))/(1+tanh(x)*tanh(y))   % 4.5.26
    coth_sum:  LEMMA n0x+n0y /= 0 IMPLIES                                % 4.5.27
                     coth(n0x+n0y)
                               = (1+coth(n0x)*coth(n0y))/(coth(n0x)+coth(n0y))

  % Half-angle Formulas

    sinh_half:  LEMMA sinh(x/2) = LET y = sqrt((cosh(x)-1)/2) IN         % 4.5.28
                                  IF x >= 0 THEN y ELSE -y ENDIF
    cosh_half:  LEMMA cosh(x/2) = sqrt((cosh(x)+1)/2)                    % 4.5.29
    tanh_half1: LEMMA tanh(x/2) = LET y = sqrt((cosh(x)-1)/(cosh(x)+1))  % 4.5.30
                                  IN IF x >= 0 THEN y ELSE -y ENDIF
    tanh_half2: LEMMA tanh(n0x/2) = (cosh(n0x)-1)/sinh(n0x)              % 4.5.30
    tanh_half3: LEMMA tanh(x/2) = sinh(x)/(cosh(x)+1)                    % 4.5.30

  % Multiple-angle Formulas

    sinh2x:     LEMMA sinh(2*x) = 2*sinh(x)*cosh(x)                      % 4.5.31
    sinh2x_B:   LEMMA sinh(2*x) = 2*tanh(x)/(1-sq(tanh(x)))              % 4.5.31
    cosh2x:     LEMMA cosh(2*x) = 2*sq(cosh(x))-1                        % 4.5.32
    cosh2x_B:   LEMMA cosh(2*x) = 2*sq(sinh(x))+1                        % 4.5.32
    cosh2x_C:   LEMMA cosh(2*x) = sq(cosh(x)) + sq(sinh(x))              % 4.5.32
    tanh2x:     LEMMA tanh(2*x) = 2*tanh(x)/(1+sq(tanh(x)))              % 4.5.33
    sinh3x:     LEMMA sinh(3*x) = 3*sinh(x) + 4*sinh(x)^3                % 4.5.34
    cosh3x:     LEMMA cosh(3*x) = 4*cosh(x)^3-3*cosh(x)                  % 4.5.35
    sinh4x:     LEMMA sinh(4*x)                                          % 4.5.36
                                = 4*sinh(x)*cosh(x)*(sq(sinh(x)) + sq(cosh(x)))
    cosh4x:     LEMMA cosh(4*x)                                          % 4.5.37
                                = cosh(x)^4+6*sq(sinh(x)*cosh(x))+sinh(x)^4

  % Products

    sinh_times_sinh: LEMMA sinh(x)*sinh(y) = (cosh(x+y)-cosh(x-y))/2     % 4.5.38
    cosh_times_cosh: LEMMA cosh(x)*cosh(y) = (cosh(x+y)+cosh(x-y))/2     % 4.5.39
    sinh_times_cosh: LEMMA sinh(x)*cosh(y) = (sinh(x+y)+sinh(x-y))/2     % 4.5.40

  % Addition and Subtraction

    sum_sinh:   LEMMA sinh(x)+sinh(y) = 2*sinh((x+y)/2)*cosh((x-y)/2)    % 4.5.41
    diff_sinh:  LEMMA sinh(x)-sinh(y) = 2*cosh((x+y)/2)*sinh((x-y)/2)    % 4.5.42
    sum_cosh:   LEMMA cosh(x)+cosh(y) = 2*cosh((x+y)/2)*cosh((x-y)/2)    % 4.5.43
    diff_cosh:  LEMMA cosh(x)-cosh(y) = 2*sinh((x+y)/2)*sinh((x-y)/2)    % 4.5.44
    sum_tanh:   LEMMA tanh(x)+tanh(y) = sinh(x+y)/(cosh(x)*cosh(y))      % 4.5.45
    sum_coth:   LEMMA coth(n0x)+coth(n0y)                                % 4.5.46
                                      = sinh(n0x+n0y)/(sinh(n0x)*sinh(n0y))

  % Relations between squares of hyperbolic sines and cosines

    diff_sinh_sq: LEMMA sq(sinh(x))-sq(sinh(y)) = sinh(x+y)*sinh(x-y)    % 4.5.47
    diff_cosh_sq: LEMMA sq(cosh(x))-sq(cosh(y)) = sinh(x+y)*sinh(x-y)    % 4.5.47
    sum_cosh_sinh_sq: LEMMA sq(sinh(x))+sq(cosh(y))                      % 4.5.48
                                                = cosh(x+y)*cosh(x-y)

  % De Moivre's Theorem

    hyperbolic_deMoivre: LEMMA (cosh(x)+sinh(x))^n = cosh(n*x)+sinh(n*x) % 4.5.53

  % Derivatives

    sinh_derivable2:  LEMMA derivable?(sinh)
    cosh_derivable2:  LEMMA derivable?(cosh)

    tanh_derivable2:  LEMMA derivable?(tanh)

    deriv_sinh:       LEMMA deriv(sinh) = cosh                           % 4.5.71
    deriv_cosh:       LEMMA deriv(cosh) = sinh                           % 4.5.72
    deriv_tanh:       LEMMA deriv(tanh) = sech*sech                      % 4.5.73

  % Series expansions

    sinh_series_n(x:real,n:nat):real
      = sigma(0,n,LAMBDA (i:nat): x^(2*i+1)/factorial(2*i+1))

    sinh_taylors: LEMMA EXISTS (c: between[real](0,x)):                  % 4.5.62
               sinh(x) = sinh_series_n(x,n) + cosh(c)*x^(2*n+3)/factorial(2*n+3)







  % Logarithmic representations of inverse hyperbolics

    asinh(x:real):       real   = ln(x+sqrt(sq(x)+1))                    % 4.6.20
    acosh(x:posreal_ge1):nnreal = ln(x+sqrt(sq(x)-1))                    % 4.6.21
    atanh(x:real_abs_lt1):real  = ln((1+x)/(1-x))/2                      % 4.6.22
     
  % Bijection relations

    sinh_bij: LEMMA bijective?[real,real](sinh)
    cosh_bij: LEMMA bijective?[nnreal,posreal_ge1](nnreal_cosh)
    tanh_bij: LEMMA bijective?[real,real_abs_lt1](tanh)
    csch_bij: LEMMA bijective?[posreal,posreal](posreal_csch)
    sech_bij: LEMMA bijective?[nnreal,posreal_le1](nnreal_sech)
    coth_bij: LEMMA bijective?[posreal,posreal_gt1](posreal_coth)

    asinh_alt_def: LEMMA asinh(x) = inverse(sinh)(x)

    asinh_sinh:              LEMMA asinh(sinh(x)) = x
    sinh_asinh:              LEMMA sinh(asinh(x)) = x
    asinh_strict_increasing: LEMMA strict_increasing?(asinh)
    asinh_bij:               LEMMA bijective?[real,real](asinh)

  % Derivatives

    asinh_derivable2: LEMMA derivable?(asinh)
    acosh_derivable2: LEMMA
                       derivable?[posreal_gt1](LAMBDA (x:posreal_gt1): acosh(x))
    atanh_derivable2: LEMMA derivable?[real_abs_lt1](atanh)

    deriv_asinh:      LEMMA deriv(asinh)                 	              % 4.6.37
                                  =  (LAMBDA (x:real): 1/sqrt(1+sq(x)))
    deriv_acosh:      LEMMA                                              % 4.6.38
                deriv[posreal_gt1](LAMBDA (x:posreal_gt1): acosh(x))
                                  = (LAMBDA (x:posreal_gt1): 1/sqrt(sq(x)-1))
    deriv_atanh:      LEMMA deriv[real_abs_lt1](atanh)                   % 4.6.39
                                  =  (LAMBDA (x:real_abs_lt1): 1/(1-sq(x)))

  % Taylor Series for atanh

    z:  VAR real_abs_lt1
    pn: VAR posnat

    atanhF(n:nat)(i:nat):int
      = IF i > 2*n OR odd?(i) THEN 0 ELSE factorial(2*n)*C(2*n+1,i) ENDIF

    atanhD(n:nat)(x:real):real = (1-sq(x))^(2*n+1)

    atanhN(n:nat):[real->real] = polynomial(atanhF(n),2*n)

    atanh_taylors_prep1: LEMMA
      derivable_n_times?(atanhN(n),m) AND derivable_n_times?(atanhD(n),m)

    atanh_taylors_prep2: LEMMA
      deriv(atanhN(n))
        = IF n = 0 THEN const_fun(0)
                   ELSE polynomial(LAMBDA (i:nat): (i+1)*atanhF(n)(i+1),2*n-1)
          ENDIF

    atanh_taylors_prep3: LEMMA
      deriv(atanhD(n)) = (LAMBDA (z:real): -(4*n+2)*z*
                      IF n = 0 THEN 1 ELSE (1-sq(z))*atanhD(n-1)(z) ENDIF)

    atanh_taylors_prep4: LEMMA
      deriv(deriv(atanhN(n)))
        = IF n = 0 THEN const_fun(0)
                   ELSE polynomial(LAMBDA (i:nat): (i+2)*(i+1)*atanhF(n)(i+2),2*n-2)
          ENDIF

    atanh_taylors_prep5: LEMMA FORALL (f:[real_abs_lt1->real],
                                       g:[real_abs_lt1->nzreal]):
      derivable?[real_abs_lt1](f) AND derivable?[real_abs_lt1](g) IMPLIES
         derivable?[real_abs_lt1](f/g^pn) AND
         deriv[real_abs_lt1](f/g^pn)
            = (deriv[real_abs_lt1](f)*g-pn*f*deriv[real_abs_lt1](g))/(g^(pn+1))

    atanhND(n:nat):[real_abs_lt1->real]
        = (LAMBDA (x:real_abs_lt1): atanhN(n)(x)/atanhD(n)(x))

    atanh_taylors_prep6: LEMMA
      nderiv[real_abs_lt1](2,LAMBDA (x:real_abs_lt1): atanhN(n)(x)/atanhD(n)(x))
        = (LAMBDA (x:real_abs_lt1): atanhN(n+1)(x)/atanhD(n+1)(x))

    atanh_taylors_prep7: LEMMA
      derivable_n_times?[real_abs_lt1](atanhND(n),2*m)

    atanh_taylors_prep8: LEMMA nderiv[real_abs_lt1](2*m,atanhND(n))=atanhND(n+m)

    atanh_nderiv: LEMMA
      nderiv[real_abs_lt1](n,atanh)
        = IF    n = 0    THEN atanh
          ELSIF even?(n) THEN deriv[real_abs_lt1](atanhND(n/2-1))
                         ELSE atanhND((n-1)/2) ENDIF

    atanh_nderiv_0: LEMMA
      nderiv[real_abs_lt1](n,atanh)(0)
        = IF even?(n) THEN 0 ELSE factorial(n-1) ENDIF

    atanh_n_times_derivable: LEMMA derivable_n_times?[real_abs_lt1](atanh,n)

    atanh_series_term(z:real_abs_lt1):[nat->real]
        = (LAMBDA (n:nat): z^(2*n+1)/(2*n+1))
    atanh_series_n(z:real_abs_lt1,n:nat):real = sigma(0,n,atanh_series_term(z))

    atanh_series_eqv: LEMMA
     atanh_series_n(z,n) = sigma(0,2*n+2,
        LAMBDA (nn:nat): IF nn > 2*n+2 OR nn = 0 THEN 0 ELSE
                           nderiv[real_abs_lt1](nn,atanh)(0)*
                                                       z^nn/factorial(nn) ENDIF)

    atanh_taylors: LEMMA (EXISTS (c: between[real_abs_lt1](0,z)): 
                 atanh(z) = atanh_series_n(z,n) + 
                                   nderiv[real_abs_lt1](2*n+3,atanh)(c)*
                                                      z^(2*n+3)/factorial(2*n+3))

    atanh_series: LEMMA abs(atanh(z)-atanh_series_n(z,n)) <=
                     ((1+z)^(2*n+3)+(1-z)^(2*n+3))/(2*(2*n+3)*(1-sq(z))^(2*n+3))

  END hyperbolic

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

  % Subtype TCC generated (at line 59, column 34) for  (exp(x) + exp(-x)) / 2
      % expected type  posreal_ge1
  cosh_TCC1: OBLIGATION FORALL (x: real): (exp(x) + exp(-x)) / 2 >= 1;

  % Subtype TCC generated (at line 60, column 42) for  cosh(x)
      % expected type  nznum
  tanh_TCC1: OBLIGATION FORALL (x: real): cosh(x) /= 0;

  % Subtype TCC generated (at line 60, column 34) for  sinh(x) / cosh(x)
      % expected type  real_abs_lt1
  tanh_TCC2: OBLIGATION
    FORALL (x: real): -1 < sinh(x) / cosh(x) & sinh(x) / cosh(x) < 1;

  % Subtype TCC generated (at line 61, column 36) for  sinh(n0x)
      % expected type  nznum
  csch_TCC1: OBLIGATION FORALL (n0x: nzreal): sinh(n0x) /= 0;

  % Subtype TCC generated (at line 62, column 34) for  1 / cosh(x)
      % expected type  posreal_le1
  sech_TCC1: OBLIGATION
    FORALL (x: real):
      1 / cosh(x) >= 0 AND 1 / cosh(x) > 0 AND 1 / cosh(x) <= 1;

  % Subtype TCC generated (at line 63, column 36) for  tanh(n0x)
      % expected type  nznum
  coth_TCC1: OBLIGATION FORALL (n0x: nzreal): tanh(n0x) /= 0;

  % Subtype TCC generated (at line 63, column 34) for  1 / tanh(n0x)
      % expected type  real_abs_gt1
  coth_TCC2: OBLIGATION
    FORALL (n0x: nzreal): 1 / tanh(n0x) < -1 OR 1 < 1 / tanh(n0x);

  % Subtype TCC generated (at line 68, column 42) for  csch(px)
      % expected type  posreal
  posreal_csch_TCC1: OBLIGATION
    FORALL (px: posreal): csch(px) >= 0 AND csch(px) > 0;

  % Subtype TCC generated (at line 70, column 42) for  coth(px)
      % expected type  posreal_gt1
  posreal_coth_TCC1: OBLIGATION FORALL (px: posreal): coth(px) > 1;

  % Subtype TCC generated (at line 112, column 50) for
      % (1 + tanh(x) * tanh(y))
      % expected type  nznum
  tanh_sum_TCC1: OBLIGATION FORALL (x, y: real): (1 + tanh(x) * tanh(y)) /= 0;

  % Subtype TCC generated (at line 115, column 56) for
      % (coth(n0x) + coth(n0y))
      % expected type  nznum
  coth_sum_TCC1: OBLIGATION
    FORALL (n0x, n0y: nzreal):
      n0x + n0y /= 0 IMPLIES (coth(n0x) + coth(n0y)) /= 0;

  % Subtype TCC generated (at line 119, column 45) for  (cosh(x) - 1) / 2
      % expected type  nnx: nonneg_real
  sinh_half_TCC1: OBLIGATION FORALL (x: real): (cosh(x) - 1) / 2 >= 0;

  % Subtype TCC generated (at line 121, column 37) for  (cosh(x) + 1) / 2
      % expected type  nnx: nonneg_real
  cosh_half_TCC1: OBLIGATION FORALL (x: real): (cosh(x) + 1) / 2 >= 0;

  % Subtype TCC generated (at line 122, column 58) for  (cosh(x) + 1)
      % expected type  nznum
  tanh_half1_TCC1: OBLIGATION FORALL (x: real): (cosh(x) + 1) /= 0;

  % Subtype TCC generated (at line 122, column 45) for
      % (cosh(x) - 1) / (cosh(x) + 1)
      % expected type  nnx: nonneg_real
  tanh_half1_TCC2: OBLIGATION
    FORALL (x: real): (cosh(x) - 1) / (cosh(x) + 1) >= 0;

  % Subtype TCC generated (at line 130, column 43) for  (1 - sq(tanh(x)))
      % expected type  nznum
  sinh2x_B_TCC1: OBLIGATION FORALL (x: real): (1 - sq(tanh(x))) /= 0;

  % Subtype TCC generated (at line 135, column 54) for  3
      % expected type  {i: int | sinh(x) /= 0 OR i >= 0}
  sinh3x_TCC1: OBLIGATION FORALL (x: real): sinh(x) /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 140, column 72) for  4
      % expected type  {i: int | sinh(x) /= 0 OR i >= 0}
  cosh4x_TCC1: OBLIGATION FORALL (x: real): sinh(x) /= 0 OR 4 >= 0;

  % Subtype TCC generated (at line 154, column 49) for  (cosh(x) * cosh(y))
      % expected type  nznum
  sum_tanh_TCC1: OBLIGATION FORALL (x, y: real): (cosh(x) * cosh(y)) /= 0;

  % Subtype TCC generated (at line 156, column 53) for
      % (sinh(n0x) * sinh(n0y))
      % expected type  nznum
  sum_coth_TCC1: OBLIGATION
    FORALL (n0x, n0y: nzreal): (sinh(n0x) * sinh(n0y)) /= 0;

  % Subtype TCC generated (at line 167, column 47) for  n
      % expected type  {i: int | (cosh(x) + sinh(x)) /= 0 OR i >= 0}
  hyperbolic_deMoivre_TCC1: OBLIGATION
    FORALL (n: nat, x: real): (cosh(x) + sinh(x)) /= 0 OR n >= 0;

  % Assuming TCC generated (at line 29, column 12) for
      % analysis@derivatives[real]
      % generated from assumption derivatives.deriv_domain
  sinh_derivable2_TCC1: OBLIGATION deriv_domain?[real];

  % Assuming TCC generated (at line 29, column 12) for
      % analysis@derivatives[real]
      % generated from assumption derivatives.not_one_element
  sinh_derivable2_TCC2: OBLIGATION not_one_element?[real];

  % Subtype TCC generated (at line 176, column 32) for  sinh
      % expected type  deriv_fun[real]
  deriv_sinh_TCC1: OBLIGATION derivable?[real](sinh);

  % Subtype TCC generated (at line 177, column 32) for  cosh
      % expected type  deriv_fun[real]
  deriv_cosh_TCC1: OBLIGATION derivable?[real](cosh);

  % Subtype TCC generated (at line 178, column 32) for  tanh
      % expected type  deriv_fun[real]
  deriv_tanh_TCC1: OBLIGATION derivable?[real](tanh);

  % Subtype TCC generated (at line 183, column 14) for  n
      % expected type  T_high[nat]
  sinh_series_n_TCC1: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 183, column 35) for  (2 * i + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  sinh_series_n_TCC2: OBLIGATION
    FORALL (x: real, i: nat): x /= 0 OR (2 * i + 1) >= 0;

  % Assuming TCC generated (at line 19, column 5) for  analysis@taylors[real]
      % generated from assumption taylors.connected_domain
  sinh_taylors_TCC1: OBLIGATION connected?[real];

  % Subtype TCC generated (at line 186, column 55) for  (2 * n + 3)
      % expected type  {i: int | x /= 0 OR i >= 0}
  sinh_taylors_TCC2: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)):
      x /= 0 OR (2 * n + 3) >= 0;

  % Subtype TCC generated (at line 196, column 35) for  x + sqrt(sq(x) + 1)
      % expected type  posreal
  asinh_TCC1: OBLIGATION
    FORALL (x: real): x + sqrt(sq(x) + 1) >= 0 AND x + sqrt(sq(x) + 1) > 0;

  % Subtype TCC generated (at line 197, column 42) for  sq(x) - 1
      % expected type  nnx: nonneg_real
  acosh_TCC1: OBLIGATION FORALL (x: posreal_ge1): sq(x) - 1 >= 0;

  % Subtype TCC generated (at line 197, column 35) for  x + sqrt(sq(x) - 1)
      % expected type  posreal
  acosh_TCC2: OBLIGATION
    FORALL (x: posreal_ge1):
      x + sqrt(sq(x) - 1) >= 0 AND x + sqrt(sq(x) - 1) > 0;

  % Subtype TCC generated (at line 197, column 32) for
      % ln(x + sqrt(sq(x) - 1))
      % expected type  nnreal
  acosh_TCC3: OBLIGATION
    FORALL (x: posreal_ge1): ln(x + sqrt(sq(x) - 1)) >= 0;

  % Subtype TCC generated (at line 198, column 42) for  (1 - x)
      % expected type  nznum
  atanh_TCC1: OBLIGATION FORALL (x: real_abs_lt1): (1 - x) /= 0;

  % Subtype TCC generated (at line 198, column 35) for  (1 + x) / (1 - x)
      % expected type  posreal
  atanh_TCC2: OBLIGATION
    FORALL (x: real_abs_lt1):
      (1 + x) / (1 - x) >= 0 AND (1 + x) / (1 - x) > 0;

  % Subtype TCC generated (at line 220, column 75) for  x
      % expected type  posreal_ge1
  acosh_derivable2_TCC1: OBLIGATION FORALL (x: posreal_gt1): x >= 1;

  % Assuming TCC generated (at line 24, column 4) for
      % analysis@derivatives[posreal_gt1]
      % generated from assumption derivatives.deriv_domain
  acosh_derivable2_TCC2: OBLIGATION deriv_domain?[posreal_gt1];

  % Assuming TCC generated (at line 26, column 4) for
      % analysis@derivatives[posreal_gt1]
      % generated from assumption derivatives.not_one_element
  acosh_derivable2_TCC3: OBLIGATION not_one_element?[posreal_gt1];

  % Assuming TCC generated (at line 24, column 4) for
      % analysis@derivatives[real_abs_lt1]
      % generated from assumption derivatives.deriv_domain
  atanh_derivable2_TCC1: OBLIGATION deriv_domain?[real_abs_lt1];

  % Assuming TCC generated (at line 26, column 4) for
      % analysis@derivatives[real_abs_lt1]
      % generated from assumption derivatives.not_one_element
  atanh_derivable2_TCC2: OBLIGATION not_one_element?[real_abs_lt1];

  % Subtype TCC generated (at line 223, column 32) for  asinh
      % expected type  deriv_fun[real]
  deriv_asinh_TCC1: OBLIGATION derivable?[real](asinh);

  % Subtype TCC generated (at line 226, column 33) for
      % LAMBDA (x: posreal_gt1): acosh(x)
      % expected type  deriv_fun[posreal_gt1]
  deriv_acosh_TCC1: OBLIGATION
    derivable?[posreal_gt1](LAMBDA (x: posreal_gt1): acosh(x));

  % Subtype TCC generated (at line 227, column 66) for  sq(x) - 1
      % expected type  nnx: nonneg_real
  deriv_acosh_TCC2: OBLIGATION FORALL (x: posreal_gt1): sq(x) - 1 >= 0;

  % Subtype TCC generated (at line 227, column 61) for  sqrt(sq(x) - 1)
      % expected type  nznum
  deriv_acosh_TCC3: OBLIGATION FORALL (x: posreal_gt1): sqrt(sq(x) - 1) /= 0;

  % Subtype TCC generated (at line 228, column 46) for  atanh
      % expected type  deriv_fun[real_abs_lt1]
  deriv_atanh_TCC1: OBLIGATION derivable?[real_abs_lt1](atanh);

  % Subtype TCC generated (at line 229, column 64) for  (1 - sq(x))
      % expected type  nznum
  deriv_atanh_TCC2: OBLIGATION FORALL (x: real_abs_lt1): (1 - sq(x)) /= 0;

  % Subtype TCC generated (at line 237, column 63) for  i
      % expected type  {i: nat | i <= 1 + 2 * n}
  atanhF_TCC1: OBLIGATION
    FORALL (n, i: nat): NOT i > 2 * n AND NOT odd?(i) IMPLIES i <= 1 + 2 * n;

  % Subtype TCC generated (at line 239, column 42) for  (2 * n + 1)
      % expected type  {i: int | (1 - sq(x)) /= 0 OR i >= 0}
  atanhD_TCC1: OBLIGATION
    FORALL (n: nat, x: real): (1 - sq(x)) /= 0 OR (2 * n + 1) >= 0;

  % Subtype TCC generated (at line 247, column 10) for  atanhN(n)
      % expected type  deriv_fun[real]
  atanh_taylors_prep2_TCC1: OBLIGATION
    FORALL (n: nat): derivable?[real](atanhN(n));

  % Subtype TCC generated (at line 249, column 70) for  2 * n - 1
      % expected type  nat
  atanh_taylors_prep2_TCC2: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES 2 * n - 1 >= 0;

  % Subtype TCC generated (at line 253, column 10) for  atanhD(n)
      % expected type  deriv_fun[real]
  atanh_taylors_prep3_TCC1: OBLIGATION
    FORALL (n: nat): derivable?[real](atanhD(n));

  % Subtype TCC generated (at line 254, column 58) for  n - 1
      % expected type  nat
  atanh_taylors_prep3_TCC2: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Subtype TCC generated (at line 257, column 10) for  deriv(atanhN(n))
      % expected type  deriv_fun[real]
  atanh_taylors_prep4_TCC1: OBLIGATION
    FORALL (n: nat): derivable?[real](deriv[real](atanhN(n)));

  % Subtype TCC generated (at line 259, column 76) for  2 * n - 2
      % expected type  nat
  atanh_taylors_prep4_TCC2: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES 2 * n - 2 >= 0;

  % Subtype TCC generated (at line 265, column 34) for  g ^ pn
      % expected type  [real_abs_lt1 -> nzreal]
  atanh_taylors_prep5_TCC1: OBLIGATION
    FORALL (pn: posnat, f: [real_abs_lt1 -> real],
            g: [real_abs_lt1 -> nzreal]):
      derivable?[real_abs_lt1](f) AND derivable?[real_abs_lt1](g) IMPLIES
       (FORALL (x1: real_abs_lt1): (^[real_abs_lt1](g, pn))(x1) /= 0);

  % Subtype TCC generated (at line 267, column 68) for  (g ^ (pn + 1))
      % expected type  [real_abs_lt1 -> nzreal]
  atanh_taylors_prep5_TCC2: OBLIGATION
    FORALL (pn: posnat, f: [real_abs_lt1 -> real],
            g: [real_abs_lt1 -> nzreal]):
      derivable?[real_abs_lt1](f / g ^ pn) AND
       derivable?[real_abs_lt1](f) AND derivable?[real_abs_lt1](g)
       IMPLIES
       (FORALL (x1: real_abs_lt1): (^[real_abs_lt1](g, (pn + 1)))(x1) /= 0);

  % Subtype TCC generated (at line 270, column 47) for  atanhD(n)(x)
      % expected type  nznum
  atanhND_TCC1: OBLIGATION
    FORALL (n: nat, x: real_abs_lt1): atanhD(n)(x) /= 0;

  % Subtype TCC generated (at line 273, column 27) for
      % LAMBDA (x: real_abs_lt1): atanhN(n)(x) / atanhD(n)(x)
      % expected type  nderiv_fun[real_abs_lt1](2)
  atanh_taylors_prep6_TCC1: OBLIGATION
    FORALL (n: nat):
      derivable_n_times?[real_abs_lt1]
          (LAMBDA (x: real_abs_lt1): atanhN(n)(x) / atanhD(n)(x), 2);

  % Subtype TCC generated (at line 274, column 49) for  atanhD(n + 1)(x)
      % expected type  nznum
  atanh_taylors_prep6_TCC2: OBLIGATION
    FORALL (n: nat, x: real_abs_lt1): atanhD(n + 1)(x) /= 0;

  % Subtype TCC generated (at line 279, column 54) for  atanhND(n)
      % expected type  nderiv_fun[real_abs_lt1](2 * m)
  atanh_taylors_prep8_TCC1: OBLIGATION
    FORALL (m, n: nat): derivable_n_times?[real_abs_lt1](atanhND(n), 2 * m);

  % Subtype TCC generated (at line 282, column 27) for  atanh
      % expected type  nderiv_fun[real_abs_lt1](n)
  atanh_nderiv_TCC1: OBLIGATION
    FORALL (n: nat): derivable_n_times?[real_abs_lt1](atanh, n);

  % Subtype TCC generated (at line 284, column 56) for  n / 2 - 1
      % expected type  nat
  atanh_nderiv_TCC2: OBLIGATION
    FORALL (n: nat):
      NOT n = 0 AND even?(n) IMPLIES
       integer_pred(n / 2 - 1) AND n / 2 - 1 >= 0;

  % Subtype TCC generated (at line 284, column 48) for  atanhND(n / 2 - 1)
      % expected type  deriv_fun[real_abs_lt1]
  atanh_nderiv_TCC3: OBLIGATION
    FORALL (n: nat):
      NOT n = 0 AND even?(n) IMPLIES
       derivable?[real_abs_lt1](atanhND(n / 2 - 1));

  % Subtype TCC generated (at line 285, column 36) for  (n - 1) / 2
      % expected type  nat
  atanh_nderiv_TCC4: OBLIGATION
    FORALL (n: nat):
      NOT n = 0 AND NOT even?(n) IMPLIES
       integer_pred((n - 1) / 2) AND (n - 1) / 2 >= 0;

  % Subtype TCC generated (at line 289, column 42) for  n - 1
      % expected type  nat
  atanh_nderiv_0_TCC1: OBLIGATION
    FORALL (n: nat): NOT even?(n) IMPLIES n - 1 >= 0;

  % Subtype TCC generated (at line 294, column 28) for  (2 * n + 1)
      % expected type  {i: int | z /= 0 OR i >= 0}
  atanh_series_term_TCC1: OBLIGATION
    FORALL (z: real_abs_lt1, n: nat): z /= 0 OR (2 * n + 1) >= 0;

  % Subtype TCC generated (at line 298, column 33) for  2 * n + 2
      % expected type  T_high[nat]
  atanh_series_eqv_TCC1: OBLIGATION
    FORALL (n: nat): 2 * n + 2 >= 0 OR (EXISTS (j: nat): 2 * n + 2 <= j);

  % Subtype TCC generated (at line 300, column 49) for  atanh
      % expected type  nderiv_fun[real_abs_lt1](nn)
  atanh_series_eqv_TCC2: OBLIGATION
    FORALL (n, nn: nat):
      NOT nn > 2 * n + 2 AND NOT nn = 0 IMPLIES
       derivable_n_times?[real_abs_lt1](atanh, nn);

  % Subtype TCC generated (at line 301, column 55) for  nn
      % expected type  {i: int | z /= 0 OR i >= 0}
  atanh_series_eqv_TCC3: OBLIGATION
    FORALL (n: nat, z: real_abs_lt1, nn: nat):
      NOT nn > 2 * n + 2 AND NOT nn = 0 IMPLIES z /= 0 OR nn >= 0;

  % Assuming TCC generated (at line 19, column 5) for
      % analysis@taylors[real_abs_lt1]
      % generated from assumption taylors.connected_domain
  atanh_taylors_TCC1: OBLIGATION connected?[real_abs_lt1];

  % Subtype TCC generated (at line 305, column 60) for  atanh
      % expected type  nderiv_fun[real_abs_lt1](3 + 2 * n)
  atanh_taylors_TCC2: OBLIGATION
    FORALL (n: nat, z: real_abs_lt1, c: between[real_abs_lt1](0, z)):
      derivable_n_times?[real_abs_lt1](atanh, 3 + 2 * n);

  % Subtype TCC generated (at line 306, column 55) for  (2 * n + 3)
      % expected type  {i: int | z /= 0 OR i >= 0}
  atanh_taylors_TCC3: OBLIGATION
    FORALL (n: nat, z: real_abs_lt1, c: between[real_abs_lt1](0, z)):
      z /= 0 OR (2 * n + 3) >= 0;

  % Subtype TCC generated (at line 309, column 27) for  (2 * n + 3)
      % expected type  {i: int | (1 + z) /= 0 OR i >= 0}
  atanh_series_TCC1: OBLIGATION
    FORALL (n: nat, z: real_abs_lt1): (1 + z) /= 0 OR (2 * n + 3) >= 0;

  % Subtype TCC generated (at line 309, column 50) for
      % (2 * (2 * n + 3) * (1 - sq(z)) ^ (2 * n + 3))
      % expected type  nznum
  atanh_series_TCC2: OBLIGATION
    FORALL (n: nat, z: real_abs_lt1):
      (2 * (2 * n + 3) * (1 - sq(z)) ^ (2 * n + 3)) /= 0;


