# TheoryBodies

body:
  %------------------------------------------------------------------------------
  % Appoximation results
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  appendix: THEORY

  BEGIN
    IMPORTING prelude_aux,
              prelude_A4,
              reals@sqrt

    n,m:     VAR nat
    i,p,r:   VAR int
    pn,q:    VAR posnat
    px,py:   VAR posreal
    x,e1,e2: VAR real

    lemma_A1: LEMMA m*m <= n AND n < (m+1)*(m+1) IFF m = floor(sqrt(n))

    lemma_A2: LEMMA r = round(p/q) IFF (r-1/2)*q <= p AND p < (r+1/2)*q

    lemma_A3: LEMMA i = floor(log2(px)) IFF 2^i <= px AND px < 2^(i+1)

    lemma_A4: LEMMA e1 = 2^ -(n+floor(log2(pn))+2) AND e2 = 2^ -n AND
                    -1 < x AND x < 1 =>
                    x^pn-e2 < (x-e1)^pn AND x^pn-e2 < (x+e1)^pn AND
                    (x-e1)^pn < x^pn+e2 AND (x+e1)^pn < x^pn+e2

    epsilon_log2_aux: LEMMA FORALL (n:posnat): EXISTS (p:nat): n < 2^p

    epsilon_log2: LEMMA EXISTS (p:nat): 1/2^p < px

    floor_sqrt_aux(n,m:nat): RECURSIVE nat =
          (IF (m+1)*(m+1) <= n THEN 1+floor_sqrt_aux(n,m+1) ELSE 0 ENDIF)
      MEASURE (LAMBDA n,m: (IF n >= (m+1)*(m+1) THEN n-m ELSE 0 ENDIF))

    floor_sqrt(n:nat): nat = floor_sqrt_aux(n,0)

    floor_sqrt_def: LEMMA floor_sqrt(n) = floor(sqrt(n))

    floor_log2(n:posnat): RECURSIVE nat =
      (IF n >= 2 THEN 1 + floor_log2(floor(n/2)) ELSE 0 ENDIF)
      MEASURE (LAMBDA n:n)

    floor_log2_def: LEMMA floor_log2(pn) = floor(log2(pn))

  END appendix

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

  % Subtype TCC generated (at line 30, column 20) for  pn
      % expected type  {i: int | x /= 0 OR i >= 0}
  lemma_A4_TCC1: OBLIGATION
    FORALL (e1, e2: real, n: nat, pn: posnat, x: real):
      x < 1 AND
       -1 < x AND e2 = 2 ^ -n AND e1 = 2 ^ -(n + floor(log2(pn)) + 2)
       IMPLIES x /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 30, column 35) for  pn
      % expected type  {i: int | (x - e1) /= 0 OR i >= 0}
  lemma_A4_TCC2: OBLIGATION
    FORALL (e1, e2: real, n: nat, pn: posnat, x: real):
      x < 1 AND
       -1 < x AND e2 = 2 ^ -n AND e1 = 2 ^ -(n + floor(log2(pn)) + 2)
       IMPLIES (x - e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 30, column 59) for  pn
      % expected type  {i: int | NOT e1 + x = 0 OR i >= 0}
  lemma_A4_TCC3: OBLIGATION
    FORALL (e1, e2: real, n: nat, pn: posnat, x: real):
           x < 1 AND -1 < x AND e2 = 2 ^ -n
       AND e1 = 2 ^ -(n + floor(log2(pn)) + 2)
       AND x ^ pn - e2 < (x - e1) ^ pn
       IMPLIES NOT e1 + x = 0 OR pn >= 0;

  % Subtype TCC generated (at line 39, column 51) for  n - m
      % expected type  naturalnumber
  floor_sqrt_aux_TCC1: OBLIGATION
    FORALL (n, m): n >= (m + 1) * (m + 1) IMPLIES n - m >= 0;

  % Termination TCC generated (at line 38, column 36) for
      % floor_sqrt_aux(n, m + 1)
  floor_sqrt_aux_TCC2: OBLIGATION
    FORALL (n, m: nat):
      (m + 1) * (m + 1) <= n IMPLIES
       (IF n >= (m + 1 + 1) * (m + 1 + 1) THEN n - (m + 1) ELSE 0 ENDIF) <
        (IF n >= (m + 1) * (m + 1) THEN n - m ELSE 0 ENDIF);

  % Subtype TCC generated (at line 46, column 35) for  floor(n / 2)
      % expected type  posnat
  floor_log2_TCC1: OBLIGATION
    FORALL (n: posnat): n >= 2 IMPLIES floor(n / 2) > 0;

  % Termination TCC generated (at line 46, column 24) for
      % floor_log2(floor(n / 2))
  floor_log2_TCC2: OBLIGATION
    FORALL (n: posnat):
      n >= 2 IMPLIES
       restrict[nat, posnat, nat]((LAMBDA n: n))(floor(n / 2)) <
        restrict[nat, posnat, nat]((LAMBDA n: n))(n);


body:
  %------------------------------------------------------------------------------
  % Cauchy property
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  cauchy  : THEORY

    BEGIN
    IMPORTING prelude_aux,
              appendix

    x: VAR real
    p: VAR nat
    c: VAR [nat->int]

    cauchy_prop(x, c): bool  = (FORALL p: c(p)-1 < x*2^p AND x*2^p < c(p)+1)

    cauchy_real?(c):     bool = EXISTS (x:real):       cauchy_prop(x,c)
    cauchy_nzreal?(c):   bool = EXISTS (x:nzreal):     cauchy_prop(x,c)
    cauchy_nnreal?(c):   bool = EXISTS (x:nnreal):     cauchy_prop(x,c)
    cauchy_npreal?(c):   bool = EXISTS (x:npreal):     cauchy_prop(x,c)
    cauchy_posreal?(c):  bool = EXISTS (x:posreal):    cauchy_prop(x,c)
    cauchy_negreal?(c):  bool = EXISTS (x:negreal):    cauchy_prop(x,c)
    cauchy_smallreal?(c):bool = EXISTS (sx:smallreal): cauchy_prop(sx,c)

    cauchy_real:     NONEMPTY_TYPE = (cauchy_real?)   CONTAINING (LAMBDA p:0)
    cauchy_nzreal:   NONEMPTY_TYPE = (cauchy_nzreal?) CONTAINING (LAMBDA p:2^p)
    cauchy_nnreal:   NONEMPTY_TYPE = (cauchy_nnreal?) CONTAINING (LAMBDA p:2^p)
    cauchy_npreal:   NONEMPTY_TYPE = (cauchy_npreal?) CONTAINING (LAMBDA p:0)
    cauchy_posreal:  NONEMPTY_TYPE = (cauchy_posreal?) CONTAINING (LAMBDA p:2^p)
    cauchy_negreal:  NONEMPTY_TYPE = (cauchy_negreal?) CONTAINING (LAMBDA p:-2^p)
    cauchy_smallreal:
                     NONEMPTY_TYPE = (cauchy_smallreal?) CONTAINING (LAMBDA p:0)

    JUDGEMENT cauchy_nzreal    SUBTYPE_OF cauchy_real
    JUDGEMENT cauchy_nnreal    SUBTYPE_OF cauchy_real
    JUDGEMENT cauchy_npreal    SUBTYPE_OF cauchy_real
    JUDGEMENT cauchy_posreal   SUBTYPE_OF cauchy_nnreal
    JUDGEMENT cauchy_posreal   SUBTYPE_OF cauchy_nzreal
    JUDGEMENT cauchy_negreal   SUBTYPE_OF cauchy_nzreal
    JUDGEMENT cauchy_negreal   SUBTYPE_OF cauchy_npreal
    JUDGEMENT cauchy_smallreal SUBTYPE_OF cauchy_real

    cx: VAR cauchy_real

    cauchy_zero:cauchy_nnreal = (LAMBDA p:0)

    unique_cauchy_zero:  LEMMA cauchy_prop(x,cauchy_zero) <=> x = 0
    unique_cauchy_zero2: LEMMA cauchy_prop(0,cx) <=>
                               (FORALL p: cx(p) = cauchy_zero(p))
    unique_cauchy_zero3: LEMMA cauchy_prop(0,cx) <=> cx = cauchy_zero

  END cauchy

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

  % Subtype TCC generated (at line 29, column 64) for  (LAMBDA p: 0)
      % expected type  cauchy_real
  cauchy_real_TCC1: OBLIGATION cauchy_real?((LAMBDA p: 0));

  % Subtype TCC generated (at line 30, column 64) for  (LAMBDA p: 2 ^ p)
      % expected type  cauchy_nzreal
  cauchy_nzreal_TCC1: OBLIGATION cauchy_nzreal?((LAMBDA p: 2 ^ p));

  % Subtype TCC generated (at line 31, column 64) for  (LAMBDA p: 2 ^ p)
      % expected type  cauchy_nnreal
  cauchy_nnreal_TCC1: OBLIGATION cauchy_nnreal?((LAMBDA p: 2 ^ p));

  % Subtype TCC generated (at line 32, column 64) for  (LAMBDA p: 0)
      % expected type  cauchy_npreal
  cauchy_npreal_TCC1: OBLIGATION cauchy_npreal?((LAMBDA p: 0));

  % Subtype TCC generated (at line 33, column 65) for  (LAMBDA p: 2 ^ p)
      % expected type  cauchy_posreal
  cauchy_posreal_TCC1: OBLIGATION cauchy_posreal?((LAMBDA p: 2 ^ p));

  % Subtype TCC generated (at line 34, column 65) for  (LAMBDA p: -2 ^ p)
      % expected type  cauchy_negreal
  cauchy_negreal_TCC1: OBLIGATION cauchy_negreal?((LAMBDA p: -2 ^ p));

  % Subtype TCC generated (at line 36, column 67) for  (LAMBDA p: 0)
      % expected type  cauchy_smallreal
  cauchy_smallreal_TCC1: OBLIGATION cauchy_smallreal?((LAMBDA p: 0));

  % Judgement subtype TCC generated (at line 38, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC1: OBLIGATION FORALL (x: cauchy_nzreal): cauchy_real?(x);

  % Judgement subtype TCC generated (at line 39, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC2: OBLIGATION FORALL (x: cauchy_nnreal): cauchy_real?(x);

  % Judgement subtype TCC generated (at line 40, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC3: OBLIGATION FORALL (x: cauchy_npreal): cauchy_real?(x);

  % Judgement subtype TCC generated (at line 41, column 12) for  x
      % expected type  cauchy_nnreal
  subtype_TCC4: OBLIGATION FORALL (x: cauchy_posreal): cauchy_nnreal?(x);

  % Judgement subtype TCC generated (at line 42, column 12) for  x
      % expected type  cauchy_nzreal
  subtype_TCC5: OBLIGATION FORALL (x: cauchy_posreal): cauchy_nzreal?(x);

  % Judgement subtype TCC generated (at line 43, column 12) for  x
      % expected type  cauchy_nzreal
  subtype_TCC6: OBLIGATION FORALL (x: cauchy_negreal): cauchy_nzreal?(x);

  % Judgement subtype TCC generated (at line 44, column 12) for  x
      % expected type  cauchy_npreal
  subtype_TCC7: OBLIGATION FORALL (x: cauchy_negreal): cauchy_npreal?(x);

  % Judgement subtype TCC generated (at line 45, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC8: OBLIGATION FORALL (x: cauchy_smallreal): cauchy_real?(x);

  % Subtype TCC generated (at line 49, column 31) for  (LAMBDA p: 0)
      % expected type  cauchy_nnreal
  cauchy_zero_TCC1: OBLIGATION cauchy_nnreal?((LAMBDA p: 0));


body:
  %------------------------------------------------------------------------------
  % Addition
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  add: THEORY

  BEGIN

    IMPORTING appendix,
              cauchy

    cx, cy: VAR cauchy_real
    x, y:   VAR real
    p:      VAR nat

    cauchy_add(cx,cy): cauchy_real
             = (LAMBDA p: round((cx(p+2) + cy(p+2))/4))

    add_lemma: LEMMA cauchy_prop(x,cx) AND cauchy_prop(y,cy) =>
                     cauchy_prop(x+y, cauchy_add(cx,cy))

  END add

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

  % Subtype TCC generated (at line 21, column 14) for
      % (LAMBDA p: round((cx(p + 2) + cy(p + 2)) / 4))
      % expected type  cauchy_real
  cauchy_add_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, cy: cauchy_real):
      cauchy_real?(LAMBDA p: round((cx(p + 2) + cy(p + 2)) / 4));


body:
  %------------------------------------------------------------------------------
  % Negation
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  neg: THEORY

  BEGIN

    IMPORTING cauchy

    cx: VAR cauchy_real
    x:  VAR real
    p:  VAR nat
    nzcx: VAR cauchy_nzreal
    pcx: VAR cauchy_posreal
    ncx: VAR cauchy_negreal

    cauchy_neg(cx): cauchy_real = (LAMBDA p: -cx(p))

    neg_lemma: LEMMA cauchy_prop(x,cx) IFF cauchy_prop(-x, cauchy_neg(cx))

    neg_cauchy_nzreal_is_cauchy_nzreal:
      JUDGEMENT cauchy_neg(nzcx) HAS_TYPE cauchy_nzreal

    neg_cauchy_posreal_is_cauchy_negreal:
      JUDGEMENT cauchy_neg(pcx) HAS_TYPE cauchy_negreal

    neg_cauchy_negreal_is_cauchy_posreal:
      JUDGEMENT cauchy_neg(ncx) HAS_TYPE cauchy_posreal

  END neg

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

  % Subtype TCC generated (at line 22, column 33) for  (LAMBDA p: -cx(p))
      % expected type  cauchy_real
  cauchy_neg_TCC1: OBLIGATION
    FORALL (cx: cauchy_real): cauchy_real?(LAMBDA p: -cx(p));

  % Judgement subtype TCC generated (at line 27, column 14) for
      % cauchy_neg(nzcx)
      % expected type  cauchy_nzreal
  neg_cauchy_nzreal_is_cauchy_nzreal: OBLIGATION
    FORALL (nzcx): cauchy_nzreal?(cauchy_neg(nzcx));

  % Judgement subtype TCC generated (at line 30, column 14) for
      % cauchy_neg(pcx)
      % expected type  cauchy_negreal
  neg_cauchy_posreal_is_cauchy_negreal: OBLIGATION
    FORALL (pcx): cauchy_negreal?(cauchy_neg(pcx));

  % Judgement subtype TCC generated (at line 33, column 14) for
      % cauchy_neg(ncx)
      % expected type  cauchy_posreal
  neg_cauchy_negreal_is_cauchy_posreal: OBLIGATION
    FORALL (ncx): cauchy_posreal?(cauchy_neg(ncx));


body:
  unique: THEORY

    BEGIN
    IMPORTING prelude_aux
    IMPORTING cauchy
    IMPORTING neg
    IMPORTING add

    p,s:   VAR nat
    x,y: VAR real
    cx:  VAR cauchy_real
    nzcx:  VAR cauchy_nzreal
    nncx:  VAR cauchy_nnreal
    npcx:  VAR cauchy_npreal
    ncx:  VAR cauchy_negreal
    pcx:  VAR cauchy_posreal
    px:    VAR posreal
    nzx:   VAR nzreal
    f:     VAR [nzreal->nzreal]
    cf:    VAR [cauchy_nzreal->cauchy_nzreal]

    unique_cauchy: LEMMA cauchy_prop(x,cx) AND cauchy_prop(y,cx) => x = y

    cauchy_dich1: LEMMA cauchy_posreal?(nzcx) IFF NOT cauchy_negreal?(nzcx)
    cauchy_dich2: LEMMA cauchy_negreal?(nzcx) IFF NOT cauchy_posreal?(nzcx)
    cauchy_dich3: LEMMA cauchy_nnreal?(nncx) IFF NOT cauchy_negreal?(nncx)
    cauchy_dich4: LEMMA cauchy_npreal?(npcx) IFF NOT cauchy_posreal?(npcx)
    cauchy_dich5: LEMMA cauchy_negreal?(nzcx) OR cauchy_posreal?(nzcx)
    cauchy_trich: LEMMA cauchy_negreal?(cx) OR cx = cauchy_zero OR cauchy_posreal?(cx)

    cauchy_pos_characteristic: LEMMA 0 <= pcx(p)
    cauchy_neg_characteristic: LEMMA ncx(p) <= 0

    cauchy_pos_monotonic: LEMMA 3 <= pcx(s) => 3 <= pcx(s+p)
    cauchy_monotonic:     LEMMA 3 <= abs(nzcx(s)) => 3 <= abs(nzcx(s+p))

    odd_real_fn?(f:[nzreal->nzreal]):bool = FORALL (x:nzreal): (f(-x) = -f(x))
    odd_cauchy_fn?(cf:[cauchy_nzreal->cauchy_nzreal]):bool
      = FORALL (cx:cauchy_nzreal):(cf(cauchy_neg(cx)) = cauchy_neg(cf(cx)))

    cauchy_odd_extend: LEMMA odd_real_fn?(f) AND odd_cauchy_fn?(cf) AND
      (FORALL (px:posreal, pcx:cauchy_posreal):
                cauchy_prop(px,pcx) => cauchy_prop(f(px),cf(pcx))) =>
      (cauchy_prop(nzx,nzcx) => cauchy_prop(f(nzx),cf(nzcx)))


    END unique


body:
  %------------------------------------------------------------------------------
  % Power
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  power: THEORY

  BEGIN

    IMPORTING prelude_aux, prelude_A4, appendix, cauchy, unique

    w,x,y,z,a,b: VAR real
    pn,q0,q1: VAR posnat
    p,q,p1,n: VAR nat
    cx: VAR cauchy_real
    scx: VAR cauchy_smallreal
    sx: VAR smallreal
    r,X,Y,X0: VAR int
    rx: VAR rat
    e1: VAR posreal

    abs_ge0:       LEMMA 0 <= abs(x)
    abs_neg:       LEMMA abs(-x) = abs(x)
    abs_interval:  LEMMA abs(x-y) < a <=> x-a < y AND y < x+a
    abs_interval1: LEMMA abs(x) < a <=> -a < x AND x < a
    abs_interval2: LEMMA abs(x) <= a <=> -a <= x AND x <= a
    triangle_open: LEMMA abs(x-y) < a AND abs(y-z) < b => abs(x-z) < a+b
    abs_error:     LEMMA abs(x-y) < a AND abs(w-z) < b => abs(x+w-(y+z)) < a+b

    lemma_A2_generalized: LEMMA r = round(x) => r-1/2 <= x AND x < r+1/2

    cauchy_power_lt1_n_odd: LEMMA
       odd?(pn) AND sx+e1 < 0 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_n_even: LEMMA
       even?(pn) AND sx+e1 < 0 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_snz_odd: LEMMA
       odd?(pn) AND sx < 0 AND sx+e1 = 0 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_snz_even: LEMMA
       even?(pn) AND sx < 0 AND sx+e1 = 0 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_sn_odd: LEMMA
       odd?(pn) AND sx < 0 AND 0 < sx+e1 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_sn_even: LEMMA
       even?(pn) AND sx < 0 AND 0 < sx+e1 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_z: LEMMA
       sx = 0 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_sp_odd: LEMMA
       odd?(pn) AND 0 < sx AND sx-e1 < 0 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_sp_even: LEMMA
       even?(pn) AND 0 < sx AND sx-e1 < 0 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_pz: LEMMA
       sx-e1 = 0 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_p: LEMMA
       0 < sx-e1 AND e1 = 2^-(p+floor(log2(pn))+3) AND
       Y = round ((rx*e1)^pn*2^p) AND rx-1 < sx / e1 AND sx / e1 < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_main_generalized: LEMMA
       Y = round ((rx*2^-(p+floor(log2(pn))+3))^pn*2^p) AND
       rx-1 < sx * 2^(p+floor(log2(pn))+3) AND
       sx * 2^(p+floor(log2(pn))+3) < rx+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_main: LEMMA
       Y = round ((X*2^-(p+floor(log2(pn))+3))^pn*2^p) AND
       X-1 < sx * 2^(p+floor(log2(pn))+3) AND
       sx * 2^(p+floor(log2(pn))+3) < X+1 =>
       Y-1 < sx^pn * 2^p AND sx^pn * 2^p < 1+Y

    cauchy_power_lt1_isreal: LEMMA cauchy_real?
         (LAMBDA p: round ((scx(p+floor(log2(pn))+3) *
                                               2^-(p+floor(log2(pn))+3))^pn*2^p))

    cauchy_power_lt1(scx:cauchy_smallreal, pn:posnat):cauchy_real
       = (LAMBDA p: round ((scx(p+floor(log2(pn))+3) *
                                               2^-(p+floor(log2(pn))+3))^pn*2^p))

    power_lemma_lt1: LEMMA cauchy_prop(sx,scx)
                         => cauchy_prop(sx^pn, cauchy_power_lt1(scx,pn))

    cauchy_power_div1: LEMMA X0-1 < x AND x < X0+1 AND
                       p = floor(log2(abs(X0)+1))+1 =>
                       -(2^p) < x AND x < 2^p

    cauchy_power_main: LEMMA
       X0-1 < x AND x < X0+1 AND q = 1+floor(log2(abs(X0)+1)) AND
       p1 = p+floor(log2(pn))+3+pn*q AND Y = round ((X/2^p1)^pn*2^p) AND
       X-1 < x * 2^p1 AND x * 2^p1 < X+1 =>
       Y-1 < x^pn * 2^p AND x^pn * 2^p < 1+Y

    cauchy_power_isreal: LEMMA cauchy_real?
     (LAMBDA p:
        LET p1 = p+floor_log2(pn)+3+pn*(1+floor_log2(abs(cx(0))+1))
        IN  round((cx(p1)*2^-(p1))^pn*2^p))

    cauchy_power(cx:cauchy_real, pn:posnat):cauchy_real
       = (LAMBDA p: LET p1 = p+floor_log2(pn)+3+pn*(1+floor_log2(abs(cx(0))+1))
                    IN  round((cx(p1)*2^-(p1))^pn*2^p))

    power_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(x^pn,cauchy_power(cx,pn))

  END power

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

  % Subtype TCC generated (at line 37, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_n_odd_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      odd?(pn) AND sx + e1 < 0 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3)
       IMPLIES (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 38, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_n_odd_TCC2: OBLIGATION
    FORALL (Y: int, e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
           sx / e1 < rx + 1 AND rx - 1 < sx / e1
       AND Y = round((rx * e1) ^ pn * 2 ^ p)
       AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) AND sx + e1 < 0 AND odd?(pn)
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 42, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_n_even_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      even?(pn) AND sx + e1 < 0 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3)
       IMPLIES (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 43, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_n_even_TCC2: OBLIGATION
    FORALL (Y: int, e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
           sx / e1 < rx + 1 AND rx - 1 < sx / e1
       AND Y = round((rx * e1) ^ pn * 2 ^ p)
       AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) AND sx + e1 < 0 AND even?(pn)
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 47, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_snz_odd_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      odd?(pn) AND
       sx < 0 AND sx + e1 = 0 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3)
       IMPLIES (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 48, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_snz_odd_TCC2: OBLIGATION
    FORALL (Y: int, e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
           sx / e1 < rx + 1 AND rx - 1 < sx / e1
       AND Y = round((rx * e1) ^ pn * 2 ^ p)
       AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) AND sx + e1 = 0 AND sx < 0
       AND odd?(pn)
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 52, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_snz_even_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      even?(pn) AND
       sx < 0 AND sx + e1 = 0 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3)
       IMPLIES (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 53, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_snz_even_TCC2: OBLIGATION
    FORALL (Y: int, e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
           sx / e1 < rx + 1 AND rx - 1 < sx / e1
       AND Y = round((rx * e1) ^ pn * 2 ^ p)
       AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) AND sx + e1 = 0 AND sx < 0
       AND even?(pn)
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 57, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_sn_odd_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      odd?(pn) AND
       sx < 0 AND 0 < sx + e1 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3)
       IMPLIES (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 58, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_sn_odd_TCC2: OBLIGATION
    FORALL (Y: int, e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
           sx / e1 < rx + 1 AND rx - 1 < sx / e1
       AND Y = round((rx * e1) ^ pn * 2 ^ p)
       AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) AND 0 < sx + e1 AND sx < 0
       AND odd?(pn)
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 62, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_sn_even_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      even?(pn) AND
       sx < 0 AND 0 < sx + e1 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3)
       IMPLIES (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 63, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_sn_even_TCC2: OBLIGATION
    FORALL (Y: int, e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
           sx / e1 < rx + 1 AND rx - 1 < sx / e1
       AND Y = round((rx * e1) ^ pn * 2 ^ p)
       AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) AND 0 < sx + e1 AND sx < 0
       AND even?(pn)
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 67, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_z_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      sx = 0 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) IMPLIES
       (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 68, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_z_TCC2: OBLIGATION
    FORALL (Y: int, e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
           sx / e1 < rx + 1 AND rx - 1 < sx / e1
       AND Y = round((rx * e1) ^ pn * 2 ^ p)
       AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) AND sx = 0
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 72, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_sp_odd_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      odd?(pn) AND
       0 < sx AND sx - e1 < 0 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3)
       IMPLIES (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 77, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_sp_even_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      even?(pn) AND
       0 < sx AND sx - e1 < 0 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3)
       IMPLIES (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 82, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_pz_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      sx - e1 = 0 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) IMPLIES
       (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 87, column 24) for  pn
      % expected type  {i: int | (rx * e1) /= 0 OR i >= 0}
  cauchy_power_lt1_p_TCC1: OBLIGATION
    FORALL (e1: posreal, p: nat, pn: posnat, rx: rat, sx: smallreal):
      0 < sx - e1 AND e1 = 2 ^ -(p + floor(log2(pn)) + 3) IMPLIES
       (rx * e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 91, column 46) for  pn
      % expected type  {i: int |
                     %          NOT (rx * 2 ^ -(3 + p + floor(log2(pn)))) = 0
                     %           OR i >= 0}
  cauchy_power_lt1_main_generalized_TCC1: OBLIGATION
    FORALL (p: nat, pn: posnat, rx: rat):
      NOT (rx * 2 ^ -(3 + p + floor(log2(pn)))) = 0 OR pn >= 0;

  % Subtype TCC generated (at line 94, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_main_generalized_TCC2: OBLIGATION
    FORALL (Y: int, p: nat, pn: posnat, rx: rat, sx: smallreal):
      sx * 2 ^ (p + floor(log2(pn)) + 3) < rx + 1 AND
       rx - 1 < sx * 2 ^ (p + floor(log2(pn)) + 3) AND
        Y = round((rx * 2 ^ -(p + floor(log2(pn)) + 3)) ^ pn * 2 ^ p)
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 97, column 45) for  pn
      % expected type  {i: int |
                     %          NOT (X * 2 ^ -(3 + p + floor(log2(pn)))) = 0
                     %           OR i >= 0}
  cauchy_power_lt1_main_TCC1: OBLIGATION
    FORALL (X: int, p: nat, pn: posnat):
      NOT (X * 2 ^ -(3 + p + floor(log2(pn)))) = 0 OR pn >= 0;

  % Subtype TCC generated (at line 100, column 14) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  cauchy_power_lt1_main_TCC2: OBLIGATION
    FORALL (X, Y: int, p: nat, pn: posnat, sx: smallreal):
      sx * 2 ^ (p + floor(log2(pn)) + 3) < X + 1 AND
       X - 1 < sx * 2 ^ (p + floor(log2(pn)) + 3) AND
        Y = round((X * 2 ^ -(p + floor(log2(pn)) + 3)) ^ pn * 2 ^ p)
       IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 103, column 30) for
      % p + floor(log2(pn)) + 3
      % expected type  nat
  cauchy_power_lt1_isreal_TCC1: OBLIGATION
    FORALL (pn: posnat, p): p + floor(log2(pn)) + 3 >= 0;

  % Subtype TCC generated (at line 103, column 48) for
      % 3 + p + floor(log2(pn))
      % expected type  nat
  cauchy_power_lt1_isreal_TCC2: OBLIGATION
    FORALL (pn: posnat, p): 3 + p + floor(log2(pn)) >= 0;

  % Subtype TCC generated (at line 104, column 71) for  pn
      % expected type  {i: int |
                     %          NOT (scx(3 + p + floor(log2(pn))) *
                     %                2 ^ -(3 + p + floor(log2(pn))))
                     %               = 0
                     %           OR i >= 0}
  cauchy_power_lt1_isreal_TCC3: OBLIGATION
    FORALL (pn: posnat, scx: cauchy_smallreal, p):
      NOT (scx(3 + p + floor(log2(pn))) * 2 ^ -(3 + p + floor(log2(pn)))) = 0
       OR pn >= 0;

  % Subtype TCC generated (at line 107, column 8) for
      % (LAMBDA p:
      %    round((scx(p + floor(log2(pn)) + 3) *
      %            2 ^ -(p + floor(log2(pn)) + 3))
      %           ^ pn
      %           * 2 ^ p))
      % expected type  cauchy_real
  cauchy_power_lt1_TCC1: OBLIGATION
    FORALL (scx: cauchy_smallreal, pn: posnat):
      cauchy_real?((LAMBDA p:
                      round((scx(p + floor(log2(pn)) + 3) *
                              2 ^ -(p + floor(log2(pn)) + 3))
                             ^ pn
                             * 2 ^ p)));

  % Subtype TCC generated (at line 111, column 41) for  pn
      % expected type  {i: int | sx /= 0 OR i >= 0}
  power_lemma_lt1_TCC1: OBLIGATION
    FORALL (pn: posnat, scx: cauchy_smallreal, sx: smallreal):
      cauchy_prop(sx, scx) IMPLIES sx /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 119, column 59) for  pn
      % expected type  {i: int | (X / 2 ^ p1) /= 0 OR i >= 0}
  cauchy_power_main_TCC1: OBLIGATION
    FORALL (X, X0: int, p, p1: nat, pn: posnat, q: nat, x: real):
      X0 - 1 < x AND
       x < X0 + 1 AND
        q = 1 + floor(log2(abs(X0) + 1)) AND
         p1 = p + floor(log2(pn)) + 3 + pn * q
       IMPLIES (X / 2 ^ p1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 121, column 13) for  pn
      % expected type  {i: int | x /= 0 OR i >= 0}
  cauchy_power_main_TCC2: OBLIGATION
    FORALL (X, X0, Y: int, p, p1: nat, pn: posnat, q: nat, x: real):
           x * 2 ^ p1 < X + 1 AND X - 1 < x * 2 ^ p1
       AND Y = round((X / 2 ^ p1) ^ pn * 2 ^ p)
       AND p1 = p + floor(log2(pn)) + 3 + pn * q
       AND q = 1 + floor(log2(abs(X0) + 1)) AND x < X0 + 1 AND X0 - 1 < x
       IMPLIES x /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 126, column 33) for  pn
      % expected type  {i: int | (cx(p1) * 2 ^ -(p1)) /= 0 OR i >= 0}
  cauchy_power_isreal_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, pn: posnat, p, p1: posint):
      p1 = p + floor_log2(pn) + 3 + pn * (1 + floor_log2(abs(cx(0)) + 1))
       IMPLIES (cx(p1) * 2 ^ -p1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 129, column 8) for
      % (LAMBDA p:
      %    LET p1 =
      %          p + floor_log2(pn) + 3 +
      %           pn * (1 + floor_log2(abs(cx(0)) + 1))
      %      IN round((cx(p1) * 2 ^ -(p1)) ^ pn * 2 ^ p))
      % expected type  cauchy_real
  cauchy_power_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, pn: posnat):
      cauchy_real?((LAMBDA p:
                      LET p1 =
                            p + floor_log2(pn) + 3 +
                             pn * (1 + floor_log2(abs(cx(0)) + 1))
                        IN round((cx(p1) * 2 ^ -(p1)) ^ pn * 2 ^ p)));

  % Subtype TCC generated (at line 132, column 56) for  pn
      % expected type  {i: int | x /= 0 OR i >= 0}
  power_lemma_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, pn: posnat, x: real):
      cauchy_prop(x, cx) IMPLIES x /= 0 OR pn >= 0;


body:
  %------------------------------------------------------------------------------
  % Summation
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  sum: THEORY

  BEGIN

    IMPORTING prelude_aux, prelude_A4, appendix, cauchy, unique, power,
              reals@sigma[nat]

    x,y:      VAR real
    xs,ys:    VAR [nat-> real]
    p,p1,n,m: VAR nat
    X,Y,i,j:  VAR int
    pn:       VAR posnat
    cxs:      VAR [nat->cauchy_real]

    cauchys_to_reals (cxs,p): [nat->real] = (LAMBDA (m:nat): (cxs(m))(p)*2^-p)

    sum_lemma2: LEMMA
      (FORALL (n:nat): cauchy_prop(xs(n),cxs(n))) =>
      abs(sigma(0,n,xs) - sigma(0,n,cauchys_to_reals(cxs,p))) < (n+1)*2^-p

    cauchy_sum_aux (cxs:[nat->cauchy_real],n,p:nat): RECURSIVE int
     = (IF n = 0 THEN cxs(0)(p) ELSE cauchy_sum_aux(cxs,n-1,p) + cxs(n)(p) ENDIF)
        MEASURE (LAMBDA cxs,n,p: n)

    sum_lemma3: LEMMA cauchy_sum_aux(cxs,n,p)*2^-p
                                             = sigma(0,n,cauchys_to_reals(cxs,p))

    cauchy_sum_type_int (cxs:[nat->cauchy_real],n,p:nat): int
     = round(cauchy_sum_aux(cxs,n,p+floor_log2(n+1)+2)/2^(floor_log2(n+1)+2))

    sum_lemma4: LEMMA
        abs(sigma(0,n,cauchys_to_reals(cxs,p+floor(log2(n+1))+2))
                  - cauchy_sum_type_int(cxs,n,p)*2^-p) <= 2^-(p+1)

    sum_lemma5: LEMMA (FORALL (n:nat): cauchy_prop(xs(n),cxs(n))) =>
      abs(sigma(0,n,xs) - cauchy_sum_type_int(cxs,n,p)*2^-p) < 2^-p

    cauchys_prop(xs:[nat -> real], cs:[nat -> cauchy_real]): bool
       = (FORALL (n:nat): cauchy_prop(xs(n), cs(n)))

    cauchys_real? (cs:[nat->cauchy_real]):bool
          = EXISTS (xs:[nat -> real]): cauchys_prop(xs,cs)

    cauchys_real: NONEMPTY_TYPE = (cauchys_real?)
                                         CONTAINING (LAMBDA n: LAMBDA p:0)

    cauchy_sum (cxs:cauchys_real,n): cauchy_real
     = (LAMBDA p: cauchy_sum_type_int(cxs,n,p))


    sum_lemma: LEMMA (FORALL (n:nat): cauchy_prop(xs(n),cxs(n))) =>
                     cauchy_prop(sigma(0,m,xs), cauchy_sum(cxs,m))

  END sum

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

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

  % Subtype TCC generated (at line 27, column 14) for  0
      % expected type  T_low[nat]
  sum_lemma2_TCC1: OBLIGATION
    FORALL (cxs: [nat -> cauchy_real], xs: [nat -> real]):
      (FORALL (n: nat): cauchy_prop(xs(n), cxs(n))) IMPLIES
       0 >= 0 OR (EXISTS (j: nat): j <= 0);

  % Subtype TCC generated (at line 27, column 16) for  n
      % expected type  T_high[nat]
  sum_lemma2_TCC2: OBLIGATION
    FORALL (cxs: [nat -> cauchy_real], n1: nat, xs: [nat -> real]):
      (FORALL (n: nat): cauchy_prop(xs(n), cxs(n))) IMPLIES
       n1 >= 0 OR (EXISTS (j: nat): n1 <= j);

  % Subtype TCC generated (at line 30, column 54) for  n - 1
      % expected type  nat
  cauchy_sum_aux_TCC1: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Termination TCC generated (at line 30, column 35) for
      % cauchy_sum_aux(cxs, n - 1, p)
  cauchy_sum_aux_TCC2: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 34, column 51) for  0
      % expected type  T_low[nat]
  sum_lemma3_TCC1: OBLIGATION 0 >= 0 OR (EXISTS (j: nat): j <= 0);

  % Subtype TCC generated (at line 34, column 53) for  n
      % expected type  T_high[nat]
  sum_lemma3_TCC2: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 40, column 41) for
      % p + floor(log2(n + 1)) + 2
      % expected type  nat
  sum_lemma4_TCC1: OBLIGATION
    FORALL (n, p: nat): p + floor(log2(n + 1)) + 2 >= 0;

  % Subtype TCC generated (at line 53, column 61) for  LAMBDA p: 0
      % expected type  cauchy_real
  cauchys_real_TCC1: OBLIGATION cauchy_real?(LAMBDA p: 0);

  % Subtype TCC generated (at line 53, column 51) for  (LAMBDA n: LAMBDA p: 0)
      % expected type  cauchys_real
  cauchys_real_TCC2: OBLIGATION cauchys_real?((LAMBDA n: LAMBDA p: 0));

  % Subtype TCC generated (at line 56, column 6) for
      % (LAMBDA p: cauchy_sum_type_int(cxs, n, p))
      % expected type  cauchy_real
  cauchy_sum_TCC1: OBLIGATION
    FORALL (cxs: cauchys_real, n: nat):
      cauchy_real?(LAMBDA p: cauchy_sum_type_int(cxs, n, p));

  % Subtype TCC generated (at line 60, column 57) for  cxs
      % expected type  cauchys_real
  sum_lemma_TCC1: OBLIGATION
    FORALL (cxs: [nat -> cauchy_real], xs: [nat -> real]):
      (FORALL (n: nat): cauchy_prop(xs(n), cxs(n))) IMPLIES
       cauchys_real?(cxs);


body:
  %------------------------------------------------------------------------------
  % Top file for exact_real_arith
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  mul: THEORY

  BEGIN

    IMPORTING prelude_aux, appendix, cauchy

    x,y,z : VAR real
    n1,n2,n,m,r : VAR int
    nnx,nny: VAR nonneg_real
    npx,npy: VAR nonpos_real
    nx, ny:  VAR negreal
    px, py:  VAR posreal
    cx, cy: VAR cauchy_real
    s,s1,s2,p:       VAR nat

    D1: LEMMA n-1 < x AND x < n+1 AND x = 0 => n =  0
    D2: LEMMA n-1 < x AND x < n+1 AND x < 0 => n <= 0
    D3: LEMMA n-1 < x AND x < n+1 AND 0 < x => 0 <= n

    negreal_times_posreal_is_negreal: LEMMA nx*py < 0

    lt_times_lt_nonneg1: LEMMA nnx < x AND nny < y => nnx*nny < x*y
    lt_times_lt_nonneg2: LEMMA nnx < x AND y < npy => x*y < nnx*npy

    D_pp: LEMMA n-1 < px AND px < n+1 AND m-1 < py AND py < m+1                =>
                n*m-abs(n)-abs(m)-1 < px*py AND px*py < n*m+abs(n)+abs(m)+1
    D_pn: LEMMA n-1 < px AND px < n+1 AND m-1 < ny AND ny < m+1                =>
                n*m-abs(n)-abs(m)-1 < px*ny AND px*ny < n*m+abs(n)+abs(m)+1
    D_nn: LEMMA n-1 < nx AND nx < n+1 AND m-1 < ny AND ny < m+1                =>
                n*m-abs(n)-abs(m)-1 < nx*ny AND nx*ny < n*m+abs(n)+abs(m)+1
    D_p0: LEMMA n-1 < px AND px < n+1 AND m-1 < y AND y < m+1 AND y = 0        =>
                n*m-abs(n)-abs(m)-1 < px*y AND px*y < n*m+abs(n) + abs(m)+1
    D_n0: LEMMA n-1 < nx AND nx < n+1 AND m-1 < y AND y < m+1 AND y = 0        =>
                n*m-abs(n)-abs(m)-1 < nx*y AND nx*y < n*m+abs(n) + abs(m)+1


    D:    LEMMA n-1 < x AND x < n+1 AND m-1 < y AND y < m+1 =>
                n*m-abs(n)-abs(m)-1 < x*y AND x*y < n*m+abs(n)+abs(m)+1

    mul_p1: LEMMA s = floor(log2(abs(cx(0))+2))+3 =>
                2^(s-3) <= abs(cx(0))+2 AND abs(cx(0))+2 < 2^(s-2)

    mul_p2: LEMMA s = floor(log2(abs(cx(0))+2))+3 AND n = cx(p) AND 0 < p
            => abs(n)+1 <= 2^p*(abs(cx(0))+2)
                AND 2^p*(abs(cx(0))+2) < 2^(p+s-2)

    mul_p3: LEMMA s = floor(log2(abs(cx(0))+2))+3 AND 0 < p
            => abs(cx(p))+1 <= 2^(p+s-2)

    mul_p4: LEMMA s1 = floor(log2(abs(cx(0))+2))+3 AND
                  s2 = floor(log2(abs(cy(0))+2))+3
            => abs(cx(p+s2)) + abs(cy(p+s1)) + 1 < 2^(p+s1+s2-1)

    mul_p5: LEMMA s1 = floor(log2(abs(cx(0))+2))+3 AND
                  s2 = floor(log2(abs(cy(0))+2))+3 AND
                  n1 = cx(p+s2) AND
                  n2 = cy(p+s1) AND
                  r  = round((n1*n2)/2^(p+s1+s2))
            => 2^(p+s1+s2)*(r-1) <= n1*n2 - abs(n1) - abs(n2) -1 AND
                    n1*n2 + abs(n1) + abs(n2) +1 <= 2^(p+s1+s2)*(r+1)

    mul_p6: LEMMA s1 = floor(log2(abs(cx(0))+2))+3 AND
                  s2 = floor(log2(abs(cy(0))+2))+3 AND
                  n1 = cx(p+s2) AND
                  n2 = cy(p+s1) AND
                  r  = round((n1*n2)/2^(p+s1+s2)) AND
                  cauchy_prop(x,cx) AND
                  cauchy_prop(y,cy)
            => r-1 < 2^p*x*y AND 2^p*x*y < r+1

    cauchy_mul_type: LEMMA
      cauchy_real?(LAMBDA p:
                     round(
                           (cx(p + (floor(log2(abs(cy(0)) + 2)) + 3)) *
                            cy(p + (floor(log2(abs(cx(0)) + 2)) + 3))) /
                            2 ^ (p + (floor(log2(abs(cx(0)) + 2)) + 3) +
                                     (floor(log2(abs(cy(0)) + 2)) + 3))))

    cauchy_mul(c1, c2:cauchy_real): cauchy_real
      = (LAMBDA p: LET s1 = floor_log2(abs(c1(0))+2)+3,
                       s2 = floor_log2(abs(c2(0))+2)+3 IN
         round((c1(p+s2)*c2(p+s1))/2^(p+s1+s2)))

    mul_lemma: LEMMA cauchy_prop(x,cx) AND cauchy_prop(y,cy)
                     => cauchy_prop(x*y, cauchy_mul(cx,cy))

  END mul

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

  % Subtype TCC generated (at line 82, column 29) for
      % p + (floor(log2(abs(cy(0)) + 2)) + 3)
      % expected type  nat
  cauchy_mul_type_TCC1: OBLIGATION
    FORALL (cy: cauchy_real, p): p + (floor(log2(abs(cy(0)) + 2)) + 3) >= 0;

  % Subtype TCC generated (at line 88, column 7) for
      % (LAMBDA p:
      %    LET s1 = floor_log2(abs(c1(0)) + 2) + 3,
      %        s2 = floor_log2(abs(c2(0)) + 2) + 3
      %      IN round((c1(p + s2) * c2(p + s1)) / 2 ^ (p + s1 + s2)))
      % expected type  cauchy_real
  cauchy_mul_TCC1: OBLIGATION
    FORALL (c1, c2: cauchy_real):
      cauchy_real?(LAMBDA p:
                     LET s1 = floor_log2(abs(c1(0)) + 2) + 3,
                         s2 = floor_log2(abs(c2(0)) + 2) + 3
                       IN
                       round((c1(p + s2) * c2(p + s1)) / 2 ^ (p + s1 + s2)));


body:
  %------------------------------------------------------------------------------
  % Powerseries
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  powerseries: THEORY

  BEGIN

    IMPORTING prelude_aux, appendix, cauchy, mul, power, sum


    i,n,m: VAR nat
    cxs:   VAR [nat->cauchy_real]
    cx:    VAR cauchy_real
    x:     VAR real
    xs:    VAR [nat->real]

    powerseries (x,xs,n): real
     = sigma(0,n,(LAMBDA i: IF i = 0 THEN xs(i) ELSE xs(i)*x^i ENDIF))

    cauchy_powerseries (cx:cauchy_real,cxs:cauchys_real,n): cauchy_real
     = cauchy_sum ((LAMBDA i: IF i = 0 THEN cxs(i)
                              ELSE cauchy_mul(cxs(i),
                                   cauchy_power(cx,i)) ENDIF), n)

    powerseries_lemma: LEMMA (FORALL n: cauchy_prop(xs(n),cxs(n))) AND
                             cauchy_prop(x,cx) =>
                             cauchy_prop(powerseries(x,xs,m),
  				       cauchy_powerseries(cx,cxs,m))

  END powerseries

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

  % Subtype TCC generated (at line 23, column 11) for  0
      % expected type  T_low[nat]
  powerseries_TCC1: OBLIGATION 0 >= 0 OR (EXISTS (j: nat): j <= 0);

  % Subtype TCC generated (at line 23, column 13) for  n
      % expected type  T_high[nat]
  powerseries_TCC2: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 23, column 59) for  i
      % expected type  {i: int | x /= 0 OR i >= 0}
  powerseries_TCC3: OBLIGATION
    FORALL (x: real, i): NOT i = 0 IMPLIES x /= 0 OR i >= 0;

  % Subtype TCC generated (at line 28, column 49) for  i
      % expected type  posnat
  cauchy_powerseries_TCC1: OBLIGATION FORALL (i): NOT i = 0 IMPLIES i > 0;

  % Subtype TCC generated (at line 26, column 18) for
      % (LAMBDA i:
      %    IF i = 0 THEN cxs(i)
      %    ELSE cauchy_mul(cxs(i), cauchy_power(cx, i))
      %    ENDIF)
      % expected type  cauchys_real
  cauchy_powerseries_TCC2: OBLIGATION
    FORALL (cx: cauchy_real, cxs: cauchys_real):
      cauchys_real?((LAMBDA i:
                       IF i = 0 THEN cxs(i)
                       ELSE cauchy_mul(cxs(i), cauchy_power(cx, i))
                       ENDIF));

  % Subtype TCC generated (at line 33, column 33) for  cxs
      % expected type  cauchys_real
  powerseries_lemma_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, cxs: [nat -> cauchy_real], x: real,
            xs: [nat -> real]):
      (cauchy_prop(x, cx) AND (FORALL n: cauchy_prop(xs(n), cxs(n)))) IMPLIES
       cauchys_real?(cxs);


body:
  bisection_nat_sqrt: THEORY

  BEGIN

    IMPORTING appendix

    n,m,x: VAR nat
    pn:    VAR posnat

    fs_lt?(n,m):bool = sq(m+1) <= n
    fs_eq?(n,m):bool = sq(m) <= n AND n < sq(m+1)
    fs_gt?(n,m):bool = n < sq(m)

    fs_lt?(n)(m):bool = fs_lt?(n,m)
    fs_le?(n)(m):bool = fs_lt?(n,m) OR fs_eq?(n,m)
    fs_eq?(n)(m):bool = fs_eq?(n,m)
    fs_gt?(n)(m):bool = fs_gt?(n,m)
    fs_ge?(n)(m):bool = fs_eq?(n,m) OR fs_gt?(n,m)

    fs_lt_def: LEMMA fs_lt?(n,m) => (NOT fs_eq?(n,m) AND NOT fs_gt?(n,m))
    fs_eq_def: LEMMA fs_eq?(n,m) => (NOT fs_lt?(n,m) AND NOT fs_gt?(n,m))
    fs_gt_def: LEMMA fs_gt?(n,m) => (NOT fs_lt?(n,m) AND NOT fs_eq?(n,m))

    fs_trichotomy: LEMMA fs_lt?(n,m) OR fs_eq?(n,m) OR fs_gt?(n,m)

    fs_le_ge: LEMMA fs_le?(x)(m) AND fs_ge?(x)(n) AND m /= n => m < n

    bisection_sqrt_aux(x:nat,m:(fs_le?(x)),n:(fs_ge?(x))): RECURSIVE nat
      = IF m = n THEN m ELSE LET t = floor((n+m)/2) IN
            IF    fs_lt?(x,t) THEN bisection_sqrt_aux(x,t+1,n)
            ELSIF fs_eq?(x,t) THEN t
                              ELSE bisection_sqrt_aux(x,m,t) ENDIF ENDIF
        MEASURE (LAMBDA (x:nat,m:(fs_le?(x)),n:(fs_ge?(x))): (n-m)+1)

    bisection_sqrt_aux_prop: LEMMA fs_le?(x)(m) AND fs_ge?(x)(n) =>
                                   fs_eq?(x,bisection_sqrt_aux(x,m,n))

    bisection_sqrt(n):nat = bisection_sqrt_aux(n,0,n)

    bisection_sqrt_def: LEMMA bisection_sqrt(n) = floor(sqrt(n))

  END bisection_nat_sqrt

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

  % Subtype TCC generated (at line 33, column 59) for  (n - m) + 1
      % expected type  naturalnumber
  bisection_sqrt_aux_TCC1: OBLIGATION
    FORALL (x: nat, m: (fs_le?(x)), n: (fs_ge?(x))): (n - m) + 1 >= 0;

  % Subtype TCC generated (at line 30, column 25) for  t
      % expected type  nat
  bisection_sqrt_aux_TCC2: OBLIGATION
    FORALL (x: nat, m: (fs_le?(x)), n: (fs_ge?(x))):
      NOT m = n IMPLIES
       (FORALL (t: {i | i <= (m + n) / 2 & (m + n) / 2 < 1 + i}):
          t = floor((n + m) / 2) IMPLIES t >= 0);

  % Subtype TCC generated (at line 30, column 54) for  t + 1
      % expected type  (fs_le?(x))
  bisection_sqrt_aux_TCC3: OBLIGATION
    FORALL (x: nat, m: (fs_le?(x)), n: (fs_ge?(x))):
      NOT m = n IMPLIES
       (FORALL (t: {i | i <= (m + n) / 2 & (m + n) / 2 < 1 + i}):
          fs_lt?(x, t) AND t = floor((n + m) / 2) IMPLIES
           t + 1 >= 0 AND fs_le?(x)(t + 1));

  % Termination TCC generated (at line 30, column 33) for
      % bisection_sqrt_aux(x, t + 1, n)
  bisection_sqrt_aux_TCC4: OBLIGATION
    FORALL (x: nat, m: (fs_le?(x)), n: (fs_ge?(x))):
      NOT m = n IMPLIES
       (FORALL (t: {i | i <= (m + n) / 2 & (m + n) / 2 < 1 + i}):
          fs_lt?(x, t) AND t = floor((n + m) / 2) IMPLIES
           (n - (t + 1)) + 1 < (n - m) + 1);

  % Subtype TCC generated (at line 32, column 56) for  t
      % expected type  (fs_ge?(x))
  bisection_sqrt_aux_TCC5: OBLIGATION
    FORALL (x: nat, m: (fs_le?(x)), n: (fs_ge?(x))):
      NOT m = n IMPLIES
       (FORALL (t: {i | i <= (m + n) / 2 & (m + n) / 2 < 1 + i}):
          NOT fs_eq?(x, t) AND NOT fs_lt?(x, t) AND t = floor((n + m) / 2)
           IMPLIES t >= 0 AND fs_ge?(x)(t));

  % Termination TCC generated (at line 32, column 33) for
      % bisection_sqrt_aux(x, m, t)
  bisection_sqrt_aux_TCC6: OBLIGATION
    FORALL (x: nat, m: (fs_le?(x)), n: (fs_ge?(x))):
      NOT m = n IMPLIES
       (FORALL (t: {i | i <= (m + n) / 2 & (m + n) / 2 < 1 + i}):
          NOT fs_eq?(x, t) AND NOT fs_lt?(x, t) AND t = floor((n + m) / 2)
           IMPLIES (t - m) + 1 < (n - m) + 1);

  % Subtype TCC generated (at line 38, column 47) for  0
      % expected type  (fs_le?(n))
  bisection_sqrt_TCC1: OBLIGATION FORALL (n: nat): fs_le?(n)(0);

  % Subtype TCC generated (at line 38, column 49) for  n
      % expected type  (fs_ge?(n))
  bisection_sqrt_TCC2: OBLIGATION FORALL (n: nat): fs_ge?(n)(n);


body:
  %------------------------------------------------------------------------------
  % sqrt
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  sqrtx: THEORY

  BEGIN

    IMPORTING prelude_aux, appendix, cauchy, unique, reals@sqrt,
              bisection_nat_sqrt

    cx:      VAR cauchy_real
    x:       VAR real
    p,n,r:   VAR nat
    nncx:    VAR cauchy_nnreal
    nnx,nny: VAR nnreal

    nnsqrt(x):nnreal = IF 0 <= x THEN sqrt(x) ELSE 0 ENDIF

    sqrt_p1: LEMMA 0 < n AND r = floor(sqrt(n))
                => (r-1)^2 <= n-1 AND n+1 <= (r+1)^2

    sqrt_p2: LEMMA 0 < n AND r = floor(sqrt(n)) AND
                   n-1 < nnx * 2 ^ (2 * p) AND nnx * 2 ^ (2 * p) < n+1
                => (r-1)^2 < nnx*2 ^ (2 * p) AND nnx*2 ^ (2 * p) < (r+1)^2

    sqrt_p3: LEMMA 0 <= nncx(p)

    cauchy_nnsqrt(nncx): cauchy_nnreal = (LAMBDA p: bisection_sqrt(nncx(2*p)))

    sqrt_nn_lemma: LEMMA cauchy_prop(nnx,nncx)
           => cauchy_prop(sqrt(nnx), cauchy_nnsqrt(nncx))

    cauchy_sqrt(nncx):cauchy_nnreal = cauchy_nnsqrt(nncx)

    sqrt_lemma: LEMMA cauchy_prop(nnx,nncx) =>
                      cauchy_prop(sqrt(nnx),cauchy_sqrt(nncx))

  END sqrtx

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

  % Subtype TCC generated (at line 22, column 41) for  x
      % expected type  nnx: nonneg_real
  nnsqrt_TCC1: OBLIGATION FORALL (x: real): 0 <= x IMPLIES x >= 0;

  % Subtype TCC generated (at line 25, column 23) for  2
      % expected type  {i: int | (r - 1) /= 0 OR i >= 0}
  sqrt_p1_TCC1: OBLIGATION
    FORALL (n, r: nat):
      r = floor(sqrt(n)) AND 0 < n IMPLIES (r - 1) /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 25, column 49) for  2
      % expected type  {i: int | NOT 1 + r = 0 OR i >= 0}
  sqrt_p1_TCC2: OBLIGATION
    FORALL (n, r: nat):
      r = floor(sqrt(n)) AND 0 < n AND (r - 1) ^ 2 <= n - 1 IMPLIES
       NOT 1 + r = 0 OR 2 >= 0;

  % Subtype TCC generated (at line 29, column 71) for  2
      % expected type  {i: int | NOT 1 + r = 0 OR i >= 0}
  sqrt_p2_TCC1: OBLIGATION
    FORALL (n: nat, nnx: nnreal, p, r: nat):
           nnx * 2 ^ (2 * p) < n + 1 AND n - 1 < nnx * 2 ^ (2 * p)
       AND r = floor(sqrt(n)) AND 0 < n AND (r - 1) ^ 2 < nnx * 2 ^ (2 * p)
       IMPLIES NOT 1 + r = 0 OR 2 >= 0;

  % Subtype TCC generated (at line 33, column 65) for  nncx(2 * p)
      % expected type  nat
  cauchy_nnsqrt_TCC1: OBLIGATION
    FORALL (nncx: cauchy_nnreal, p): nncx(2 * p) >= 0;

  % Subtype TCC generated (at line 33, column 40) for
      % (LAMBDA p: bisection_sqrt(nncx(2 * p)))
      % expected type  cauchy_nnreal
  cauchy_nnsqrt_TCC2: OBLIGATION
    FORALL (nncx: cauchy_nnreal):
      cauchy_nnreal?(LAMBDA p: bisection_sqrt(nncx(2 * p)));


body:
  %------------------------------------------------------------------------------
  % Multiplication/division by 2^n
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  shift: THEORY

  BEGIN

    IMPORTING prelude_aux, appendix, cauchy

    x:   VAR real
    cx:  VAR cauchy_real
    n,p: VAR nat

    div2n(x,n):real = x/2^n

    mul2n(x,n):real = x*2^n

    cauchy_div2n(cx,n):cauchy_real
      = (LAMBDA p: IF p >= n THEN cx (p-n) ELSE round (cx(p)/2^n) ENDIF)

    cauchy_mul2n(cx,n):cauchy_real = (LAMBDA p: cx(p+n))

    lemma_div2n: LEMMA cauchy_prop(x,cx) =>
                       cauchy_prop(div2n(x,n),cauchy_div2n(cx,n))

    lemma_mul2n: LEMMA cauchy_prop(x,cx) =>
                       cauchy_prop(mul2n(x,n),cauchy_mul2n(cx,n))

  END shift

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

  % Subtype TCC generated (at line 24, column 36) for  p - n
      % expected type  nat
  cauchy_div2n_TCC1: OBLIGATION FORALL (n: nat, p): p >= n IMPLIES p - n >= 0;

  % Subtype TCC generated (at line 24, column 7) for
      % (LAMBDA p: IF p >= n THEN cx(p - n) ELSE round(cx(p) / 2 ^ n) ENDIF)
      % expected type  cauchy_real
  cauchy_div2n_TCC2: OBLIGATION
    FORALL (cx: cauchy_real, n: nat):
      cauchy_real?(LAMBDA p:
                     IF p >= n THEN cx(p - n)
                     ELSE round(cx(p) / 2 ^ n)
                     ENDIF);

  % Subtype TCC generated (at line 26, column 36) for  (LAMBDA p: cx(p + n))
      % expected type  cauchy_real
  cauchy_mul2n_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, n: nat): cauchy_real?(LAMBDA p: cx(p + n));


body:
  %------------------------------------------------------------------------------
  % Reciprocal
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  inv: THEORY

  BEGIN

    IMPORTING prelude_aux, appendix, cauchy, unique, neg, min_nat[nat]

    cx:   VAR cauchy_real
    x:    VAR real
    s,p:  VAR nat
    nzcx: VAR cauchy_nzreal
    nzx:  VAR nzreal
    pcx:  VAR cauchy_posreal
    px:   VAR posreal
    pn:   VAR posnat
    n,r:  VAR int
    nn:   VAR negint
    nzn:  VAR nzint
    nx:   VAR negreal

    expt_x2:     LEMMA x^2 = x*x
    expt_times2: LEMMA nzx^(2*s) = nzx^s*nzx^s

    minimum_inv_exists: LEMMA nonempty?({s | 3 <= abs(nzcx(s))})

    minimum_inv(nzcx):nat = min_nat.min({s | 3 <= abs(nzcx(s))})

    minimum_inv_prop0: LEMMA s = minimum_inv(nzcx) => 3 <= abs(nzcx(s))

    minimum_inv_prop1: LEMMA s = minimum_inv(nzcx) AND cauchy_prop(x,nzcx)
                       => 2 <= abs(x)*2^s
    minimum_inv_prop2:
       LEMMA 2 <= abs(nzx)*2^s AND n-1 < nzx*2^(p+2*s+2) AND nzx*2^(p+2*s+2)< n+1
             => n /= 0

    minimum_inv_aux(nzcx:cauchy_nzreal,s:{n:nat | n <=  minimum_inv(nzcx)}):
     RECURSIVE nat
      = IF 3 <= abs(nzcx(s)) THEN s ELSE minimum_inv_aux(nzcx,s+1) ENDIF
        MEASURE (LAMBDA (nzcx:cauchy_nzreal,s:{n:nat | n <=  minimum_inv(nzcx)}):
                 IF 3 <= abs(nzcx(s)) THEN 0 
                                ELSE minimum_inv(nzcx)-s ENDIF)

    minimum_inv_impl(nzcx):nat = minimum_inv_aux(nzcx,0)

    minimum_inv_impl_def: LEMMA minimum_inv(nzcx) = minimum_inv_impl(nzcx)

    inv_p0: LEMMA 2^(p+s+3) -1 < pn => 6 <= pn
    inv_p1: LEMMA 2^(p+s+3) -1 < pn => 2^(2*p+2*s+3) < pn*(pn-1)
    inv_p2: LEMMA 2^(p+s+3) -1 < pn => 2^(2*p+2*s+3) < pn*(pn+1)
    inv_p3: LEMMA 2^(p+s+3) -1 < pn => 2^(2*p+2*s+2)/pn -(pn-1)/2 < 0
    inv_p4: LEMMA 2^(p+s+3) -1 < pn => 2^(2*p+2*s+2)/pn -(pn+1)/2 < 0
    inv_p5: LEMMA r = round(2^(2*p+2*s+2)/pn) AND 2^(p+s+3) -1 < pn
                                    => (r-1)*(pn+1) < 2^(2*p+2*s+2)
    inv_p6: LEMMA r = round(2^(2*p+2*s+2)/pn) AND 2^(p+s+3) -1 < pn
                                    => 2^(2*p+2*s+2) < (r+1)*(pn-1)
    inv_p7: LEMMA r = round(2^(2*p+2*s+2)/pn) AND 2^(p+s+3) -1 < pn
                => (r-1)/2^p < 2^(p+2*s+2)/(pn+1) AND
                        2^(p+2*s+2)/(pn-1) < (r+1)/2^p

    inv_p8: LEMMA 2 <= px*2^s AND pn-1 < px*2^(p+2*s+2) AND px*2^(p+2*s+2) < pn+1
                => 2^(p+s+3) -1 < pn

    inv_p9: LEMMA 2 <= px*2^s AND r = round(2^(2*p+2*s+2)/pn) AND
                  pn-1 < px*2^(p+2*s+2) AND px*2^(p+2*s+2) < pn+1
                => (r-1)*px < 2^p AND 2^p < (r+1)*px

    inv_n5: LEMMA r = round(2^(2*p+2*s+2)/nn) AND 2^(p+s+3) -1 < -1*nn
                                    => (r-1) < 2^(2*p+2*s+2)/(nn+1)
    inv_n6: LEMMA r = round(2^(2*p+2*s+2)/nn) AND 2^(p+s+3) -1 < -1*nn
                                    => 2^(2*p+2*s+2)/(nn-1) < (r+1)
    inv_n7: LEMMA r = round(2^(2*p+2*s+2)/nn) AND 2^(p+s+3) -1 < -nn
                => (r-1)/2^p < 2^(p+2*s+2)/(nn+1) AND
                        2^(p+2*s+2)/(nn-1) < (r+1)/2^p

    inv_n8: LEMMA 2 <= -nx*2^s AND nn-1 < nx*2^(p+2*s+2) AND nx*2^(p+2*s+2) < nn+1
                => 2^(p+s+3) -1 < -nn

    inv_n9: LEMMA 2 <= -nx*2^s AND r = round(2^(2*p+2*s+2)/nn) AND
                  nn-1 < nx*2^(p+2*s+2) AND nx*2^(p+2*s+2) < nn+1
                => (r-1) < 2^p/nx AND 2^p/nx < (r+1)

    inv_p: LEMMA 2 <= abs(nzx)*2^s AND r = round(2^(2*p+2*s+2)/nzn) AND
                  nzn-1 < nzx*2^(p+2*s+2) AND nzx*2^(p+2*s+2) < nzn+1
                => (r-1) < 2^p/nzx AND 2^p/nzx < (r+1)


    minimum_inv_prop3: LEMMA s = minimum_inv(nzcx) AND cauchy_prop(nzx,nzcx) =>
            cauchy_prop(1/nzx,LAMBDA p: round(2^(2*p+2*s+2)/nzcx(p+2*s+2)))

    cauchy_nz_inv(nzcx:cauchy_nzreal):cauchy_nzreal
      = (LAMBDA p: LET s = minimum_inv_impl(nzcx)
                   IN round(2^(2*p+2*s+2)/nzcx(p+2*s+2)))

    inv_nz_lemma: LEMMA cauchy_prop(nzx,nzcx)
           => cauchy_prop(1/nzx, cauchy_nz_inv(nzcx))

    cauchy_inv(nzcx): cauchy_nzreal = cauchy_nz_inv(nzcx)

    inv(nzx:nonzero_real):nzreal = 1/nzx

    inv_lemma: LEMMA cauchy_prop(nzx,nzcx) => cauchy_prop(1/nzx,cauchy_inv(nzcx))

  END inv

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

  % Subtype TCC generated (at line 28, column 23) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  expt_x2_TCC1: OBLIGATION FORALL (x: real): x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 29, column 26) for  (2 * s)
      % expected type  {i: int | nzx /= 0 OR i >= 0}
  expt_times2_TCC1: OBLIGATION
    FORALL (nzx: nzreal, s: nat): nzx /= 0 OR (2 * s) >= 0;

  % Subtype TCC generated (at line 29, column 37) for  s
      % expected type  {i: int | nzx /= 0 OR i >= 0}
  expt_times2_TCC2: OBLIGATION
    FORALL (nzx: nzreal, s: nat): nzx /= 0 OR s >= 0;

  % Subtype TCC generated (at line 33, column 38) for  {s | 3 <= abs(nzcx(s))}
      % expected type  S: (nonempty?[nat])
  minimum_inv_TCC1: OBLIGATION
    FORALL (nzcx: cauchy_nzreal): nonempty?[nat]({s | 3 <= abs(nzcx(s))});

  % Subtype TCC generated (at line 48, column 35) for  minimum_inv(nzcx) - s
      % expected type  naturalnumber
  minimum_inv_aux_TCC1: OBLIGATION
    FORALL (nzcx: cauchy_nzreal, s: {n: nat | n <= minimum_inv(nzcx)}):
      NOT 3 <= abs(nzcx(s)) IMPLIES minimum_inv(nzcx) - s >= 0;

  % Subtype TCC generated (at line 45, column 60) for  s + 1
      % expected type  {n: nat | n <= minimum_inv(nzcx)}
  minimum_inv_aux_TCC2: OBLIGATION
    FORALL (nzcx: cauchy_nzreal, s: {n: nat | n <= minimum_inv(nzcx)}):
      NOT 3 <= abs(nzcx(s)) IMPLIES s + 1 <= minimum_inv(nzcx);

  % Termination TCC generated (at line 45, column 39) for
      % minimum_inv_aux(nzcx, s + 1)
  minimum_inv_aux_TCC3: OBLIGATION
    FORALL (nzcx: cauchy_nzreal, s: {n: nat | n <= minimum_inv(nzcx)}):
      NOT 3 <= abs(nzcx(s)) IMPLIES
       IF 3 <= abs(nzcx(s + 1)) THEN 0 ELSE minimum_inv(nzcx) - (s + 1) ENDIF
        < IF 3 <= abs(nzcx(s)) THEN 0 ELSE minimum_inv(nzcx) - s ENDIF;

  % Subtype TCC generated (at line 50, column 52) for  0
      % expected type  {n: nat | n <= minimum_inv(nzcx)}
  minimum_inv_impl_TCC1: OBLIGATION
    FORALL (nzcx: cauchy_nzreal): 0 <= minimum_inv(nzcx);

  % Subtype TCC generated (at line 65, column 35) for  (pn - 1)
      % expected type  nznum
  inv_p7_TCC1: OBLIGATION
    FORALL (p: nat, pn: posnat, r: int, s: nat):
      2 ^ (p + s + 3) - 1 < pn AND
       r = round(2 ^ (2 * p + 2 * s + 2) / pn) AND
        (r - 1) / 2 ^ p < 2 ^ (p + 2 * s + 2) / (pn + 1)
       IMPLIES (pn - 1) /= 0;

  % Subtype TCC generated (at line 75, column 60) for  (nn + 1)
      % expected type  nznum
  inv_n5_TCC1: OBLIGATION
    FORALL (nn: negint, p: nat, r: int, s: nat):
      2 ^ (p + s + 3) - 1 < -1 * nn AND
       r = round(2 ^ (2 * p + 2 * s + 2) / nn)
       IMPLIES (nn + 1) /= 0;

  % Subtype TCC generated (at line 77, column 52) for  (nn - 1)
      % expected type  nznum
  inv_n6_TCC1: OBLIGATION
    FORALL (nn: negint, p: nat, r: int, s: nat):
      2 ^ (p + s + 3) - 1 < -1 * nn AND
       r = round(2 ^ (2 * p + 2 * s + 2) / nn)
       IMPLIES (nn - 1) /= 0;

  % Subtype TCC generated (at line 79, column 42) for  (nn + 1)
      % expected type  nznum
  inv_n7_TCC1: OBLIGATION
    FORALL (nn: negint, p: nat, r: int, s: nat):
      2 ^ (p + s + 3) - 1 < -nn AND r = round(2 ^ (2 * p + 2 * s + 2) / nn)
       IMPLIES (nn + 1) /= 0;

  % Subtype TCC generated (at line 80, column 35) for  (nn - 1)
      % expected type  nznum
  inv_n7_TCC2: OBLIGATION
    FORALL (nn: negint, p: nat, r: int, s: nat):
      2 ^ (p + s + 3) - 1 < -nn AND
       r = round(2 ^ (2 * p + 2 * s + 2) / nn) AND
        (r - 1) / 2 ^ p < 2 ^ (p + 2 * s + 2) / (nn + 1)
       IMPLIES (nn - 1) /= 0;

  % Subtype TCC generated (at line 95, column 58) for  nzcx(p + 2 * s + 2)
      % expected type  nznum
  minimum_inv_prop3_TCC1: OBLIGATION
    FORALL (nzcx: cauchy_nzreal, nzx: nzreal, s: nat):
      cauchy_prop(nzx, nzcx) AND s = minimum_inv(nzcx) IMPLIES
       (FORALL (p): nzcx(p + 2 * s + 2) /= 0);

  % Subtype TCC generated (at line 99, column 40) for  nzcx(p + 2 * s + 2)
      % expected type  nznum
  cauchy_nz_inv_TCC1: OBLIGATION
    FORALL (nzcx: cauchy_nzreal, p, s: nat):
      s = minimum_inv_impl(nzcx) IMPLIES nzcx(p + 2 * s + 2) /= 0;

  % Subtype TCC generated (at line 98, column 7) for
      % (LAMBDA p:
      %    LET s = minimum_inv_impl(nzcx) IN
      %      round(2 ^ (2 * p + 2 * s + 2) / nzcx(p + 2 * s + 2)))
      % expected type  cauchy_nzreal
  cauchy_nz_inv_TCC2: OBLIGATION
    FORALL (nzcx: cauchy_nzreal):
      cauchy_nzreal?((LAMBDA p:
                        LET s = minimum_inv_impl(nzcx) IN
                          round(2 ^ (2 * p + 2 * s + 2) /
                                 nzcx(p + 2 * s + 2))));


body:
  %------------------------------------------------------------------------------
  % Division
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  div: THEORY

  BEGIN

    IMPORTING mul, inv

    x,y:   VAR real
    nzy:   VAR nonzero_real
    cx,cy: VAR cauchy_real
    nzcy:  VAR cauchy_nzreal
    
    div(x,nzy):real = x * inv(nzy)

    cauchy_div(cx,nzcy):cauchy_real = cauchy_mul (cx, cauchy_inv(nzcy))

    div_lemma: LEMMA cauchy_prop(x,cx) AND cauchy_prop(nzy,nzcy)
                     => cauchy_prop(x/nzy, cauchy_div(cx,nzcy))

  END div


body:
  %------------------------------------------------------------------------------
  % Integer equivalence
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  int: THEORY

    BEGIN
    IMPORTING cauchy

    p,m: VAR nat
    n:   VAR int

    cauchy_int(n:int):cauchy_real   = (LAMBDA p: n*2^p)
    cauchy_nat(n:nat):cauchy_nnreal = (LAMBDA p: n*2^p)

    int_lemma: LEMMA cauchy_prop(n, cauchy_int(n))

    nat_lemma: LEMMA cauchy_prop(m, cauchy_nat(m))

    END int

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

  % Subtype TCC generated (at line 17, column 37) for  (LAMBDA p: n * 2 ^ p)
      % expected type  cauchy_real
  cauchy_int_TCC1: OBLIGATION
    FORALL (n: int): cauchy_real?((LAMBDA p: n * 2 ^ p));

  % Subtype TCC generated (at line 18, column 37) for  (LAMBDA p: n * 2 ^ p)
      % expected type  cauchy_nnreal
  cauchy_nat_TCC1: OBLIGATION
    FORALL (n: nat): cauchy_nnreal?((LAMBDA p: n * 2 ^ p));


body:
  sub: THEORY

    BEGIN
    IMPORTING add
    IMPORTING neg

    cx,cy: VAR cauchy_real
    x,y:   VAR real
    p:     VAR nat

    cauchy_sub(cx,cy:cauchy_real):cauchy_real
      = cauchy_add(cx,cauchy_neg(cy))

    sub_lemma: LEMMA cauchy_prop(x,cx) AND cauchy_prop(y,cy)
                     => cauchy_prop(x-y, cauchy_sub(cx,cy))

    END sub


body:
  %------------------------------------------------------------------------------
  % log
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  log: THEORY

  BEGIN

    IMPORTING prelude_aux, cauchy, add, sub, neg, int, inv, mul, div, shift,
              sqrtx, powerseries, lnexp_fnd@ln_exp, lnexp_fnd@ln_exp_series_alt

    x:   VAR real
    c:   VAR [nat->int]
    n,p: VAR nat

    ln_smallreal: TYPE+ = {x | -1/2 <= x & x <= 1/2} CONTAINING 0

    cauchy_ln_small?(c):bool = EXISTS (x:ln_smallreal): cauchy_prop(x,c)

    cauchy_ln_small: TYPE+ = (cauchy_ln_small?) CONTAINING cauchy_int(0)

    JUDGEMENT cauchy_ln_small SUBTYPE_OF cauchy_real

    ln_medreal: TYPE+ = {x | 1/4 <= x & x <= 9/4} CONTAINING 1

    cauchy_ln_med?(c):bool = EXISTS (x:ln_medreal): cauchy_prop(x,c)

    cauchy_ln_med: TYPE+ = (cauchy_ln_med?) CONTAINING cauchy_int(1)

    JUDGEMENT cauchy_ln_med SUBTYPE_OF cauchy_posreal

    posreal_gt_quarter: TYPE+ = {x | 1/4 < x} CONTAINING 1

    cauchy_gt_quarter?(c):bool = EXISTS (x:posreal_gt_quarter): cauchy_prop(x,c)

    cauchy_gt_quarter: TYPE+ = (cauchy_gt_quarter?) CONTAINING cauchy_int(1)

    JUDGEMENT cauchy_gt_quarter SUBTYPE_OF cauchy_posreal

    ssx:    VAR ln_smallreal
    cssx:   VAR cauchy_ln_small
    mx:     VAR ln_medreal
    cmx:    VAR cauchy_ln_med
    gt_14:  VAR posreal_gt_quarter
    cgt_14: VAR cauchy_gt_quarter
    px:     VAR posreal
    pcx:    VAR cauchy_posreal

    cauchy_ln_series(n:nat): cauchy_real
      = IF    n = 0    THEN cauchy_zero
        ELSIF even?(n) THEN cauchy_div(cauchy_int(-1),cauchy_int(n))
                       ELSE cauchy_div(cauchy_int( 1),cauchy_int(n)) ENDIF

    ln_series_lemma: LEMMA
      cauchy_prop(IF n = 0 THEN 0 ELSE lnT(1)(n-1) ENDIF, cauchy_ln_series(n))

    ln_estimate_lemma:
      LEMMA cauchy_prop(ssx,cssx) =>
            cauchy_prop(ln_estimate(ssx,n),
                        cauchy_powerseries(cssx,cauchy_ln_series,n))

    cauchy_ln_drx(cssx)(p):int
     = round(cauchy_powerseries(cssx,cauchy_ln_series,p+2)(p+2)/4)

    ln_drx_lemma: LEMMA cauchy_prop(ssx,cssx) =>
                        cauchy_prop(ln(1+ssx),cauchy_ln_drx(cssx))

    JUDGEMENT cauchy_ln_drx(cssx) HAS_TYPE cauchy_real

    cauchy_ln_half:cauchy_negreal
     = cauchy_ln_drx(cauchy_neg(cauchy_div2n(cauchy_int(1),1)))

    cauchy_ln_half_lemma: LEMMA cauchy_prop(ln(1/2),cauchy_ln_half)

    cauchy_ln2:cauchy_posreal = cauchy_neg(cauchy_ln_half)

    cauchy_ln2_lemma: LEMMA cauchy_prop(ln(2),cauchy_ln2)

    cauchy_ln_sqrt2:cauchy_posreal = cauchy_div2n(cauchy_ln2,1)

    cauchy_ln_sqrt2_lemma: LEMMA cauchy_prop(ln(sqrt(2)),cauchy_ln_sqrt2)

    cauchy_ln_dr(cmx):cauchy_real
     = IF   3 <= cmx(2) AND cmx(2) <= 5
       THEN cauchy_ln_drx(cauchy_sub(cmx,cauchy_int(1)))
       ELSE cauchy_mul2n(
                cauchy_ln_drx(cauchy_sub(cauchy_sqrt(cmx),cauchy_int(1))),1)
       ENDIF

    ln_dr_lemma: LEMMA cauchy_prop(mx,cmx) =>
                       cauchy_prop(ln(mx),cauchy_ln_dr(cmx))

    cauchy_lnx(cgt_14):[nat->int]
     = LET t = cgt_14(2) IN
       IF t <= 8 THEN cauchy_ln_dr(cgt_14) ELSE
          LET n = floor_log2(t) - 1 IN
              cauchy_add(cauchy_ln_dr(cauchy_div2n(cgt_14,n)),
                         cauchy_mul(cauchy_int(n),cauchy_ln2))
       ENDIF

    ln_lemma_x: LEMMA cauchy_prop(gt_14,cgt_14) =>
                          cauchy_prop(ln(gt_14),cauchy_lnx(cgt_14))

    JUDGEMENT cauchy_lnx(cgt_14) HAS_TYPE cauchy_real

    cauchy_ln(pcx):cauchy_real
     = IF pcx(2) <= 2 THEN cauchy_neg(cauchy_lnx(cauchy_inv(pcx)))
                      ELSE cauchy_lnx(pcx) ENDIF

    ln_lemma: LEMMA cauchy_prop(px,pcx) => cauchy_prop(ln(px),cauchy_ln(pcx))

  END log

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

  % Subtype TCC generated (at line 24, column 57) for  cauchy_int(0)
      % expected type  cauchy_ln_small
  cauchy_ln_small_TCC1: OBLIGATION cauchy_ln_small?(cauchy_int(0));

  % Judgement subtype TCC generated (at line 26, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC1: OBLIGATION FORALL (x: cauchy_ln_small): cauchy_real?(x);

  % Subtype TCC generated (at line 32, column 53) for  cauchy_int(1)
      % expected type  cauchy_ln_med
  cauchy_ln_med_TCC1: OBLIGATION cauchy_ln_med?(cauchy_int(1));

  % Judgement subtype TCC generated (at line 34, column 12) for  x
      % expected type  cauchy_posreal
  subtype_TCC2: OBLIGATION FORALL (x: cauchy_ln_med): cauchy_posreal?(x);

  % Subtype TCC generated (at line 40, column 61) for  cauchy_int(1)
      % expected type  cauchy_gt_quarter
  cauchy_gt_quarter_TCC1: OBLIGATION cauchy_gt_quarter?(cauchy_int(1));

  % Judgement subtype TCC generated (at line 42, column 12) for  x
      % expected type  cauchy_posreal
  subtype_TCC3: OBLIGATION FORALL (x: cauchy_gt_quarter): cauchy_posreal?(x);

  % Subtype TCC generated (at line 55, column 52) for  cauchy_int(n)
      % expected type  cauchy_nzreal
  cauchy_ln_series_TCC1: OBLIGATION
    FORALL (n: nat):
      even?(n) AND NOT n = 0 IMPLIES cauchy_nzreal?(cauchy_int(n));

  % Subtype TCC generated (at line 56, column 52) for  cauchy_int(n)
      % expected type  cauchy_nzreal
  cauchy_ln_series_TCC2: OBLIGATION
    FORALL (n: nat):
      NOT even?(n) AND NOT n = 0 IMPLIES cauchy_nzreal?(cauchy_int(n));

  % Subtype TCC generated (at line 59, column 44) for  n - 1
      % expected type  nat
  ln_series_lemma_TCC1: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Subtype TCC generated (at line 64, column 46) for  cauchy_ln_series
      % expected type  cauchys_real
  ln_estimate_lemma_TCC1: OBLIGATION
    FORALL (cssx: cauchy_ln_small, ssx: ln_smallreal):
      cauchy_prop(ssx, cssx) IMPLIES cauchys_real?(cauchy_ln_series);

  % Subtype TCC generated (at line 67, column 35) for  cauchy_ln_series
      % expected type  cauchys_real
  cauchy_ln_drx_TCC1: OBLIGATION cauchys_real?(cauchy_ln_series);

  % Subtype TCC generated (at line 70, column 37) for  1 + ssx
      % expected type  posreal
  ln_drx_lemma_TCC1: OBLIGATION
    FORALL (cssx: cauchy_ln_small, ssx: ln_smallreal):
      cauchy_prop(ssx, cssx) IMPLIES 1 + ssx >= 0 AND 1 + ssx > 0;

  % Judgement subtype TCC generated (at line 72, column 12) for
      % cauchy_ln_drx(cssx)
      % expected type  cauchy_real
  cauchy_ln_drx_TCC2: OBLIGATION
    FORALL (cssx): cauchy_real?(cauchy_ln_drx(cssx));

  % Subtype TCC generated (at line 75, column 19) for
      % cauchy_neg(cauchy_div2n(cauchy_int(1), 1))
      % expected type  cauchy_ln_small
  cauchy_ln_half_TCC1: OBLIGATION
    cauchy_ln_small?(cauchy_neg(cauchy_div2n(cauchy_int(1), 1)));

  % Subtype TCC generated (at line 75, column 5) for
      % cauchy_ln_drx(cauchy_neg(cauchy_div2n(cauchy_int(1), 1)))
      % expected type  cauchy_negreal
  cauchy_ln_half_TCC2: OBLIGATION
    cauchy_negreal?(cauchy_ln_drx(cauchy_neg(cauchy_div2n
                                             (cauchy_int(1), 1))));

  % Subtype TCC generated (at line 83, column 35) for
      % cauchy_div2n(cauchy_ln2, 1)
      % expected type  cauchy_posreal
  cauchy_ln_sqrt2_TCC1: OBLIGATION
    cauchy_posreal?(cauchy_div2n(cauchy_ln2, 1));

  % Subtype TCC generated (at line 89, column 24) for
      % cauchy_sub(cmx, cauchy_int(1))
      % expected type  cauchy_ln_small
  cauchy_ln_dr_TCC1: OBLIGATION
    FORALL (cmx: cauchy_ln_med):
      3 <= cmx(2) AND cmx(2) <= 5 IMPLIES
       cauchy_ln_small?(cauchy_sub(cmx, cauchy_int(1)));

  % Subtype TCC generated (at line 91, column 28) for
      % cauchy_sub(cauchy_sqrt(cmx), cauchy_int(1))
      % expected type  cauchy_ln_small
  cauchy_ln_dr_TCC2: OBLIGATION
    FORALL (cmx: cauchy_ln_med):
      NOT (3 <= cmx(2) AND cmx(2) <= 5) IMPLIES
       cauchy_ln_small?(cauchy_sub(cauchy_sqrt(cmx), cauchy_int(1)));

  % Subtype TCC generated (at line 95, column 36) for  mx
      % expected type  posreal
  ln_dr_lemma_TCC1: OBLIGATION
    FORALL (cmx: cauchy_ln_med, mx: ln_medreal):
      cauchy_prop(mx, cmx) IMPLIES mx >= 0 AND mx > 0;

  % Subtype TCC generated (at line 99, column 33) for  cgt_14
      % expected type  cauchy_ln_med
  cauchy_lnx_TCC1: OBLIGATION
    FORALL (cgt_14: cauchy_gt_quarter, t: int):
      t <= 8 AND t = cgt_14(2) IMPLIES cauchy_ln_med?(cgt_14);

  % Subtype TCC generated (at line 100, column 27) for  t
      % expected type  posnat
  cauchy_lnx_TCC2: OBLIGATION
    FORALL (cgt_14: cauchy_gt_quarter, t: int):
      NOT t <= 8 AND t = cgt_14(2) IMPLIES t >= 0 AND t > 0;

  % Subtype TCC generated (at line 101, column 56) for  n
      % expected type  nat
  cauchy_lnx_TCC3: OBLIGATION
    FORALL (cgt_14: cauchy_gt_quarter, t: int):
      NOT t <= 8 AND t = cgt_14(2) IMPLIES
       (FORALL (n: int): n = floor_log2(t) - 1 IMPLIES n >= 0);

  % Subtype TCC generated (at line 101, column 36) for
      % cauchy_div2n(cgt_14, n)
      % expected type  cauchy_ln_med
  cauchy_lnx_TCC4: OBLIGATION
    FORALL (cgt_14: cauchy_gt_quarter, t: int):
      NOT t <= 8 AND t = cgt_14(2) IMPLIES
       (FORALL (n: int):
          n = floor_log2(t) - 1 IMPLIES
           cauchy_ln_med?(cauchy_div2n(cgt_14, n)));

  % Subtype TCC generated (at line 106, column 39) for  gt_14
      % expected type  posreal
  ln_lemma_x_TCC1: OBLIGATION
    FORALL (cgt_14: cauchy_gt_quarter, gt_14: posreal_gt_quarter):
      cauchy_prop(gt_14, cgt_14) IMPLIES gt_14 >= 0 AND gt_14 > 0;

  % Judgement subtype TCC generated (at line 108, column 12) for
      % cauchy_lnx(cgt_14)
      % expected type  cauchy_real
  cauchy_lnx_TCC5: OBLIGATION
    FORALL (cgt_14): cauchy_real?(cauchy_lnx(cgt_14));

  % Subtype TCC generated (at line 111, column 47) for  cauchy_inv(pcx)
      % expected type  cauchy_gt_quarter
  cauchy_ln_TCC1: OBLIGATION
    FORALL (pcx: cauchy_posreal):
      pcx(2) <= 2 IMPLIES cauchy_gt_quarter?(cauchy_inv(pcx));

  % Subtype TCC generated (at line 112, column 36) for  pcx
      % expected type  cauchy_gt_quarter
  cauchy_ln_TCC2: OBLIGATION
    FORALL (pcx: cauchy_posreal):
      NOT pcx(2) <= 2 IMPLIES cauchy_gt_quarter?(pcx);


body:
  %------------------------------------------------------------------------------
  % exp
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  exp: THEORY

  BEGIN

    IMPORTING prelude_aux, cauchy, inv, int, shift, powerseries, log,
              reals@factorial, lnexp_fnd@ln_exp, lnexp_fnd@ln_exp_series_alt,
              lnexp_fnd@ln_approx

    n,p: VAR nat
    x:   VAR real
    cx:  VAR cauchy_real
    sx:  VAR smallreal
    csx: VAR cauchy_smallreal

    cauchy_exp_series(n): cauchy_nnreal = cauchy_inv(cauchy_int(factorial(n)))

    exp_series_lemma: LEMMA cauchy_prop(expT(1)(n), cauchy_exp_series(n))

    exp_estimate_lemma:
      LEMMA cauchy_prop(x,cx) =>
            cauchy_prop(exp_estimate(x,n),
                        cauchy_powerseries(cx,cauchy_exp_series,n))

    cauchy_exp_dr(csx)(p):int
      = round(cauchy_powerseries(csx,cauchy_exp_series,p+3)(p+2)/4)

    exp_dr_lemma: LEMMA cauchy_prop(sx,csx) =>
                        cauchy_prop(exp(sx),cauchy_exp_dr(csx))

    JUDGEMENT cauchy_exp_dr(csx) HAS_TYPE cauchy_posreal

    cauchy_exp(cx):[nat->int]
      = LET n  = cauchy_div(cx,cauchy_ln2)(0),
            cy = cauchy_sub(cx,cauchy_mul(cauchy_int(n),cauchy_ln2))
        IN IF    n < 0 THEN cauchy_div2n(cauchy_exp_dr(cy),-n)
           ELSIF n > 0 THEN cauchy_mul2n(cauchy_exp_dr(cy),n)
                       ELSE cauchy_exp_dr(cy) ENDIF

    exp_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(exp(x),cauchy_exp(cx))

    cauchy_exp_is_posreal: JUDGEMENT cauchy_exp(cx) HAS_TYPE cauchy_posreal

  END exp

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

  % Subtype TCC generated (at line 23, column 51) for
      % cauchy_int(factorial(n))
      % expected type  cauchy_nzreal
  cauchy_exp_series_TCC1: OBLIGATION
    FORALL (n: nat): cauchy_nzreal?(cauchy_int(factorial(n)));

  % Subtype TCC generated (at line 23, column 40) for
      % cauchy_inv(cauchy_int(factorial(n)))
      % expected type  cauchy_nnreal
  cauchy_exp_series_TCC2: OBLIGATION
    FORALL (n: nat): cauchy_nnreal?(cauchy_inv(cauchy_int(factorial(n))));

  % Subtype TCC generated (at line 30, column 44) for  cauchy_exp_series
      % expected type  cauchys_real
  exp_estimate_lemma_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, x: real):
      cauchy_prop(x, cx) IMPLIES cauchys_real?(cauchy_exp_series);

  % Subtype TCC generated (at line 33, column 35) for  cauchy_exp_series
      % expected type  cauchys_real
  cauchy_exp_dr_TCC1: OBLIGATION cauchys_real?(cauchy_exp_series);

  % Judgement subtype TCC generated (at line 38, column 12) for
      % cauchy_exp_dr(csx)
      % expected type  cauchy_posreal
  cauchy_exp_dr_TCC2: OBLIGATION
    FORALL (csx): cauchy_posreal?(cauchy_exp_dr(csx));

  % Subtype TCC generated (at line 43, column 53) for  cy
      % expected type  cauchy_smallreal
  cauchy_exp_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, n: int):
      n = cauchy_div(cx, cauchy_ln2)(0) IMPLIES
       (FORALL (cy: cauchy_real):
          n < 0 AND
           cy = cauchy_sub(cx, cauchy_mul(cauchy_int(n), cauchy_ln2))
           IMPLIES cauchy_smallreal?(cy));

  % Subtype TCC generated (at line 43, column 57) for  -n
      % expected type  nat
  cauchy_exp_TCC2: OBLIGATION
    FORALL (cx: cauchy_real, n: int):
      n = cauchy_div(cx, cauchy_ln2)(0) IMPLIES
       (FORALL (cy: cauchy_real):
          n < 0 AND
           cy = cauchy_sub(cx, cauchy_mul(cauchy_int(n), cauchy_ln2))
           IMPLIES -n >= 0);

  % Subtype TCC generated (at line 44, column 53) for  cy
      % expected type  cauchy_smallreal
  cauchy_exp_TCC3: OBLIGATION
    FORALL (cx: cauchy_real, n: int):
      n = cauchy_div(cx, cauchy_ln2)(0) IMPLIES
       (FORALL (cy: cauchy_real):
          n > 0 AND
           NOT n < 0 AND
            cy = cauchy_sub(cx, cauchy_mul(cauchy_int(n), cauchy_ln2))
           IMPLIES cauchy_smallreal?(cy));

  % Subtype TCC generated (at line 44, column 57) for  n
      % expected type  nat
  cauchy_exp_TCC4: OBLIGATION
    FORALL (cx: cauchy_real, n: int):
      n = cauchy_div(cx, cauchy_ln2)(0) IMPLIES
       (FORALL (cy: cauchy_real):
          n > 0 AND
           NOT n < 0 AND
            cy = cauchy_sub(cx, cauchy_mul(cauchy_int(n), cauchy_ln2))
           IMPLIES n >= 0);

  % Subtype TCC generated (at line 45, column 40) for  cy
      % expected type  cauchy_smallreal
  cauchy_exp_TCC5: OBLIGATION
    FORALL (cx: cauchy_real, n: int):
      n = cauchy_div(cx, cauchy_ln2)(0) IMPLIES
       (FORALL (cy: cauchy_real):
          NOT n > 0 AND
           NOT n < 0 AND
            cy = cauchy_sub(cx, cauchy_mul(cauchy_int(n), cauchy_ln2))
           IMPLIES cauchy_smallreal?(cy));

  % Judgement subtype TCC generated (at line 49, column 35) for  cauchy_exp(cx)
      % expected type  cauchy_posreal
  cauchy_exp_is_posreal: OBLIGATION
    FORALL (cx): cauchy_posreal?(cauchy_exp(cx));


body:
  %------------------------------------------------------------------------------
  % Hyperbolic functions
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  hyperbolicx: THEORY

  BEGIN

    IMPORTING lnexp_fnd@hyperbolic, log, exp

    x:    VAR real
    nzx:  VAR nzreal
    sx:   VAR smallreal
    cx:   VAR cauchy_real
    cnzx: VAR cauchy_nzreal
    csx:  VAR cauchy_smallreal

    cauchy_sinh(cx):  [nat->int]
     = cauchy_div2n(cauchy_sub(cauchy_exp(cx),cauchy_exp(cauchy_neg(cx))),1)
    cauchy_cosh(cx):  [nat->int]
     = cauchy_div2n(cauchy_add(cauchy_exp(cx),cauchy_exp(cauchy_neg(cx))),1)

    sinh_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(sinh(x),cauchy_sinh(cx))
    cosh_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(cosh(x),cauchy_cosh(cx))

    cauchy_sinh_type: JUDGEMENT cauchy_sinh(cx)   HAS_TYPE cauchy_real
    cauchy_cosh_type: JUDGEMENT cauchy_cosh(cx)   HAS_TYPE cauchy_posreal

    cauchy_coth(cnzx):[nat->int]
     = cauchy_div(cauchy_cosh(cnzx),cauchy_sinh(cnzx))

    cauchy_tanh(cx):  [nat->int] = cauchy_div(cauchy_sinh(cx),cauchy_cosh(cx))
    cauchy_csch(cnzx):[nat->int] = cauchy_inv(cauchy_sinh(cnzx))
    cauchy_sech(cx)  :[nat->int] = cauchy_inv(cauchy_cosh(cx))

    tanh_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(tanh(x),cauchy_tanh(cx))
    sech_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(sech(x),cauchy_sech(cx))
    coth_lemma: LEMMA cauchy_prop(nzx,cnzx)
                                     => cauchy_prop(coth(nzx),cauchy_coth(cnzx))
    csch_lemma: LEMMA cauchy_prop(nzx,cnzx)
                                     => cauchy_prop(csch(nzx),cauchy_csch(cnzx))

    cauchy_tanh_type: JUDGEMENT cauchy_tanh(cx)   HAS_TYPE cauchy_smallreal
    cauchy_coth_type: JUDGEMENT cauchy_coth(cnzx) HAS_TYPE cauchy_nzreal
    cauchy_csch_type: JUDGEMENT cauchy_csch(cnzx) HAS_TYPE cauchy_nzreal
    cauchy_sech_type: JUDGEMENT cauchy_sech(cx)   HAS_TYPE cauchy_posreal


    cauchy_ge1?(c:[nat->int]):bool = EXISTS (x:posreal_ge1): cauchy_prop(x,c)

    cauchy_ge1: TYPE+ = (cauchy_ge1?) CONTAINING cauchy_int(1)

    JUDGEMENT cauchy_ge1 SUBTYPE_OF cauchy_posreal

    ge1x:  VAR posreal_ge1
    cge1x: VAR cauchy_ge1

    cauchy_asinh(cx):[nat->int]
     = cauchy_ln(cauchy_add(cx,cauchy_sqrt(cauchy_add(cauchy_mul(cx,cx),
                                                      cauchy_int(1)))))

    cauchy_acosh(cge1x):[nat->int]
     = cauchy_ln(cauchy_add(cge1x,cauchy_sqrt(cauchy_sub(cauchy_mul(cge1x,cge1x),
                                                         cauchy_int(1)))))

    cauchy_atanh(csx):[nat->int]
     = cauchy_div2n(cauchy_ln(cauchy_div(cauchy_add(cauchy_int(1),csx),
                                         cauchy_sub(cauchy_int(1),csx))),1)

    asinh_lemma: LEMMA cauchy_prop(x,cx) =>
                       cauchy_prop(asinh(x),cauchy_asinh(cx))
    acosh_lemma: LEMMA cauchy_prop(ge1x,cge1x) =>
                       cauchy_prop(acosh(ge1x),cauchy_acosh(cge1x))
    atanh_lemma: LEMMA cauchy_prop(sx,csx) =>
                       cauchy_prop(atanh(sx),cauchy_atanh(csx))

    cauchy_asinh_type: JUDGEMENT cauchy_asinh(cx)    HAS_TYPE cauchy_real
    cauchy_acosh_type: JUDGEMENT cauchy_acosh(cge1x) HAS_TYPE cauchy_nnreal
    cauchy_atanh_type: JUDGEMENT cauchy_atanh(csx)   HAS_TYPE cauchy_real

  END hyperbolicx

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

  % Judgement subtype TCC generated (at line 30, column 30) for
      % cauchy_sinh(cx)
      % expected type  cauchy_real
  cauchy_sinh_type: OBLIGATION FORALL (cx): cauchy_real?(cauchy_sinh(cx));

  % Judgement subtype TCC generated (at line 31, column 30) for
      % cauchy_cosh(cx)
      % expected type  cauchy_posreal
  cauchy_cosh_type: OBLIGATION FORALL (cx): cauchy_posreal?(cauchy_cosh(cx));

  % Subtype TCC generated (at line 34, column 34) for  cauchy_sinh(cnzx)
      % expected type  cauchy_nzreal
  cauchy_coth_TCC1: OBLIGATION
    FORALL (cnzx: cauchy_nzreal): cauchy_nzreal?(cauchy_sinh(cnzx));

  % Judgement subtype TCC generated (at line 47, column 30) for
      % cauchy_tanh(cx)
      % expected type  cauchy_smallreal
  cauchy_tanh_type: OBLIGATION
    FORALL (cx): cauchy_smallreal?(cauchy_tanh(cx));

  % Judgement subtype TCC generated (at line 48, column 30) for
      % cauchy_coth(cnzx)
      % expected type  cauchy_nzreal
  cauchy_coth_type: OBLIGATION
    FORALL (cnzx): cauchy_nzreal?(cauchy_coth(cnzx));

  % Judgement subtype TCC generated (at line 49, column 30) for
      % cauchy_csch(cnzx)
      % expected type  cauchy_nzreal
  cauchy_csch_type: OBLIGATION
    FORALL (cnzx): cauchy_nzreal?(cauchy_csch(cnzx));

  % Judgement subtype TCC generated (at line 50, column 30) for
      % cauchy_sech(cx)
      % expected type  cauchy_posreal
  cauchy_sech_type: OBLIGATION FORALL (cx): cauchy_posreal?(cauchy_sech(cx));

  % Subtype TCC generated (at line 55, column 47) for  cauchy_int(1)
      % expected type  cauchy_ge1
  cauchy_ge1_TCC1: OBLIGATION cauchy_ge1?(cauchy_int(1));

  % Judgement subtype TCC generated (at line 57, column 12) for  x
      % expected type  cauchy_posreal
  subtype_TCC1: OBLIGATION FORALL (x: cauchy_ge1): cauchy_posreal?(x);

  % Subtype TCC generated (at line 63, column 41) for
      % cauchy_add(cauchy_mul(cx, cx), cauchy_int(1))
      % expected type  cauchy_nnreal
  cauchy_asinh_TCC1: OBLIGATION
    FORALL (cx: cauchy_real):
      cauchy_nnreal?(cauchy_add(cauchy_mul(cx, cx), cauchy_int(1)));

  % Subtype TCC generated (at line 63, column 15) for
      % cauchy_add(cx,
      %            cauchy_sqrt(cauchy_add(cauchy_mul(cx, cx), cauchy_int(1))))
      % expected type  cauchy_posreal
  cauchy_asinh_TCC2: OBLIGATION
    FORALL (cx: cauchy_real):
      cauchy_posreal?(cauchy_add(cx,
                                 cauchy_sqrt(cauchy_add
                                             (cauchy_mul(cx, cx),
                                              cauchy_int(1)))));

  % Subtype TCC generated (at line 67, column 44) for
      % cauchy_sub(cauchy_mul(cge1x, cge1x), cauchy_int(1))
      % expected type  cauchy_nnreal
  cauchy_acosh_TCC1: OBLIGATION
    FORALL (cge1x: cauchy_ge1):
      cauchy_nnreal?(cauchy_sub(cauchy_mul(cge1x, cge1x), cauchy_int(1)));

  % Subtype TCC generated (at line 67, column 15) for
      % cauchy_add(cge1x,
      %            cauchy_sqrt(cauchy_sub(cauchy_mul(cge1x, cge1x),
      %                                   cauchy_int(1))))
      % expected type  cauchy_posreal
  cauchy_acosh_TCC2: OBLIGATION
    FORALL (cge1x: cauchy_ge1):
      cauchy_posreal?(cauchy_add(cge1x,
                                 cauchy_sqrt(cauchy_sub
                                             (cauchy_mul(cge1x, cge1x),
                                              cauchy_int(1)))));

  % Subtype TCC generated (at line 72, column 39) for
      % cauchy_sub(cauchy_int(1), csx)
      % expected type  cauchy_nzreal
  cauchy_atanh_TCC1: OBLIGATION
    FORALL (csx: cauchy_smallreal):
      cauchy_nzreal?(cauchy_sub(cauchy_int(1), csx));

  % Subtype TCC generated (at line 71, column 28) for
      % cauchy_div(cauchy_add(cauchy_int(1), csx),
      %            cauchy_sub(cauchy_int(1), csx))
      % expected type  cauchy_posreal
  cauchy_atanh_TCC2: OBLIGATION
    FORALL (csx: cauchy_smallreal):
      cauchy_posreal?(cauchy_div(cauchy_add(cauchy_int(1), csx),
                                 cauchy_sub(cauchy_int(1), csx)));

  % Judgement subtype TCC generated (at line 81, column 31) for
      % cauchy_asinh(cx)
      % expected type  cauchy_real
  cauchy_asinh_type: OBLIGATION FORALL (cx): cauchy_real?(cauchy_asinh(cx));

  % Judgement subtype TCC generated (at line 82, column 31) for
      % cauchy_acosh(cge1x)
      % expected type  cauchy_nnreal
  cauchy_acosh_type: OBLIGATION
    FORALL (cge1x): cauchy_nnreal?(cauchy_acosh(cge1x));

  % Judgement subtype TCC generated (at line 83, column 31) for
      % cauchy_atanh(csx)
      % expected type  cauchy_real
  cauchy_atanh_type: OBLIGATION FORALL (csx): cauchy_real?(cauchy_atanh(csx));


body:
  remx: THEORY

  BEGIN

    b: VAR posnat
    i: VAR int
    n: VAR nat

    modx(b)(n):below[b] = n - b*floor(n/b)

    modx_def: LEMMA modx(b)(n) = rem(b)(n)

    remx(b)(i):below[b] = IF i>=0 THEN modx(b)(i) ELSE modx(b)(i*(1-b)) ENDIF

    remx_def: LEMMA remx(b)(i) = rem(b)(i)

  END remx

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

  % Subtype TCC generated (at line 9, column 24) for  n - b * floor(n / b)
      % expected type  below[b]
  modx_TCC1: OBLIGATION
    FORALL (b: posnat, n: nat):
      n - b * floor(n / b) >= 0 AND n - b * floor(n / b) < b;

  % Subtype TCC generated (at line 13, column 61) for  i * (1 - b)
      % expected type  nat
  remx_TCC1: OBLIGATION
    FORALL (b: posnat, i: int): NOT i >= 0 IMPLIES i * (1 - b) >= 0;


body:
  %------------------------------------------------------------------------------
  % Arctangent
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  atanx: THEORY

  BEGIN

    IMPORTING prelude_aux, sqrtx, int, add, sub, mul, div, shift, cauchy,
              sum, power, powerseries, trig_fnd@atan

    p:   VAR nat

    ssmallreal: NONEMPTY_TYPE = {x:real | -1/2 < x & x < 1/2} CONTAINING 0

    cauchy_ssmallreal?(c:[nat->int]):bool=EXISTS (x:ssmallreal): cauchy_prop(x,c)

    cauchy_ssmallreal: NONEMPTY_TYPE=(cauchy_ssmallreal?) CONTAINING (LAMBDA p:0)

    JUDGEMENT cauchy_ssmallreal SUBTYPE_OF cauchy_real

    vsmallreal: NONEMPTY_TYPE = {x:real | 0 <= x & x < 1/4} CONTAINING 0

    cauchy_vsmallreal?(c:[nat->int]):bool=EXISTS (x:vsmallreal):cauchy_prop(x,c)

    cauchy_vsmallreal:NONEMPTY_TYPE=(cauchy_vsmallreal?) CONTAINING (LAMBDA p:0)

    JUDGEMENT cauchy_vsmallreal SUBTYPE_OF cauchy_real

    x:     VAR real
    cx:    VAR cauchy_real
    ssx:   VAR ssmallreal
    cssx:  VAR cauchy_ssmallreal
    n:     VAR nat
    vsx:   VAR vsmallreal
    cvsx:  VAR cauchy_vsmallreal

    cauchy_atan_drx_series(n:nat): cauchy_real
      = (IF even?(n) THEN cauchy_div(cauchy_int( 1),cauchy_int(2*n+1))
                     ELSE cauchy_div(cauchy_int(-1),cauchy_int(2*n+1)) ENDIF)

    atan_series_lemma:
       LEMMA cauchy_prop(atan_series_coef(n), cauchy_atan_drx_series(n))

    cauchy_atan_drxx(cvsx:cauchy_vsmallreal): [nat->int]
      = (LAMBDA p:
          round(cauchy_powerseries(cvsx,cauchy_atan_drx_series,p+2)(p+2)/4))

    cauchy_atan_drxx_prop: LEMMA cauchy_prop(vsx,cvsx) =>
        cauchy_prop(IF vsx = 0 THEN 1 ELSE atan(sqrt(vsx))/sqrt(vsx) ENDIF,
                    cauchy_atan_drxx(cvsx))

    cauchy_atan_dr(cssx:cauchy_ssmallreal): cauchy_real
      = cauchy_mul(cssx,cauchy_atan_drxx(cauchy_mul(cssx,cssx)))

    atan_dr_lemma: LEMMA cauchy_prop(ssx,cssx) =>
                     cauchy_prop(atan(ssx),cauchy_atan_dr(cssx))

    cauchy_pi: cauchy_real
      = cauchy_sub(cauchy_mul2n(cauchy_atan_dr(cauchy_div(cauchy_int(1),
                                                          cauchy_int(5))),4),
                   cauchy_mul2n(cauchy_atan_dr(cauchy_div(cauchy_int(1),
                                                          cauchy_int(239))),2))

    pi_lemma: LEMMA cauchy_prop(pi,cauchy_pi)

  % |x-cx(3)| < 1/8 IMPLIES
  %   (-4) <= t <= -3  => -1/2 < x < -1/4 =>
  %    -2  <= t <=  2  => -3/8 < x <  3/8
  %     3  <= t <= (4) =>  1/4 < x <  1/2 => 

  %  cauchy_atan_dr(csx:cauchy_real): cauchy_real
  %    = LET t  = csx(3),
  %          p6 = cauchy_div(cauchy_pi,cauchy_int(6)),
  %          s3 = cauchy_sqrt(cauchy_int(3)),
  %          n  = cauchy_div(cauchy_add(cauchy_mul(csx,s3), cauchy_int(1)),
  %                          cauchy_sub(s3,csx)),
  %          p  = cauchy_div(cauchy_sub(cauchy_mul(csx,s3), cauchy_int(1)),
  %                          cauchy_add(s3,csx))
  %      IN    IF t < -4 THEN cauchy_sub(cauchy_atan_drx(n),p6)
  %         ELSIF t <  5 THEN cauchy_atan_drx(csx)
  %                      ELSE cauchy_add(cauchy_atan_drx(p),p6)
  %                      ENDIF

  % Was |x-cx(2)| < 1/4 IMPLIES
  %   t <= -5      =>        x < -1   =>    0 < -1/x    < 1
  %   t = -4       => -5/4 < x < -3/4 => -1/7 < x+1/x-1 < 1/9
  %   -3 <= t <= 3 =>                      -1 <    x    < 1
  %   t = 4        =>  3/4 < x <  5/4 => -1/7 < x-1/x+1 < 1/9
  %   5 <= t       =>    1 < x        =>    0 <  1/x    < 1


  % |x-cx(3)| < 1/8 IMPLIES
  %         t <= -20 =>         x < -19/8 =>    0  <  -1/x   <  8/19
  %  -19 <= t <=  -4 =>  -5/2 < x <  -3/8 => -5/11 < x+1/x-1 <  3/7
  %   -3 <= t <=   3 =>                      -1/2  <     x   <  1/2
  %    4 <= t <=  19 =>   3/8 < x <   5/2 => -5/11 < x-1/x+1 <  3/7
  %   20 <= t        =>  19/8 < x         =>    0  <   1/x   <  8/19


    cauchy_atan(cx:cauchy_real): cauchy_real
      = LET t = cx(3),
            cxm1 = cauchy_sub(cx,cauchy_int(1)),
            cxp1 = cauchy_add(cx,cauchy_int(1)),
            p2 = cauchy_div2n(cauchy_pi,1),
            p4 = cauchy_div2n(cauchy_pi,2)
        IN    IF t <= -20 THEN cauchy_sub(
                                     cauchy_atan_dr(cauchy_neg(cauchy_inv(cx))),
                                     p2)
           ELSIF t <=  -4 THEN cauchy_sub(cauchy_neg(p4),
                                          cauchy_atan_dr(cauchy_div(cxp1,cxm1)))
           ELSIF t <=   3 THEN cauchy_atan_dr(cx)
           ELSIF t <=  19 THEN cauchy_add(p4,
                                          cauchy_atan_dr(cauchy_div(cxm1,cxp1)))
                          ELSE cauchy_sub(p2, cauchy_atan_dr(cauchy_inv(cx)))  
                          ENDIF

    atan_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(atan(x),cauchy_atan(cx))

  END atanx

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

  % Subtype TCC generated (at line 22, column 68) for  (LAMBDA p: 0)
      % expected type  cauchy_ssmallreal
  cauchy_ssmallreal_TCC1: OBLIGATION cauchy_ssmallreal?((LAMBDA p: 0));

  % Judgement subtype TCC generated (at line 24, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC1: OBLIGATION FORALL (x: cauchy_ssmallreal): cauchy_real?(x);

  % Subtype TCC generated (at line 30, column 67) for  (LAMBDA p: 0)
      % expected type  cauchy_vsmallreal
  cauchy_vsmallreal_TCC1: OBLIGATION cauchy_vsmallreal?((LAMBDA p: 0));

  % Judgement subtype TCC generated (at line 32, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC2: OBLIGATION FORALL (x: cauchy_vsmallreal): cauchy_real?(x);

  % Subtype TCC generated (at line 43, column 50) for  cauchy_int(2 * n + 1)
      % expected type  cauchy_nzreal
  cauchy_atan_drx_series_TCC1: OBLIGATION
    FORALL (n: nat): even?(n) IMPLIES cauchy_nzreal?(cauchy_int(2 * n + 1));

  % Subtype TCC generated (at line 44, column 50) for  cauchy_int(2 * n + 1)
      % expected type  cauchy_nzreal
  cauchy_atan_drx_series_TCC2: OBLIGATION
    FORALL (n: nat):
      NOT even?(n) IMPLIES cauchy_nzreal?(cauchy_int(2 * n + 1));

  % Subtype TCC generated (at line 51, column 38) for  cauchy_atan_drx_series
      % expected type  cauchys_real
  cauchy_atan_drxx_TCC1: OBLIGATION cauchys_real?(cauchy_atan_drx_series);

  % Subtype TCC generated (at line 54, column 51) for  vsx
      % expected type  nnx: nonneg_real
  cauchy_atan_drxx_prop_TCC1: OBLIGATION
    FORALL (cvsx: cauchy_vsmallreal, vsx: vsmallreal):
      cauchy_prop(vsx, cvsx) AND NOT vsx = 0 IMPLIES vsx >= 0;

  % Subtype TCC generated (at line 54, column 57) for  sqrt(vsx)
      % expected type  nznum
  cauchy_atan_drxx_prop_TCC2: OBLIGATION
    FORALL (cvsx: cauchy_vsmallreal, vsx: vsmallreal):
      cauchy_prop(vsx, cvsx) AND NOT vsx = 0 IMPLIES sqrt(vsx) /= 0;

  % Subtype TCC generated (at line 58, column 39) for  cauchy_mul(cssx, cssx)
      % expected type  cauchy_vsmallreal
  cauchy_atan_dr_TCC1: OBLIGATION
    FORALL (cssx: cauchy_ssmallreal):
      cauchy_vsmallreal?(cauchy_mul(cssx, cssx));

  % Subtype TCC generated (at line 58, column 22) for
      % cauchy_atan_drxx(cauchy_mul(cssx, cssx))
      % expected type  cauchy_real
  cauchy_atan_dr_TCC2: OBLIGATION
    FORALL (cssx: cauchy_ssmallreal):
      cauchy_real?(cauchy_atan_drxx(cauchy_mul(cssx, cssx)));

  % Subtype TCC generated (at line 65, column 56) for  cauchy_int(5)
      % expected type  cauchy_nzreal
  cauchy_pi_TCC1: OBLIGATION cauchy_nzreal?(cauchy_int(5));

  % Subtype TCC generated (at line 64, column 45) for
      % cauchy_div(cauchy_int(1), cauchy_int(5))
      % expected type  cauchy_ssmallreal
  cauchy_pi_TCC2: OBLIGATION
    cauchy_ssmallreal?(cauchy_div(cauchy_int(1), cauchy_int(5)));

  % Subtype TCC generated (at line 67, column 56) for  cauchy_int(239)
      % expected type  cauchy_nzreal
  cauchy_pi_TCC3: OBLIGATION cauchy_nzreal?(cauchy_int(239));

  % Subtype TCC generated (at line 66, column 45) for
      % cauchy_div(cauchy_int(1), cauchy_int(239))
      % expected type  cauchy_ssmallreal
  cauchy_pi_TCC4: OBLIGATION
    cauchy_ssmallreal?(cauchy_div(cauchy_int(1), cauchy_int(239)));

  % Subtype TCC generated (at line 112, column 72) for  cx
      % expected type  cauchy_nzreal
  cauchy_atan_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                      t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2) IMPLIES
                       cauchy_nzreal?(cx)))));

  % Subtype TCC generated (at line 112, column 50) for
      % cauchy_neg(cauchy_inv(cx))
      % expected type  cauchy_ssmallreal
  cauchy_atan_TCC2: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                      t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2) IMPLIES
                       cauchy_ssmallreal?(cauchy_neg(cauchy_inv(cx)))))));

  % Subtype TCC generated (at line 115, column 71) for  cxm1
      % expected type  cauchy_nzreal
  cauchy_atan_TCC3: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                      t <= -4 AND
                       NOT t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2)
                       IMPLIES cauchy_nzreal?(cxm1)))));

  % Subtype TCC generated (at line 115, column 55) for  cauchy_div(cxp1, cxm1)
      % expected type  cauchy_ssmallreal
  cauchy_atan_TCC4: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                      t <= -4 AND
                       NOT t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2)
                       IMPLIES cauchy_ssmallreal?(cauchy_div(cxp1, cxm1))))));

  % Subtype TCC generated (at line 116, column 44) for  cx
      % expected type  cauchy_ssmallreal
  cauchy_atan_TCC5: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                      t <= 3 AND
                       NOT t <= -4 AND
                        NOT t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2)
                       IMPLIES cauchy_ssmallreal?(cx)))));

  % Subtype TCC generated (at line 118, column 71) for  cxp1
      % expected type  cauchy_nzreal
  cauchy_atan_TCC6: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                           t <= 19 AND NOT t <= 3 AND NOT t <= -4
                       AND NOT t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2)
                       IMPLIES cauchy_nzreal?(cxp1)))));

  % Subtype TCC generated (at line 118, column 55) for  cauchy_div(cxm1, cxp1)
      % expected type  cauchy_ssmallreal
  cauchy_atan_TCC7: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                           t <= 19 AND NOT t <= 3 AND NOT t <= -4
                       AND NOT t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2)
                       IMPLIES cauchy_ssmallreal?(cauchy_div(cxm1, cxp1))))));

  % Subtype TCC generated (at line 119, column 70) for  cx
      % expected type  cauchy_nzreal
  cauchy_atan_TCC8: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                           NOT t <= 19 AND NOT t <= 3 AND NOT t <= -4
                       AND NOT t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2)
                       IMPLIES cauchy_nzreal?(cx)))));

  % Subtype TCC generated (at line 119, column 59) for  cauchy_inv(cx)
      % expected type  cauchy_ssmallreal
  cauchy_atan_TCC9: OBLIGATION
    FORALL (cx: cauchy_real, t: int):
      t = cx(3) IMPLIES
       (FORALL (cxm1: cauchy_real):
          cxm1 = cauchy_sub(cx, cauchy_int(1)) IMPLIES
           (FORALL (cxp1: cauchy_real):
              cxp1 = cauchy_add(cx, cauchy_int(1)) IMPLIES
               (FORALL (p2: cauchy_real):
                  p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
                   (FORALL (p4: cauchy_real):
                           NOT t <= 19 AND NOT t <= 3 AND NOT t <= -4
                       AND NOT t <= -20 AND p4 = cauchy_div2n(cauchy_pi, 2)
                       IMPLIES cauchy_ssmallreal?(cauchy_inv(cx))))));


body:
  %------------------------------------------------------------------------------
  % sin/cos
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  sincosx: THEORY

  BEGIN

    IMPORTING prelude_aux, atanx, trig_fnd@sincos, trig_fnd@trig_values,
              reals@factorial_props, trig_fnd@trig_approx, remx

    n,p: VAR nat
    x:   VAR real
    cx:  VAR cauchy_real

    real_3pi16: TYPE+ = {x | -3*pi/16 < x & x < 3*pi/16} CONTAINING 0

    cauchy_real_3pi16?(c:[nat->int]):bool 
                                      =EXISTS (x:real_3pi16): cauchy_prop(x,c)

    cauchy_real_3pi16: TYPE+=(cauchy_real_3pi16?) CONTAINING (LAMBDA p:0)

    nnsreal: TYPE+ = {x | 0 <= x & x < 1/2} CONTAINING 0

    cauchy_nnsreal?(c:[nat->int]):bool = EXISTS (x:nnsreal): cauchy_prop(x,c)

    cauchy_nnsreal: TYPE+=(cauchy_nnsreal?) CONTAINING (LAMBDA p:0)

    JUDGEMENT nnsreal           SUBTYPE_OF nnreal
    JUDGEMENT cauchy_nnsreal    SUBTYPE_OF cauchy_real
    JUDGEMENT cauchy_real_3pi16 SUBTYPE_OF cauchy_real

    sx:   VAR real_3pi16
    snx:  VAR nnsreal
    csx:  VAR cauchy_real_3pi16
    ssx:  VAR ssmallreal
    cssx: VAR cauchy_ssmallreal
    csnx: VAR cauchy_nnsreal

    cauchy_sin_series(n):cauchy_real
      = cauchy_div(cauchy_int((-1)^n),cauchy_int(factorial(2*n+1)))

    cauchy_cos_series(n):cauchy_real
      = cauchy_div(cauchy_int((-1)^n),cauchy_int(factorial(2*n)))

    sin_series_lemma: LEMMA cauchy_prop(sin_term(1)(n), cauchy_sin_series(n))

    cos_series_lemma: LEMMA cauchy_prop(cos_term(1)(n), cauchy_cos_series(n))

    cauchy_sin_drx(csnx): cauchy_real
      = (LAMBDA p: round(cauchy_powerseries(csnx,cauchy_sin_series,p+2)(p+2)/4))

    cauchy_cos_drx(csnx): cauchy_real
      = (LAMBDA p: round(cauchy_powerseries(csnx,cauchy_cos_series,p+2)(p+2)/4))

    sin_drx_lemma: LEMMA cauchy_prop(snx,csnx) AND snx /= 0 =>
                  cauchy_prop(sin(sqrt(snx))/sqrt(snx),cauchy_sin_drx(csnx))

    cauchy_sin_dr(csx): cauchy_real
      = cauchy_mul(csx,cauchy_sin_drx(cauchy_mul(csx,csx)))

    cauchy_cos_dr(csx): cauchy_real = cauchy_cos_drx(cauchy_mul(csx,csx))

    sin_dr_lemma: LEMMA cauchy_prop(sx,csx) =>
                        cauchy_prop(sin(sx),cauchy_sin_dr(csx))

    cos_dr_lemma: LEMMA cauchy_prop(sx,csx) =>
                        cauchy_prop(cos(sx),cauchy_cos_dr(csx))

    cauchy_sin(cx): cauchy_real
      = LET p2  = cauchy_div2n(cauchy_pi,2),
            s2  = cauchy_sqrt(cauchy_div2n(cauchy_int(1),1)),
            s   = round(cauchy_div(cx,p2)(2)/4),
            n   = remx(8)(s),
            cy  = cauchy_sub(cx, cauchy_mul(p2, cauchy_int(s))),
            sin = cauchy_sin_dr(cy),
            cos = cauchy_cos_dr(cy)
        IN IF    n = 0 THEN sin
           ELSIF n = 1 THEN cauchy_mul(s2, cauchy_add(cos, sin))
           ELSIF n = 2 THEN cos
           ELSIF n = 3 THEN cauchy_mul(s2, cauchy_sub(cos, sin))
           ELSIF n = 4 THEN cauchy_neg(sin)
           ELSIF n = 5 THEN cauchy_neg(cauchy_mul(s2, cauchy_add(cos, sin)))
           ELSIF n = 6 THEN cauchy_neg(cos)
                       ELSE cauchy_neg(cauchy_mul(s2, cauchy_sub(cos, sin)))
           ENDIF

    sin_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(sin(x),cauchy_sin(cx))

    cauchy_cos(cx): cauchy_real
      = LET p2  = cauchy_div2n(cauchy_pi,2),
            s2  = cauchy_sqrt(cauchy_div2n(cauchy_int(1),1)),
            s   = round(cauchy_div(cx,p2)(2)/4),
            n   = remx(8)(s),
            cy  = cauchy_sub(cx, cauchy_mul(p2, cauchy_int(s))),
            sin = cauchy_sin_dr(cy),
            cos = cauchy_cos_dr(cy)
        IN IF    n = 0 THEN cos
           ELSIF n = 1 THEN cauchy_mul(s2, cauchy_sub(cos, sin))
           ELSIF n = 2 THEN cauchy_neg(sin)
           ELSIF n = 3 THEN cauchy_neg(cauchy_mul(s2, cauchy_add(cos, sin)))
           ELSIF n = 4 THEN cauchy_neg(cos)
           ELSIF n = 5 THEN cauchy_neg(cauchy_mul(s2, cauchy_sub(cos, sin)))
           ELSIF n = 6 THEN sin
                       ELSE cauchy_mul(s2, cauchy_add(cos, sin))
           ENDIF

    cos_lemma: LEMMA cauchy_prop(x,cx) => cauchy_prop(cos(x),cauchy_cos(cx))

  END sincosx

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

  % Subtype TCC generated (at line 20, column 66) for  0
      % expected type  real_3pi16
  real_3pi16_TCC1: OBLIGATION -3 * pi / 16 < 0 & 0 < 3 * pi / 16;

  % Subtype TCC generated (at line 25, column 60) for  (LAMBDA p: 0)
      % expected type  cauchy_real_3pi16
  cauchy_real_3pi16_TCC1: OBLIGATION cauchy_real_3pi16?((LAMBDA p: 0));

  % Subtype TCC generated (at line 31, column 54) for  (LAMBDA p: 0)
      % expected type  cauchy_nnsreal
  cauchy_nnsreal_TCC1: OBLIGATION cauchy_nnsreal?((LAMBDA p: 0));

  % Judgement subtype TCC generated (at line 33, column 12) for  x
      % expected type  nnreal
  subtype_TCC1: OBLIGATION FORALL (x: nnsreal): x >= 0;

  % Judgement subtype TCC generated (at line 34, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC2: OBLIGATION FORALL (x: cauchy_nnsreal): cauchy_real?(x);

  % Judgement subtype TCC generated (at line 35, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC3: OBLIGATION FORALL (x: cauchy_real_3pi16): cauchy_real?(x);

  % Subtype TCC generated (at line 45, column 36) for
      % cauchy_int(factorial(2 * n + 1))
      % expected type  cauchy_nzreal
  cauchy_sin_series_TCC1: OBLIGATION
    FORALL (n: nat): cauchy_nzreal?(cauchy_int(factorial(2 * n + 1)));

  % Subtype TCC generated (at line 48, column 36) for
      % cauchy_int(factorial(2 * n))
      % expected type  cauchy_nzreal
  cauchy_cos_series_TCC1: OBLIGATION
    FORALL (n: nat): cauchy_nzreal?(cauchy_int(factorial(2 * n)));

  % Subtype TCC generated (at line 55, column 47) for  cauchy_sin_series
      % expected type  cauchys_real
  cauchy_sin_drx_TCC1: OBLIGATION cauchys_real?(cauchy_sin_series);

  % Subtype TCC generated (at line 55, column 7) for
      % (LAMBDA p:
      %    round(cauchy_powerseries(csnx, cauchy_sin_series, p + 2)(p + 2) /
      %           4))
      % expected type  cauchy_real
  cauchy_sin_drx_TCC2: OBLIGATION
    FORALL (csnx: cauchy_nnsreal):
      cauchy_real?(LAMBDA p:
                     round(cauchy_powerseries(csnx, cauchy_sin_series, p + 2)
                                             (p + 2)
                            / 4));

  % Subtype TCC generated (at line 58, column 47) for  cauchy_cos_series
      % expected type  cauchys_real
  cauchy_cos_drx_TCC1: OBLIGATION cauchys_real?(cauchy_cos_series);

  % Subtype TCC generated (at line 58, column 7) for
      % (LAMBDA p:
      %    round(cauchy_powerseries(csnx, cauchy_cos_series, p + 2)(p + 2) /
      %           4))
      % expected type  cauchy_real
  cauchy_cos_drx_TCC2: OBLIGATION
    FORALL (csnx: cauchy_nnsreal):
      cauchy_real?(LAMBDA p:
                     round(cauchy_powerseries(csnx, cauchy_cos_series, p + 2)
                                             (p + 2)
                            / 4));

  % Subtype TCC generated (at line 61, column 43) for  sqrt(snx)
      % expected type  nznum
  sin_drx_lemma_TCC1: OBLIGATION
    FORALL (csnx: cauchy_nnsreal, snx: nnsreal):
      snx /= 0 AND cauchy_prop(snx, csnx) IMPLIES sqrt(snx) /= 0;

  % Subtype TCC generated (at line 64, column 36) for  cauchy_mul(csx, csx)
      % expected type  cauchy_nnsreal
  cauchy_sin_dr_TCC1: OBLIGATION
    FORALL (csx: cauchy_real_3pi16): cauchy_nnsreal?(cauchy_mul(csx, csx));

  % Subtype TCC generated (at line 76, column 28) for
      % cauchy_div2n(cauchy_int(1), 1)
      % expected type  cauchy_nnreal
  cauchy_sin_TCC1: OBLIGATION
    FORALL (p2: cauchy_real):
      p2 = cauchy_div2n(cauchy_pi, 2) IMPLIES
       cauchy_nnreal?(cauchy_div2n(cauchy_int(1), 1));

  % Subtype TCC generated (at line 77, column 36) for  p2
      % expected type  cauchy_nzreal
  cauchy_sin_TCC2: OBLIGATION
    FORALL (p2: cauchy_real):
      p2 = cauchy_div2n(cauchy_pi, 2) IMPLIES
       (FORALL (s2: cauchy_nnreal):
          s2 = cauchy_sqrt(cauchy_div2n(cauchy_int(1), 1)) IMPLIES
           cauchy_nzreal?(p2));

  % Subtype TCC generated (at line 80, column 30) for  cy
      % expected type  cauchy_real_3pi16
  cauchy_sin_TCC3: OBLIGATION
    FORALL (cx: cauchy_real, p2: cauchy_real):
      p2 = cauchy_div2n(cauchy_pi, 2) IMPLIES
       (FORALL (s2: cauchy_nnreal):
          s2 = cauchy_sqrt(cauchy_div2n(cauchy_int(1), 1)) IMPLIES
           (FORALL (s: int):
              s = round(cauchy_div(cx, p2)(2) / 4) IMPLIES
               (FORALL (n: below[8]):
                  n = remx(8)(s) IMPLIES
                   (FORALL (cy: cauchy_real):
                      cy = cauchy_sub(cx, cauchy_mul(p2, cauchy_int(s)))
                       IMPLIES cauchy_real_3pi16?(cy)))));


body:
  %------------------------------------------------------------------------------
  % sec/cosec/cot
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  trigx: THEORY

  BEGIN

    IMPORTING sincosx

    x: VAR real
    c: VAR [nat->int]

    sin_nz: TYPE+ = {x | sin(x) /= 0} CONTAINING pi/2
    cos_nz: TYPE+ = {x | cos(x) /= 0} CONTAINING 0

    nsx: VAR sin_nz
    ncx: VAR cos_nz

    cauchy_sin_nz?(c):bool = EXISTS nsx: cauchy_prop(nsx,c)
    cauchy_cos_nz?(c):bool = EXISTS ncx: cauchy_prop(ncx,c)

    cauchy_sin_nz: TYPE+ = (cauchy_sin_nz?) CONTAINING cauchy_div2n(cauchy_pi,1)
    cauchy_cos_nz: TYPE+ = (cauchy_cos_nz?) CONTAINING cauchy_zero

    JUDGEMENT cauchy_sin_nz SUBTYPE_OF cauchy_real
    JUDGEMENT cauchy_cos_nz SUBTYPE_OF cauchy_real

    cnsx: VAR cauchy_sin_nz
    cncx: VAR cauchy_cos_nz

    cauchy_sec(cncx):  cauchy_nzreal = cauchy_inv(cauchy_cos(cncx))
    cauchy_cosec(cnsx):cauchy_nzreal = cauchy_inv(cauchy_sin(cnsx))

    cauchy_tan(cncx):cauchy_real = cauchy_div(cauchy_sin(cncx),cauchy_cos(cncx))
    cauchy_cot(cnsx):cauchy_real = cauchy_div(cauchy_cos(cnsx),cauchy_sin(cnsx))

  % The following should be in the trig/trig_fnd library ...

    sec(ncx):  nzreal = 1/cos(ncx)
    cosec(nsx):nzreal = 1/sin(nsx)
    cot(nsx):  real   = cos(nsx)/sin(nsx)

    sec_lemma:   LEMMA cauchy_prop(ncx,cncx) =>
                       cauchy_prop(sec(ncx),cauchy_sec(cncx))
    cosec_lemma: LEMMA cauchy_prop(nsx,cnsx) =>
                       cauchy_prop(cosec(nsx),cauchy_cosec(cnsx))
    tan_lemma:   LEMMA cauchy_prop(ncx,cncx) =>
                       cauchy_prop(tan(ncx),cauchy_tan(cncx))
    cot_lemma:   LEMMA cauchy_prop(nsx,cnsx) =>
                       cauchy_prop(cot(nsx),cauchy_cot(cnsx))

  END trigx

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

  % Subtype TCC generated (at line 18, column 47) for  pi / 2
      % expected type  sin_nz
  sin_nz_TCC1: OBLIGATION sin(pi / 2) /= 0;

  % Subtype TCC generated (at line 19, column 47) for  0
      % expected type  cos_nz
  cos_nz_TCC1: OBLIGATION cos(0) /= 0;

  % Subtype TCC generated (at line 27, column 53) for
      % cauchy_div2n(cauchy_pi, 1)
      % expected type  cauchy_sin_nz
  cauchy_sin_nz_TCC1: OBLIGATION cauchy_sin_nz?(cauchy_div2n(cauchy_pi, 1));

  % Subtype TCC generated (at line 28, column 53) for  cauchy_zero
      % expected type  cauchy_cos_nz
  cauchy_cos_nz_TCC1: OBLIGATION cauchy_cos_nz?(cauchy_zero);

  % Judgement subtype TCC generated (at line 30, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC1: OBLIGATION FORALL (x: cauchy_sin_nz): cauchy_real?(x);

  % Judgement subtype TCC generated (at line 31, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC2: OBLIGATION FORALL (x: cauchy_cos_nz): cauchy_real?(x);

  % Subtype TCC generated (at line 36, column 48) for  cauchy_cos(cncx)
      % expected type  cauchy_nzreal
  cauchy_sec_TCC1: OBLIGATION
    FORALL (cncx: cauchy_cos_nz): cauchy_nzreal?(cauchy_cos(cncx));

  % Subtype TCC generated (at line 37, column 48) for  cauchy_sin(cnsx)
      % expected type  cauchy_nzreal
  cauchy_cosec_TCC1: OBLIGATION
    FORALL (cnsx: cauchy_sin_nz): cauchy_nzreal?(cauchy_sin(cnsx));

  % Subtype TCC generated (at line 44, column 24) for  cos(ncx)
      % expected type  nznum
  sec_TCC1: OBLIGATION FORALL (ncx: cos_nz): cos(ncx) /= 0;

  % Subtype TCC generated (at line 45, column 24) for  sin(nsx)
      % expected type  nznum
  cosec_TCC1: OBLIGATION FORALL (nsx: sin_nz): sin(nsx) /= 0;

  % Subtype TCC generated (at line 53, column 37) for  ncx
      % expected type  (Tan?)
  tan_lemma_TCC1: OBLIGATION
    FORALL (cncx: cauchy_cos_nz, ncx: cos_nz):
      cauchy_prop(ncx, cncx) IMPLIES Tan?(ncx);


body:
  test: THEORY

  BEGIN

    IMPORTING trigx,
              hyperbolicx

    new_pi_bnds:    LEMMA % 60 dp
          3.141592653589793238462643383279502884197169399375105820974944 < pi AND
     pi < 3.141592653589793238462643383279502884197169399375105820974945

    new_ln2_bnds:   LEMMA % 60 dp
      LET l = ln(2) IN
          0.693147180559945309417232121458176568075500134360255254120680 < l  AND
      l < 0.693147180559945309417232121458176568075500134360255254120681

    new_e_bnds:     LEMMA % 60 dp
          2.718281828459045235360287471352662497757247093699959574966967 < e  AND
      e < 2.718281828459045235360287471352662497757247093699959574966968

    new_sqrt2_bnds: LEMMA % 60 dp
      LET s = sqrt(2) IN
          1.414213562373095048801688724209698078569671875376948073176679 < s  AND
      s < 1.414213562373095048801688724209698078569671875376948073176680

  %%% THE COMMENTED LEMMAS CAN BE PROVED AS THE PREVIOUS LEMMAS, BUT THEY
  %%% TAKE TOO MUCH TIME (CAM)

  %  new_sin1_bnds: LEMMA % 60 dp
  %    LET s = sin(1) IN
  %        0.841470984807896506652502321630298999622563060798371065672751 < s  AND
  %    s < 0.841470984807896506652502321630298999622563060798371065672752

  %  new_cos1_bnds: LEMMA % 60 dp
  %    LET c = cos(1) IN
  %        0.540302305868139717400936607442976603732310420617922227670097 < c  AND
  %    c < 0.540302305868139717400936607442976603732310420617922227670098

  END test


body:
  %------------------------------------------------------------------------------
  % Arcsine
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  asinx: THEORY

  BEGIN

    IMPORTING atanx, trig_fnd@asin

    cauchy_real_abs_le1?(c:[nat->int]):bool
                           = EXISTS (x:real_abs_le1): cauchy_prop(x,c)

    cauchy_real_abs_le1: NONEMPTY_TYPE
                           = (cauchy_real_abs_le1?) CONTAINING (LAMBDA (p:nat):0)

    JUDGEMENT cauchy_real_abs_le1 SUBTYPE_OF cauchy_real

    x:  VAR real_abs_le1
    cx: VAR cauchy_real_abs_le1

  %  asin x  = if x0 >  0 then piBy2 - atan (s/x) else
  %            if x0 == 0 then atan (x/s)         else
  %            {- x0 <  0 -}   atan (s/x) - piBy2
  %            where (CR_ x') = x; x0 = x' 0; s = sqrt (fromInteger 1 - x*x)

    cauchy_asin(cx):cauchy_real
      = LET t  = cx(0),
            s  = cauchy_sqrt(cauchy_sub(cauchy_int(1),cauchy_mul(cx,cx))),
            p2 = cauchy_div2n(cauchy_pi,1)
        IN IF    t = 0 THEN cauchy_atan(cauchy_div(cx,s))
           ELSE LET a  = cauchy_atan(cauchy_div(s,cx)) IN
           IF t > 0 THEN cauchy_sub(p2,a)
                    ELSE cauchy_sub(cauchy_neg(p2),a) ENDIF ENDIF

    asin_lemma: LEMMA cauchy_prop(x,cx) IMPLIES
                                            cauchy_prop(asin(x),cauchy_asin(cx))

  END asinx

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

  % Subtype TCC generated (at line 19, column 62) for  (LAMBDA (p: nat): 0)
      % expected type  cauchy_real_abs_le1
  cauchy_real_abs_le1_TCC1: OBLIGATION
    cauchy_real_abs_le1?((LAMBDA (p: nat): 0));

  % Judgement subtype TCC generated (at line 21, column 12) for  x
      % expected type  cauchy_real
  subtype_TCC1: OBLIGATION FORALL (x: cauchy_real_abs_le1): cauchy_real?(x);

  % Subtype TCC generated (at line 33, column 27) for
      % cauchy_sub(cauchy_int(1), cauchy_mul(cx, cx))
      % expected type  cauchy_nnreal
  cauchy_asin_TCC1: OBLIGATION
    FORALL (cx: cauchy_real_abs_le1, t: int):
      t = cx(0) IMPLIES
       cauchy_nnreal?(cauchy_sub(cauchy_int(1), cauchy_mul(cx, cx)));

  % Subtype TCC generated (at line 35, column 52) for  s
      % expected type  cauchy_nzreal
  cauchy_asin_TCC2: OBLIGATION
    FORALL (cx: cauchy_real_abs_le1, t: int):
      t = cx(0) IMPLIES
       (FORALL (s: cauchy_nnreal):
          s = cauchy_sqrt(cauchy_sub(cauchy_int(1), cauchy_mul(cx, cx)))
           IMPLIES
           (FORALL (p2: cauchy_real):
              t = 0 AND p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
               cauchy_nzreal?(s)));

  % Subtype TCC generated (at line 36, column 48) for  cx
      % expected type  cauchy_nzreal
  cauchy_asin_TCC3: OBLIGATION
    FORALL (cx: cauchy_real_abs_le1, t: int):
      t = cx(0) IMPLIES
       (FORALL (s: cauchy_nnreal):
          s = cauchy_sqrt(cauchy_sub(cauchy_int(1), cauchy_mul(cx, cx)))
           IMPLIES
           (FORALL (p2: cauchy_real):
              NOT t = 0 AND p2 = cauchy_div2n(cauchy_pi, 1) IMPLIES
               cauchy_nzreal?(cx)));


body:
  %------------------------------------------------------------------------------
  % Arcosine
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  acosx: THEORY

  BEGIN

    IMPORTING asinx, trig_fnd@acos

    x:  VAR real_abs_le1
    cx: VAR cauchy_real_abs_le1

    cauchy_acos(cx):cauchy_real
      = cauchy_sub(cauchy_div2n(cauchy_pi, 1), cauchy_asin(cx))

    acos_lemma: LEMMA cauchy_prop(x,cx) IMPLIES
                                            cauchy_prop(acos(x),cauchy_acos(cx))

  END acosx


body:
  series: THEORY

    BEGIN
    IMPORTING prelude_aux

    x,y:   VAR real
    xs,ys: VAR [nat-> real]
    n,m:   VAR nat

    sum (xs:[nat->real],n:nat): RECURSIVE real
     = (IF n = 0 THEN xs(0) ELSE sum(xs,n-1) + xs(n) ENDIF)
        MEASURE (LAMBDA xs,n: n)

    sum_lemma1: LEMMA (FORALL (m:nat): xs(m) = ys(m) * x) =>
                        sum(xs,n) = x * sum(ys,n)

    geometric_series(x:real):[nat->real]
                  = (LAMBDA (n:nat): IF n=0 THEN 1 ELSE x^n ENDIF)

    geometric_series_aux1: LEMMA -1 < x AND x < 1 =>
                                 sum(geometric_series(x),n) = (1-x^(n+1))/(1-x)

    geometric_series_aux_odd:  LEMMA odd?(n)  AND -1 < x AND x < 1 =>
       sum(geometric_series(x),n) = (1+x)*sum(geometric_series(x*x),(n-1)/2)

    geometric_series_aux_even: LEMMA even?(n) AND n > 0 AND -1 < x AND x < 1 =>
       sum(geometric_series(x),n) = (1+x)*sum(geometric_series(x*x),n/2-1) + x^n

    geometric_series_approx_set(x:real):setof[real]
      = {y | EXISTS (n:nat): y = sum(geometric_series(x),n)}

    geometric_series_approx_set_contains1:
          LEMMA member(1,geometric_series_approx_set(x))

    geometric_series_approx_set_nonempty:
          LEMMA nonempty?(geometric_series_approx_set(x))

    geometric_series_approx_set_pos_upper_bound: LEMMA 0 <= x AND x < 1 =>
          upper_bound?(1/(1-x),geometric_series_approx_set(x))

    geometric_series_approx_set_pos_least_upper_bound: LEMMA 0 <= x AND x < 1 =>
          least_upper_bound?(1/(1-x),geometric_series_approx_set(x))

    geometric_series_pos_limit: LEMMA 0 <= x AND x < 1 =>
                        lub(geometric_series_approx_set(x)) = 1/(1-x)

  %  geometric_series_pos_limit: LEMMA 0 < x AND x < 1 =>
  %                      lub(geometric_series_approx_set(x)) = 1/(1-x)
    END series

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

  % Subtype TCC generated (at line 11, column 38) for  n - 1
      % expected type  nat
  sum_TCC1: OBLIGATION FORALL (n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Termination TCC generated (at line 11, column 31) for  sum(xs, n - 1)
  sum_TCC2: OBLIGATION FORALL (n: nat): NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 18, column 56) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  geometric_series_TCC1: OBLIGATION
    FORALL (x: real, n: nat): NOT n = 0 IMPLIES x /= 0 OR n >= 0;

  % Subtype TCC generated (at line 21, column 66) for  (n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  geometric_series_aux1_TCC1: OBLIGATION
    FORALL (n: nat, x: real): x < 1 AND -1 < x IMPLIES x /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 21, column 73) for  (1 - x)
      % expected type  nznum
  geometric_series_aux1_TCC2: OBLIGATION
    FORALL (x: real): x < 1 AND -1 < x IMPLIES (1 - x) /= 0;

  % Subtype TCC generated (at line 24, column 66) for  (n - 1) / 2
      % expected type  nat
  geometric_series_aux_odd_TCC1: OBLIGATION
    FORALL (n: nat, x: real):
      x < 1 AND -1 < x AND odd?(n) IMPLIES
       integer_pred((n - 1) / 2) AND (n - 1) / 2 >= 0;

  % Subtype TCC generated (at line 27, column 66) for  n / 2 - 1
      % expected type  nat
  geometric_series_aux_even_TCC1: OBLIGATION
    FORALL (n: nat, x: real):
      x < 1 AND -1 < x AND n > 0 AND even?(n) IMPLIES
       integer_pred(n / 2 - 1) AND n / 2 - 1 >= 0;

  % Subtype TCC generated (at line 27, column 77) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  geometric_series_aux_even_TCC2: OBLIGATION
    FORALL (n: nat, x: real):
      x < 1 AND -1 < x AND n > 0 AND even?(n) IMPLIES x /= 0 OR n >= 0;

  % Subtype TCC generated (at line 39, column 24) for  (1 - x)
      % expected type  nznum
  geometric_series_approx_set_pos_upper_bound_TCC1: OBLIGATION
    FORALL (x: real): x < 1 AND 0 <= x IMPLIES (1 - x) /= 0;

  % Subtype TCC generated (at line 39, column 29) for
      % geometric_series_approx_set(x)
      % expected type  (nonempty?[real])
  geometric_series_approx_set_pos_upper_bound_TCC2: OBLIGATION
    FORALL (x: real):
      x < 1 AND 0 <= x IMPLIES
       nonempty?[real](geometric_series_approx_set(x));

  % Subtype TCC generated (at line 45, column 26) for
      % geometric_series_approx_set(x)
      % expected type  SA: (bounded_above?)
  geometric_series_pos_limit_TCC1: OBLIGATION
    FORALL (x: real):
      x < 1 AND 0 <= x IMPLIES
       nonempty?[real](geometric_series_approx_set(x)) AND
        bounded_above?(geometric_series_approx_set(x));


body:
  %------------------------------------------------------------------------------
  % max of two reals
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  max: THEORY

  BEGIN

    IMPORTING cauchy

    x,y:   VAR real
    cx,cy: VAR cauchy_real
    p:     VAR nat

    cauchy_max(cx,cy):cauchy_real = (LAMBDA p: max(cx(p),cy(p)))

    max_lemma: LEMMA cauchy_prop(x,cx) AND cauchy_prop(y,cy) =>
                     cauchy_prop(max(x,y), cauchy_max(cx,cy))

  END max

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

  % Subtype TCC generated (at line 19, column 35) for
      % (LAMBDA p: max(cx(p), cy(p)))
      % expected type  cauchy_real
  cauchy_max_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, cy: cauchy_real):
      cauchy_real?(LAMBDA p: max(cx(p), cy(p)));


body:
  %------------------------------------------------------------------------------
  % Top file for exact_real_arith
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  min: THEORY

  BEGIN

    IMPORTING cauchy

    x,y:   VAR real
    cx,cy: VAR cauchy_real
    p:     VAR nat

    cauchy_min(cx,cy): cauchy_real = (LAMBDA p: min(cx(p),cy(p)))

    min_lemma: LEMMA cauchy_prop(x,cx) AND cauchy_prop(y,cy) =>
                     cauchy_prop(min(x,y), cauchy_min(cx,cy))

  END min

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

  % Subtype TCC generated (at line 19, column 36) for
      % (LAMBDA p: min(cx(p), cy(p)))
      % expected type  cauchy_real
  cauchy_min_TCC1: OBLIGATION
    FORALL (cx: cauchy_real, cy: cauchy_real):
      cauchy_real?(LAMBDA p: min(cx(p), cy(p)));


body:
  %------------------------------------------------------------------------------
  % Rationals
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  rat: THEORY

  BEGIN

    IMPORTING cauchy, int, div

    x:   VAR rat
    i:   VAR int
    pn:  VAR posnat
    pns: VAR (nonempty?[posnat])

    denominators(x):(nonempty?[posnat]) = {pn | EXISTS i: x = i/pn}
    denominator(x):posnat = min(denominators(x))

    numerator(x):int      = x*denominator(x)

    cauchy_rat(x):cauchy_real
     = cauchy_div(cauchy_int(numerator(x)),cauchy_int(denominator(x)))

    rat_lemma: LEMMA cauchy_prop(x, cauchy_rat(x))

  END rat

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

  % Subtype TCC generated (at line 20, column 40) for
      % {pn | EXISTS i: x = i / pn}
      % expected type  (nonempty?[posnat])
  denominators_TCC1: OBLIGATION
    FORALL (x: rat): nonempty?[posnat]({pn | EXISTS i: x = i / pn});

  % Subtype TCC generated (at line 23, column 26) for  x * denominator(x)
      % expected type  int
  numerator_TCC1: OBLIGATION
    FORALL (x: rat): integer_pred(x * denominator(x));

  % Subtype TCC generated (at line 26, column 41) for
      % cauchy_int(denominator(x))
      % expected type  cauchy_nzreal
  cauchy_rat_TCC1: OBLIGATION
    FORALL (x: rat): cauchy_nzreal?(cauchy_int(denominator(x)));


body:
  %------------------------------------------------------------------------------
  % Definition and properties of sqrt
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  prelude_sqrt: THEORY

    BEGIN
    IMPORTING prelude_aux

    nnx,nny,nnz: VAR nnreal
    px,py,pz:    VAR posreal
    y,w:         VAR real

    square_le1: LEMMA nnx*nnx <= (nnx+nny)*(nnx+nny)
    square_le2: LEMMA nnx*nnx <= 1       <=> nnx <= 1
    square_le3: LEMMA nnx*nnx < nny*nny  <=> nnx < nny
    square_eq1: LEMMA nnx*nnx = nny*nny  <=> nnx = nny
    square_le4: LEMMA nnx*nnx <= nny*nny <=> nnx <= nny
    square_le5: LEMMA 1 < px*px          <=> 1 < px
    square_le6: LEMMA nnx*nnx <= py AND 1 < py => nnx < py

    square_archimedean1: LEMMA EXISTS (n:posnat): 1/(n*n) < px
    square_archimedean2: LEMMA EXISTS (n:posnat): 2/n + 1/(n*n) < px

    square_exist_lt1: LEMMA py <= 1 AND py*py < px =>
                            EXISTS pz: py < pz AND pz*pz < px
    square_exist_lt2: LEMMA EXISTS pz: pz*pz < px
    square_exist_lt3: LEMMA nny*nny < px => EXISTS pz: nny < pz AND  pz*pz < px

    square_exist_gt3: LEMMA nnx < py*py =>
                            EXISTS nnz: nnz < py AND  nnx < nnz*nnz

    sqrt_set(nnx:nnreal):setof[nnreal] = {y | y*y <= nnx}

    sqrt_set_UB(nnx:nnreal):nnreal = IF nnx <= 1 THEN 1 ELSE nnx ENDIF

    sqrt_set_nonempty: LEMMA nonempty?(sqrt_set(nnx))
    sqrt_set_has_UB: LEMMA upper_bound?(sqrt_set_UB(nnx),sqrt_set(nnx))
    sqrt_set_LUB: LEMMA nny*nny = nnx <=> least_upper_bound?(nny,sqrt_set(nnx))

    square(nnx:nnreal):nnreal = nnx*nnx

    square_injective:  LEMMA injective?(square)
    
    square_surjective: LEMMA surjective?(square)
    square_bijective:  LEMMA bijective?(square)

    sqrt:[nnreal->nnreal] = inverse(square)

    square_is:    LEMMA square(nnx) = nnx*nnx
    sqrt_square1: LEMMA square(sqrt(nnx))=nnx
    sqrt_square2: LEMMA sqrt(square(nnx))=nnx
    square_times: LEMMA square(nnx*nny) = square(nnx)*square(nny)
    sqrt_times:   LEMMA sqrt(nnx)*sqrt(nny) = sqrt(nnx*nny)
    sqrt_zero:    LEMMA sqrt(0) = 0
    sqrt_one:     LEMMA sqrt(1) = 1
    both_sides_sqrt1:    LEMMA sqrt(nnx) =  nny       <=> nnx     =  nny*nny
    both_sides_sqrt2:    LEMMA sqrt(nnx) =  sqrt(nny) <=> nnx     =  nny
    both_sides_sqrt_lt1: LEMMA sqrt(nnx) <  nny       <=> nnx     <  nny*nny
    both_sides_sqrt_lt2: LEMMA sqrt(nnx) <  sqrt(nny) <=> nnx     <  nny
    both_sides_sqrt_lt3: LEMMA nnx       <  sqrt(nny) <=> nnx*nnx <  nny
    both_sides_sqrt_le1: LEMMA sqrt(nnx) <= nny       <=> nnx     <= nny*nny
    both_sides_sqrt_le2: LEMMA sqrt(nnx) <= sqrt(nny) <=> nnx     <= nny
    both_sides_sqrt_le3: LEMMA nnx       <= sqrt(nny) <=> nnx*nnx <= nny

    END prelude_sqrt

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

  % Subtype TCC generated (at line 42, column 55) for
      % extend[real, nnreal, bool, FALSE](sqrt_set(nnx))
      % expected type  (nonempty?[real])
  sqrt_set_has_UB_TCC1: OBLIGATION
    FORALL (nnx: nnreal):
      nonempty?[real](extend[real, nnreal, bool, FALSE](sqrt_set(nnx)));


body:
  top : THEORY
  BEGIN

    IMPORTING field_examples,
              interval_examples,
  	    interval_examples4Q,
              metit_examples,
              sturm_examples,
              checker_example

  END top


body:
  checker_example : THEORY
  BEGIN
   
    IMPORTING PVSioChecker@pvsio_checker,
              is_prime

    check?(fin:IStream,fout:OStream) : bool = 
      LET n  = str2pvs[nat](readln_checker(fin)),  % Read n from file
          io = str2pvs[bool](readln_checker(fin)), % Read output from file
          pvs = is_prime?(n) IN
        check_bool(fout,"",pvs,io) % Check PVS output against ouput in file       

    main(file:string,records:nat): void =
      checker(file,check?,records)

  END checker_example


body:
  sturm_examples: THEORY
  BEGIN

    IMPORTING Sturm@strategies

    x : VAR real

    example_1: LEMMA 
      160*((x-1/2)^2*(x-9)^4*(x+8.5)^2 + 0.1) /= 0 
  %|- example_1 : PROOF
  %|- (sturm)
  %|- QED

    example_2: LEMMA FORALL (x:real): 
       (x-1/2)^2*(x-9)^4*(x+8.5)^2 >= 0
  %|- example_2 : PROOF
  %|- (sturm)
  %|- QED

   example_3: LEMMA 
    (x^16-x^15-3*x^13+x^12-x^11+2*x^10-6*x^9+8*x^8 
     -7*x^7-6*x^6+5*x^5+4*x^4-3*x^3+350*x + 478)^2 /= 0
  %|- example_3 : PROOF
  %|- (sturm)
  %|- QED

    example_4: LEMMA 
      x<0 IMPLIES x^101 < -x
  %|- example_4 : PROOF
  %|- (sturm)
  %|- QED

    example_5: LEMMA 
      x<0 IMPLIES x^5-2*x^3 < 6
  %|- example_5 : PROOF
  %|- (sturm)
  %|- QED

    example_6: LEMMA x^2 - 2*x + 1 >= 0
  %|- example_6 : PROOF
  %|- (sturm)
  %|- QED

    example_7: LEMMA x*(1-x) <= 1/4
  %|- example_7 : PROOF
  %|- (sturm)
  %|- QED


  %% Examples with quantifications in antecedent and consequent

   example_8: LEMMA
     EXISTS (x:real) : x >= 0 AND x^2 - x < 0
  %|- example_8 : PROOF
  %|- (sturm)
  %|- QED

   example_n8: LEMMA
     NOT (FORALL (x:real) : x >= 0 IMPLIES x^2 >= x)
  %|- example_n8 : PROOF
  %|- (sturm -1)
  %|- QED

   example_80: LEMMA
     EXISTS (x:real) : x >= 0 AND x^2 - x = 0
  %|- example_80 : PROOF
  %|- (sturm)
  %|- QED

   example_n80: LEMMA
     NOT (FORALL (x:real) : x >= 0 IMPLIES x^2 /= x)
  %|- example_n80 : PROOF
  %|- (sturm -1)
  %|- QED

   example_9: LEMMA 
     FORALL (x:real) : x<0 IMPLIES x^5 < -x
  %|- example_9 : PROOF
  %|- (sturm)
  %|- QED

   example_n9: LEMMA
     NOT (EXISTS (x:real): x < 0 AND x^5 >= -x)
  %|- example_n9 : PROOF
  %|- (sturm -1)
  %|- QED

   example_90: LEMMA x<0 IMPLIES x^5 /= 0
  %|- example_90 : PROOF
  %|- (sturm)
  %|- QED

   example_n90: LEMMA
     NOT (EXISTS (x:real): x < 0 AND x^5 = 0)
  %|- example_n90 : PROOF
  %|- (sturm -1)
  %|- QED

    example_10 : LEMMA 
      NOT EXISTS (x:posreal) : x^3 <= 0
  %|- example_10 : PROOF
  %|- (sturm -1)
  %|- QED

    example_11 : LEMMA
      FORALL (x:real | abs(x) <= 1) : (x-1)*(x+1) <= 0
  %|- example_11 : PROOF
  %|- (sturm)
  %|- QED

    example_12: LEMMA
      x^120-2*x^60+1 >= 0
  %|- example_12 : PROOF
  %|- (sturm)
  %|- QED

    legendre : LEMMA
      abs(x) < 1 IMPLIES
      3969/65536 + 63063/4096 * x^6 + 1792791/4096 * x^10 +
      3002285/4096 * x^18 + 6600165/4096 * x^14
      - 72765/65536 * x^4 - 3558555/32768 * x^8
      - 10207769/65536 * x^20 - 35043645/32768 * x^12
      - 95851899/65536 * x^16 > 0
  %|- legendre : PROOF
  %|- (sturm)
  %|- QED

    legendre3 : LEMMA
      abs(x) < 1 IMPLIES
      (3969/65536 + 63063/4096 * x^6 + 1792791/4096 * x^10 +
       3002285/4096 * x^18 + 6600165/4096 * x^14
       - 72765/65536 * x^4 - 3558555/32768 * x^8
       - 10207769/65536 * x^20 - 35043645/32768 * x^12
       - 95851899/65536 * x^16)^3 > 0
  %|- legendre3 : PROOF
  %|- (sturm)
  %|- QED

    harrison_sos : LEMMA
      ((x-1)^8 + 2*(x-x)^8 + (x-3)^8 -2)/4 >= 0
  %|- harrison_sos : PROOF
  %|- (sturm)
  %|- QED

  %% Examples with interval notations, including extended intervals, i.e., 
  %% reals@RealInt and interval_arith@interval

    example_13 : LEMMA 
      FORALL (x:real | x ## [|-2,1|]) : x^4-x^3-19*x^2-11*x+30 <= 31.7
  %|- example_13 : PROOF
  %|- (sturm)
  %|- QED

    example_14 : LEMMA 
      FORALL (x:real) : x ## [| 0, oo |] IMPLIES -x^3 <= 0
  %|- example_14 : PROOF
  %|- (sturm)
  %|- QED

    example_15 : LEMMA 
      FORALL (x:real) : x ## [| open(1), oo |] IMPLIES -x^3 < 1
  %|- example_15 : PROOF
  %|- (sturm)
  %|- QED

    example_16 : LEMMA 
      FORALL (x:real) : x ## [| -oo, 1 |] IMPLIES x*(1-x) <= 0.25
  %|- example_16 : PROOF
  %|- (sturm)
  %|- QED

    example_17 : LEMMA
      FORALL (x:real): x>0 IMPLIES x^15*(2-x)^20*(6-x)^2*(12-x)^4*(20-x)^6>=0
  %|- example_17 : PROOF
  %|- (sturm)
  %|- QED


  % Examples of monotonicity

    mono_example_1 : LEMMA
      FORALL (x,y:real) : x >= 1 AND x < y IMPLIES (x-1/4)^2 <= y*y-(1/2)*y+(1/16)
  %|- mono_example_1 : PROOF
  %|- (mono-poly)
  %|- QED

    mono_example_2 : LEMMA
      FORALL (x,y:real) : x < y IMPLIES x^5 /= y^5
  %|- mono_example_2 : PROOF
  %|- (mono-poly)
  %|- QED

    mono_example_3: LEMMA
      FORALL (x,y:real) : 0.4 <= x AND x < y AND y <= 0.6 IMPLIES
      x^5-x^3+x/5>y*(y^4-y^2+1/5)
  %|- mono_example_3 : PROOF
  %|- (mono-poly)
  %|- QED

    mono_example_4: LEMMA
      FORALL (x,y:real): x /= y IMPLIES x^3 /= y^3
  %|- mono_example_4 : PROOF
  %|- (mono-poly)
  %|- QED

    mono_example_5: LEMMA
      EXISTS (x,y:real): x < y AND x^2 >= sq(y)
  %|- mono_example_5 : PROOF
  %|- (mono-poly)
  %|- QED

    mono_example_6: LEMMA
      EXISTS (x:real,y:real|y>=-1): x > y AND x^4 < y^4
  %|- mono_example_6 : PROOF
  %|- (mono-poly)
  %|- QED

   END sturm_examples

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

  % Subtype TCC generated (at line 9, column 17) for  2
      % expected type  {i: int | NOT (x - 1/2) = 0 OR i >= 0}
  example_1_TCC1: OBLIGATION FORALL (x: real): NOT (x - 1/2) = 0 OR 2 >= 0;

  % Subtype TCC generated (at line 9, column 25) for  4
      % expected type  {i: int | (x - 9) /= 0 OR i >= 0}
  example_1_TCC2: OBLIGATION FORALL (x: real): (x - 9) /= 0 OR 4 >= 0;

  % Subtype TCC generated (at line 9, column 35) for  2
      % expected type  {i: int | NOT (x + 17/2) = 0 OR i >= 0}
  example_1_TCC3: OBLIGATION FORALL (x: real): NOT (x + 17/2) = 0 OR 2 >= 0;

  % Subtype TCC generated (at line 21, column 5) for  16
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC1: OBLIGATION FORALL (x: real): x /= 0 OR 16 >= 0;

  % Subtype TCC generated (at line 21, column 10) for  15
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC2: OBLIGATION FORALL (x: real): x /= 0 OR 15 >= 0;

  % Subtype TCC generated (at line 21, column 17) for  13
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC3: OBLIGATION FORALL (x: real): x /= 0 OR 13 >= 0;

  % Subtype TCC generated (at line 21, column 22) for  12
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC4: OBLIGATION FORALL (x: real): x /= 0 OR 12 >= 0;

  % Subtype TCC generated (at line 21, column 27) for  11
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC5: OBLIGATION FORALL (x: real): x /= 0 OR 11 >= 0;

  % Subtype TCC generated (at line 21, column 34) for  10
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC6: OBLIGATION FORALL (x: real): x /= 0 OR 10 >= 0;

  % Subtype TCC generated (at line 21, column 41) for  9
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC7: OBLIGATION FORALL (x: real): x /= 0 OR 9 >= 0;

  % Subtype TCC generated (at line 21, column 47) for  8
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC8: OBLIGATION FORALL (x: real): x /= 0 OR 8 >= 0;

  % Subtype TCC generated (at line 22, column 8) for  7
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC9: OBLIGATION FORALL (x: real): x /= 0 OR 7 >= 0;

  % Subtype TCC generated (at line 22, column 14) for  6
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC10: OBLIGATION FORALL (x: real): x /= 0 OR 6 >= 0;

  % Subtype TCC generated (at line 22, column 20) for  5
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC11: OBLIGATION FORALL (x: real): x /= 0 OR 5 >= 0;

  % Subtype TCC generated (at line 22, column 26) for  4
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC12: OBLIGATION FORALL (x: real): x /= 0 OR 4 >= 0;

  % Subtype TCC generated (at line 22, column 32) for  3
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_3_TCC13: OBLIGATION FORALL (x: real): x /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 22, column 47) for  2
      % expected type  {i: int |
                     %          NOT 478 + 350 * x + 4 * x ^ 4 + 5 * x ^ 5 +
                     %               8 * x ^ 8
                     %               + 2 * x ^ 10
                     %               + x ^ 12
                     %               + x ^ 16
                     %               - 7 * x ^ 7
                     %               - 6 * x ^ 6
                     %               - 6 * x ^ 9
                     %               - 3 * x ^ 3
                     %               - 3 * x ^ 13
                     %               - x ^ 11
                     %               - x ^ 15
                     %               = 0
                     %           OR i >= 0}
  example_3_TCC14: OBLIGATION
    FORALL (x: real):
      NOT 478 + 350 * x + 4 * x ^ 4 + 5 * x ^ 5 + 8 * x ^ 8 + 2 * x ^ 10 +
           x ^ 12
           + x ^ 16
           - 7 * x ^ 7
           - 6 * x ^ 6
           - 6 * x ^ 9
           - 3 * x ^ 3
           - 3 * x ^ 13
           - x ^ 11
           - x ^ 15
           = 0
       OR 2 >= 0;

  % Subtype TCC generated (at line 28, column 18) for  101
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_4_TCC1: OBLIGATION
    FORALL (x: real): x < 0 IMPLIES x /= 0 OR 101 >= 0;

  % Subtype TCC generated (at line 39, column 21) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_6_TCC1: OBLIGATION FORALL (x: real): x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 112, column 6) for  120
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_12_TCC1: OBLIGATION FORALL (x: real): x /= 0 OR 120 >= 0;

  % Subtype TCC generated (at line 112, column 14) for  60
      % expected type  {i: int | x /= 0 OR i >= 0}
  example_12_TCC2: OBLIGATION FORALL (x: real): x /= 0 OR 60 >= 0;

  % Subtype TCC generated (at line 120, column 21) for  18
      % expected type  {i: int | x /= 0 OR i >= 0}
  legendre_TCC1: OBLIGATION
    FORALL (x: real): abs(x) < 1 IMPLIES x /= 0 OR 18 >= 0;

  % Subtype TCC generated (at line 120, column 43) for  14
      % expected type  {i: int | x /= 0 OR i >= 0}
  legendre_TCC2: OBLIGATION
    FORALL (x: real): abs(x) < 1 IMPLIES x /= 0 OR 14 >= 0;

  % Subtype TCC generated (at line 122, column 25) for  20
      % expected type  {i: int | x /= 0 OR i >= 0}
  legendre_TCC3: OBLIGATION
    FORALL (x: real): abs(x) < 1 IMPLIES x /= 0 OR 20 >= 0;

  % Subtype TCC generated (at line 134, column 30) for  3
      % expected type  {i: int |
                     %          NOT 3969/65536 - 95851899/65536 * x ^ 16 -
                     %               35043645/32768 * x ^ 12
                     %               - 10207769/65536 * x ^ 20
                     %               - 3558555/32768 * x ^ 8
                     %               - 72765/65536 * x ^ 4
                     %               + 63063/4096 * x ^ 6
                     %               + 1792791/4096 * x ^ 10
                     %               + 3002285/4096 * x ^ 18
                     %               + 6600165/4096 * x ^ 14
                     %               = 0
                     %           OR i >= 0}
  legendre3_TCC1: OBLIGATION
    FORALL (x: real):
      abs(x) < 1 IMPLIES
       NOT 3969/65536 - 95851899/65536 * x ^ 16 - 35043645/32768 * x ^ 12 -
            10207769/65536 * x ^ 20
            - 3558555/32768 * x ^ 8
            - 72765/65536 * x ^ 4
            + 63063/4096 * x ^ 6
            + 1792791/4096 * x ^ 10
            + 3002285/4096 * x ^ 18
            + 6600165/4096 * x ^ 14
            = 0
        OR 3 >= 0;

  % Subtype TCC generated (at line 140, column 11) for  8
      % expected type  {i: int | (x - 1) /= 0 OR i >= 0}
  harrison_sos_TCC1: OBLIGATION FORALL (x: real): (x - 1) /= 0 OR 8 >= 0;

  % Subtype TCC generated (at line 140, column 33) for  8
      % expected type  {i: int | (x - 3) /= 0 OR i >= 0}
  harrison_sos_TCC2: OBLIGATION FORALL (x: real): (x - 3) /= 0 OR 8 >= 0;

  % Subtype TCC generated (at line 173, column 44) for  20
      % expected type  {i: int | (2 - x) /= 0 OR i >= 0}
  example_17_TCC1: OBLIGATION
    FORALL (x: real): x > 0 IMPLIES (2 - x) /= 0 OR 20 >= 0;

  % Subtype TCC generated (at line 173, column 53) for  2
      % expected type  {i: int | (6 - x) /= 0 OR i >= 0}
  example_17_TCC2: OBLIGATION
    FORALL (x: real): x > 0 IMPLIES (6 - x) /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 173, column 62) for  4
      % expected type  {i: int | (12 - x) /= 0 OR i >= 0}
  example_17_TCC3: OBLIGATION
    FORALL (x: real): x > 0 IMPLIES (12 - x) /= 0 OR 4 >= 0;

  % Subtype TCC generated (at line 173, column 71) for  6
      % expected type  {i: int | (20 - x) /= 0 OR i >= 0}
  example_17_TCC4: OBLIGATION
    FORALL (x: real): x > 0 IMPLIES (20 - x) /= 0 OR 6 >= 0;

  % Subtype TCC generated (at line 182, column 57) for  2
      % expected type  {i: int | NOT (x - 1/4) = 0 OR i >= 0}
  mono_example_1_TCC1: OBLIGATION
    FORALL (x, y: real): x >= 1 AND x < y IMPLIES NOT (x - 1/4) = 0 OR 2 >= 0;

  % Subtype TCC generated (at line 188, column 47) for  5
      % expected type  {i: int | y /= 0 OR i >= 0}
  mono_example_2_TCC1: OBLIGATION
    FORALL (x, y: real): x < y IMPLIES y /= 0 OR 5 >= 0;

  % Subtype TCC generated (at line 195, column 21) for  4
      % expected type  {i: int | y /= 0 OR i >= 0}
  mono_example_3_TCC1: OBLIGATION
    FORALL (x, y: real):
      0.4 <= x AND x < y AND y <= 0.6 IMPLIES y /= 0 OR 4 >= 0;

  % Subtype TCC generated (at line 195, column 25) for  2
      % expected type  {i: int | y /= 0 OR i >= 0}
  mono_example_3_TCC2: OBLIGATION
    FORALL (x, y: real):
      0.4 <= x AND x < y AND y <= 0.6 IMPLIES y /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 201, column 47) for  3
      % expected type  {i: int | y /= 0 OR i >= 0}
  mono_example_4_TCC1: OBLIGATION
    FORALL (x, y: real): x /= y IMPLIES y /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 213, column 52) for  4
      % expected type  {i: int | y /= 0 OR i >= 0}
  mono_example_6_TCC1: OBLIGATION
    FORALL (x: real, y: real | y >= -1): x > y IMPLIES y /= 0 OR 4 >= 0;


body:
  %% metit_examples.pvs

  metit_examples : theory
  BEGIN

    IMPORTING trig@atan,
              lnexp@ln_exp,
  	    interval_arith@interval

    x,y : var real

    simple : LEMMA
      FORALL(x:real):
         x*(1-x) <= 1/4
    %|- simple : PROOF (metit) QED

    simple_abs : LEMMA 
      FORALL (x:real,y:posreal):
        abs(x*y) <= 1 IMPLIES x*y <= abs(x)*y
  % The proof command (metit) also works. This example illustrates that
  % metit can be called with multiple formulas. 
  %|- simple_abs : PROOF
  %|- (then (skeep :preds? t) (metit (-3 -4 1)))
  %|- QED

    v   : VAR posreal
    phi : VAR real

    sqrtx3 : LEMMA
      x ## [|1,2|] IMPLIES
      sqrt(x)+sqrt(3) <  pi + 0.01
  %|- sqrtx3 : PROOF (metit) QED

    g : MACRO posreal = 9.8 % [m/s^2]
    
    tr_35 : LEMMA
      abs(phi) <= 35 AND 
      v   ## [| 200, 250 |] IMPLIES
      abs(180*g*tan(phi*pi/180)/(pi*v*0.514)) ## [|0.000, 3.825|]
  %|- tr_35 : PROOF (metit) QED

    V: MACRO posreal=250*0.514  %[m/s]

    tr(phi:(Tan?)): MACRO real = g*tan(phi)/V

    tr_35_le : LEMMA
      3*pi/180 <= tr(35*pi/180)
  %|- tr_35_le : PROOF (metit) QED

    sqrt23 : LEMMA
      sqrt(2)+sqrt(3)-pi ## [|0.002, 0.007|]
  %|- sqrt23 : PROOF (metit) QED

    sin6sqrt2 : LEMMA
      sin(6*pi/180)+sqrt(2) ## [|1.517, 1.520|]
  %|- sin6sqrt2 : PROOF (metit) QED

    G(x|x < 1): MACRO real = 3*x/2 - ln(1-x)

    X : MACRO posreal = 0.5828
    
    A_and_S : LEMMA
      G(X) > 0
  %|- A_and_S : PROOF (metit) QED

    r(x) : MACRO real = x - (11184811/33554432) * x^3 
                          - (13421773/67108864) * x^5

    ex(x) : MACRO real = atan(x) - r(x)

    atan_implementation : LEMMA
      abs(x) <= 0.33 IMPLIES
      abs(ex(x)) <= 2^-9
  %|- atan_implementation : PROOF (metit) QED

  % The following problem provided by Anthony Narkawicz comes from 
  % the proof of the repulsive criteria in ACCoRD

  ajn : LEMMA
      FORALL(sx,sy,vx,vy,nvx,nvy,nwx,nwy,eps,pt,px:real) :
         px > 0 AND pt > 0 AND (eps = 1 OR eps = -1)
         AND nvx * sx + nvy * sy + nvx * nvx * pt + nvy * nvy * pt >= 0
         AND sx * vx + sy * vy < 0 AND sx * vy * eps - sy * vx * eps <= 0
         AND nvy * sx * eps - nvx * sy * eps < 0
         AND nvx * vy * eps - nvy * vx * eps < 0
         AND nvy * sx * eps - nvx * sy * eps <= 0
         AND -1 * (nwx * sy * eps) - nvy * nwx * eps * pt + nwy * sx * eps +
              nvx * nwy * eps * pt
              < 0
         AND nwx * sx + nwy * sy + nvx * nwx * pt + nvy * nwy * pt >
              nvx * sx + nvy * sy + nvx * nvx * pt + nvy * nvy * pt
         AND nwx * vy * eps - nwy * vx * eps < 0
         IMPLIES
         -1 * (nvx * sy * eps * pt) - nwx * sy * eps * px +
          nvy * sx * eps * pt
          + nwy * sx * eps * px < 0

  %|- ajn : PROOF
  %|- (metit)
  %|- QED

  % The following problems were suggested by Behzad Akbarpour

    epsilon : MACRO real = 0.1

    ex1_ba : LEMMA
      x ## [|0,1|] IMPLIES
      x - x^2  - epsilon <= ln (1 + x)
  %|- ex1_ba : PROOF (metit) QED

    ex2_ba : LEMMA
      x ## [|0,0.9|] IMPLIES
      ln(1-x) - epsilon <= -x 
  %|- ex2_ba : PROOF (metit) QED

    ex3_ba : LEMMA
      x ## [|0,1/2|] IMPLIES
      -x - 2*sq(x) - epsilon <= ln(1 - x)
  %|- ex3_ba : PROOF (metit) QED

    ex4_ba : LEMMA
      x ## [|0,1|] IMPLIES
      abs(ln(1+x) - x) - epsilon <= sq(x)
  %|- ex4_ba : PROOF (metit) QED

    ex5_ba : LEMMA
      x ## [|-1/2,0|] IMPLIES
      abs(ln(1+x) - x) - epsilon <= 2*sq(x)
  %|- ex5_ba : PROOF (metit) QED

    ex6_ba : LEMMA
      x ## [|0,1|] IMPLIES
      exp(x) - epsilon <= 1 + x + sq(x)
  %|- ex6_ba : PROOF (metit) QED

    ex7_ba : LEMMA
      x ## [|0,1|] IMPLIES
      exp(x-x^2) - epsilon <= 1 + x
  %|- ex7_ba : PROOF (metit) QED

    quadratic : LEMMA
      FORALL(a,b,c,t:real) :
        a > 0 AND
        a*sq(t) + b*t + c < 0 IMPLIES
        sq(b) > 4*a*c
  %|- quadratic : PROOF (metit) QED

  %% The following examples are taken from
  %% Formal verification of analog designs using MetiTarski
  %% William Denman, Behzad Akbarpour, Sofiene Tahar, Mohamed H. Zaki, and Lawrence C. Paulson,
  %% FMCAD 2009

    Tunnel_3_IL : LEMMA
      x ## [| 0, 2.39*10^(-9) |] IMPLIES
      -0.0059 - 0.000016*exp(-2.55*10^8*x) + 0.031*exp(-5.49*10^7*x) <= 0.03
  %|- Tunnel_3_IL : PROOF (metit) QED

    Tunnel_3_IL_LU : LEMMA
      x ## [| 0, 8.17*10^(-8) |] IMPLIES
      -0.0006427443996*exp(-2.559889987*(10^8*x)) - 0.07600397043 + 
       0.1443470449*exp(-4.211001275*(10^6*x)) 
        ## [| 0, 0.08 |]
  %|- Tunnel_3_IL_LU : PROOF (metit) QED

  %% The following problem is taken from
  %% A. Ayad and C. Marche, Multi-prover verification of floating-point programs,
  %% 5th IJCAR 2010.
    Ayad_Marche : LEMMA
      FORALL (r:real) : abs(r) <= 1 IMPLIES
        abs(0.9890365552 + 1.130258690*r + 0.5540440796*r*r - exp(r)) <= (1-2^-16)*2^-4
  %|- Ayad_Marche : PROOF (metit) QED

  END metit_examples

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

  % Subtype TCC generated (at line 31, column 9) for  x
      % expected type  nnx: nonneg_real
  sqrtx3_TCC1: OBLIGATION FORALL (x: real): x ## [|1, 2|] IMPLIES x >= 0;

  % Subtype TCC generated (at line 39, column 18) for  phi * pi / 180
      % expected type  (Tan?)
  tr_35_TCC1: OBLIGATION
    FORALL (phi: real, v: posreal):
      v ## [|200, 250|] AND abs(phi) <= 35 IMPLIES Tan?(phi * pi / 180);

  % Subtype TCC generated (at line 47, column 19) for  35 * pi / 180
      % expected type  (Tan?)
  tr_35_le_TCC1: OBLIGATION Tan?(35 * pi / 180);

  % Subtype TCC generated (at line 58, column 38) for  1 - x
      % expected type  posreal
  G_TCC1: OBLIGATION FORALL (x: real | x < 1): 1 - x >= 0 AND 1 - x > 0;

  % Subtype TCC generated (at line 66, column 50) for  3
      % expected type  {i: int | x /= 0 OR i >= 0}
  r_TCC1: OBLIGATION FORALL (x: real): x /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 67, column 50) for  5
      % expected type  {i: int | x /= 0 OR i >= 0}
  r_TCC2: OBLIGATION FORALL (x: real): x /= 0 OR 5 >= 0;

  % Subtype TCC generated (at line 108, column 10) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  ex1_ba_TCC1: OBLIGATION
    FORALL (x: real): x ## [|0, 1|] IMPLIES x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 108, column 30) for  1 + x
      % expected type  posreal
  ex1_ba_TCC2: OBLIGATION
    FORALL (x: real): x ## [|0, 1|] IMPLIES 1 + x >= 0 AND 1 + x > 0;

  % Subtype TCC generated (at line 113, column 7) for  1 - x
      % expected type  posreal
  ex2_ba_TCC1: OBLIGATION
    FORALL (x: real): x ## [|0, 0.9|] IMPLIES 1 - x >= 0 AND 1 - x > 0;

  % Subtype TCC generated (at line 118, column 33) for  1 - x
      % expected type  posreal
  ex3_ba_TCC1: OBLIGATION
    FORALL (x: real): x ## [|0, 1 / 2|] IMPLIES 1 - x >= 0 AND 1 - x > 0;

  % Subtype TCC generated (at line 128, column 11) for  1 + x
      % expected type  posreal
  ex5_ba_TCC1: OBLIGATION
    FORALL (x: real): x ## [|-1 / 2, 0|] IMPLIES 1 + x >= 0 AND 1 + x > 0;


body:
  %% interval_examples4Q.pvs
  %% 
  %% These examples only deal with rational expressions, for that reason the theory 
  %% just imports strategies4Q. 
  %%  

  interval_examples4Q : theory
  BEGIN

    IMPORTING interval_arith@strategies4Q

    x,y : var real

    %%%% Examples of numerical

    zero_to_one_quarter : LEMMA
      x ## [|0,1|] IMPLIES
      x*(1-x) ## [|0.0000, 0.2501|]
  %% The expression (! 1 1) refers to formula 1, 1st term, i.e., x*(1-x)
  %|- zero_to_one_quarter : PROOF
  %|- (then (skeep) (numerical (! 1 1) :precision 4 :maxdepth 20 :verbose? t))
  %|- QED

    x0,x1,x2,x3,x4,x5,x6,x7 : VAR real

    Heart(x0,x1,x2,x3,x4,x5,x6,x7): MACRO real = 
      -x0*x5^3+3*x0*x5*x6^2-x2*x6^3+3*x2*x6*x5^2-x1*x4^3+3*x1*x4*x7^2-x3*x7^3+3*x3*x7*x4^2-0.9563453

    hdp_mm: LEMMA 
      -0.1 <= x0 AND x0 <= 0.4 AND 
       0.4 <= x1  AND x1 <= 1 AND 
      -0.7 <= x2 AND x2 <= -0.4 AND 
      -0.7 <= x3 AND x3 <= 0.4 AND 
       0.1 <= x4  AND x4 <= 0.2 AND
      -0.1 <= x5 AND x5 <= 0.2 AND 
      -0.3 <= x6 AND x6 <= 1.1 AND 
      -1.1 <= x7 AND x7 <= -0.3 IMPLIES 
       Heart(x0,x1,x2,x3,x4,x5,x6,x7) ## [|-1.852, 1.518|]

  %% The expression (! 1 1) refers to formula 1, 1st term, i.e., polynomial Heart
  %|- hdp_mm : PROOF
  %|- (then (skeep) (numerical (! 1 1) :verbose? t))
  %|- QED

    %%%% Examples of interval

    hdp_minmax: LEMMA 
      -0.1 <= x0 AND x0 <= 0.4 AND 
       0.4 <= x1  AND x1 <= 1 AND 
      -0.7 <= x2 AND x2 <= -0.4 AND 
      -0.7 <= x3 AND x3 <= 0.4 AND 
       0.1 <= x4  AND x4 <= 0.2 AND
      -0.1 <= x5 AND x5 <= 0.2 AND 
      -0.3 <= x6 AND x6 <= 1.1 AND 
      -1.1 <= x7 AND x7 <= -0.3 IMPLIES 
       Heart(x0,x1,x2,x3,x4,x5,x6,x7) ## [| -1.76, 1.46 |]

  %|- hdp_minmax : PROOF
  %|- (then (skeep) (interval))
  %|- QED

    common_point: LEMMA 
      EXISTS (x,y,z:real): abs(x) <= 10 AND abs(y) <= 10 AND z ## [|0,1/2|] AND 
        LET x2 = x^2,
            y2 = y^2 IN
          x2-2*x+1+y2-2*y+1<1 AND x2 + y2 < 3-2*y+0.01

  %|- common_point : PROOF (interval :verbose? t) QED

     Eps : posreal = 0.0001

     simple_ite : LEMMA
       FORALL (x:real | x ## [| 0, 10 |]) :
         IF x <= 1 THEN sq(x) <= x+Eps
         ELSE sq(x) >= x-Eps
         ENDIF

  %|- simple_ite : PROOF
  %|- (interval)
  %|- QED


  END interval_examples4Q

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

  % Subtype TCC generated (at line 27, column 11) for  3
      % expected type  {i: int | x5 /= 0 OR i >= 0}
  Heart_TCC1: OBLIGATION FORALL (x5: real): x5 /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 27, column 24) for  2
      % expected type  {i: int | x6 /= 0 OR i >= 0}
  Heart_TCC2: OBLIGATION FORALL (x6: real): x6 /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 27, column 32) for  3
      % expected type  {i: int | x6 /= 0 OR i >= 0}
  hdp_mm_TCC1: OBLIGATION
    FORALL (x0, x1, x2, x3, x4, x5, x6, x7: real):
           x7 <= -0.3 AND -1.1 <= x7 AND x6 <= 1.1 AND -0.3 <= x6
       AND x5 <= 0.2 AND -0.1 <= x5 AND x4 <= 0.2 AND 0.1 <= x4 AND x3 <= 0.4
       AND -0.7 <= x3 AND x2 <= -0.4 AND -0.7 <= x2 AND x1 <= 1 AND 0.4 <= x1
       AND x0 <= 0.4 AND -0.1 <= x0
       IMPLIES x6 /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 27, column 45) for  2
      % expected type  {i: int | x5 /= 0 OR i >= 0}
  hdp_mm_TCC2: OBLIGATION
    FORALL (x0, x1, x2, x3, x4, x5, x6, x7: real):
           x7 <= -0.3 AND -1.1 <= x7 AND x6 <= 1.1 AND -0.3 <= x6
       AND x5 <= 0.2 AND -0.1 <= x5 AND x4 <= 0.2 AND 0.1 <= x4 AND x3 <= 0.4
       AND -0.7 <= x3 AND x2 <= -0.4 AND -0.7 <= x2 AND x1 <= 1 AND 0.4 <= x1
       AND x0 <= 0.4 AND -0.1 <= x0
       IMPLIES x5 /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 27, column 53) for  3
      % expected type  {i: int | x4 /= 0 OR i >= 0}
  hdp_mm_TCC3: OBLIGATION
    FORALL (x0, x1, x2, x3, x4, x5, x6, x7: real):
           x7 <= -0.3 AND -1.1 <= x7 AND x6 <= 1.1 AND -0.3 <= x6
       AND x5 <= 0.2 AND -0.1 <= x5 AND x4 <= 0.2 AND 0.1 <= x4 AND x3 <= 0.4
       AND -0.7 <= x3 AND x2 <= -0.4 AND -0.7 <= x2 AND x1 <= 1 AND 0.4 <= x1
       AND x0 <= 0.4 AND -0.1 <= x0
       IMPLIES x4 /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 27, column 66) for  2
      % expected type  {i: int | x7 /= 0 OR i >= 0}
  hdp_mm_TCC4: OBLIGATION
    FORALL (x0, x1, x2, x3, x4, x5, x6, x7: real):
           x7 <= -0.3 AND -1.1 <= x7 AND x6 <= 1.1 AND -0.3 <= x6
       AND x5 <= 0.2 AND -0.1 <= x5 AND x4 <= 0.2 AND 0.1 <= x4 AND x3 <= 0.4
       AND -0.7 <= x3 AND x2 <= -0.4 AND -0.7 <= x2 AND x1 <= 1 AND 0.4 <= x1
       AND x0 <= 0.4 AND -0.1 <= x0
       IMPLIES x7 /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 27, column 74) for  3
      % expected type  {i: int | x7 /= 0 OR i >= 0}
  hdp_mm_TCC5: OBLIGATION
    FORALL (x0, x1, x2, x3, x4, x5, x6, x7: real):
           x7 <= -0.3 AND -1.1 <= x7 AND x6 <= 1.1 AND -0.3 <= x6
       AND x5 <= 0.2 AND -0.1 <= x5 AND x4 <= 0.2 AND 0.1 <= x4 AND x3 <= 0.4
       AND -0.7 <= x3 AND x2 <= -0.4 AND -0.7 <= x2 AND x1 <= 1 AND 0.4 <= x1
       AND x0 <= 0.4 AND -0.1 <= x0
       IMPLIES x7 /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 27, column 87) for  2
      % expected type  {i: int | x4 /= 0 OR i >= 0}
  hdp_mm_TCC6: OBLIGATION
    FORALL (x0, x1, x2, x3, x4, x5, x6, x7: real):
           x7 <= -0.3 AND -1.1 <= x7 AND x6 <= 1.1 AND -0.3 <= x6
       AND x5 <= 0.2 AND -0.1 <= x5 AND x4 <= 0.2 AND 0.1 <= x4 AND x3 <= 0.4
       AND -0.7 <= x3 AND x2 <= -0.4 AND -0.7 <= x2 AND x1 <= 1 AND 0.4 <= x1
       AND x0 <= 0.4 AND -0.1 <= x0
       IMPLIES x4 /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 65, column 17) for  2
      % expected type  {i: int | y /= 0 OR i >= 0}
  common_point_TCC1: OBLIGATION
    FORALL (x, y, z: real):
      z ## [|0, 1 / 2|] AND abs(y) <= 10 AND abs(x) <= 10 IMPLIES
       (FORALL (x2: real): x2 = x ^ 2 IMPLIES y /= 0 OR 2 >= 0);


body:
  %% interval_examples.pvs
  %% 
  %% These examples deal with arbitrary real-valued expressions, for that reason the theory 
  %% imports strategies instead of strategies4Q.
  %%  

  interval_examples : theory
  BEGIN

    IMPORTING interval_arith@strategies

    x,y : var real

    %%%% Examples of numerical

    sqrt23 : LEMMA
      sqrt(2)+sqrt(3)-pi ## [|0.002, 0.007|]
  %% The expression (! 1 1) refers to formula 1, 1st term: sqrt(2)+sqrt(3)-pi
  %|- sqrt23 : PROOF
  %|- (numerical (! 1 1) :verbose? t)
  %|- QED

    sin6sqrt2 : LEMMA
      sin(6*pi/180)+sqrt(2) ## [|1.517, 1.520|]
  %% The expression (! 1 1) refers to formula 1, 1st term: sin(6*pi/180)+sqrt(2)
  %|- sin6sqrt2 : PROOF (numerical (! 1 1)) QED

    %%%% Examples of interval

    sqrtx3 : LEMMA
      x ## [|1,2|] IMPLIES
      sqrt(x)+sqrt(3) <  pi + 0.01
  %|- sqrtx3 : PROOF (interval) QED

    g : posreal = 9.8 % Gravitational acceleration [m/s^2]
    
    v     : VAR posreal % Ground speed [knots]
    phi   : VAR {deg:real| Tan?(pi*deg/180)} % Bank angle [deg]

    %% Turn rate [deg/sec]
    tr(v,phi) : MACRO real =
      LET PI = pi IN
        ((180*g)/(PI*v*0.514) )*tan((PI*phi)/180)

    tr_250_35 : LEMMA
      LET tr = tr(250,35) IN
        3 <= tr AND tr <= 3.1
  %|- tr_250_35 : PROOF (interval) QED

    tr_200_250_abs_35 : LEMMA
      abs(phi) <= 35 AND 
      v   ## [| 200, 250 |] IMPLIES
      abs(tr(v,phi)) <= 3.825
  %|- tr_200_250_abs_35 : PROOF
  %|- (then (skeep) (interval))
  %|- QED

    G(x|x < 1): MACRO real = 3*x/2 - ln(1-x)

    X : posreal = 0.5828
    
    A_and_S : LEMMA
      G(X) > 0
  %|- A_and_S : PROOF
  %|- (interval)
  %|- QED

    common_point: LEMMA EXISTS (x,y,theta,r:real): 
      abs(x) <= 1 AND abs(y) <= 1 AND abs(theta) <= 3 AND r ## [|0,1|] AND
      x^2 + y^2 < 3-2*sqrt(2)+0.1 AND (x-(1+r*cos(theta)))^2 + (y-(1+r*sin(theta)))^2 < 0.1
  %|- common_point : PROOF (interval :verbose? t) QED

    r(x) : MACRO real = x - (11184811/33554432) * x^3 
                          - (13421773/67108864) * x^5

    ex(x) : MACRO real = atan(x) - r(x)

    atan_implementation : LEMMA
      abs(x) <= 0.33 IMPLIES
      abs(ex(x)) <= 2^-9
  %|- atan_implementation : PROOF (interval) QED

  % The following problems were suggested by Behzad Akbarpour

    epsilon : real = 0.1

    ex1_ba : LEMMA
      x ## [|0,1|] IMPLIES
      x - x^2  - epsilon <= ln (1 + x)
  %|- ex1_ba : PROOF (interval) QED

    ex2_ba : LEMMA
      x ## [|0,0.9|] IMPLIES
      ln(1-x) - epsilon <= -x 
  %|- ex2_ba : PROOF (interval) QED

    ex3_ba : LEMMA
      x ## [|0,1/2|] IMPLIES
      -x - 2*sq(x) - epsilon <= ln(1 - x)
  %|- ex3_ba : PROOF (interval) QED

    ex4_ba : LEMMA
      x ## [|0,1|] IMPLIES
      abs(ln(1+x) - x) - epsilon <= sq(x)
  %|- ex4_ba : PROOF (interval) QED

    ex5_ba : LEMMA
      x ## [|-1/2,0|] IMPLIES
      abs(ln(1+x) - x) - epsilon <= 2*sq(x)
  %|- ex5_ba : PROOF (interval) QED

    ex6_ba : LEMMA
      x ## [|0,1|] IMPLIES
      exp(x) - epsilon <= 1 + x + sq(x)
  %|- ex6_ba : PROOF (interval) QED

    ex7_ba : LEMMA
      x ## [|0,1|] IMPLIES
      exp(x-x^2) - epsilon <= 1 + x
  %|- ex7_ba : PROOF (interval) QED

  %% The following examples are taken from
  %% Formal verification of analog designs using MetiTarski
  %% William Denman, Behzad Akbarpour, Sofiene Tahar, Mohamed H. Zaki, and Lawrence C. Paulson,
  %% FMCAD 2009

    Tunnel_3_IL : LEMMA
      FORALL (x:real | x ## [| 0, 2.39*10^(-9) |]):
      -0.0059 - 0.000016*exp(-2.55*10^8*x) + 0.031*exp(-5.49*10^7*x) <= 0.03
  %|- Tunnel_3_IL : PROOF (interval) QED

    Tunnel_3_IL_LU : LEMMA
      FORALL (x:real | x ## [| 0, 8.17*10^(-8) |]):
      -0.0006427443996*exp(-2.559889987*(10^8*x)) - 0.07600397043 + 
       0.1443470449*exp(-4.211001275*(10^6*x)) 
        ## [| 0, 0.08 |]
  %|- Tunnel_3_IL_LU : PROOF (interval) QED

  END interval_examples

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

  % Subtype TCC generated (at line 32, column 9) for  x
      % expected type  nnx: nonneg_real
  sqrtx3_TCC1: OBLIGATION FORALL (x: real): x ## [|1, 2|] IMPLIES x >= 0;

  % Subtype TCC generated (at line 43, column 34) for  (PI * phi) / 180
      % expected type  (Tan?)
  tr_TCC1: OBLIGATION
    FORALL (phi: {deg: real | Tan?(pi * deg / 180)},
            PI: {r: posreal | pi_lb < r AND r < pi_ub}):
      PI = pi IMPLIES Tan?((PI * phi) / 180);

  % Subtype TCC generated (at line 43, column 34) for  (PI * 35) / 180
      % expected type  (Tan?)
  tr_250_35_TCC1: OBLIGATION
    FORALL (PI: {r: posreal | pi_lb < r AND r < pi_ub}):
      PI = pi IMPLIES Tan?((PI * 35) / 180);

  % Subtype TCC generated (at line 58, column 38) for  1 - x
      % expected type  posreal
  G_TCC1: OBLIGATION FORALL (x: real | x < 1): 1 - x >= 0 AND 1 - x > 0;

  % Subtype TCC generated (at line 63, column 6) for  X
      % expected type  {x | x < 1}
  A_and_S_TCC1: OBLIGATION X < 1;

  % Subtype TCC generated (at line 58, column 38) for  1 - X
      % expected type  posreal
  A_and_S_TCC2: OBLIGATION 1 - X >= 0 AND 1 - X > 0;

  % Subtype TCC generated (at line 70, column 6) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  common_point_TCC1: OBLIGATION
    FORALL (x, y, theta, r: real):
      r ## [|0, 1|] AND abs(theta) <= 3 AND abs(y) <= 1 AND abs(x) <= 1
       IMPLIES x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 70, column 12) for  2
      % expected type  {i: int | y /= 0 OR i >= 0}
  common_point_TCC2: OBLIGATION
    FORALL (x, y, theta, r: real):
      r ## [|0, 1|] AND abs(theta) <= 3 AND abs(y) <= 1 AND abs(x) <= 1
       IMPLIES y /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 70, column 57) for  2
      % expected type  {i: int | NOT x - 1 - r * cos(theta) = 0 OR i >= 0}
  common_point_TCC3: OBLIGATION
    FORALL (x, y, theta, r: real):
           x ^ 2 + y ^ 2 < 3 - 2 * sqrt(2) + 0.1 AND r ## [|0, 1|]
       AND abs(theta) <= 3 AND abs(y) <= 1 AND abs(x) <= 1
       IMPLIES NOT x - 1 - r * cos(theta) = 0 OR 2 >= 0;

  % Subtype TCC generated (at line 70, column 82) for  2
      % expected type  {i: int | NOT y - 1 - r * sin(theta) = 0 OR i >= 0}
  common_point_TCC4: OBLIGATION
    FORALL (x, y, theta, r: real):
           x ^ 2 + y ^ 2 < 3 - 2 * sqrt(2) + 0.1 AND r ## [|0, 1|]
       AND abs(theta) <= 3 AND abs(y) <= 1 AND abs(x) <= 1
       IMPLIES NOT y - 1 - r * sin(theta) = 0 OR 2 >= 0;

  % Subtype TCC generated (at line 73, column 50) for  3
      % expected type  {i: int | x /= 0 OR i >= 0}
  r_TCC1: OBLIGATION FORALL (x: real): x /= 0 OR 3 >= 0;

  % Subtype TCC generated (at line 74, column 50) for  5
      % expected type  {i: int | x /= 0 OR i >= 0}
  r_TCC2: OBLIGATION FORALL (x: real): x /= 0 OR 5 >= 0;

  % Subtype TCC generated (at line 89, column 10) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  ex1_ba_TCC1: OBLIGATION
    FORALL (x: real): x ## [|0, 1|] IMPLIES x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 89, column 30) for  1 + x
      % expected type  posreal
  ex1_ba_TCC2: OBLIGATION
    FORALL (x: real): x ## [|0, 1|] IMPLIES 1 + x >= 0 AND 1 + x > 0;

  % Subtype TCC generated (at line 94, column 7) for  1 - x
      % expected type  posreal
  ex2_ba_TCC1: OBLIGATION
    FORALL (x: real): x ## [|0, 0.9|] IMPLIES 1 - x >= 0 AND 1 - x > 0;

  % Subtype TCC generated (at line 99, column 33) for  1 - x
      % expected type  posreal
  ex3_ba_TCC1: OBLIGATION
    FORALL (x: real): x ## [|0, 1 / 2|] IMPLIES 1 - x >= 0 AND 1 - x > 0;

  % Subtype TCC generated (at line 109, column 11) for  1 + x
      % expected type  posreal
  ex5_ba_TCC1: OBLIGATION
    FORALL (x: real): x ## [|-1 / 2, 0|] IMPLIES 1 + x >= 0 AND 1 + x > 0;


body:
  %% Examples of strategies in Field 6.0
  %% Cesar Munoz 
  %% http://shemesh.larc.nasa.gov/people/cam/Field
  %% NASA LaRC

  field_examples : THEORY
  BEGIN

    a,b,c    : VAR real
    pa,pb,pc : VAR posreal
    nza,nzb  : VAR nzreal

    f1 : LEMMA 
      a > 1 AND b > 1 =>
      (a+1)/((a+1)/(b+1)) - b = 1
  %|- f1 : PROOF (then (skeep) (field)) QED

    f2 : LEMMA 
      b >1 AND a > 1 =>
      (b-1)/((b-1)/(a-1)) - a = -1 
  %|- f2 : PROOF (then (skeep) (field)) QED

    f3 : LEMMA 
      b >1 AND a > 1 =>
      (b-1)/((b-1)/(a-1)) - a < 0
  %|- f3 : PROOF (then (skeep) (field)) QED

    f4 : LEMMA 
      (pa+1)/((pa+1)/(pb+1)) - pb >= 1
  %|- f4 : PROOF (then (skeep) (field)) QED

    f5 : LEMMA 
      (1+pb+(pa*pb+pa))/(1+pa) - pb = 1
  %|- f5 : PROOF (then (skeep) (field)) QED

    f6 : LEMMA 
      a > 1 IMPLIES
      a/((a-1) * (a+1)) - 1 /((a-1)*(a+1)) >= 1 /(a+1) - 1
  %|- f6 : PROOF (then (skeep) (field)) QED

    f7: LEMMA 
      1 - pa*(pb+1) = (pa-1)/(pb+1) IMPLIES
      1/(1+ pb/(1+ 1/(1+pb))) = pa 
  %|- f7 : PROOF (then (skeep) (field)) QED

    f8: LEMMA 
      1 - pa*(pb+1) = (pa-1)/(pb+1) IMPLIES
      1/(1+ pb/(1+ 1/(1+pb))) >= pa
  %|- f8 : PROOF (then (skeep) (field)) QED

    f9: LEMMA 
      1 - pa*(pb+1) = (pa-1)/(pb+1) IMPLIES
      1/(1+ pb/(1+ 1/(1+pb))) <= pa   
  %|- f9 : PROOF (then (skeep) (field)) QED

    f10 : LEMMA 
      a*(pa+b)/(pa+1) - b*(pa+a)/(pa+1) = 0 IMPLIES a = b
  %|- f10 : PROOF (then (skeep) (field - :cancel? t)) QED

    f11 : LEMMA 
      a /= 1 IMPLIES
      1 / (1-a) = 1 + a + a * a + (a*a*a)/(1-a)
  %|- f11 : PROOF (then (skeep) (field 2)) QED

    cf1 : LEMMA
      4*(pa*pb) + (pa*6)*pa = pa*((c+1)*2) =>
      2*pb + 3*pa - 1 = c
  %|- cf1 : PROOF (then (skeep) (cancel-formula -)) QED

    cf2 : LEMMA 
      4*(pa*pb) + (pa*6)*pa <= pa*((c+1)*2) =>
      2*pb + 3*pa - c <= 1
  %|- cf2 : PROOF (then (skeep) (cancel-formula -)) QED
   
    cf3 : LEMMA 
      4*((pa+1)*pb) + ((pa+1)*6)*(pa+1) = -(pa+1)*((c+1)*2) IMPLIES
      2*pb + 3*(pa+1) + c + 1  = 0
  %|- cf3 : PROOF (then (skeep) (cancel-formula -)) QED

    cf4 : LEMMA 
     c+2 < 0 IMPLIES
     c*(c+2)*pa + pa*2*(c+2) > pb*pa*(c+2)
  %|- cf4 : PROOF (then (skeep) (cancel-formula)) QED

    cf5 : LEMMA  
     c+2 < 0 AND
     c*(c+2)*pa + pa*2*(c+2) < b*pa*(c+2) IMPLIES
     b < 0
  %|- cf5 : PROOF (then (skeep) (cancel-formula -2)) QED

    gr1 : LEMMA 
      a /= -4 IMPLIES
      (a+3)*(a*a+9*a+20)/(a+4) = (a+3)*(a+5)
  %|- gr1 : PROOF (grind-reals) QED

    gr2 : LEMMA 
      a /= 6 AND a /= 0 AND b = 3/(a*a-6*a) IMPLIES
      (a+3)/(a*(a-6)) = 1/(a-6)+b 
  %|- gr2 : PROOF (grind-reals) QED

    gr3 : LEMMA 
      a /= 6 AND a /=0 IMPLIES
      (a+3)/(a*(a-6)) = 1/(a-6)+3/(a*(a-6))
  %|- gr3 : PROOF (grind-reals) QED

  %%% The following examples are taken from developments at NASA LaRC
    IMPORTING reals@sqrt

    A           : VAR nzreal
    B,C,Delta,x : VAR real
    eps         : VAR {x:real|x=1 OR x=-1}

    quadratic : LEMMA 
      Delta = (B * B) - (4 * (A * C)) AND
      Delta >= 0 AND
      x = (eps * sqrt(Delta) - B) / (2 * A)
      IMPLIES A * x * x + B * x + C = 0
  %|- quadratic : PROOF
  %|- (then (skeep :preds? t) (replaces (-6 -8)) (field 2))
  %|- QED
    
    t,vix,viy,vox,voy,s : VAR real
    D                   : VAR posreal

    kb3d : LEMMA 
      vox > 0 AND
      s*s - D*D > D AND
      s * vix * voy - s * viy * vox /= 0 AND
      ((s * s - D * D) * voy - D * vox * sqrt(s * s - D * D)) / 
       (s * (vix * voy - vox * viy)) * s * vox /= 0 AND
      voy * sqrt(s * s - D * D) - D * vox /= 0 
      IMPLIES
      (viy * sqrt(s * s - D * D) - vix * D) /
      (voy * sqrt(s * s - D * D) - vox * D)
       =
      (D * D - s * s) /
      (((s * s - D * D) * voy - D * vox * sqrt(s * s - D * D)) / 
        (s * (vix * voy - vox * viy)) * s * vox) + 
      vix / vox
  %|- kb3d : PROOF (grind-reals) QED

  END field_examples

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

  % Subtype TCC generated (at line 15, column 18) for  (b + 1)
      % expected type  nznum
  f1_TCC1: OBLIGATION
    FORALL (a, b: real): b > 1 AND a > 1 IMPLIES (b + 1) /= 0;

  % Subtype TCC generated (at line 15, column 11) for  ((a + 1) / (b + 1))
      % expected type  nznum
  f1_TCC2: OBLIGATION
    FORALL (a, b: real): b > 1 AND a > 1 IMPLIES ((a + 1) / (b + 1)) /= 0;

  % Subtype TCC generated (at line 20, column 18) for  (a - 1)
      % expected type  nznum
  f2_TCC1: OBLIGATION
    FORALL (a, b: real): a > 1 AND b > 1 IMPLIES (a - 1) /= 0;

  % Subtype TCC generated (at line 20, column 11) for  ((b - 1) / (a - 1))
      % expected type  nznum
  f2_TCC2: OBLIGATION
    FORALL (a, b: real): a > 1 AND b > 1 IMPLIES ((b - 1) / (a - 1)) /= 0;

  % Subtype TCC generated (at line 38, column 7) for  ((a - 1) * (a + 1))
      % expected type  nznum
  f6_TCC1: OBLIGATION
    FORALL (a: real): a > 1 IMPLIES ((a - 1) * (a + 1)) /= 0;

  % Subtype TCC generated (at line 38, column 48) for  (a + 1)
      % expected type  nznum
  f6_TCC2: OBLIGATION FORALL (a: real): a > 1 IMPLIES (a + 1) /= 0;

  % Subtype TCC generated (at line 62, column 9) for  (1 - a)
      % expected type  nznum
  f11_TCC1: OBLIGATION FORALL (a: real): a /= 1 IMPLIES (1 - a) /= 0;

  % Subtype TCC generated (at line 93, column 24) for  (a + 4)
      % expected type  nznum
  gr1_TCC1: OBLIGATION FORALL (a: real): a /= -4 IMPLIES (a + 4) /= 0;

  % Subtype TCC generated (at line 97, column 33) for  (a * a - 6 * a)
      % expected type  nznum
  gr2_TCC1: OBLIGATION
    FORALL (a: real): a /= 6 AND a /= 0 IMPLIES (a * a - 6 * a) /= 0;

  % Subtype TCC generated (at line 98, column 11) for  (a * (a - 6))
      % expected type  nznum
  gr2_TCC2: OBLIGATION
    FORALL (a, b: real):
      b = 3 / (a * a - 6 * a) AND a /= 0 AND a /= 6 IMPLIES
       (a * (a - 6)) /= 0;

  % Subtype TCC generated (at line 98, column 25) for  (a - 6)
      % expected type  nznum
  gr2_TCC3: OBLIGATION
    FORALL (a, b: real):
      b = 3 / (a * a - 6 * a) AND a /= 0 AND a /= 6 IMPLIES (a - 6) /= 0;

  % Subtype TCC generated (at line 103, column 11) for  (a * (a - 6))
      % expected type  nznum
  gr3_TCC1: OBLIGATION
    FORALL (a: real): a /= 0 AND a /= 6 IMPLIES (a * (a - 6)) /= 0;

  % Subtype TCC generated (at line 103, column 25) for  (a - 6)
      % expected type  nznum
  gr3_TCC2: OBLIGATION
    FORALL (a: real): a /= 0 AND a /= 6 IMPLIES (a - 6) /= 0;

  % Subtype TCC generated (at line 129, column 44) for  s * s - D * D
      % expected type  nnx: nonneg_real
  kb3d_TCC1: OBLIGATION
    FORALL (D: posreal, s, vix, viy, vox, voy: real):
      vox > 0 AND s * s - D * D > D AND s * vix * voy - s * viy * vox /= 0
       IMPLIES s * s - D * D >= 0;

  % Subtype TCC generated (at line 130, column 6) for
      % (s * (vix * voy - vox * viy))
      % expected type  nznum
  kb3d_TCC2: OBLIGATION
    FORALL (D: posreal, s, vix, viy, vox, voy: real):
      vox > 0 AND s * s - D * D > D AND s * vix * voy - s * viy * vox /= 0
       IMPLIES (s * (vix * voy - vox * viy)) /= 0;

  % Subtype TCC generated (at line 134, column 5) for
      % (voy * sqrt(s * s - D * D) - vox * D)
      % expected type  nznum
  kb3d_TCC3: OBLIGATION
    FORALL (D: posreal, s, vix, viy, vox, voy: real):
           voy * sqrt(s * s - D * D) - D * vox /= 0
       AND ((s * s - D * D) * voy - D * vox * sqrt(s * s - D * D)) /
            (s * (vix * voy - vox * viy))
            * s
            * vox
            /= 0
       AND s * vix * voy - s * viy * vox /= 0 AND s * s - D * D > D
       AND vox > 0
       IMPLIES (voy * sqrt(s * s - D * D) - vox * D) /= 0;

  % Subtype TCC generated (at line 139, column 10) for  vox
      % expected type  nznum
  kb3d_TCC4: OBLIGATION
    FORALL (D: posreal, s, vix, viy, vox, voy: real):
           voy * sqrt(s * s - D * D) - D * vox /= 0
       AND ((s * s - D * D) * voy - D * vox * sqrt(s * s - D * D)) /
            (s * (vix * voy - vox * viy))
            * s
            * vox
            /= 0
       AND s * vix * voy - s * viy * vox /= 0 AND s * s - D * D > D
       AND vox > 0
       IMPLIES vox /= 0;


body:
  %-------------------------------------------------------------------------
  % top file for Extended nnreals
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0           20/08/07	Initial (DRL)
  %-------------------------------------------------------------------------

  top: THEORY

  BEGIN

    IMPORTING code_product,       % A coding for diagonalizing a sequence
              double_index,       % double and single indexing for sequences
              double_nn_sequence, % Convergence properties of doubly indexed
                                  % sequences of nnreals
              extended_nnreal     % The extended non-negative reals.

  END top


body:
  %-------------------------------------------------------------------------
  % code product
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0           04/05/09    Initial (DRL)
  %
  %
  % Diagonal traversal (through the indices of a doubly-indexed set)
  %
  % For the first ten naturals we get:
  %    (double_index_i(n),double_index_j(n)) =
  %   (0,0),(1,0),(0,1),(2,0),(1,1),(0,2),(3,0),(2,1),(1,2),(0,3),(4,0)
  % and so on...
  %-------------------------------------------------------------------------

  code_product: THEORY

  BEGIN

    IMPORTING reals@sqrt % proof only

    i,j,n,m: VAR nat

    double_index_n(i,j):nat = ((i+j)*(1+i+j))/2 + j

    double_index_triangle(n):nat = {i | (i*(i+1))/2 <= n AND n < ((i+1)*(i+2))/2}

    double_index_triangle_def: LEMMA
      (double_index_triangle(n)*(double_index_triangle(n)+1))/2 <= n AND
      n < ((double_index_triangle(n)+1)*(double_index_triangle(n)+2))/2

    double_index_triangle_increasing: LEMMA
      FORALL i,j: i <= j => double_index_triangle(i) <= double_index_triangle(j)

    double_index_triangle_bound:      LEMMA double_index_triangle(n) <= n

    double_index_j(n):nat
      = n - (double_index_triangle(n)*(double_index_triangle(n)+1))/2

    double_index_j_bound: LEMMA double_index_j(n) <= double_index_triangle(n)

    double_index_i(n):nat = double_index_triangle(n)-double_index_j(n)

    double_index_i_bound: LEMMA double_index_i(n) <= double_index_triangle(n)

    double_index_n_increasing: LEMMA
      FORALL n,m: n < m => double_index_n(n,j) < double_index_n(m,j)

    double_index_n_ij: LEMMA
      double_index_n(double_index_i(n),double_index_j(n)) = n

    double_index_ij_n: LEMMA
      double_index_i(double_index_n(i,j)) = i AND
      double_index_j(double_index_n(i,j)) = j

    double_index_n_bijective: LEMMA bijective?[[nat,nat],nat](double_index_n)

  END code_product

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

  % Subtype TCC generated (at line 25, column 28) for
      % ((i + j) * (1 + i + j)) / 2 + j
      % expected type  nat
  double_index_n_TCC1: OBLIGATION
    FORALL (i: nat, j: nat):
      integer_pred(((i + j) * (1 + i + j)) / 2 + j) AND
       ((i + j) * (1 + i + j)) / 2 + j >= 0;

  % Subtype TCC generated (at line 27, column 33) for
      % {i | (i * (i + 1)) / 2 <= n AND n < ((i + 1) * (i + 2)) / 2}
      % expected type  (singleton?[nat])
  double_index_triangle_TCC1: OBLIGATION
    FORALL (n: nat):
      singleton?[nat]
          ({i | (i * (i + 1)) / 2 <= n AND n < ((i + 1) * (i + 2)) / 2});

  % Subtype TCC generated (at line 39, column 6) for
      % n - (double_index_triangle(n) * (double_index_triangle(n) + 1)) / 2
      % expected type  nat
  double_index_j_TCC1: OBLIGATION
    FORALL (n: nat):
      integer_pred(n -
                    (double_index_triangle(n) *
                      (double_index_triangle(n) + 1))
                     / 2)
       AND
       n - (double_index_triangle(n) * (double_index_triangle(n) + 1)) / 2 >=
        0;

  % Subtype TCC generated (at line 43, column 26) for
      % double_index_triangle(n) - double_index_j(n)
      % expected type  nat
  double_index_i_TCC1: OBLIGATION
    FORALL (n: nat): double_index_triangle(n) - double_index_j(n) >= 0;


body:
  %-------------------------------------------------------------------------
  % doubly index sequences
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0           04/05/09    Initial (DRL)
  %
  % Diagonal traversal (through the indices of a doubly-indexed set)
  %
  % For the first ten naturals we get:
  %    (double_index_i(n),double_index_j(n)) =
  %   (0,0),(1,0),(0,1),(2,0),(1,1),(0,2),(3,0),(2,1),(1,2),(0,3),(4,0)
  % and so on...
  %-------------------------------------------------------------------------
  double_index[T:TYPE]: THEORY

  BEGIN

    IMPORTING code_product

    i,j,n: VAR nat
    u: VAR [[nat,nat]->T]
    v: VAR [nat->T]

    single_index(u):[nat->T] = (lambda n: u(double_index_i(n),double_index_j(n)))

    double_index(v):[[nat,nat]->T] = v o double_index_n

    single_double: LEMMA single_index(double_index(v)) = v

    double_single: LEMMA double_index(single_index(u)) = u

  END double_index


body:
  %-------------------------------------------------------------------------
  % Convergence properties of doubly-indexed sequences of nnreals
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0           04/05/09    Initial (DRL)
  %-------------------------------------------------------------------------

  double_nn_sequence: THEORY

  BEGIN

    IMPORTING analysis@real_fun_supinf[nnreal],
              double_index[nnreal],
              series@series_aux,
              sigma_set@absconv_series_aux

    u: VAR [[nat,nat]->nnreal]
    v: VAR [nat->nnreal]
    l: VAR nnreal
    i,j,n: VAR nat
    z: VAR real

    nn_series_increasing: LEMMA increasing?(series(v))

    nn_index_scaf1: LEMMA 
      series(single_index(u))(double_index_n(0,n)) = 
        sigma(0, n, LAMBDA i: sigma(0,n-i,lambda j: u(i,j)))

    nn_double_index_incr: LEMMA double_index_n(i,j) = double_index_n(0,i+j)-i

    nn_index_scaf2: LEMMA
        sigma(0,n, LAMBDA i: sigma(0,n,lambda j: u(i,j))) <= 
          series(single_index(u))(double_index_n(0,2*n))

    nn_index_scaf3: LEMMA EXISTS n:
        sigma(0,i, LAMBDA i: sigma(0,j,lambda j: u(i,j))) <=
          series(single_index(u))(n)

    nn_index_scaf4: LEMMA EXISTS i,j:
        series(single_index(u))(n) <=
          sigma(0,i, LAMBDA i: sigma(0,j,lambda j: u(i,j)))

    nn_convegent_bounded: LEMMA convergent?(series(v)) <=> 
                                bounded_above?(Im(series(v)))

    nn_limit_lub: LEMMA convergent?(series(v)) =>
                        limit(series(v)) = lub(Im(series(v)))

    nn_convergence_least_upper_bound: LEMMA increasing?(v) =>
      (convergence(v,l) <=> least_upper_bound?(l,Im(v)))

    double_series: LEMMA
      series(LAMBDA i: series(LAMBDA j: u(i,j))(j))(i) =
          series(LAMBDA j: series(lambda i: u(i,j))(i))(j)

    double_subseq_convergent: LEMMA convergent?(series(single_index(u))) =>
                                    convergent?(series(LAMBDA j: u(i,j)))

    double_subseq_bounded: LEMMA
      bounded_above?(Im(series(single_index(u)))) =>
        bounded_above?(Im(series(LAMBDA j: u(i,j))))

    series_limit_def: LEMMA
      (FORALL i: convergent?(LAMBDA j: u(i,j))) =>
      series(lambda i: limit(lambda j: u(i,j)))(i) =
             limit(lambda j: series(lambda i: u(i,j))(i))

    double_approx: LEMMA
      (FORALL i: convergent?(series(LAMBDA j: u(i,j)))) =>
      series(lambda i: limit(series(lambda j: u(i,j))))(i)
        = limit(series(lambda j: series(lambda i: u(i,j))(i)))

    double_approx1: LEMMA convergence(series(single_index(u)),l) <=>
      least_upper_bound?(l,{z | exists i,j:
                   series(lambda j: series(lambda i: u(i,j))(i))(j) =z})

    double_approx2: LEMMA (FORALL i: convergent?(series(LAMBDA j: u(i,j)))) =>
      (convergence(series(lambda i: limit(series(lambda j: u(i,j)))),l) <=>
       least_upper_bound?(l,{z | exists i,j:
                   series(lambda j: series(lambda i: u(i,j))(i))(j) =z}))

    double_left_convergence: LEMMA
      convergence(series(single_index(u)),l) <=>
      (FORALL i: convergent?(series(LAMBDA j: u(i,j)))) AND
      convergence(series(lambda i: limit(series(lambda j: u(i,j)))),l)

    double_left_convergent: LEMMA 
      convergent?(series(single_index(u))) <=>
      (FORALL i: convergent?(series(LAMBDA j: u(i,j)))) AND
      convergent?(series(lambda i: limit(series(lambda j: u(i,j)))))

    double_left_limit: LEMMA convergent?(series(single_index(u))) =>
      limit(series(single_index(u)))
        = limit(series(lambda i: limit(series(lambda j: u(i,j)))))

    double_right_convergence: LEMMA
      convergence(series(single_index(u)),l) <=>
      convergence(series(single_index(lambda j,i: u(i,j))),l)

    double_right_convergent: LEMMA
      convergent?(series(single_index(u))) <=>
      convergent?(series(single_index(lambda j,i: u(i,j))))

    double_right_limit: LEMMA convergent?(series(single_index(u))) =>
      limit(series(single_index(u)))
        = limit(series(single_index(lambda j,i: u(i,j))))

  END double_nn_sequence

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

  % Subtype TCC generated (at line 28, column 15) for  n
      % expected type  T_high[nat]
  nn_index_scaf1_TCC1: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 28, column 36) for  n - i
      % expected type  T_high[nat]
  nn_index_scaf1_TCC2: OBLIGATION
    FORALL (n: nat, i): n - i >= 0 OR (EXISTS (j: nat): n - i <= j);

  % Subtype TCC generated (at line 48, column 45) for  Im(series(v))
      % expected type  SA: (bounded_above?)
  nn_limit_lub_TCC1: OBLIGATION
    FORALL (v: [nat -> nnreal]):
      convergent?(series(v)) IMPLIES bounded_above?(Im[nat](series(v)));

  % Subtype TCC generated (at line 66, column 27) for  LAMBDA j: u(i, j)
      % expected type  (convergent?)
  series_limit_def_TCC1: OBLIGATION
    FORALL (u: [[nat, nat] -> nnreal]):
      (FORALL i: convergent?(LAMBDA j: u(i, j))) IMPLIES
       (FORALL (i1): convergent?(LAMBDA j: u(i1, j)));

  % Subtype TCC generated (at line 67, column 17) for
      % LAMBDA j: series(LAMBDA i: u(i, j))(i)
      % expected type  (convergent?)
  series_limit_def_TCC2: OBLIGATION
    FORALL (i1: nat, u: [[nat, nat] -> nnreal]):
      (FORALL i: convergent?(LAMBDA j: u(i, j))) IMPLIES
       convergent?(LAMBDA j: series(LAMBDA i: u(i, j))(i1));

  % Subtype TCC generated (at line 71, column 27) for
      % series(LAMBDA j: u(i, j))
      % expected type  (convergent?)
  double_approx_TCC1: OBLIGATION
    FORALL (u: [[nat, nat] -> nnreal]):
      (FORALL i: convergent?(series(LAMBDA j: u(i, j)))) IMPLIES
       (FORALL (i1): convergent?(series(LAMBDA j: u(i1, j))));

  % Subtype TCC generated (at line 72, column 14) for
      % series(LAMBDA j: series(LAMBDA i: u(i, j))(i))
      % expected type  (convergent?)
  double_approx_TCC2: OBLIGATION
    FORALL (i1: nat, u: [[nat, nat] -> nnreal]):
      (FORALL i: convergent?(series(LAMBDA j: u(i, j)))) IMPLIES
       convergent?(series(LAMBDA j: series(LAMBDA i: u(i, j))(i1)));

  % Subtype TCC generated (at line 75, column 25) for
      % {z |
      %    EXISTS i, j: series(LAMBDA j: series(LAMBDA i: u(i, j))(i))(j) = z}
      % expected type  (nonempty?[real])
  double_approx1_TCC1: OBLIGATION
    FORALL (u: [[nat, nat] -> nnreal]):
      nonempty?[real]
          ({z |
              EXISTS i, j:
                series(LAMBDA j: series(LAMBDA i: u(i, j))(i))(j) = z});

  % Subtype TCC generated (at line 95, column 37) for
      % series(LAMBDA j: u(i, j))
      % expected type  (convergent?)
  double_left_limit_TCC1: OBLIGATION
    FORALL (u: [[nat, nat] -> nnreal]):
      convergent?(series(single_index(u))) IMPLIES
       (FORALL (i): convergent?(series(LAMBDA j: u(i, j))));

  % Subtype TCC generated (at line 95, column 14) for
      % series(LAMBDA i: limit(series(LAMBDA j: u(i, j))))
      % expected type  (convergent?)
  double_left_limit_TCC2: OBLIGATION
    FORALL (u: [[nat, nat] -> nnreal]):
      convergent?(series(single_index(u))) IMPLIES
       convergent?(series(LAMBDA i: limit(series(LAMBDA j: u(i, j)))));

  % Subtype TCC generated (at line 107, column 14) for
      % series(single_index(LAMBDA j, i: u(i, j)))
      % expected type  (convergent?)
  double_right_limit_TCC1: OBLIGATION
    FORALL (u: [[nat, nat] -> nnreal]):
      convergent?(series(single_index(u))) IMPLIES
       convergent?(series(single_index[nnreal](LAMBDA j, i: u(i, j))));


body:
  %-------------------------------------------------------------------------
  % Extended nnreals
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0           20/08/07	Initial (DRL)
  %-------------------------------------------------------------------------

  extended_nnreal: THEORY

  BEGIN

    IMPORTING series@series_aux,
              sigma_set@absconv_series_aux,
              reals@sigma[nat],
              analysis@epsilon_lemmas

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

    extended_nnreal: TYPE+ = [bool,nnreal] CONTAINING (TRUE,0)

    i,j,low,high: VAR nat
    x,y,x1,y1,x2,y2: VAR extended_nnreal
    z:   VAR real
    S,T: VAR [nat->extended_nnreal]
    U:   VAR [nat->nnreal]
    X:   VAR set[extended_nnreal]
    epsilon: VAR posreal
    c:   VAR nnreal

    x_inf(X):extended_nnreal
      = IF (FORALL (x:(X)): NOT x`1)
        THEN (FALSE,0)
        ELSE (TRUE,glb({z | EXISTS x: X(x) AND x`1 AND x`2 = z})) ENDIF

    x_sup(X):extended_nnreal
      = IF empty?(X)
        THEN (TRUE,0)
        ELSIF (EXISTS (x:(X)): NOT x`1) OR
              NOT bounded_above?({z | EXISTS x: X(x) AND x`1 AND x`2 = z})
        THEN (FALSE,0)
        ELSE (TRUE,lub({z | EXISTS x: X(x) AND x`1 AND x`2 = z})) ENDIF

    x_inf(S):extended_nnreal = x_inf(image(S,fullset[nat]))
    x_sup(S):extended_nnreal = x_sup(image(S,fullset[nat]))

    x_sigma(low,high,S):extended_nnreal
      = IF (FORALL i: low <= i AND i <= high => S(i)`1)
        THEN (TRUE,sigma(low,high,lambda i: S(i)`2))
        ELSE (FALSE,0) ENDIF

    x_sum(S):extended_nnreal
      = IF (FORALL i: S(i)`1) AND convergent?(series(lambda i: S(i)`2))
        THEN (TRUE,limit(series(lambda i: S(i)`2)))
        ELSE (FALSE,0) ENDIF

    x_sum(U):extended_nnreal
      = IF convergent?(series(U))
        THEN (TRUE,limit(series(U)))
        ELSE (FALSE,0) ENDIF

    x_converges?(S,x):bool
      = IF (FORALL i: S(i)`1) AND convergent?(lambda i: S(i)`2)
        THEN x`1 AND x`2 = limit(lambda i: S(i)`2)
        ELSE NOT x`1 ENDIF

    x_limit(S):extended_nnreal
      = IF (FORALL i: S(i)`1) AND convergent?(lambda i: S(i)`2)
        THEN (TRUE,limit(lambda i: S(i)`2))
        ELSE (FALSE,0) ENDIF

    x_add(x,y):extended_nnreal
      = IF x`1 AND y`1 THEN (TRUE,x`2+y`2) ELSE (FALSE,0) ENDIF

    x_add(x,c):extended_nnreal = IF x`1 THEN (TRUE,x`2+c) ELSE (FALSE,0) ENDIF

    x_eq(x,y):bool = (x`1 = y`1) AND (x`1 => x`2 = y`2)
    x_le(x,y):bool = (x`1 AND y`1 AND x`2 <= y`2) OR (NOT y`1)
    x_lt(x,y):bool = (x`1 AND y`1 AND x`2 <  y`2) OR (NOT y`1)

    x_eq(x,c):bool = x`1 AND x`2 = c

    x_times(x,y):extended_nnreal
      = IF (x`1 AND y`1) OR x_eq(x,0) OR x_eq(y,0) THEN (TRUE,x`2*y`2)
                                                   ELSE (FALSE,0) ENDIF

    x_times(x,c):extended_nnreal = IF x`1 OR c = 0 THEN (TRUE,x`2*c)
                                                   ELSE (FALSE,0) ENDIF
    x_times(c,x):extended_nnreal = x_times(x,c)

    x_add_commutative:   LEMMA commutative?(x_add)
    x_add_associative:   LEMMA associative?(x_add)
    x_times_commutative: LEMMA commutative?(x_times)
    x_times_associative: LEMMA associative?(x_times)
    x_eq_equivalence:    LEMMA equivalence?(x_eq)
    x_le_preorder:       LEMMA preorder?(x_le)
    x_le_antisymmetric:  LEMMA x_le(x,y) AND x_le(y,x) => x_eq(x,y)

    x_sigma_le: LEMMA (FORALL i: low <= i AND i <= high => x_le(S(i),T(i))) =>
                      x_le(x_sigma(low,high,S),x_sigma(low,high,T))

    x_sigma_lt: LEMMA (FORALL i: low <= i AND i <= high => x_lt(S(i),T(i))) AND
                      low <= high =>
                      x_lt(x_sigma(low,high,S),x_sigma(low,high,T))

    x_sum_le: LEMMA (FORALL i: x_le(S(i),T(i))) => x_le(x_sum(S),x_sum(T))
    x_sum_eq: LEMMA (FORALL i: x_eq(S(i),T(i))) => x_eq(x_sum(S),x_sum(T))
    x_sum_lt: LEMMA (FORALL i: x_lt(S(i),T(i))) => x_lt(x_sum(S),x_sum(T))

    x_inf_le: LEMMA (FORALL i: x_le(S(i),T(i))) => x_le(x_inf(S),x_inf(T))

    x_le_add: LEMMA x_le(x1,y1) AND x_le(x2,y2) =>
                    x_le(x_add(x1,x2),x_add(y1,y2))

    x_add_sum: LEMMA x_eq(x_add(x_sum(S),x_sum(T)),
                          x_sum(lambda i: x_add(S(i),T(i))))

    x_limit_to_sum: LEMMA (FORALL i: x_eq(S(i),x_sigma(0,i,T))) =>
                          x_eq(x_limit(S),x_sum(T))

    x_times_sum: LEMMA (FORALL i: x_eq(x_times(x,S(i)),T(i))) =>
                       x_eq(x_times(x,x_sum(S)),x_sum(T))

    epsilon_x_le: LEMMA
      x_le(x,y) <=> (FORALL epsilon: x_le(x,x_add(y,epsilon)))

    IMPORTING double_index[extended_nnreal],
              double_nn_sequence

    U: VAR [[nat,nat]->extended_nnreal]

    double_x_sum: LEMMA x_eq(x_sum(single_index(U)),
                             x_sum(lambda i: x_sum(lambda j: U(i,j))))

    double_x_sum_eq: LEMMA x_eq(x_sum(lambda i: x_sum(lambda j: U(i,j))),
                                x_sum(lambda j: x_sum(lambda i: U(i,j))))

  END extended_nnreal

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

  % Subtype TCC generated (at line 34, column 21) for
      % {z | EXISTS x: X(x) AND x`1 AND x`2 = z}
      % expected type  SB: (bounded_below?)
  x_inf_TCC1: OBLIGATION
    FORALL (X: set[extended_nnreal]):
      NOT (FORALL (x: (X)): NOT x`1) IMPLIES
       nonempty?[real]({z | EXISTS x: X(x) AND x`1 AND x`2 = z}) AND
        bounded_below?({z | EXISTS x: X(x) AND x`1 AND x`2 = z});

  % Subtype TCC generated (at line 34, column 17) for
      % glb({z | EXISTS x: X(x) AND x`1 AND x`2 = z})
      % expected type  nnreal
  x_inf_TCC2: OBLIGATION
    FORALL (X: set[extended_nnreal]):
      NOT (FORALL (x: (X)): NOT x`1) IMPLIES
       glb({z | EXISTS x: X(x) AND x`1 AND x`2 = z}) >= 0;

  % Subtype TCC generated (at line 40, column 31) for
      % {z | EXISTS x: X(x) AND x`1 AND x`2 = z}
      % expected type  (nonempty?[real])
  x_sup_TCC1: OBLIGATION
    FORALL (X: set[extended_nnreal]):
      NOT (EXISTS (x: (X)): NOT x`1) AND NOT empty?(X) IMPLIES
       nonempty?[real]({z | EXISTS x: X(x) AND x`1 AND x`2 = z});

  % Subtype TCC generated (at line 42, column 21) for
      % {z | EXISTS x: X(x) AND x`1 AND x`2 = z}
      % expected type  SA: (bounded_above?)
  x_sup_TCC2: OBLIGATION
    FORALL (X: set[extended_nnreal]):
      NOT (EXISTS (x: (X)): NOT x`1) AND
       bounded_above?({z | EXISTS x: X(x) AND x`1 AND x`2 = z}) AND
        NOT empty?(X)
       IMPLIES
       nonempty?[real]({z | EXISTS x: X(x) AND x`1 AND x`2 = z}) AND
        bounded_above?({z | EXISTS x: X(x) AND x`1 AND x`2 = z});

  % Subtype TCC generated (at line 42, column 17) for
      % lub({z | EXISTS x: X(x) AND x`1 AND x`2 = z})
      % expected type  nnreal
  x_sup_TCC3: OBLIGATION
    FORALL (X: set[extended_nnreal]):
      NOT (EXISTS (x: (X)): NOT x`1) AND
       bounded_above?({z | EXISTS x: X(x) AND x`1 AND x`2 = z}) AND
        NOT empty?(X)
       IMPLIES lub({z | EXISTS x: X(x) AND x`1 AND x`2 = z}) >= 0;

  % Subtype TCC generated (at line 49, column 27) for  high
      % expected type  T_high[nat]
  x_sigma_TCC1: OBLIGATION
    FORALL (low: nat, high: nat, S: [nat -> extended_nnreal]):
      (FORALL i: low <= i AND i <= high => S(i)`1) IMPLIES
       high >= 0 OR (EXISTS (j: nat): high <= j);

  % Subtype TCC generated (at line 54, column 17) for
      % limit(series(LAMBDA i: S(i)`2))
      % expected type  nnreal
  x_sum_TCC1: OBLIGATION
    FORALL (S: [nat -> extended_nnreal]):
      (FORALL i: S(i)`1) AND convergent?(series(LAMBDA i: S(i)`2)) IMPLIES
       limit(series(LAMBDA i: S(i)`2)) >= 0;

  % Subtype TCC generated (at line 59, column 17) for  limit(series(U))
      % expected type  nnreal
  x_sum_TCC2: OBLIGATION
    FORALL (U: [nat -> nnreal]):
      convergent?(series(U)) IMPLIES limit(series(U)) >= 0;

  % Subtype TCC generated (at line 69, column 17) for  limit(LAMBDA i: S(i)`2)
      % expected type  nnreal
  x_limit_TCC1: OBLIGATION
    FORALL (S: [nat -> extended_nnreal]):
      (FORALL i: S(i)`1) AND convergent?(LAMBDA i: S(i)`2) IMPLIES
       limit(LAMBDA i: S(i)`2) >= 0;


body:
  % Contributors:
  %  Paul Miner -- NASA Langley
  %  Jeff Maddalon -- NASA Langley
  %  Alfons Geser -- NIA ( now HTWK Leipzig)
  %  Lee Pike -- NASA Langley (now Galois, Inc.)

  top: THEORY

    BEGIN

    IMPORTING
      core_top,  % generalized consensus protocols
      virtual_clock_top % High-level clock synchronization resulst

    END top


body:
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % File Name    : event_sequences.pvs
  %
  % Purpose      : Defines properties of event sequences to support
  %                proofs in theory interval_clocks 
  %
  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


  event_sequences : THEORY

    BEGIN

    t: VAR real
    i, j, k: VAR nat
    f: VAR [nat -> real]

    increasing?(f): bool =
      FORALL (i:nat): f(i) < f(i + 1)
   
    unbounded?(f):bool =
      FORALL t: EXISTS k: t < f(k)

    event_sequence: TYPE =
      { f | increasing?(f) AND unbounded?(f)}

    es, es1, es2: VAR event_sequence

    increasing_ind: LEMMA %%% ONLY NEEDED FOR LEMMA nondecreasing
      es(i) < es(i + 1 + j)

    nondecreasing: LEMMA
      i <= j IMPLIES es(i) <= es(j)

    future_events(es)(t)(k): boolean = t < es(1 + k)

    future_events_nonempty: JUDGEMENT
      future_events(es)(t) HAS_TYPE (nonempty?[nat])

    index_of(es)(t): nat = min( future_events(es)(t) )
  % was:  index_of(es)(t): nat = min( {k | t < es(k + 1)} )

    index_le: LEMMA
      es(0) <= t
    IMPLIES
      es(index_of(es)(t)) <= t

    lt_index: LEMMA
      t < es(index_of(es)(t) + 1)

    index_le_alt: LEMMA
      index_of(es)(t) > 0
    IMPLIES
      es(index_of(es)(t)) <= t

    index_rewrite: LEMMA
      index_of(es)(es(i)) = i

    index_conversion_left: LEMMA
      t < es(k + 1)
    IMPLIES
      index_of(es)(t) <= k

    index_conversion_right: LEMMA
      es(k) <= t
    IMPLIES
      k <= index_of(es)(t)

    index_ordered: LEMMA
        (FORALL k: es1(k) <= es2(k))
      IMPLIES
        index_of(es2)(t) <= index_of(es1)(t)

    nonoverlap?(es1, es2): bool =
      FORALL k: es1(k) <= es2(k + 1)

    cross_nondecreasing: LEMMA  %%% NOT USED
      nonoverlap?(es1, es2) AND j < k => es1(j) <= es2(k)

    nonoverlap_index_bound: LEMMA 
        nonoverlap?(es1, es2)
      IMPLIES
        index_of(es2)(t) <= index_of(es1)(t) + 1

    END event_sequences

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

  % Judgement subtype TCC generated (at line 39, column 4) for
      % future_events(es)(t)
      % expected type  (nonempty?[nat])
  future_events_nonempty: OBLIGATION
    FORALL (es, t): nonempty?[nat](future_events(es)(t));


body:
  %
  %
  % Purpose: A proof that the least upper bound of an above bounded set 
  %          of integers is in the set. This includes the JUDGEMENT that 
  %          the least upper bound is an integer.
  %
  % Author: Alfons Geser National Institute of Aerospace, 2003
  %
  %

  bounded_ints: THEORY

  BEGIN

    IMPORTING reals@bounded_reals[int]

    SS: VAR sup_set

    sup_int_int: JUDGEMENT sup(SS) HAS_TYPE int

    sup_int_in_set: LEMMA
      in_set(sup(SS),SS)

    sup_int_is_in_set: JUDGEMENT sup(SS) HAS_TYPE (SS)

  END bounded_ints

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

  % Judgement subtype TCC generated (at line 19, column 25) for  sup(SS)
      % expected type  int
  sup_int_int: OBLIGATION
    FORALL (SS): rational_pred(sup[int](SS)) AND integer_pred(sup[int](SS));

  % Judgement subtype TCC generated (at line 24, column 31) for  sup(SS)
      % expected type  (SS)
  sup_int_is_in_set: OBLIGATION FORALL (SS): SS(sup[int](SS));


body:
  %
  %
  % Purpose: rewrite rules for inequalities involving floor and ceiling
  %
  %

  floor_ceiling_ineq: THEORY


  BEGIN

   a, b: VAR real
   i: VAR integer

   ge_floor_l: LEMMA floor(a) >= i IFF a >= i
   ge_floor_r: LEMMA i >= floor(a) IFF i+1 > a
   gt_floor_l: LEMMA floor(a) > i IFF a >= i+1
   gt_floor_r: LEMMA i > floor(a) IFF i > a
   le_floor_l: LEMMA floor(a) <= i IFF a < i+1
   le_floor_r: LEMMA i <= floor(a) IFF i <= a
   lt_floor_l: LEMMA floor(a) < i IFF a < i
   lt_floor_r: LEMMA i < floor(a) IFF i+1 <= a

   floor_monotone: LEMMA a <= b IMPLIES floor(a) <= floor(b)

   ge_ceiling_l: LEMMA ceiling(a) >= i IFF a > i-1
   ge_ceiling_r: LEMMA i >= ceiling(a) IFF i >= a
   gt_ceiling_l: LEMMA ceiling(a) > i IFF a > i
   gt_ceiling_r: LEMMA i > ceiling(a) IFF i-1 >= a
   le_ceiling_l: LEMMA ceiling(a) <= i IFF a <= i
   le_ceiling_r: LEMMA i <= ceiling(a) IFF i-1 < a
   lt_ceiling_l: LEMMA ceiling(a) < i IFF a <= i-1
   lt_ceiling_r: LEMMA i < ceiling(a) IFF i < a

   ceiling_monotone: LEMMA a <= b IMPLIES ceiling(a) <= ceiling(b)

  END floor_ceiling_ineq


body:
  %
  %
  % Purpose : Rewrite rules to resolve inequalities involving max or min
  %
  %

  minmax_ineq : THEORY

  BEGIN

  a, b, c, d: VAR real

  min_le : LEMMA min(a,b) <= c IFF (a <= c OR b <= c)
  min_lt : LEMMA min(a,b) < c IFF (a < c OR b < c)
  min_ge : LEMMA min(a,b) >= c IFF (a >= c AND b >= c)
  min_gt : LEMMA min(a,b) > c IFF (a > c AND b > c)
  le_min : LEMMA a <= min(b,c) IFF (a <= b AND a <= c)
  lt_min : LEMMA a < min(b,c) IFF (a < b AND a < c)
  ge_min : LEMMA a >= min(b,c) IFF (a >= b OR a >= c)
  gt_min : LEMMA a > min(b,c) IFF (a > b OR a > c)

  max_le : LEMMA max(a,b) <= c IFF (a <= c AND b <= c)
  max_lt : LEMMA max(a,b) < c IFF (a < c AND b < c)
  max_ge : LEMMA max(a,b) >= c IFF (a >= c OR b >= c)
  max_gt : LEMMA max(a,b) > c IFF (a > c OR b > c)
  le_max : LEMMA a <= max(b,c) IFF (a <= b OR a <= c)
  lt_max : LEMMA a < max(b,c) IFF (a < b OR a < c)
  ge_max : LEMMA a >= max(b,c) IFF (a >= b AND a >= c)
  gt_max : LEMMA a > max(b,c) IFF (a > b AND a > c)

  max_triangle: LEMMA max(a+c,b+d) <= max(a,b) + max(c,d)
  min_commutative: LEMMA min(a,b) = min(b,a)
  max_commutative: LEMMA max(a,b) = max(b,a)

  END minmax_ineq


body:
  %
  %
  % Purpose : extra properties of absolute value
  %
  %

  abs_props: THEORY

  BEGIN

    IMPORTING minmax_ineq

    x, y: VAR real
    nny: VAR nnreal

    abs_max: LEMMA
      abs(x) = max(-x,x)

    abs_add: LEMMA
      x*y >= 0 IMPLIES abs(x+y) = abs(x) + abs(y)

    abs_le_nonneg: LEMMA
      abs(x) <= nny IFF -nny <= x AND x <= nny

    abs_diff_commutes: LEMMA abs(x-y) = abs(y-x)  % from hacks

  END abs_props


body:
  %
  % Purpose      : This theory provides the basic definitions and
  %                properties concerning  the relative drift of good
  %                oscillators.  The drift bounds for a good oscillator
  %                are captured in the declared type `good_clock'.
  %                A good_clock is a function from Clocktime (integer) to
  %                realtime (real) with a bounded rate of drift.
  %
  % Assumptions  : Oscillators have a bounded rate of drift with respect
  %                to (Newtonian) real time.  This bound is captured by
  %                formal parameter rho.
  %

  physical_clocks
  [
     rho : nonneg_real 
  ] : THEORY

    BEGIN

    IMPORTING 
       abs_props, floor_ceiling_ineq

  % First define drift in terms of rho so that that we can use simpler
  % terms for bounding relative drift.

    rate: posreal = 1 + rho
    drift: nonneg_real = rate - 1 / rate 
    drift_def: LEMMA drift = (rate * rate - 1) / rate
    drift_bound: LEMMA drift <= 2 * rho

  % Various variable declarations

    X: VAR nat
    T, T1, T2: VAR int
    t: VAR real
    clock: VAR [int -> real]
    skew : VAR nnreal
    adj: VAR real

  % TYPE good_clock formalizes the notion of oscillator drift within
  % some bound, rho.  In essence, a good oscillator is characterized by
  % the behavior of an (imaginary) unbounded counter.

    good_clock: NONEMPTY_TYPE =
      { clock | 
           FORALL T: 
             1 / rate <= clock(T + 1) - clock(T) AND
                         clock(T + 1) - clock(T) <= rate
      } CONTAINING LAMBDA T: T

    c, c1, c2: VAR good_clock

    clock_edge?(c, t): bool = EXISTS T: t = c(T)

    drift_left_nat: LEMMA
      X / rate <= c(T + X) - c(T)

    drift_right_nat: LEMMA
      c(T + X) - c(T) <= X * rate

    drift_left: LEMMA
        T1 <= T2 IMPLIES
          (T2 - T1) / rate <= c(T2) - c(T1)

    drift_right: LEMMA
        T1 <= T2 IMPLIES
          c(T2) - c(T1) <= (T2 - T1) * rate

    abs_drift_lb: LEMMA
        abs(T1 - T2) / rate <= abs(c(T1) - c(T2)) 

    clock_nondecreasing: LEMMA
         T1 <= T2 IMPLIES c(T1) <= c(T2)

    clock_increasing: LEMMA
         T1 < T2 IMPLIES c(T1) < c(T2)

    clock_nondecreasing_alt: LEMMA
         c(T1) <= c(T2) IMPLIES T1 <= T2

    clock_eq_arg: LEMMA
         c(T1) = c(T2) IMPLIES T1 = T2

    offset_clocks?(c1, c2): bool =
      EXISTS T2: FORALL T1: c1(T1) = c2(T1 + T2)

    relative_drift: LEMMA
      c1(T1 + X) - c2(T2 + X) <= c1(T1) - c2(T2) + drift * X

    nonoverlap_basis: LEMMA
      c1(T) - c2(T) <= adj AND
      T2 - T1 > rate * adj AND
      T1 <= T AND 
      T <= T2
    IMPLIES
      c1(T1) < c2(T2)

    skew_basis_0: LEMMA
      c1(T) - c2(T) <= adj AND
      c2(T2) < c1(T1) AND
      T1 <= T AND 
      T <= T2
    IMPLIES
      T2 - T1 < rate * adj

    skew_bound_1: LEMMA
      c1(T) - c2(T) <= skew AND
      c2(T2) <= c1(T1)  AND
      T1 <= T + X AND 
      T - X <= T2
    IMPLIES
      T2 - T1 <= rate * (skew + drift * X)

    skew_bound_2: LEMMA
      c1(T) - c2(T) <= skew AND
      c2(T2) < c1(T1)  AND
      T1 <= T + X AND 
      T - X <= T2
    IMPLIES
      T2 - T1 < rate * (skew + drift * X)

  % basis of skew_conversion_sym in inverse_clocks:

    skew_bound: LEMMA
        abs(c1(T) - c2(T)) <= skew AND
        abs(T2 - T) <= X AND
        c1(T1) <= c2(T2) AND
        c2(T2) < c1(T1 + 1)
      IMPLIES
        abs(T1 - T2) <= ceiling(rate * (skew + drift * X))

  % offset properties for accuracy

    lower_offset: LEMMA
        T1 - X <= T2
      IMPLIES
        T2 - T1 <= rate * (c(T2) - c(T1) + drift * X)

    upper_offset: LEMMA
        T1 - X <= T2
      IMPLIES
        (c(T2) - c(T1) - drift * X) / rate <= T2 - T1 

    END physical_clocks

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

  % Subtype TCC generated (at line 28, column 23) for  rate - 1 / rate
      % expected type  nonneg_real
  drift_TCC1: OBLIGATION rate - 1 / rate >= 0;

  % Subtype TCC generated (at line 50, column 17) for  LAMBDA T: T
      % expected type  good_clock
  good_clock_TCC1: OBLIGATION
    FORALL (T_1: int): 1 / rate <= 1 + T_1 - T_1 AND 1 + T_1 - T_1 <= rate;


body:
  %
  % Purpose      : This theory provides the basic definitions and
  %                properties for the pseudo-inverse function to a clock.
  %                The pseudo-inverse is a function from realtime to Clocktime.
  %
  % Assumptions  : Oscillators have a bounded rate of drift with respect
  %                to (Newtonian) real time.  This bound is captured by
  %                formal parameter rho.
  %
  % Guarantees   : Skew conversion results to transform bounds on
  %                realtime separation of good_clocks at a given
  %                Clocktime to Clocktime separation at specific
  %                realtimes. 
  %
  inverse_clocks
  [
     rho : nonneg_real 
  ] : THEORY

    BEGIN

    IMPORTING 
       physical_clocks[rho], bounded_ints

  % Various variable declarations

    T, T1, T2: VAR int
    t, t1, t2: VAR real
    c, c1, c2: VAR good_clock
    skew: VAR nonneg_real

  % Every clock c has a corresponding Clock

    lower_Clocktime_exists: LEMMA EXISTS T: c(T) <= t

    upper_Clocktime_exists: LEMMA EXISTS T: t < c(T)

    past_ticks(c)(t)(T): boolean = c(T) <= t

    past_ticks_max_set: JUDGEMENT past_ticks(c)(t) HAS_TYPE max_set[int]

    C(c)(t): int = max(past_ticks(c)(t))

    Clock_rewrite: LEMMA C(c)(c(T)) = T

    Clock_lower: LEMMA c(C(c)(t)) <= t

    Clock_upper: LEMMA t < c(C(c)(t) + 1)

    Clock_nondecreasing: LEMMA 
      t1 <= t2 IMPLIES C(c)(t1) <= C(c)(t2)

    offset(c, T)(t): MACRO real = c(C(c)(t) + T)

    alt_clock_edge: LEMMA
      clock_edge?(c, t) IFF c(C(c)(t)) = t

    conversion_left: LEMMA  %%% UNUSED
      t <= c(T)
    IMPLIES
      C(c)(t) <= T

    conversion_left_alt: LEMMA
      C(c)(t) <= T IFF t < c(T + 1)

    conversion_right: LEMMA
      T <= C(c)(t) IFF c(T) <= t

    % conversion from real time precision to clock time precision

    X : VAR nat

    obs?(X, T, c, t): bool = c(T - X) <= t AND t < c(T + X)

    obs_bound: LEMMA obs?(X, T, c, t) IMPLIES abs(C(c)(t) - T) <= X

    precision_conversion_sym: LEMMA
        abs(c1(T) - c2(T)) <= skew AND
        obs?(X, T, c2, t) AND
        c1(C(c1)(t)) <= c2(C(c2)(t)) 
      IMPLIES 
        abs(C(c1)(t) - C(c2)(t)) <= ceiling(rate * (skew + drift * X))

    precision_conversion: THEOREM
        abs(c1(T) - c2(T)) <= skew AND
        obs?(X, T, c1, t) AND
        obs?(X, T, c2, t)
      IMPLIES 
        abs(C(c1)(t) - C(c2)(t)) <= ceiling(rate * (skew + drift * X))

    lower_accuracy_conversion: LEMMA
        c(T - X) <= t
      IMPLIES
        (t - c(T) - drift * X) / rate < 1 + C(c)(t) - T

    upper_accuracy_conversion: LEMMA
        c(T - X) <= t
      IMPLIES
        C(c)(t) - T <= (t - c(T) + drift * X) * rate

    END inverse_clocks

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

  % Judgement subtype TCC generated (at line 40, column 32) for
      % past_ticks(c)(t)
      % expected type  max_set[int]
  past_ticks_max_set: OBLIGATION
    FORALL (c, t):
      nonempty?[int](past_ticks(c)(t)) AND
       above_bounded[int](past_ticks(c)(t)) AND
        in_set[int](sup[int](past_ticks(c)(t)), past_ticks(c)(t));


body:
  %
  % Purpose      : Verify that any synchronization protocol with the
  %                properties that all good clocks starts each interval
  %                within a bounded skew of each other, and there is a
  %                bound on the magnitude of any adjustment in a round
  %                will satisfy the synchronization requirements of
  %                precision.   
  %

  interval_clocks
  [
      P: posnat,      % Nominal duration of a synchronization interval
      T0: int,        % Clocktime at start of protocol
      rho: nnreal     % Bound on drift for a good oscillator
  ] : THEORY

     BEGIN

    IMPORTING
       physical_clocks[rho]

    interval_clock: TYPE = [nat -> good_clock]

    i, j, k: VAR nat
    t: VAR real
    p, pl, pu, adj, alpha: VAR real
    pi: VAR nnreal
    T, T1, T2: VAR int
    X: VAR nat
    c: VAR good_clock
    ic, ic1, ic2: VAR interval_clock

    % Nominal start of round k

    T(k): int = P*k + T0

    T_def: LEMMA T(k + 1) = T(k) + P 

    T_rounds: LEMMA T(j + k) = T(k) + j * P

    t(ic)(j): real = ic(j)(T(j)) 

    % Definition of a collection of relations between
    % interval clocks sufficient for establishing precision
    % results. 

    peer_precision?(ic1, ic2, p): bool =
      FORALL j: t(ic2)(j) - t(ic1)(j) <= p

    adjustment_lower_bound?(ic1, ic2, p): bool =
      FORALL j: p <= t(ic2)(j + 1) - t(ic1)(j)

    adjustment_upper_bound?(ic1, ic2, p): bool =
      FORALL j: t(ic2)(j + 1) - t(ic1)(j) <= p

    compatible?(ic1, ic2, adj): bool =
      peer_precision?(ic1, ic2, adj) AND
      adjustment_lower_bound?(ic1, ic2, P / rate - adj) AND
      adjustment_upper_bound?(ic1, ic2, P * rate + adj)

    % Precision properties of update_lower? and update_upper?

    handover_precision_lower: LEMMA
        adjustment_lower_bound?(ic1, ic2, P / rate - adj) 
      IMPLIES
        ic1(j)(T(j + 1)) - ic2(j + 1)(T(j + 1)) <= drift * P + adj

    handover_precision_upper: LEMMA
        adjustment_upper_bound?(ic1, ic2, P * rate + adj) 
      IMPLIES
        ic2(j + 1)(T(j + 1)) - ic1(j)(T(j + 1)) <= drift * P + adj

    handover_precision: LEMMA
        adjustment_lower_bound?(ic1, ic2, P / rate - adj) AND
        adjustment_upper_bound?(ic1, ic2, P * rate + adj) 
      IMPLIES
        abs(ic1(j)(T(j + 1)) - ic2(j + 1)(T(j + 1))) <= drift * P + adj

    % Temporal separation properties guaranteed by these relations. 

    nonoverlap_peers: LEMMA
        peer_precision?(ic2, ic1, pi) AND
        T1 <= T(j) + P AND
        T(j) - P <= T1 + X AND
        X > (drift * P + pi) * rate
      IMPLIES
        ic1(j)(T1) <= ic2(j)(T1 + X)

    nonoverlap_lower: LEMMA
        adjustment_lower_bound?(ic1, ic2, P / rate - pi) AND
        T1 <= T(j + 1) AND
        T(j + 1) <= T1 + X AND
        X > (drift * P + pi) * rate
      IMPLIES
        ic1(j)(T1) <= ic2(j + 1)(T1 + X)

    nonoverlap_upper: LEMMA
        adjustment_upper_bound?(ic1, ic2, P * rate + pi) AND
        T1 <= T(j + 1) AND
        T(j + 1) <= T1 + X AND
        X > (drift * P + pi) * rate
      IMPLIES
        ic2(j + 1)(T1) <= ic1(j)(T1 + X)

    nonoverlap_round: LEMMA
        adjustment_lower_bound?(ic1, ic2, P / rate - pi) AND
        0 <= T AND
        T <= P AND
        P > (drift * P + pi) * rate
      IMPLIES
        ic1(j)(T(j) + T) < ic2(j + 1)(T(j + 1) + T)

    % accuracy properties of an interval clock

    weakly_accurate?(ic, pl, pu): bool = 
      adjustment_lower_bound?(ic, ic, pl) AND
      adjustment_upper_bound?(ic, ic, pu)

    lower_accuracy_bound?(ic, alpha, p): bool =
      EXISTS ic1:     
        adjustment_lower_bound?(ic1, ic1, P / rate - alpha) AND
        (FORALL i: t(ic1)(i) <= t(ic)(i)) AND
        t(ic)(0) - t(ic1)(0) <= p

    upper_accuracy_bound?(ic, alpha, p): bool =
      EXISTS ic1:     
        adjustment_upper_bound?(ic1, ic1, P * rate + alpha) AND
        (FORALL i: t(ic)(i) <= t(ic1)(i)) AND
        t(ic1)(0) - t(ic)(0) <= p

    lower_interval_accuracy: LEMMA
        lower_accuracy_bound?(ic, alpha, pi) AND
        p = P / rate - alpha
      IMPLIES
        j * p <= t(ic)(j) - t(ic)(0) + pi

    upper_interval_accuracy: LEMMA
        upper_accuracy_bound?(ic, alpha, pi) AND
        p = P * rate + alpha
      IMPLIES
        t(ic)(j) - t(ic)(0) - pi <= j * p

    END interval_clocks


body:
  virtual_clocks
  [
      P: posnat,      % Nominal duration of a synchronization interval
      T0: int,        % Clocktime at start of protocol
      rho: nnreal     % Bound on drift for a good oscillator
  ] : THEORY

    BEGIN

    IMPORTING
      interval_clocks[P, T0, rho],
      inverse_clocks[rho],
      event_sequences

    ic, ic1, ic2: VAR interval_clock
    es, es1, es2: VAR event_sequence
    k, A: VAR nat
    t1: VAR real
    p: VAR posreal
    adj, pi: VAR nnreal
    au, al: VAR nnreal

    %

    VC(es)(ic)(t1): int = C(ic(index_of(es)(t1)))(t1)

    VC_j: LEMMA VC(es)(ic)(es(k)) = C(ic(k))(es(k))

    % an event sequence, es, of adjustments to an interval clock, ic
    % has to satisfy these conditions:

    earliest_adjustment?(ic, A)(es): bool =
      FORALL k: ic(k)(T(k) - A) <= es(k)

    latest_adjustment?(ic, A)(es): bool =
      FORALL k: es(k + 1) <= ic(k)(T(k + 1) + A)

    earliest_cross_adjustment?(ic, A)(es): bool =
      FORALL k: ic(k)(T(k + 1) - A) <= es(k + 1)

    latest_cross_adjustment?(ic, A)(es): bool =
      FORALL k: es(k) <= ic(k)(T(k) + A)

    self_adjustment?(ic, A)(es): bool =
      earliest_adjustment?(ic, A)(es) AND
      latest_adjustment?(ic, A)(es)

    cross_adjustment?(ic, A)(es): bool =
      earliest_cross_adjustment?(ic, A)(es) AND
      latest_cross_adjustment?(ic, A)(es)

    % observability properties for virtual clock update windows

    observable_peers: LEMMA
        self_adjustment?(ic, A)(es) AND
        es(0) <= t1
      IMPLIES
        obs?(P + A, T(index_of(es)(t1)),  ic(index_of(es)(t1)), t1)

    observable_master: LEMMA
        self_adjustment?(ic1, A)(es1) AND
        cross_adjustment?(ic1, A)(es2) AND
        max(es1(0),es2(0)) <= t1 AND
        index_of(es2)(t1) = index_of(es1)(t1) + 1
      IMPLIES
        obs?(A, T(index_of(es1)(t1) + 1), ic1(index_of(es1)(t1)), t1)

    observable_slave: LEMMA
        self_adjustment?(ic2, A)(es2) AND
        cross_adjustment?(ic2, A)(es1) AND
        max(es1(0), es2(0)) <= t1 AND
        index_of(es2)(t1) = index_of(es1)(t1) + 1
      IMPLIES
        obs?(A, T(index_of(es1)(t1) + 1), ic2(index_of(es1)(t1) + 1), t1)

    % nonoverlap properties for virtual clocks

    adjustment_nonoverlap: LEMMA   %%% NOT USED, but curious
        latest_cross_adjustment?(ic, A)(es1) AND
        earliest_cross_adjustment?(ic, A)(es2) AND
        2 * A <= P
      IMPLIES
        nonoverlap?(es1, es2)

    % precision results for virtual clocks

    Pi(adj, A): int = ceiling(rate * (adj + drift * (P + A)))

    VC_precision_0: LEMMA
        peer_precision?(ic1, ic2, adj) AND
        peer_precision?(ic2, ic1, adj) AND
        self_adjustment?(ic1, A)(es1) AND
        self_adjustment?(ic2, A)(es2) AND
        max(es1(0), es2(0)) <= t1 AND
        index_of(es2)(t1) = index_of(es1)(t1)
      IMPLIES
        abs(VC(es1)(ic1)(t1) - VC(es2)(ic2)(t1)) <= Pi(adj, A)

    VC_precision_1: LEMMA
        compatible?(ic1, ic2, adj) AND
        self_adjustment?(ic1, A)(es1) AND
        self_adjustment?(ic2, A)(es2) AND
        cross_adjustment?(ic1, A)(es2) AND
        cross_adjustment?(ic2, A)(es1) AND
        max(es1(0), es2(0)) <= t1 AND
        index_of(es2)(t1) = index_of(es1)(t1) + 1
      IMPLIES
        abs(VC(es1)(ic1)(t1) - VC(es2)(ic2)(t1)) <= Pi(adj, A)

    VC_precision_sym: LEMMA
        compatible?(ic1, ic2, adj) AND
        compatible?(ic2, ic1, adj) AND
        nonoverlap?(es1, es2) AND
        self_adjustment?(ic1, A)(es1) AND
        self_adjustment?(ic2, A)(es2) AND
        cross_adjustment?(ic1, A)(es2) AND
        cross_adjustment?(ic2, A)(es1) AND
        max(es1(0), es2(0)) <= t1 AND
        index_of(es2)(t1) >= index_of(es1)(t1)
      IMPLIES
        abs(VC(es1)(ic1)(t1) - VC(es2)(ic2)(t1)) <= Pi(adj, A)

    VC_precision: THEOREM
        compatible?(ic1, ic2, adj) AND
        compatible?(ic2, ic1, adj) AND
        nonoverlap?(es1, es2) AND
        nonoverlap?(es2, es1) AND
        self_adjustment?(ic1, A)(es1) AND
        self_adjustment?(ic2, A)(es2) AND
        cross_adjustment?(ic1, A)(es2) AND
        cross_adjustment?(ic2, A)(es1) AND
        max(es1(0), es2(0)) <= t1
      IMPLIES
        abs(VC(es1)(ic1)(t1) - VC(es2)(ic2)(t1)) <= Pi(adj, A)


    % accuracy results for virtual clocks

    index_upper_bound: LEMMA
        lower_accuracy_bound?(ic, al, pi) AND
        earliest_adjustment?(ic, A)(es) AND
        p = P / rate - al AND
        es(0) <= t1
      IMPLIES
        index_of(es)(t1) <= (t1 - t(ic)(0) + A * rate + pi) / p

    VC_lower_accuracy: THEOREM
        upper_accuracy_bound?(ic, au, pi) AND
        lower_accuracy_bound?(ic, al, pi) AND
        earliest_adjustment?(ic, A)(es) AND
        p = P / rate - al AND
        es(0) <= t1
      IMPLIES
        ((t1 - t(ic)(0)) * (1 - au / p) 
         - pi * (1 + au / p)
         - A * (drift + rate * au / p)) / rate 
          < 1 + VC(es)(ic)(t1) - T(0)

    VC_upper_accuracy: THEOREM
        lower_accuracy_bound?(ic, al, pi) AND
        earliest_adjustment?(ic, A)(es) AND
        p = P / rate - al AND
        es(0) <= t1
      IMPLIES
        VC(es)(ic)(t1) - T(0) <=
          ((t1 - t(ic)(0)) * (1 + al / p) 
           + pi * (1 + al / p)
           + A * (drift + rate * al / p)) * rate

    END virtual_clocks


body:
  % to be added to Jerry James's function_image_aux theory in the prelude

  function_image_nonempty[D: TYPE, R: TYPE]: THEORY

  BEGIN

    f: VAR [D -> R]
    S: VAR set[D]

    nonempty_image: JUDGEMENT
      image(f, (S: (nonempty?[D]))) HAS_TYPE (nonempty?[R])

    nonempty_finite_image: JUDGEMENT
      image(f, (S: non_empty_finite_set[D])) HAS_TYPE non_empty_finite_set[R]

  %  image_witness: JUDGEMENT
  %    f(x: (S)) HAS_TYPE (image?(f, S))

  END function_image_nonempty

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

  % Judgement subtype TCC generated (at line 11, column 4) for  image(f, S)
      % expected type  (nonempty?[R])
  nonempty_image: OBLIGATION
    FORALL ((S: (nonempty?[D])), f): nonempty?[R](image[D, R](f, S));

  % Judgement subtype TCC generated (at line 14, column 4) for  image(f, S)
      % expected type  non_empty_finite_set[R]
  nonempty_finite_image: OBLIGATION
    FORALL ((S: non_empty_finite_set[D]), f):
      NOT empty?[R](image[D, R](f, S));


body:
  clock_minmax[rho : nonneg_real]: THEORY

    BEGIN

    IMPORTING 
      physical_clocks[rho],
      finite_sets@finite_sets_minmax_props[real, <=],
      function_image_nonempty[good_clock, real]

    c: VAR good_clock
    T: VAR int

    participant: VAR non_empty_finite_set[good_clock]

    t_at(T)(c): real = c(T)

    clock_min(participant)(T): real = min(image(t_at(T), participant))
    clock_max(participant)(T): real = max(image(t_at(T), participant))

    clock_min_witness: LEMMA 
      EXISTS c: participant(c) AND clock_min(participant)(T) = c(T)

    clock_max_witness: LEMMA 
      EXISTS c: participant(c) AND clock_max(participant)(T) = c(T)

    clock_min_is_min: LEMMA 
      participant(c) IMPLIES clock_min(participant)(T) <= c(T)

    clock_max_is_max: LEMMA 
      participant(c) IMPLIES c(T) <= clock_max(participant)(T)

    clock_min_clock: JUDGEMENT clock_min(participant) HAS_TYPE good_clock
    clock_max_clock: JUDGEMENT clock_max(participant) HAS_TYPE good_clock

    hst: VAR [nat -> non_empty_finite_set[good_clock]]
    j: VAR nat

    ic_min(hst)(j): good_clock = clock_min(hst(j))
    ic_max(hst)(j): good_clock = clock_max(hst(j))

    END clock_minmax

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

  % Judgement subtype TCC generated (at line 32, column 29) for
      % clock_min(participant)
      % expected type  good_clock[rho]
  clock_min_clock: OBLIGATION
    FORALL (participant, T):
      1 / rate[rho] <=
       clock_min(participant)(1 + T) - clock_min(participant)(T)
       AND
       clock_min(participant)(1 + T) - clock_min(participant)(T) <= rate[rho];

  % Judgement subtype TCC generated (at line 33, column 29) for
      % clock_max(participant)
      % expected type  good_clock[rho]
  clock_max_clock: OBLIGATION
    FORALL (participant, T):
      1 / rate[rho] <=
       clock_max(participant)(1 + T) - clock_max(participant)(T)
       AND
       clock_max(participant)(1 + T) - clock_max(participant)(T) <= rate[rho];


body:
  %
  % Purpose      : Definition of the constraint that is required for the
  %                theory parameters of synchronization.
  %
  synch_parameter_constraints: THEORY

    BEGIN

    P: VAR posnat
    rho, alpha_l, alpha_u, pi: VAR nonneg_real

    P_bound?(P, rho, alpha_l, alpha_u, pi): bool =
      (1 + rho) * (pi + max(alpha_l, alpha_u) + P * ((1 + rho) - 1 / (1 + rho)))  < P

    END synch_parameter_constraints


body:
  %
  % Purpose      : Definitions of various period related constants,
  %                based on paramters derived from the synchronization
  %                protocol.
  % 
  %                P 	 - nominal duration (in ticks) between
  %                     	   resynchronization events.
  %                rho	 - bound on drift for a good oscillator
  %                alpha_l - lower bound on loss of accuracy due to
  %                          computing and applying adjustment (may be 0).
  %                alpha_u - upper bound on loss of accuracy due to
  %                          computing and applying adjustment (may be 0).
  %                pi_0	 - intantaneous precision bound immediately
  %                          after applying computed adjustment (> 1)
  %
  synch_constant_definitions
  [(IMPORTING synch_parameter_constraints)
    P: posnat,
    T0: int,
    rho: nnreal,
    alpha_l, alpha_u: nnreal,
    pi_0: {pi : posreal | P_bound?(P, rho, alpha_l, alpha_u, pi)}
  ]: THEORY

    BEGIN

    IMPORTING
      physical_clocks[rho] % for definition of rate, drift

    j, k: VAR nat

    P_bound: LEMMA
      rate * (pi_0 + max(alpha_l, alpha_u) + drift * P)  < P

    rho_bound: LEMMA rho * (2 + rho) < 1  %%% NOT USED

    ADJ: nat = floor(rate * (pi_0 + max(alpha_l, alpha_u) + drift * P))

    ADJ_ineq: LEMMA
      ADJ >= floor((drift * P + pi_0) * rate)

    ADJ_ineq_l: LEMMA
      ADJ >= floor((drift * P + alpha_l + pi_0) * rate)

    ADJ_ineq_h: LEMMA
      ADJ >= floor((drift * P + alpha_u + pi_0) * rate)

    ADJ_bound: LEMMA ADJ < P

    P_min: posnat = P - ADJ %%% NOT USED
    P_max: posnat = P + ADJ

    p_min_bound: LEMMA rate * (pi_0 + max(alpha_l, alpha_u)) < P

    p_lower: posreal = P / rate - alpha_l
    p_upper: posreal = P * rate + alpha_u

    p_min: posreal = P / rate - alpha_l - pi_0
    p_max: posreal = P * rate + alpha_u + pi_0

    p_min_lower: LEMMA p_min = p_lower - pi_0
    p_max_upper: LEMMA p_max = p_upper + pi_0

    drift_P_bound: LEMMA drift * P < p_min

    Pi: posnat = ceiling(rate * (max(alpha_l, alpha_u) + pi_0 + drift * (P_max + 1)))

    END synch_constant_definitions

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

  % Subtype TCC generated (at line 50, column 18) for  P - ADJ
      % expected type  posnat
  P_min_TCC1: OBLIGATION P - ADJ >= 0 AND P - ADJ > 0;

  % Subtype TCC generated (at line 55, column 21) for  P / rate - alpha_l
      % expected type  posreal
  p_lower_TCC1: OBLIGATION
    P / rate[rho] - alpha_l >= 0 AND P / rate[rho] - alpha_l > 0;

  % Subtype TCC generated (at line 58, column 19) for
      % P / rate - alpha_l - pi_0
      % expected type  posreal
  p_min_TCC1: OBLIGATION
    P / rate[rho] - alpha_l - pi_0 >= 0 AND
     P / rate[rho] - alpha_l - pi_0 > 0;

  % Subtype TCC generated (at line 66, column 15) for
      % ceiling(rate * (max(alpha_l, alpha_u) + pi_0 + drift * (P_max + 1)))
      % expected type  posnat
  Pi_TCC1: OBLIGATION
    ceiling(rate[rho] *
             (max(alpha_l, alpha_u) + pi_0 + drift[rho] * (P_max + 1)))
     > 0;


body:
  synch_protocol_invariants
  [(IMPORTING synch_constant_definitions)
      P: posnat,     % Nominal duration of a synchronization interval
      T0: int,       % Clocktime at start of protocol
      rho: nnreal,   % Bound on drift for a good oscillator
      alpha_l, alpha_u: nnreal,  % negative and positive read error bounds
      pi_0: {pi_0: posreal | P_bound?(P, rho, alpha_l, alpha_u, pi_0)}
  ] : THEORY

    BEGIN

    IMPORTING 
      synch_constant_definitions[P, T0, rho, alpha_l, alpha_u, pi_0],
      clock_minmax[rho],
      interval_clocks[P, T0, rho]


  % Invariants for a sequence of sets of good clocks.  If the protocol
  % guarantees a sequence of non-empty sets that satisfy these
  % properties, then it also ensures the top level properties of
  % precision and accuracy.

    j, j1, j2: VAR nat
    hst, hst1, hst2: VAR [nat -> non_empty_finite_set[good_clock]]
    ic, ic1, ic2: VAR interval_clock
    T, T1, T2: VAR int
    pl, pu: VAR real
    pi, al, au: VAR nnreal

    periodic_precision?(hst, j, pi): bool =
  %    ic_max(hst)(j)(T(j)) - ic_min(hst)(j)(T(j)) <= pi
      t(ic_max(hst))(j) - t(ic_min(hst))(j) <= pi

    initial_precision?(hst, pi): bool = periodic_precision?(hst, 0, pi)

    periodic_precision_enhancement?(hst, pi): bool =
      FORALL j:
        periodic_precision?(hst, j, pi)
      IMPLIES
        periodic_precision?(hst, j + 1, pi)

    lower_accuracy_preservation?(hst, pl): bool =
      adjustment_lower_bound?(ic_min(hst), ic_min(hst), pl)

    upper_accuracy_preservation?(hst, pu): bool =
      adjustment_upper_bound?(ic_max(hst), ic_max(hst), pu)

    synch_protocol_invariants?(hst, pi, pl, pu): bool =
      periodic_precision_enhancement?(hst, pi) AND
      lower_accuracy_preservation?(hst, pl) AND
      upper_accuracy_preservation?(hst, pu)

  % Intermediate consequences of the protocol invariants related to compatible?.

    all_periodic_precision?(hst, pi): bool =
      FORALL j: periodic_precision?(hst, j, pi)

    all_periodic_precision_iff_peer_precision: LEMMA
      all_periodic_precision?(hst, pi) IFF
      peer_precision?(ic_min(hst), ic_max(hst), pi)

    all_periodic_precision: LEMMA
        initial_precision?(hst, pi) AND
        periodic_precision_enhancement?(hst, pi)
      IMPLIES
        all_periodic_precision?(hst, pi)

    minmax_adjustment_lower_bound: LEMMA
        all_periodic_precision?(hst, pi) AND
        lower_accuracy_preservation?(hst, pl)
      IMPLIES
        adjustment_lower_bound?(ic_max(hst), ic_min(hst), pl - pi)

    minmax_adjustment_upper_bound: LEMMA
        all_periodic_precision?(hst, pi) AND
        upper_accuracy_preservation?(hst, pu)
      IMPLIES
        adjustment_upper_bound?(ic_min(hst), ic_max(hst), pu + pi)

  % Relating traces from a history satisfying the invariants to the
  % compatibility relations used to establish precision and weak
  % accuracy


    trace?(ic, hst): bool = FORALL j: hst(j)(ic(j))

    min_le_trace: LEMMA
      trace?(ic, hst) IMPLIES
  %    ic_min(hst)(j)(T) <= ic(j)(T) 
      t(ic_min(hst))(j) <= t(ic)(j) 

    trace_le_max: LEMMA
      trace?(ic, hst) IMPLIES
  %    ic(j)(T) <= ic_max(hst)(j)(T)
      t(ic)(j) <= t(ic_max(hst))(j)

    trace_diff: LEMMA
        trace?(ic1, hst1) AND
        trace?(ic2, hst2)
      IMPLIES
  %      ic1(j1)(T1) - ic2(j2)(T2) <= ic_max(hst1)(j1)(T1) - ic_min(hst2)(j2)(T2)
        t(ic1)(j1) - t(ic2)(j2) <= t(ic_max(hst1))(j1) - t(ic_min(hst2))(j2)

    traces_peer_precision: LEMMA
        trace?(ic1, hst) AND
        trace?(ic2, hst) AND
        initial_precision?(hst, pi) AND
        periodic_precision_enhancement?(hst, pi)
      IMPLIES
        peer_precision?(ic1, ic2, pi)

    traces_lower: LEMMA
        trace?(ic1, hst) AND
        trace?(ic2, hst) AND
        initial_precision?(hst, pi) AND
        periodic_precision_enhancement?(hst, pi) AND
        lower_accuracy_preservation?(hst, pl)
      IMPLIES
        adjustment_lower_bound?(ic1, ic2, pl - pi)

    traces_upper: LEMMA
        trace?(ic1, hst) AND
        trace?(ic2, hst) AND
        initial_precision?(hst, pi) AND
        periodic_precision_enhancement?(hst, pi) AND
        upper_accuracy_preservation?(hst, pu)
      IMPLIES
        adjustment_upper_bound?(ic1, ic2, pu + pi)

    % mappings from traces

    traces_compatible: LEMMA
        trace?(ic1, hst) AND
        trace?(ic2, hst) AND
        initial_precision?(hst, pi) AND
        synch_protocol_invariants?(hst, pi, P / rate - al, P * rate + au)
      IMPLIES
        compatible?(ic1, ic2, pi + max(al, au))

    trace_lower_accuracy: LEMMA
        trace?(ic, hst) AND
        initial_precision?(hst, pi) AND
        synch_protocol_invariants?(hst, pi, P / rate - al, pu)
      IMPLIES
        lower_accuracy_bound?(ic, al, pi)

    trace_upper_accuracy: LEMMA
        trace?(ic, hst) AND
        initial_precision?(hst, pi) AND
        synch_protocol_invariants?(hst, pi, pl, P * rate + au)
      IMPLIES
        upper_accuracy_bound?(ic, au, pi)

    weakly_accurate_clock: TYPE = {ic | weakly_accurate?(ic, p_min, p_max)}

    trace_weakly_accurate: LEMMA
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper)
      IMPLIES
        weakly_accurate?(ic, p_min, p_max)
        
  END synch_protocol_invariants


body:
  %
  % Purpose      : There are two common scenarios for synchronization
  %                protocols to apply instantaneous adjustments.  The
  %                first is to compute a correction term for the current
  %                interval, and apply the correction when the Clocktime
  %                reaches a specific value.  The second is to set the
  %                local counter to a specific value in response to some
  %                event.  This file presents a virtual clock based upon
  %                the second scenario and shows that is satisfies the
  %                precision  and accuracy requirement of clock
  %                synchronization. 
  %
  virtual_clock_2
  [(IMPORTING synch_protocol_invariants)
      P: posnat,     % Nominal duration of a synchronization interval
      T0: int,       % Clocktime at start of protocol
      rho: nnreal,   % Bound on drift for a good oscillator
      alpha_l, alpha_u: nnreal,  % negative and positive read error bounds
      pi_0: {pi_0: posreal | P_bound?(P, rho, alpha_l, alpha_u, pi_0)}
  ] : THEORY

    BEGIN

    IMPORTING 
      synch_protocol_invariants[P, T0, rho, alpha_l, alpha_u, pi_0],
      virtual_clocks[P, T0, rho]

    hst: VAR [nat -> non_empty_finite_set[good_clock]]
    ic, ic1, ic2: VAR interval_clock
    ac, ac1, ac2: VAR weakly_accurate_clock
    t1: VAR real
    j: VAR nat
    
    % required properties of t(ac) event_sequence

    t_increasing: LEMMA increasing?(t(ac))
    t_unbounded: LEMMA unbounded?(t(ac))
    t_event_sequence: JUDGEMENT t(ac) HAS_TYPE event_sequence

    t_nonoverlap: LEMMA
        compatible?(ac1, ac2, pi_0 + max(alpha_l, alpha_u))
      IMPLIES
        nonoverlap?(t(ac1), t(ac2))

    t_early: LEMMA earliest_adjustment?(ac, 0)(t(ac))
    t_self: LEMMA self_adjustment?(ac, ADJ + 1)(t(ac))
    t_cross: LEMMA
        compatible?(ac1, ac2, pi_0 + max(alpha_l, alpha_u))
      IMPLIES
        cross_adjustment?(ac1, ADJ + 1)(t(ac2))
    
    % main results

    VC2(ac)(t1): int = VC(t(ac))(ac)(t1)

    VC_j: LEMMA VC2(ac)(t(ac)(j)) = T(j)

    VC2_precision: THEOREM
        trace?(ic1, hst) AND
        trace?(ic2, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        max(t(ic1)(0),t(ic2)(0)) <= t1
      IMPLIES
        abs(VC2(ic1)(t1) - VC2(ic2)(t1)) <= Pi

    VC2_accuracy_lower: THEOREM
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        t(ic)(0) <= t1
      IMPLIES 
        ((t1 - t(ic)(0)) * (1 - alpha_u / p_lower) 
          - pi_0 * (1 + alpha_u / p_lower)) / rate 
            < 1 + VC2(ic)(t1) - T(0)

    VC2_optimal_accuracy_lower: COROLLARY
        alpha_u = 0 AND
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        t(ic)(0) <= t1
      IMPLIES 
        ((t1 - t(ic)(0)) - pi_0) / rate 
            < 1 + VC2(ic)(t1) - T(0)

    VC2_accuracy_upper: THEOREM
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        t(ic)(0) <= t1
      IMPLIES 
        VC2(ic)(t1) - T(0) 
           <= ((t1 - t(ic)(0)) * (1 + alpha_l / p_lower)
                + pi_0 * (1 + alpha_l / p_lower)) * rate

    VC2_optimal_accuracy_upper: COROLLARY
        alpha_l = 0 AND
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        t(ic)(0) <= t1
      IMPLIES 
        VC2(ic)(t1) - T(0) 
           <= ((t1 - t(ic)(0)) + pi_0) * rate

   END virtual_clock_2

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

  % Judgement subtype TCC generated (at line 38, column 30) for  t(ac)
      % expected type  event_sequence
  t_event_sequence: OBLIGATION
    FORALL (ac):
      increasing?(t[P, T0, rho](ac)) AND unbounded?(t[P, T0, rho](ac));

  % Subtype TCC generated (at line 65, column 14) for  ic1
      % expected type  weakly_accurate_clock
                     %     [P, T0, rho, alpha_l, alpha_u, pi_0]
  VC2_precision_TCC1: OBLIGATION
    FORALL (hst: [nat -> non_empty_finite_set[good_clock[rho]]],
            ic1, ic2: interval_clock[P, T0, rho], t1: real):
           max(t(ic1)(0), t(ic2)(0)) <= t1
       AND synch_protocol_invariants?(hst, pi_0, p_lower, p_upper)
       AND initial_precision?(hst, pi_0) AND trace?(ic2, hst)
       AND trace?(ic1, hst)
       IMPLIES
       weakly_accurate?[P, T0, rho]
           (ic1, p_min[P, T0, rho, alpha_l, alpha_u, pi_0],
            p_max[P, T0, rho, alpha_l, alpha_u, pi_0]);

  % Subtype TCC generated (at line 65, column 29) for  ic2
      % expected type  weakly_accurate_clock
                     %     [P, T0, rho, alpha_l, alpha_u, pi_0]
  VC2_precision_TCC2: OBLIGATION
    FORALL (hst: [nat -> non_empty_finite_set[good_clock[rho]]],
            ic1, ic2: interval_clock[P, T0, rho], t1: real):
           max(t(ic1)(0), t(ic2)(0)) <= t1
       AND synch_protocol_invariants?(hst, pi_0, p_lower, p_upper)
       AND initial_precision?(hst, pi_0) AND trace?(ic2, hst)
       AND trace?(ic1, hst)
       IMPLIES
       weakly_accurate?[P, T0, rho]
           (ic2, p_min[P, T0, rho, alpha_l, alpha_u, pi_0],
            p_max[P, T0, rho, alpha_l, alpha_u, pi_0]);

  % Subtype TCC generated (at line 75, column 20) for  ic
      % expected type  weakly_accurate_clock
                     %     [P, T0, rho, alpha_l, alpha_u, pi_0]
  VC2_accuracy_lower_TCC1: OBLIGATION
    FORALL (hst: [nat -> non_empty_finite_set[good_clock[rho]]],
            ic: interval_clock[P, T0, rho], t1: real):
      t(ic)(0) <= t1 AND
       synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        initial_precision?(hst, pi_0) AND trace?(ic, hst)
       IMPLIES
       weakly_accurate?[P, T0, rho]
           (ic, p_min[P, T0, rho, alpha_l, alpha_u, pi_0],
            p_max[P, T0, rho, alpha_l, alpha_u, pi_0]);


body:
  %
  % Purpose      : There are two common scenarios for synchronization
  %                protocols to apply instantaneous adjustments.  The
  %                first is to compute a correction term for the current
  %                interval,and apply the correction when the Clocktime
  %                reaches a specific value.  The second is to set the
  %                local counter to a specific value in response to some event.
  %                This file presents a virtual clock based upon the first
  %                scenario and shows that is satisfies the Precision
  %                requirement of clock synchronization 
  %

  virtual_clock_1
  [(IMPORTING synch_protocol_invariants)
      P: posnat,     % Nominal duration of a synchronization interval
      T0: int,       % Clocktime at start of protocol
      rho: nnreal,   % Bound on drift for a good oscillator
      alpha_l, alpha_u: nnreal,  % negative and positive read error bounds
      pi_0: {pi_0: posreal | P_bound?(P, rho, alpha_l, alpha_u, pi_0)}
  ] : THEORY

    BEGIN

    IMPORTING 
      synch_protocol_invariants[P, T0, rho, alpha_l, alpha_u, pi_0],
      virtual_clocks[P, T0, rho]


    hst: VAR [nat -> non_empty_finite_set[good_clock]]
    ic, ic1, ic2: VAR interval_clock
    t1: VAR real

    ac, ac1, ac2: VAR weakly_accurate_clock
    k : VAR nat
    j: VAR posint

    % Definition and required properties of turns(ac) event_sequence

    turns(ac)(k): real = IF k = 0 THEN ac(0)(T(0)) ELSE ac(k-1)(T(k)) ENDIF

    turns_increasing: LEMMA increasing?(turns(ac))
    turns_unbounded: LEMMA unbounded?(turns(ac))
    turns_event_sequence: JUDGEMENT turns(ac) HAS_TYPE event_sequence

    turns_nonoverlap: LEMMA
        compatible?(ac1, ac2, pi_0 + max(alpha_l, alpha_u)) AND
        compatible?(ac2, ac1, pi_0 + max(alpha_l, alpha_u))
      IMPLIES
        nonoverlap?(turns(ac1), turns(ac2))
    
    turns_early: LEMMA earliest_adjustment?(ac, ADJ + 1)(turns(ac))
    turns_self: LEMMA self_adjustment?(ac, ADJ + 1)(turns(ac))
    turns_cross: LEMMA
         compatible?(ac1, ac2, pi_0 + max(alpha_l, alpha_u)) AND
         compatible?(ac2, ac1, pi_0 + max(alpha_l, alpha_u))
      IMPLIES
        cross_adjustment?(ac1, ADJ + 1)(turns(ac2))

    % main results

    VC1(ac)(t1): int = VC(turns(ac))(ac)(t1)

    VC1_j: LEMMA VC1(ac)(turns(ac)(j)) = C(ac(j))(ac(j - 1)(T(j)))

    VC1_precision: THEOREM
        trace?(ic1, hst) AND
        trace?(ic2, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        max(t(ic1)(0),t(ic2)(0)) <= t1
      IMPLIES
        abs(VC1(ic1)(t1) - VC1(ic2)(t1)) <= Pi

    VC1_accuracy_lower: THEOREM
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        t(ic)(0) <= t1
      IMPLIES 
        ((t1 - t(ic)(0)) *  (1 - (alpha_u / p_lower)) 
          - pi_0 * (1 + alpha_u / p_lower)
          - (drift + rate * (alpha_u / p_lower)) * (1 + ADJ)) / rate
            < 1 + VC1(ic)(t1) - T(0)

    VC1_optimal_accuracy_lower: COROLLARY
        alpha_u = 0 AND
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        t(ic)(0) <= t1
      IMPLIES 
        ((t1 - t(ic)(0)) - pi_0) / rate 
            - drift * (1 + ADJ) / rate
                  < 1 + VC1(ic)(t1) - T(0)

    VC1_accuracy_upper: THEOREM
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        t(ic)(0) <= t1
      IMPLIES 
        VC1(ic)(t1) - T(0) 
           <= ((t1 - t(ic)(0)) * (1 + alpha_l / p_lower) 
               + pi_0 * (1 + alpha_l / p_lower)) * rate
               + (1 + ADJ) * (drift + rate * alpha_l / p_lower) * rate

    VC1_optimal_accuracy_upper: COROLLARY
        alpha_l = 0 AND
        trace?(ic, hst) AND
        initial_precision?(hst, pi_0) AND
        synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        t(ic)(0) <= t1
      IMPLIES 
        VC1(ic)(t1) - T(0) 
           <= ((t1 - t(ic)(0)) + pi_0) * rate
                + (1 + ADJ) * drift * rate

    END virtual_clock_1

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

  % Subtype TCC generated (at line 39, column 57) for  k - 1
      % expected type  nat
  turns_TCC1: OBLIGATION
    FORALL (ac: weakly_accurate_clock[P, T0, rho, alpha_l, alpha_u, pi_0],
            k: nat):
      NOT k = 0 IMPLIES k - 1 >= 0;

  % Judgement subtype TCC generated (at line 43, column 34) for  turns(ac)
      % expected type  event_sequence
  turns_event_sequence: OBLIGATION
    FORALL (ac): increasing?(turns(ac)) AND unbounded?(turns(ac));

  % Subtype TCC generated (at line 63, column 51) for  j - 1
      % expected type  nat
  VC1_j_TCC1: OBLIGATION FORALL (j: posint): j - 1 >= 0;

  % Subtype TCC generated (at line 72, column 14) for  ic1
      % expected type  weakly_accurate_clock
                     %     [P, T0, rho, alpha_l, alpha_u, pi_0]
  VC1_precision_TCC1: OBLIGATION
    FORALL (hst: [nat -> non_empty_finite_set[good_clock[rho]]],
            ic1, ic2: interval_clock[P, T0, rho], t1: real):
           max(t(ic1)(0), t(ic2)(0)) <= t1
       AND synch_protocol_invariants?(hst, pi_0, p_lower, p_upper)
       AND initial_precision?(hst, pi_0) AND trace?(ic2, hst)
       AND trace?(ic1, hst)
       IMPLIES
       weakly_accurate?[P, T0, rho]
           (ic1, p_min[P, T0, rho, alpha_l, alpha_u, pi_0],
            p_max[P, T0, rho, alpha_l, alpha_u, pi_0]);

  % Subtype TCC generated (at line 72, column 29) for  ic2
      % expected type  weakly_accurate_clock
                     %     [P, T0, rho, alpha_l, alpha_u, pi_0]
  VC1_precision_TCC2: OBLIGATION
    FORALL (hst: [nat -> non_empty_finite_set[good_clock[rho]]],
            ic1, ic2: interval_clock[P, T0, rho], t1: real):
           max(t(ic1)(0), t(ic2)(0)) <= t1
       AND synch_protocol_invariants?(hst, pi_0, p_lower, p_upper)
       AND initial_precision?(hst, pi_0) AND trace?(ic2, hst)
       AND trace?(ic1, hst)
       IMPLIES
       weakly_accurate?[P, T0, rho]
           (ic2, p_min[P, T0, rho, alpha_l, alpha_u, pi_0],
            p_max[P, T0, rho, alpha_l, alpha_u, pi_0]);

  % Subtype TCC generated (at line 83, column 20) for  ic
      % expected type  weakly_accurate_clock
                     %     [P, T0, rho, alpha_l, alpha_u, pi_0]
  VC1_accuracy_lower_TCC1: OBLIGATION
    FORALL (hst: [nat -> non_empty_finite_set[good_clock[rho]]],
            ic: interval_clock[P, T0, rho], t1: real):
      t(ic)(0) <= t1 AND
       synch_protocol_invariants?(hst, pi_0, p_lower, p_upper) AND
        initial_precision?(hst, pi_0) AND trace?(ic, hst)
       IMPLIES
       weakly_accurate?[P, T0, rho]
           (ic, p_min[P, T0, rho, alpha_l, alpha_u, pi_0],
            p_max[P, T0, rho, alpha_l, alpha_u, pi_0]);


body:
  %
  % General theories for a class of clock synchronization algorithms.
  % The heritage of these theories traces back to Schneider's general
  % proof.  The central idea is that any periodic protocol that
  % satisfies precision enhancement and accuracy preservation will
  % preserve precision and accuracy.  These theories resolve all of the
  % limitations of Miner's earlier formalization in Ehdm.

  % These theories were developed by Alfons Geser and Paul Miner
  %

  virtual_clock_top: THEORY

  BEGIN

    IMPORTING
      virtual_clock_1, 
      virtual_clock_2

  END virtual_clock_top


body:
  %
  %
  % Purpose: rewrite rules for the properties that 
  %          binary relations may have
  %
  % Author: Alfons Geser (geser@nianet.org), NIA
  %
  %

  relations_extra[T: TYPE]: THEORY

  BEGIN

    IMPORTING relations[T], orders[T]

    x, y, z: VAR T
    R: VAR pred[[T, T]]
    p: VAR pred[T]

    asymmetric?(R): bool = FORALL x, y: NOT R(x, y) OR NOT R(y, x)

    strict_order_is_asymmetric: JUDGEMENT
      (strict_order?) SUBTYPE_OF (asymmetric?)

    asymmetric_is_antisymmetric: JUDGEMENT
      (asymmetric?) SUBTYPE_OF (antisymmetric?)

    asymmetric_is_irreflexive: JUDGEMENT
      (asymmetric?) SUBTYPE_OF (irreflexive?)

    reflexive: LEMMA FORALL (R: (reflexive?)): FORALL x: R(x, x)
    irreflexive: LEMMA FORALL (R: (irreflexive?)): FORALL x: NOT R(x, x)
    symmetric: LEMMA FORALL (R: (symmetric?)): FORALL x, y: R(x, y) => R(y, x)
    antisymmetric: LEMMA
      FORALL (R: (antisymmetric?)): FORALL x, y: R(x, y) & R(y, x) => x = y
    asymmetric: LEMMA
      FORALL (R: (asymmetric?)): FORALL x, y: NOT R(x, y) OR NOT R(y, x)
  % connected? is the same as trichotomous?
  %  connected: LEMMA FORALL (R: (connected?)): x = y OR R(x, y) OR R(y, x)
    transitive: LEMMA
      FORALL (R: (transitive?)): FORALL x, y, z: R(x, y) & R(y, z) => R(x, z)

    dichotomous: LEMMA
      FORALL (R: (dichotomous?)): FORALL x, y: R(x, y) OR R(y, x)
    trichotomous: LEMMA
      FORALL (R: (trichotomous?)): FORALL x, y: R(x, y) OR R(y, x) OR x = y

    dichotomous_is_trichotomous: JUDGEMENT
      (dichotomous?) SUBTYPE_OF (trichotomous?)

    well_founded: LEMMA FORALL (R: (well_founded?)):
      FORALL p:
        (EXISTS y: p(y))
          IMPLIES EXISTS (y: (p)): FORALL (x: (p)): NOT R(x, y)

    reflexive_closure(R): (reflexive?) = union(R, =)
    irreflexive_kernel(R): (irreflexive?) = difference(R, =)
    symmetric_closure(R): (symmetric?) = union(R, converse(R))
    symmetric_kernel(R): (symmetric?) = intersection(R, converse(R))

    reflexive_closure_preserves_transitive: JUDGEMENT
      reflexive_closure(R: (transitive?)) HAS_TYPE (preorder?)

    strict_order_to_partial_order: JUDGEMENT
      reflexive_closure(R: (strict_order?)) HAS_TYPE (partial_order?)

    reflexive_closure_dichotomous: JUDGEMENT
      reflexive_closure(R: (trichotomous?)) HAS_TYPE (dichotomous?)

    strict_total_order_to_total_order: JUDGEMENT
      reflexive_closure(R: (strict_total_order?)) HAS_TYPE (total_order?)

    partial_order_to_strict_order: JUDGEMENT
      irreflexive_kernel(R: (partial_order?)) HAS_TYPE (strict_order?)

    irreflexive_kernel_trichotomous: JUDGEMENT
      irreflexive_kernel(R: (dichotomous?)) HAS_TYPE (trichotomous?)

    total_order_to_strict_total_order: JUDGEMENT
      irreflexive_kernel(R: (total_order?)) HAS_TYPE (strict_total_order?)

    symmetric_kernel_of_preorder: JUDGEMENT
      symmetric_kernel(R: (preorder?)) HAS_TYPE (equivalence?)

  END relations_extra

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

  % Judgement subtype TCC generated (at line 23, column 4) for  x
      % expected type  (asymmetric?)
  strict_order_is_asymmetric: OBLIGATION
    FORALL (x: (strict_order?)): asymmetric?(x);

  % Judgement subtype TCC generated (at line 26, column 4) for  x
      % expected type  (antisymmetric?)
  asymmetric_is_antisymmetric: OBLIGATION
    FORALL (x: (asymmetric?)): antisymmetric?[T](x);

  % Judgement subtype TCC generated (at line 29, column 4) for  x
      % expected type  (irreflexive?)
  asymmetric_is_irreflexive: OBLIGATION
    FORALL (x: (asymmetric?)): irreflexive?[T](x);

  % Judgement subtype TCC generated (at line 49, column 4) for  x
      % expected type  (trichotomous?)
  dichotomous_is_trichotomous: OBLIGATION
    FORALL (x: (dichotomous?)): trichotomous?[T](x);

  % Subtype TCC generated (at line 56, column 39) for  union(R, =)
      % expected type  (reflexive?)
  reflexive_closure_TCC1: OBLIGATION
    FORALL (R: pred[[T, T]]): reflexive?[T](union[[T, T]](R, =));

  % Subtype TCC generated (at line 57, column 42) for  difference(R, =)
      % expected type  (irreflexive?)
  irreflexive_kernel_TCC1: OBLIGATION
    FORALL (R: pred[[T, T]]): irreflexive?[T](difference[[T, T]](R, =));

  % Subtype TCC generated (at line 58, column 39) for  union(R, converse(R))
      % expected type  (symmetric?)
  symmetric_closure_TCC1: OBLIGATION
    FORALL (R: pred[[T, T]]):
      symmetric?[T](union[[T, T]](R, converse[T, T](R)));

  % Subtype TCC generated (at line 59, column 38) for
      % intersection(R, converse(R))
      % expected type  (symmetric?)
  symmetric_kernel_TCC1: OBLIGATION
    FORALL (R: pred[[T, T]]):
      symmetric?[T](intersection[[T, T]](R, converse[T, T](R)));

  % Judgement subtype TCC generated (at line 62, column 4) for
      % reflexive_closure(R)
      % expected type  (preorder?)
  reflexive_closure_preserves_transitive: OBLIGATION
    FORALL (R: (transitive?)): preorder?[T](reflexive_closure(R));

  % Judgement subtype TCC generated (at line 65, column 4) for
      % reflexive_closure(R)
      % expected type  (partial_order?)
  strict_order_to_partial_order: OBLIGATION
    FORALL (R: (strict_order?)): partial_order?[T](reflexive_closure(R));

  % Judgement subtype TCC generated (at line 68, column 4) for
      % reflexive_closure(R)
      % expected type  (dichotomous?)
  reflexive_closure_dichotomous: OBLIGATION
    FORALL (R: (trichotomous?)): dichotomous?[T](reflexive_closure(R));

  % Judgement subtype TCC generated (at line 71, column 4) for
      % reflexive_closure(R)
      % expected type  (total_order?)
  strict_total_order_to_total_order: OBLIGATION
    FORALL (R: (strict_total_order?)): total_order?[T](reflexive_closure(R));

  % Judgement subtype TCC generated (at line 74, column 4) for
      % irreflexive_kernel(R)
      % expected type  (strict_order?)
  partial_order_to_strict_order: OBLIGATION
    FORALL (R: (partial_order?)): strict_order?[T](irreflexive_kernel(R));

  % Judgement subtype TCC generated (at line 77, column 4) for
      % irreflexive_kernel(R)
      % expected type  (trichotomous?)
  irreflexive_kernel_trichotomous: OBLIGATION
    FORALL (R: (dichotomous?)): trichotomous?[T](irreflexive_kernel(R));

  % Judgement subtype TCC generated (at line 80, column 4) for
      % irreflexive_kernel(R)
      % expected type  (strict_total_order?)
  total_order_to_strict_total_order: OBLIGATION
    FORALL (R: (total_order?)): strict_total_order?[T](irreflexive_kernel(R));

  % Judgement subtype TCC generated (at line 83, column 4) for
      % symmetric_kernel(R)
      % expected type  (equivalence?)
  symmetric_kernel_of_preorder: OBLIGATION
    FORALL (R: (preorder?)): equivalence?[T](symmetric_kernel(R));


body:
  %
  %
  % Purpose : the choice function that selects a median value if the
  %           set of enabled sources is nonempty, otherwise a default value
  %
  %

  local[
    T: TYPE+
  ]: THEORY

  BEGIN

    IMPORTING
      structures@seqs[T]

  %  transform_local: TYPE = [s:ne_seqs[T] -> {t:ne_seqs[T] | s`length = t`length}]
    transform_local: TYPE = [ne_seqs[T] -> ne_seqs[T]]
    select_local:    TYPE = [ne_seqs[T] -> T]

  % Some local computations needed...
  %   filter: replace, remove
  %   transform: minmax, reduce, fill
  %   select: avg, maj, choose, plurality

  END local


body:
  %
  %
  % Purpose: results to get rid of is_finite TCCs
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  %
   
  finite_sets_below_extra[N: nat]: THEORY
   
  BEGIN
   
    IMPORTING finite_sets@finite_sets_below[N]
   
    below_is_finite_type: LEMMA is_finite_type[below(N)]
   
    set_below_is_finite: JUDGEMENT set[below(N)] SUBTYPE_OF finite_set[below(N)]
   
  END finite_sets_below_extra

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

  % Judgement subtype TCC generated (at line 16, column 33) for  x
      % expected type  finite_set[below(N)]
  set_below_is_finite: OBLIGATION
    FORALL (x: set[below(N)]): is_finite[below(N)](x);


body:
  %
  %
  % Purpose : Functions and properties that apply to
  %           a parallel group of nodes
  %                
  %
  %

  node[
    N: posnat,
    T: TYPE+
  ]: THEORY

  BEGIN

    IMPORTING
      finite_sets_below_extra[N],
      structures@seqs[T],
      local[T]


    vec:           TYPE = [below(N) -> T]
    compute_stage: TYPE = [vec -> vec]

    nodeid_set:    TYPE = finite_set[below(N)]
    nodeid_nonempty: TYPE = non_empty_finite_set[below(N)]
    check_local:   TYPE = [vec -> nodeid_set]
    choice_local:  TYPE = [vec, nodeid_set -> T]

    n, n1, n2: VAR below(N)
    t, default: VAR T
    v, v1, v2: VAR vec
    nodes: VAR nodeid_set
    enabled: VAR nodeid_nonempty

    uniform?(v, t)(nodes) : bool =
       FORALL n: nodes(n) IMPLIES v(n) = t

    enabled_symmetric?(nodes, v1, v2): bool =
      FORALL n: nodes(n) IMPLIES v1(n) = v2(n)

    % all enabled nodes who have the given value
    uniform_nodes(nodes, v, t): nodeid_set =
      {n | nodes(n) AND v(n) = t}

    uniform_char: LEMMA
      uniform?(v, t)(uniform_nodes(nodes, v, t))

    enabled_symmetric_uniform: LEMMA
        enabled_symmetric?(nodes, v1, v2) 
      IMPLIES
        uniform_nodes(nodes, v1, t) = uniform_nodes(nodes, v2, t)



    filter_local: TYPE = [vec, nodeid_nonempty -> ne_seqs[T]]

    filter: VAR filter_local
    transform: VAR transform_local
    selection: VAR select_local

    % Build a choice function as a simple composition of 
    % individual filter, transform, and selection functions
  %  choice_builder(filter, transform, selection): choice_local =
  %    selection o transform o filter



    % Conversion from vec, enabled to finite sequence
   %  THIS probably should be elevated to a Theory parameter ...
    m(enabled): (bijective?[below(card(enabled)), (enabled)])

    % filter the the unenabled elements out of the vector and put the remaining elements
    % in a sequence.

    vec2seq(v, nodes): finite_sequence[T] =
      (# length := card(nodes),
         seq := LAMBDA (i: below(card(nodes))): 
           IF empty?(nodes) THEN choose({t:T|TRUE}) ELSE v(m(nodes)(i)) ENDIF 
      #)

    vec2seq_agreement: LEMMA
        enabled_symmetric?(nodes, v1, v2)
      IMPLIES
        vec2seq(v1, nodes) = vec2seq(v2, nodes)

    vec2seq_type: JUDGEMENT vec2seq(v, enabled) HAS_TYPE ne_seqs[T]

  END node

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

  % Existence TCC generated (at line 71, column 2) for
      % m(enabled): (bijective?[below(card(enabled)), (enabled)])
  m_TCC1: OBLIGATION
    EXISTS (x:
              [enabled: nodeid_nonempty ->
                 (bijective?[below(card[below(N)](enabled)), (enabled)])]):
      TRUE;

  % Subtype TCC generated (at line 79, column 38) for  {t: T | TRUE}
      % expected type  p: (nonempty?[T])
  vec2seq_TCC1: OBLIGATION
    FORALL (nodes: nodeid_set, i: below(card[below(N)](nodes))):
      empty?(nodes) IMPLIES nonempty?[T]({t: T | TRUE});

  % Judgement subtype TCC generated (at line 87, column 26) for
      % vec2seq(v, enabled)
      % expected type  ne_seqs[T]
  vec2seq_type: OBLIGATION
    FORALL (enabled, v): length(vec2seq(v, enabled)) > 0;


body:
  %
  %
  % Purpose : properties of the min/max of the results 
  %           from a set of parallel nodes
  %
  %

  select_minmax[N: posnat, T: TYPE+, <=: (total_order?[T])]: THEORY

    BEGIN

    IMPORTING
      finite_sets@finite_sets_minmax[T, <=],
      node[N, T],
      relations_extra[T]

    node_set: VAR non_empty_finite_set[below(N)]
    v: VAR vec
    n: VAR below(N)
    t: VAR T

    v_min(v, node_set): T = min(image(v, node_set))

    v_max(v, node_set): T = max(image(v, node_set))

    v_min_witness: LEMMA
      EXISTS n: node_set(n) AND v_min(v, node_set) = v(n)

    v_max_witness: LEMMA
      EXISTS n: node_set(n) AND v_max(v, node_set) = v(n)

    v_min_is_min: LEMMA
      node_set(n) IMPLIES v_min(v, node_set) <= v(n)

    v_max_is_max: LEMMA
      node_set(n) IMPLIES v(n) <= v_max(v, node_set)

    min_le_max: LEMMA
      v_min(v, node_set) <= v_max(v, node_set)

    min_le_max_alt: LEMMA
      v_max(v, node_set) = v_min(v, node_set) IFF
        (v_max(v, node_set) <= v_min(v, node_set))

    v_minmax_choose: LEMMA
      uniform?(v, t)(node_set) IFF 
        (v_max(v, node_set) = v_min(v, node_set) AND v_min(v, node_set) = t)

    v_minmax_choose_alt: LEMMA
      uniform?(v, t)(node_set) IFF 
        (v_max(v, node_set) <= t AND t <= v_min(v, node_set))

    END select_minmax

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

  % Subtype TCC generated (at line 22, column 30) for  image(v, node_set)
      % expected type  SS: non_empty_finite_set[T]
  v_min_TCC1: OBLIGATION
    FORALL (v: vec[N, T], node_set: non_empty_finite_set[below(N)]):
      NOT empty?[T](image[below(N), T](v, node_set));


body:
  tau_declaration  % [ parameters ]
  		: THEORY

    BEGIN

    % ASSUMING
     % assuming declarations
    % ENDASSUMING

    tau_type: TYPE = [ pn: posnat -> {t: nat | 2 * t < pn}]

    n: VAR nat
    pn: VAR posnat
   
    nada: tau_type = LAMBDA pn: 0
    mid: tau_type = LAMBDA pn: floor((pn - 1) / 2)
    byz: tau_type = LAMBDA pn: floor(pn/3)

    weber(n): tau_type = LAMBDA pn: IF  floor(n/2) < pn AND pn <= n THEN pn - 1 - floor(n/2) ELSE 0 ENDIF

    END tau_declaration

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

  % Subtype TCC generated (at line 15, column 30) for  0
      % expected type  {t: nat | 2 * t < pn}
  nada_TCC1: OBLIGATION FORALL (pn): 2 * 0 < pn;

  % Subtype TCC generated (at line 16, column 29) for  floor((pn - 1) / 2)
      % expected type  {t: nat | 2 * t < pn}
  mid_TCC1: OBLIGATION
    FORALL (pn): floor((pn - 1) / 2) >= 0 AND 2 * floor((pn - 1) / 2) < pn;

  % Subtype TCC generated (at line 17, column 29) for  floor(pn / 3)
      % expected type  {t: nat | 2 * t < pn}
  byz_TCC1: OBLIGATION FORALL (pn): 2 * floor(pn / 3) < pn;

  % Subtype TCC generated (at line 19, column 71) for  pn - 1 - floor(n / 2)
      % expected type  {t: nat | 2 * t < pn}
  weber_TCC1: OBLIGATION
    FORALL (n: nat, pn):
      floor(n / 2) < pn AND pn <= n IMPLIES
       pn - 1 - floor(n / 2) >= 0 AND 2 * (pn - 1 - floor(n / 2)) < pn;


body:
  %
  %
  % Purpose : the pigeonhole principle 
  %
  %

  pigeonhole[T: TYPE]: THEORY

  BEGIN

    A, A1, A2, B, C, S, S1, S2, S3: VAR finite_set[T]
    x: VAR T
    n: VAR nat  

    pigeonhole: THEOREM
        card(A) + card(B) > card(union(A, B)) 
      IMPLIES
        EXISTS x: A(x) AND B(x)

    card_difference_alt: LEMMA
      card(difference(S, C)) <= n IFF card(intersection(S, C)) >= card(S) - n

    pigeonhole_difference: THEOREM
        subset?(A, S) AND
        card(A) > n AND
        card(difference(S, B)) <= n
      IMPLIES
        EXISTS x: A(x) AND B(x)

    majority_subset?(A, S): bool = 
      2 * card(A) > card(S) AND subset?(A, S)

    simple_majority?(A, S): bool = 
      2 * card(intersection(A, S)) > card(S)

    simple_majority_subset: LEMMA
      simple_majority?(A, S) IFF majority_subset?(intersection(A, S), S)

    majority_subset_nonempty: LEMMA
        majority_subset?(A, S) 
      IMPLIES 
        NOT empty?(S)

    simple_majority_nonempty: LEMMA
        simple_majority?(A, S)
      IMPLIES
        NOT empty?(S)

    majority_nonempty: LEMMA
        majority_subset?(A, S) 
      IMPLIES 
        NOT empty?(A)

    majority_pigeonhole: THEOREM
        2 * card(A) > card(S) AND 
        subset?(A, S) AND
        2 * card(B) >= card(S) AND 
        subset?(B, S) 
      IMPLIES
        EXISTS x: A(x) AND B(x)

    simple_majority_pigeonhole: THEOREM
        simple_majority?(A, S) AND 
        simple_majority?(B, S)
      IMPLIES
        EXISTS x: A(x) AND B(x)

    median_pigeonhole: LEMMA
        majority_subset?(A, S1) AND
        majority_subset?(B, S2) AND
        card(union(S1, S2)) - card(intersection(S1, S2)) <= 1
      IMPLIES
        EXISTS x: A(x) AND B(x)

    two_thirds_majority_subset?(A, S): bool = 
      3 * card(A) >= 2 * card(S) AND 
      subset?(A, S) 

    intersection_majority?(S1, S2): bool =
      2 * card(intersection(S1, S2)) > card(union(S1, S2))

    intersection_nonempty: LEMMA
       intersection_majority?(S1, S2) IMPLIES not empty?(S1)

    intersection_majority?(S1, S2, S3): bool = 
      2 * card(intersection(S1, S2)) > card(S3)

    byzantine_intersection_majority?(S1, S2, S3): bool =
      2 * card(intersection(S1, intersection(S2, S3))) >
        card(union(S1, S2)) + card(difference(S2, S3))


    two_thirds_overlap_pigeonhole: LEMMA
        two_thirds_majority_subset?(A, S1) AND
        two_thirds_majority_subset?(B, S2) AND
        intersection_majority?(S1, S2)
      IMPLIES
        EXISTS x: A(x) AND B(x)


    IMPORTING tau_declaration

    t: VAR tau_type
    e: VAR non_empty_finite_set[T]
    s, s1, s2: VAR finite_set[T]

    quorum?(s1, t)(s2): bool = 
      NOT empty?(s1) AND card(difference(s1, s2)) <= t(card(s1))

    quorum_exists?(s, t): bool = 
      EXISTS s1: quorum?(s, t)(s1)


    % Cardinality of a tau-reduced multi-set
    M(e, t): posnat = card(e) - 2 * t(card(e))

    nada_reduce: LEMMA M(e, nada) = card(e)
    mid_reduce: LEMMA M(e, mid) <= 2
    byz_reduce: LEMMA M(e, byz) >= card(e)/3


    

  END pigeonhole

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

  % Subtype TCC generated (at line 108, column 53) for  card(s1)
      % expected type  pn: posnat
  quorum?_TCC1: OBLIGATION
    FORALL (s1: finite_set[T]): NOT empty?(s1) IMPLIES card[T](s1) > 0;

  % Subtype TCC generated (at line 115, column 36) for  card(e)
      % expected type  pn: posnat
  M_TCC1: OBLIGATION FORALL (e: non_empty_finite_set[T]): card[T](e) > 0;

  % Subtype TCC generated (at line 115, column 20) for
      % card(e) - 2 * t(card(e))
      % expected type  posnat
  M_TCC2: OBLIGATION
    FORALL (e: non_empty_finite_set[T], t: tau_type):
      card[T](e) - 2 * t(card[T](e)) >= 0 AND
       card[T](e) - 2 * t(card[T](e)) > 0;


body:
  finite_seqs[T: TYPE+]: THEORY

    BEGIN

    IMPORTING structures@seqs[T], structures@majority_seq[T]

    s, s1, s2: VAR ne_seqs
    fs: VAR finite_sequence[T]

    in_consensus_function: TYPE = [s: ne_seqs -> {t: T | in?(t, s)}]
    
    i: VAR nat
    choose(i)(s): T = 
      IF i < s`length THEN s`seq(i) 
      ELSE s`seq(0)
      ENDIF

    choose_in?: LEMMA in?(choose(i)(s), s)

    choose_consensus: JUDGEMENT choose(i) HAS_TYPE in_consensus_function

    choose_extend(s): sequence[T] = LAMBDA i: choose(i)(s)

    t, d: VAR T

    majority_function: TYPE = [fs: finite_sequence[T] -> {t: T | maj_exists(fs) => is_majority(t, fs)}]

    mf: VAR majority_function

    maj_exists_same: LEMMA
        maj_exists(fs)
      IMPLIES 
        mf(fs) = maj(fs)

    mf_lem: LEMMA
        is_majority(t, fs)
      IMPLIES
        mf(fs) = t

    majority_choose(s): T =
      IF maj_exists(s) THEN maj(s) ELSE choose(0)(s) ENDIF

    majority_choose_consensus: JUDGEMENT majority_choose HAS_TYPE in_consensus_function

    majority_choose2(fs): T = 
      IF fs`length = 0 THEN choose({t:T | TRUE})
      ELSE majority_choose(fs)
      ENDIF

    majority2_choose_majority: JUDGEMENT majority_choose2 HAS_TYPE majority_function

    k: VAR nat

    uniform(fs, t, k): finite_set[below(k)] = { i : below(k) | fs`length = k & fs`seq(i) = t }

    is_majority?(fs, t, k): bool = 2 * card(uniform(fs, t, k)) > k

    majority_same: LEMMA is_majority(t, fs) IFF is_majority?(fs, t, fs`length)


    END finite_seqs

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

  % Subtype TCC generated (at line 15, column 15) for  0
      % expected type  below[s`length]
  choose_TCC1: OBLIGATION
    FORALL (i: nat, s: ne_seqs[T]): NOT i < s`length IMPLIES 0 < s`length;

  % Judgement subtype TCC generated (at line 20, column 30) for  choose(i)
      % expected type  in_consensus_function
  choose_consensus: OBLIGATION
    FORALL (i, x1: ne_seqs[T]): in?[T](choose(i)(x1), x1);

  % Judgement subtype TCC generated (at line 43, column 39) for
      % majority_choose
      % expected type  in_consensus_function
  majority_choose_consensus: OBLIGATION
    FORALL (x1: ne_seqs[T]): in?[T](majority_choose(x1), x1);

  % Subtype TCC generated (at line 46, column 33) for  {t: T | TRUE}
      % expected type  p: (nonempty?[T])
  majority_choose2_TCC1: OBLIGATION
    FORALL (fs: finite_sequence[T]):
      fs`length = 0 IMPLIES nonempty?[T]({t: T | TRUE});

  % Subtype TCC generated (at line 47, column 25) for  fs
      % expected type  ne_seqs[T]
  majority_choose2_TCC2: OBLIGATION
    FORALL (fs: finite_sequence[T]): NOT fs`length = 0 IMPLIES length(fs) > 0;

  % Judgement subtype TCC generated (at line 50, column 39) for
      % majority_choose2
      % expected type  majority_function
  majority2_choose_majority: OBLIGATION
    FORALL (x1: finite_sequence[T]):
      maj_exists[T](x1) => is_majority[T](majority_choose2(x1), x1);

  % Subtype TCC generated (at line 54, column 84) for  i
      % expected type  below[fs`length]
  uniform_TCC1: OBLIGATION
    FORALL (fs: finite_sequence[T], k: nat, i: below(k)):
      fs`length = k IMPLIES i < fs`length;

  % Subtype TCC generated (at line 54, column 44) for
      % {i: below(k) | fs`length = k & fs`seq(i) = t}
      % expected type  finite_set[below(k)]
  uniform_TCC2: OBLIGATION
    FORALL (fs: finite_sequence[T], t: T, k: nat):
      is_finite[below(k)]({i: below(k) | fs`length = k & fs`seq(i) = t});


body:
  ordered_finite_sequences[T: TYPE+, <=:(total_order?[T])]: THEORY

    BEGIN

    IMPORTING structures@sort_seq_lems[T, <=], relations_extra[T], finite_seqs[T]

    s, s1, s2: VAR ne_seqs

    consensus_function: TYPE = [s: ne_seqs -> {t: T | min(s) <= t AND t <= max(s)}]

    cf: VAR consensus_function

    k: VAR posnat
    i,j,l: VAR nat

    extract_one: LEMMA 
      i<=j AND i<s`length AND j<s`length AND l<=j-i 
        IMPLIES (s^(i,j))`seq(l) = s`seq(i+l)
    extract_upper: LEMMA 
      i<=j AND i<s`length AND j<s`length 
        IMPLIES (s^(i,j))`seq(length(s^(i,j))-1) = s`seq(j)

    min_extract: LEMMA 
      i<=j AND i<s`length IMPLIES min(sort(s)^(i,j)) = sort(s)`seq(i)
    max_extract: LEMMA 
      i<=j AND i<s`length AND j<s`length 
        IMPLIES max(sort(s)^(i,j)) = sort(s)`seq(j)

    minmax(s): ne_seqs = (: min(s), max(s) :) % uses conversion list2finseq

    min_le_max: LEMMA min(s) <= max(s)

    min_minmax: LEMMA min(minmax(s)) = min(s)
    max_minmax: LEMMA max(minmax(s)) = max(s)

     min_in_consensus: JUDGEMENT min HAS_TYPE in_consensus_function
     max_in_consensus: JUDGEMENT max HAS_TYPE in_consensus_function
     in_consensus:     JUDGEMENT in_consensus_function SUBTYPE_OF consensus_function

    min_consensus:    JUDGEMENT min HAS_TYPE consensus_function
    max_consensus:    JUDGEMENT max HAS_TYPE consensus_function
    choose_consensus: JUDGEMENT choose(i) HAS_TYPE consensus_function
    

    IMPORTING pigeonhole,  
              finite_sets@finite_sets_below, 
              finite_sets@finite_sets_card_eq

    % Set of indexes from the unsorted seq whose value is equal or 
    % lower than the value of given index in the sorted sequence
    lower(s, k, (i: below(k))): finite_set[below(k)] = 
      {j: below(k) | s`length = k AND s`seq(j) <= sort(s)`seq(i)}
    upper(s, k, (i: below(k))): finite_set[below(k)] = 
      {j: below(k) | s`length = k AND sort(s)`seq(i) <= s`seq(j)}

    % Map a set of indexes from the sorted sequence into a set of indexes 
    % in the unsorted seq
    map_set(s, k, (a: finite_set[below(k)])): finite_set[below(k)] =
      {i: below(k) | s`length = k AND a(sort_map(s)(i))}

    map_subset_lower: LEMMA
        i<k AND s`length = k 
      IMPLIES 
        subset?(map_set(s, k, {m:below(k) | m <= i}), lower(s, k, i))

    map_subset_upper: LEMMA
        i<k AND s`length = k 
      IMPLIES 
        subset?(map_set(s, k, {m:below(k) | i <= m}), upper(s, k, i))

    % a bijective mapping function for a subset of below(k)
    mapper(s, k, (a: finite_set[below(k)]))(i:(map_set(s,k,a))): (a) = sort_map(s)(i)

    map_card_eq: LEMMA
      FORALL (a:finite_set[below(k)]):
        s`length = k 
      IMPLIES 
        card(map_set(s, k, a)) = card(a)
    
    card_below_set: LEMMA i < k IMPLIES i+1 <= card({m:below(k) | m <= i})
    card_above_set: LEMMA i < k IMPLIES k-i <= card({m:below(k) | i <= m})

    card_lower: LEMMA i < k AND s`length = k IMPLIES i + 1 <= card[below(k)](lower(s, k, i)) 
    card_upper: LEMMA i < k AND s`length = k IMPLIES k - i <= card[below(k)](upper(s, k, i))

    sort_overlap: LEMMA
        s1`length = k AND
        s2`length = k
      IMPLIES
        FORALL (i: below(k)): 
          EXISTS (j: below(k)):
            s2`seq(j) <= sort(s2)`seq(i) AND
              sort(s1)`seq(i) <= s1`seq(j)

    leq_validity: COROLLARY
        s`length = k 
      IMPLIES
        FORALL (i: below(k)): 
          EXISTS (j: below(k)):
            s`seq(j) <= sort(s)`seq(i) 

    END ordered_finite_sequences

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

  % Subtype TCC generated (at line 18, column 28) for  l
      % expected type  below[(s ^ (i, j))`length]
  extract_one_TCC1: OBLIGATION
    FORALL (i, j, l: nat, s: ne_seqs[T]):
      l <= j - i AND j < s`length AND i < s`length AND i <= j IMPLIES
       l < (^[T](s, (i, j)))`length;

  % Subtype TCC generated (at line 18, column 39) for  i + l
      % expected type  below[s`length]
  extract_one_TCC2: OBLIGATION
    FORALL (i, j, l: nat, s: ne_seqs[T]):
      l <= j - i AND j < s`length AND i < s`length AND i <= j IMPLIES
       i + l < s`length;

  % Subtype TCC generated (at line 21, column 28) for  length(s ^ (i, j)) - 1
      % expected type  below[(s ^ (i, j))`length]
  extract_upper_TCC1: OBLIGATION
    FORALL (i, j: nat, s: ne_seqs[T]):
      j < s`length AND i < s`length AND i <= j IMPLIES
       length(^[T](s, (i, j))) - 1 >= 0 AND
        length(^[T](s, (i, j))) - 1 < (^[T](s, (i, j)))`length;

  % Subtype TCC generated (at line 24, column 36) for  sort(s) ^ (i, j)
      % expected type  s: ne_seqs[T]
  min_extract_TCC1: OBLIGATION
    FORALL (i, j: nat, s: ne_seqs[T]):
      i < s`length AND i <= j IMPLIES
       length(^[T](sort[T, <=](s), (i, j))) > 0;

  % Subtype TCC generated (at line 24, column 65) for  i
      % expected type  below[sort(s)`length]
  min_extract_TCC2: OBLIGATION
    FORALL (i, j: nat, s: ne_seqs[T]):
      i < s`length AND i <= j IMPLIES i < sort[T, <=](s)`length;

  % Subtype TCC generated (at line 27, column 47) for  j
      % expected type  below[sort(s)`length]
  max_extract_TCC1: OBLIGATION
    FORALL (i, j: nat, s: ne_seqs[T]):
      j < s`length AND i < s`length AND i <= j IMPLIES
       j < sort[T, <=](s)`length;

  % Subtype TCC generated (at line 29, column 23) for
      % list2finseq[T]((: min(s), max(s) :))
      % expected type  ne_seqs[T]
  minmax_TCC1: OBLIGATION
    FORALL (s: ne_seqs[T]):
      length(list2finseq[T]((: min[T, <=](s), max[T, <=](s) :))) > 0;

  % Judgement subtype TCC generated (at line 36, column 31) for  min
      % expected type  in_consensus_function[T]
  min_in_consensus: OBLIGATION
    FORALL (x1: ne_seqs[T]): in?[T](min[T, <=](x1), x1);

  % Judgement subtype TCC generated (at line 37, column 31) for  max
      % expected type  in_consensus_function[T]
  max_in_consensus: OBLIGATION
    FORALL (x1: ne_seqs[T]): in?[T](max[T, <=](x1), x1);

  % Judgement subtype TCC generated (at line 38, column 31) for  x
      % expected type  consensus_function
  in_consensus: OBLIGATION
    FORALL (x: in_consensus_function, x1: ne_seqs[T]):
      min[T, <=](x1) <= x(x1) AND x(x1) <= max[T, <=](x1);

  % Subtype TCC generated (at line 52, column 42) for  j
      % expected type  below[s`length]
  lower_TCC1: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, (i: below(k)), j: below(k)):
      s`length = k IMPLIES j < s`length;

  % Subtype TCC generated (at line 52, column 60) for  i
      % expected type  below[sort(s)`length]
  lower_TCC2: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, (i: below(k)), j: below(k)):
      s`length = k IMPLIES i < sort[T, <=](s)`length;

  % Subtype TCC generated (at line 52, column 4) for
      % {j: below(k) | s`length = k AND s`seq(j) <= sort(s)`seq(i)}
      % expected type  finite_set[below(k)]
  lower_TCC3: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, (i: below(k))):
      is_finite[below(k)]
          ({j: below(k) |
              s`length = k AND s`seq(j) <= sort[T, <=](s)`seq(i)});

  % Subtype TCC generated (at line 54, column 4) for
      % {j: below(k) | s`length = k AND sort(s)`seq(i) <= s`seq(j)}
      % expected type  finite_set[below(k)]
  upper_TCC1: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, (i: below(k))):
      is_finite[below(k)]
          ({j: below(k) |
              s`length = k AND sort[T, <=](s)`seq(i) <= s`seq(j)});

  % Subtype TCC generated (at line 59, column 50) for  i
      % expected type  below(length(s))
  map_set_TCC1: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, i: below(k)):
      s`length = k IMPLIES i < length(s);

  % Subtype TCC generated (at line 59, column 38) for  sort_map(s)(i)
      % expected type  below(k)
  map_set_TCC2: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, i: below(k)):
      s`length = k IMPLIES sort_map[T, <=](s)(i) < k;

  % Subtype TCC generated (at line 59, column 4) for
      % {i: below(k) | s`length = k AND a(sort_map(s)(i))}
      % expected type  finite_set[below(k)]
  map_set_TCC3: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, (a: finite_set[below(k)])):
      is_finite[below(k)]
          ({i: below(k) | s`length = k AND a(sort_map[T, <=](s)(i))});

  % Subtype TCC generated (at line 64, column 28) for  {m: below(k) | m <= i}
      % expected type  finite_set[below(k)]
  map_subset_lower_TCC1: OBLIGATION
    FORALL (i: nat, k: posnat, s: ne_seqs[T]):
      s`length = k AND i < k IMPLIES
       is_finite[below(k)]({m: below(k) | m <= i});

  % Subtype TCC generated (at line 69, column 28) for  {m: below(k) | i <= m}
      % expected type  finite_set[below(k)]
  map_subset_upper_TCC1: OBLIGATION
    FORALL (i: nat, k: posnat, s: ne_seqs[T]):
      s`length = k AND i < k IMPLIES
       is_finite[below(k)]({m: below(k) | i <= m});

  % Subtype TCC generated (at line 72, column 81) for  i
      % expected type  below(length(s))
  mapper_TCC1: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, (a: finite_set[below(k)]),
            i: (map_set(s, k, a))):
      i < length(s);

  % Subtype TCC generated (at line 72, column 69) for  sort_map(s)(i)
      % expected type  (a)
  mapper_TCC2: OBLIGATION
    FORALL (s: ne_seqs[T], k: posnat, (a: finite_set[below(k)]),
            i: (map_set(s, k, a))):
      sort_map[T, <=](s)(i) < k AND a(sort_map[T, <=](s)(i));

  % Subtype TCC generated (at line 80, column 50) for  {m: below(k) | m <= i}
      % expected type  S: finite_set[below(k)]
  card_below_set_TCC1: OBLIGATION
    FORALL (i: nat, k: posnat):
      i < k IMPLIES is_finite[below(k)]({m: below(k) | m <= i});

  % Subtype TCC generated (at line 81, column 50) for  {m: below(k) | i <= m}
      % expected type  S: finite_set[below(k)]
  card_above_set_TCC1: OBLIGATION
    FORALL (i: nat, k: posnat):
      i < k IMPLIES is_finite[below(k)]({m: below(k) | i <= m});

  % Subtype TCC generated (at line 92, column 17) for  j
      % expected type  below[s2`length]
  sort_overlap_TCC1: OBLIGATION
    FORALL (k: posnat, s1, s2: ne_seqs[T]):
      s2`length = k AND s1`length = k IMPLIES
       (FORALL (i: below(k), j: below(k)): j < s2`length);

  % Subtype TCC generated (at line 92, column 36) for  i
      % expected type  below[sort(s2)`length]
  sort_overlap_TCC2: OBLIGATION
    FORALL (k: posnat, s1, s2: ne_seqs[T]):
      s2`length = k AND s1`length = k IMPLIES
       (FORALL (i: below(k), j: below(k)): i < sort[T, <=](s2)`length);


body:
  real_finite_sequences: THEORY

    BEGIN

    IMPORTING ordered_finite_sequences[real, <=], reals@sigma_below

    s, s1, s2: VAR ne_seqs
    cf, cf1, cf2: VAR consensus_function

    eps, delta: VAR nnreal
    k: VAR posnat
    i: VAR nat

    diameter?(s): nnreal = max(s) - min(s)

  % diameter?(s1 o s2)

    agreement_propagation: LEMMA
      cf1(s1) - cf2(s2) <= max(s1) - min(s2)

    similar?(s1, s2, eps): bool = 
      (s1`length = s2`length) AND 
      FORALL (i: below(s1`length)):
        s1`seq(i) - s2`seq(i) <= eps

    similar_sort: LEMMA
      similar?(s1, s2, eps) IMPLIES similar?(sort(s1), sort(s2), eps)


  %  similar_reduce: LEMMA
  %    similar?(s1, s2, eps) IMPLIES similar?(reduce(tau)(s1), reduce(tau)(s2), eps)

    inexact_consensus?(cf): bool = 
      FORALL s1, s2, eps: similar?(s1, s2, eps) IMPLIES cf(s1) - cf(s2) <= eps

    sum(s): real = sigma[below(s`length)](0, s`length - 1, s`seq)

    sum_lower: LEMMA max(s) + (s`length - 1) * min(s) <= sum(s)
    sum_upper: LEMMA sum(s) <= (s`length - 1) * max(s) + min(s)

    mean(s): real = sum(s) / s`length

    min_le_mean: LEMMA min(s) <= mean(s)
    mean_le_max: LEMMA mean(s) <= max(s)

    midpoint(s) : real = mean(minmax(s))

    midpoint_def: LEMMA midpoint(s) = (min(s) + max(s)) / 2

    mean_lower: LEMMA s`length <= k IMPLIES (max(s) + (k - 1) * min(s)) / k <= mean(s)
    mean_upper: LEMMA s`length <= k IMPLIES mean(s) <= ((k - 1) * max(s) + min(s)) / k

    mean_consensus:     JUDGEMENT mean     HAS_TYPE consensus_function
    midpoint_consensus: JUDGEMENT midpoint HAS_TYPE consensus_function
       
    inexact_min:      LEMMA inexact_consensus?(min)
    inexact_max:      LEMMA inexact_consensus?(max)
    inexact_choose:   LEMMA inexact_consensus?(choose(i))
    inexact_mean:     LEMMA inexact_consensus?(mean)
    inexact_midpoint: LEMMA inexact_consensus?(midpoint)

    mean_convergence: THEOREM
        s1`length <= k AND
        s2`length <= k AND
        max(s1) - min(s2) <= delta + eps AND
        min(s1) - max(s2) <= eps
      IMPLIES
        mean(s1) - mean(s2) <= delta * (k - 1) / k + eps

    midpoint_convergence: COROLLARY
        max(s1) - min(s2) <= delta + eps AND
        min(s1) - max(s2) <= eps
      IMPLIES
        midpoint(s1) - midpoint(s2) <= delta / 2 + eps
     
    convergent?(cf, i, k): bool =
      FORALL s1, s2, delta, eps: 
        s1`length <= i AND
        s2`length <= i AND
        max(s1) - min(s2) <= delta + eps AND
        min(s1) - max(s2) <= eps
      IMPLIES
        cf(s1) - cf(s2) <= delta * (k - 1) / k + eps

    convergent_mean    : LEMMA convergent?(mean, k, k + i)
    convergent_midpoint: LEMMA convergent?(midpoint, i, 2)
    

    END real_finite_sequences

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

  % Subtype TCC generated (at line 14, column 25) for  max(s) - min(s)
      % expected type  nnreal
  diameter?_TCC1: OBLIGATION
    FORALL (s: ne_seqs[real]): max[real, <=](s) - min[real, <=](s) >= 0;

  % Subtype TCC generated (at line 24, column 25) for  i
      % expected type  below[s2`length]
  similar?_TCC1: OBLIGATION
    FORALL (s1: ne_seqs[real], s2: ne_seqs[real]):
      (s1`length = s2`length) IMPLIES
       (FORALL (i: below(s1`length)): i < s2`length);

  % Subtype TCC generated (at line 27, column 43) for  sort(s1)
      % expected type  ne_seqs[real]
  similar_sort_TCC1: OBLIGATION
    FORALL (eps: nnreal, s1, s2: ne_seqs[real]):
      similar?(s1, s2, eps) IMPLIES length(sort[real, <=](s1)) > 0;

  % Subtype TCC generated (at line 27, column 53) for  sort(s2)
      % expected type  ne_seqs[real]
  similar_sort_TCC2: OBLIGATION
    FORALL (eps: nnreal, s1, s2: ne_seqs[real]):
      similar?(s1, s2, eps) IMPLIES length(sort[real, <=](s2)) > 0;

  % Subtype TCC generated (at line 36, column 40) for  0
      % expected type  T_low[below(s`length)]
  sum_TCC1: OBLIGATION
    FORALL (s: ne_seqs[real]):
      0 >= 0 AND 0 < s`length OR (EXISTS (j: below(s`length)): j <= 0);

  % Subtype TCC generated (at line 36, column 43) for  s`length - 1
      % expected type  T_high[below(s`length)]
  sum_TCC2: OBLIGATION
    FORALL (s: ne_seqs[real]):
      s`length - 1 >= 0 AND s`length - 1 < s`length OR
       (EXISTS (j: below(s`length)): s`length - 1 <= j);

  % Assuming TCC generated (at line 41, column 5) for
      % reals@sigma[below(s`length)]
      % generated from assumption sigma.connected_domain
  sum_TCC3: OBLIGATION
    FORALL (s: ne_seqs[real]):
      FORALL (x, y: below(s`length)), (z: integer):
        x <= z AND z <= y IMPLIES z >= 0 AND z < s`length;

  % Subtype TCC generated (at line 41, column 27) for  s`length
      % expected type  nznum
  mean_TCC1: OBLIGATION FORALL (s: ne_seqs[real]): s`length /= 0;

  % Judgement subtype TCC generated (at line 53, column 32) for  mean
      % expected type  consensus_function[real, <=]
  mean_consensus: OBLIGATION
    FORALL (x1: ne_seqs[real]):
      min[real, <=](x1) <= mean(x1) AND mean(x1) <= max[real, <=](x1);

  % Judgement subtype TCC generated (at line 54, column 32) for  midpoint
      % expected type  consensus_function[real, <=]
  midpoint_consensus: OBLIGATION
    FORALL (x1: ne_seqs[real]):
      min[real, <=](x1) <= midpoint(x1) AND midpoint(x1) <= max[real, <=](x1);


body:
  %
  %
  % Purpose : type definitions for a single stage of the protocol
  %
  %

  node_functions_stage
  [
     S: posnat,  % Number of source nodes
     D: posnat,  % Number of destination nodes
     T: TYPE+    % Message type
  ] : THEORY

  BEGIN

    IMPORTING
      node

    check_stage:       TYPE = [below(D) -> [below(S) -> [T -> bool]]]
    check_stage_alt:   TYPE = [below(D) -> check_local[S,T]]
    sent_vec_stage:    TYPE = vec[S, T]
    rcvd_matrix_stage: TYPE = [below(D) -> [below(S) -> T]]
    result_vec_stage:  TYPE = vec[D, T]
    choice_stage:      TYPE = [rcvd_matrix_stage, check_stage -> result_vec_stage]
    choice_stage_alt:  TYPE = [below(D) -> choice_local[S,T]]


    d: VAR below(D)

    filter_stage: TYPE = [below(D) -> filter_local[S,T]]

    nominal_filter(d): filter_local[S,T] = vec2seq[S, T]

  END node_functions_stage

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

  % Subtype TCC generated (at line 32, column 41) for
      % restrict
      %     [[vec[S, T], nodeid_set[S, T]],
      %      [vec[S, T], nodeid_nonempty[S, T]], finite_sequence[T]]
      %     (vec2seq[S, T])
      % expected type  filter_local[S, T]
  nominal_filter_TCC1: OBLIGATION
    FORALL (d: below(D)):
      FORALL (x1: [vec[S, T], nodeid_nonempty[S, T]]):
        length(vec2seq[S, T](x1)) > 0;


body:
  %
  %
  % Purpose : Formulations of fault assumptions for the results-based 
  %           fault model relative to a check function
  %
  %

  fault_assumptions_stage
  [
     S: posnat,  % Number of source nodes
     D: posnat,  % Number of destination nodes
     T: TYPE+    % Message type
  ] : THEORY

    BEGIN

    IMPORTING 
      pigeonhole[below(S)],
      node_functions_stage[S, D, T]


    s: VAR below(S)
    d, d1, d2: VAR below(D)

    src_set: VAR finite_set[below(S)]
    check: VAR check_stage
    rcvd:  VAR rcvd_matrix_stage 

    tau: VAR tau_type

    %

    enabled(rcvd, check)(d): finite_set[below(S)] = 
      { s | check(d)(s)(rcvd(d)(s))}

    enabled_nonempty?(rcvd, check): bool = 
      FORALL d: NOT empty?(enabled(rcvd, check)(d))

    enabled_within?(rcvd, check)(src_set): bool = 
      FORALL d: subset?(enabled(rcvd, check)(d), src_set)

    enabled?(rcvd, check): finite_set[below(S)] = 
      { s | EXISTS d : enabled(rcvd, check)(d)(s)}

    enabled_within: LEMMA
      enabled_within?(rcvd, check)(enabled?(rcvd, check))

    %
    % Abstracted single stage fault assumptions
    %

    majority?(rcvd, check)(src_set): bool = 
      FORALL d: 
        simple_majority?(src_set, enabled(rcvd, check)(d))

    quorum?(rcvd, check, tau)(src_set): bool = 
      FORALL d: quorum?(enabled(rcvd, check)(d), tau)(src_set)

    quorum_implies_majority: LEMMA
      quorum?(rcvd, check, tau)(src_set) IMPLIES
        majority?(rcvd, check)(src_set)

    majority: LEMMA
      majority?(rcvd, check) = quorum?(rcvd, check, mid)

    enabled_within_quorum: LEMMA
      enabled_within?(rcvd, check)(src_set) AND
      enabled_nonempty?(rcvd, check)
     IMPLIES
      quorum?(rcvd, check, tau)(src_set)

    enabled_within_quorum_nada: LEMMA
      enabled_nonempty?(rcvd, check) IMPLIES
        enabled_within?(rcvd, check) = quorum?(rcvd, check, nada)

    quorum_nonempty: LEMMA
        quorum?(rcvd, check, tau)(src_set)
      IMPLIES
        enabled_nonempty?(rcvd, check)

    max(rcvd, check, tau)(d): nat = 
      IF empty?(enabled(rcvd, check)(d))
        THEN 0 
        ELSE M(enabled(rcvd, check)(d), tau) - 1
      ENDIF

    %  overlap preconditions for convergence proofs
    intersection_majority?(rcvd, check)(src_set): bool =
      FORALL d1, d2:
        intersection_majority?(enabled(rcvd, check)(d1), enabled(rcvd, check)(d2), src_set)

    intersection_majority?(rcvd, check): bool =
      FORALL d1, d2:
        intersection_majority?(enabled(rcvd, check)(d1), enabled(rcvd, check)(d2))

    byzantine_intersection_majority?(rcvd, check)(src_set): bool =
      FORALL d1, d2:
        byzantine_intersection_majority?(enabled(rcvd, check)(d1), enabled(rcvd, check)(d2), src_set)

    intersection_majority_nonempty: LEMMA
        intersection_majority?(rcvd, check)
      IMPLIES 
        enabled_nonempty?(rcvd, check)

    byzantine_intersection_nonempty: LEMMA
        byzantine_intersection_majority?(rcvd, check)(src_set)
      IMPLIES 
        enabled_nonempty?(rcvd, check)

    % "src_set" may be a node that passes the common check, symmetric_denotation, 
    % or correct_denotation depending on the particular fault assumptions required. 

    intersection_majority: LEMMA
        enabled_within?(rcvd, check)(src_set) AND
        intersection_majority?(rcvd, check)(src_set)
      IMPLIES
        intersection_majority?(rcvd, check)

    uniformly_enabled?(rcvd, check)(src_set): bool = 
      FORALL s, d1, d2: 
        src_set(s) AND
        enabled(rcvd, check)(d1)(s)
      IMPLIES
        enabled(rcvd, check)(d2)(s)

    enabled_same?(rcvd, check)(src_set): bool =
      FORALL d1, d2: enabled(rcvd, check)(d1) = enabled(rcvd, check)(d2)

    uniform?(check)(src_set): bool =
      FORALL s, d1, d2:
        src_set(s)
      IMPLIES
        check(d1)(s) = check(d2)(s)

    enabled_agree: LEMMA
        enabled_within?(rcvd, check)(src_set) AND
        uniformly_enabled?(rcvd, check)(src_set)
      IMPLIES
        enabled(rcvd, check)(d1) = enabled(rcvd, check)(d2)

  END fault_assumptions_stage

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

  % Subtype TCC generated (at line 34, column 4) for
      % {s | check(d)(s)(rcvd(d)(s))}
      % expected type  finite_set[below(S)]
  enabled_TCC1: OBLIGATION
    FORALL (rcvd: rcvd_matrix_stage[S, D, T], check: check_stage[S, D, T],
            d: below(D)):
      is_finite[below(S)]({s | check(d)(s)(rcvd(d)(s))});

  % Subtype TCC generated (at line 43, column 4) for
      % {s | EXISTS d: enabled(rcvd, check)(d)(s)}
      % expected type  finite_set[below(S)]
  enabled?_TCC1: OBLIGATION
    FORALL (rcvd: rcvd_matrix_stage[S, D, T], check: check_stage[S, D, T]):
      is_finite[below(S)]({s | EXISTS d: enabled(rcvd, check)(d)(s)});

  % Subtype TCC generated (at line 84, column 11) for
      % M(enabled(rcvd, check)(d), tau) - 1
      % expected type  nat
  max_TCC1: OBLIGATION
    FORALL (rcvd: rcvd_matrix_stage[S, D, T], check: check_stage[S, D, T],
            tau: tau_type, d: below(D)):
      NOT empty?(enabled(rcvd, check)(d)) IMPLIES
       M[below(S)](enabled(rcvd, check)(d), tau) - 1 >= 0;


body:
  %
  %
  % Purpose : Describe properties about inexact communication in 
  %           relation to the results-based fault model.
  %
  %

  inexact_comm_stage
  [
      S   : posnat,     % Number of sources 
      D   : posnat      % Number of destinations
  ] : THEORY

    BEGIN

    IMPORTING 
      fault_assumptions_stage[S, D, real],
      real_finite_sequences

    epsilon, eps_u, eps_l, delta: VAR nonneg_real

    v1, v2: VAR real

    s, s1, s2: VAR below(S)
    d, d1, d2: VAR below(D)

    src_set, correct_set: VAR finite_set[below(S)]

    sent: VAR sent_vec_stage
    rcvd: VAR rcvd_matrix_stage
    check: VAR check_stage
   
    tau: VAR tau_type

    %

    correct_lower_inaccuracy?(sent, rcvd, check, epsilon)(src_set): bool =
      FORALL d, s: 
          src_set(s) AND 
          enabled(rcvd, check)(d)(s) 
        IMPLIES
          sent(s) - epsilon <= rcvd(d)(s)

    quorum_lower?(sent, rcvd, check, tau, epsilon): bool =
      EXISTS src_set:
        correct_lower_inaccuracy?(sent, rcvd, check, epsilon)(src_set) AND
        quorum?(rcvd, check, tau)(src_set)

    majority_lower?(sent, rcvd, check, epsilon): bool = 
      EXISTS src_set:
        correct_lower_inaccuracy?(sent, rcvd, check, epsilon)(src_set) AND
        majority?(rcvd, check)(src_set)

    majority_lower_rw: LEMMA
       majority_lower?(sent, rcvd, check, epsilon) = 
       quorum_lower?(sent, rcvd, check, mid, epsilon)

    %

    correct_upper_inaccuracy?(sent, rcvd, check, epsilon)(src_set): bool =
      FORALL d, s: 
          src_set(s) AND 
          enabled(rcvd, check)(d)(s) 
        IMPLIES
          rcvd(d)(s) <= sent(s) + epsilon

    quorum_upper?(sent, rcvd, check, tau, epsilon): bool =
      EXISTS src_set:
        correct_upper_inaccuracy?(sent, rcvd, check, epsilon)(src_set) AND
        quorum?(rcvd, check, tau)(src_set)

    majority_upper?(sent, rcvd, check, epsilon): bool = 
      EXISTS src_set:
        correct_upper_inaccuracy?(sent, rcvd, check, epsilon)(src_set) AND
        majority?(rcvd, check)(src_set)

    majority_upper_rw: LEMMA
       majority_upper?(sent, rcvd, check, epsilon) = 
       quorum_upper?(sent, rcvd, check, mid, epsilon)

    %

    quorum_accuracy?(sent, rcvd, check, tau, eps_l, eps_u):bool = 
      EXISTS src_set:
        correct_lower_inaccuracy?(sent, rcvd, check, eps_l)(src_set) AND
        correct_upper_inaccuracy?(sent, rcvd, check, eps_u)(src_set) AND
        quorum?(rcvd, check, tau)(src_set)

    majority_accuracy?(sent, rcvd, check, eps_l, eps_u):bool = 
      EXISTS src_set:
        correct_lower_inaccuracy?(sent, rcvd, check, eps_l)(src_set) AND
        correct_upper_inaccuracy?(sent, rcvd, check, eps_u)(src_set) AND
        majority?(rcvd, check)(src_set)

    quorum_accuracy: LEMMA
         quorum_accuracy?(sent, rcvd, check, tau, eps_l, eps_u) 
      IMPLIES
         quorum_lower?(sent, rcvd, check, tau, eps_l) AND
         quorum_upper?(sent, rcvd, check, tau, eps_u)

    majority_accuracy: LEMMA
         majority_accuracy?(sent, rcvd, check, eps_l, eps_u) 
      IMPLIES
         majority_lower?(sent, rcvd, check, eps_l) AND
         majority_upper?(sent, rcvd, check, eps_u)

    majority_accuracy_rw: LEMMA
       majority_accuracy?(sent, rcvd, check, eps_l, eps_u) = 
       quorum_accuracy?(sent, rcvd, check, mid, eps_l, eps_u)

    %

    correct_imprecision?(sent, rcvd, check, epsilon)(src_set): bool =
      FORALL d1, d2, s1, s2:
          src_set(s1) AND enabled(rcvd, check)(d1)(s1) AND
          src_set(s2) AND enabled(rcvd, check)(d2)(s2) 
        IMPLIES
          abs((rcvd(d1)(s1) - rcvd(d2)(s2)) - (sent(s1) - sent(s2))) <= epsilon

    quorum_imprecision?(sent, rcvd, check, tau, epsilon): bool =
      EXISTS src_set:
        correct_imprecision?(sent, rcvd, check, epsilon)(src_set) AND
        quorum?(rcvd, check, tau)(src_set)

    quorum_imprecision_nonempty: LEMMA
        quorum_imprecision?(sent, rcvd, check, tau, epsilon)
      IMPLIES
        enabled_nonempty?(rcvd, check)

    majority_imprecision?(sent, rcvd, check, epsilon): bool = 
      EXISTS src_set:
        correct_imprecision?(sent, rcvd, check, epsilon)(src_set) AND
        majority?(rcvd, check)(src_set)

    majority_imprecision_rw: LEMMA
       majority_imprecision?(sent, rcvd, check, epsilon) = 
       quorum_imprecision?(sent, rcvd, check, mid, epsilon)

    correct_imprecision: LEMMA
        correct_lower_inaccuracy?(sent, rcvd, check, eps_l)(src_set) AND
        correct_upper_inaccuracy?(sent, rcvd, check, eps_u)(src_set)
      IMPLIES
        correct_imprecision?(sent, rcvd, check, eps_l + eps_u)(src_set)
     
    %
      
    single_imprecision?(rcvd, check, epsilon)(src_set):bool =
      FORALL d1, d2, s:
        src_set(s) AND
        enabled(rcvd, check)(d1)(s) AND
        enabled(rcvd, check)(d2)(s) 
      IMPLIES
        abs(rcvd(d1)(s) - rcvd(d2)(s)) <= epsilon

    all_symmetric?(rcvd, check, epsilon): bool = 
      EXISTS src_set:
        single_imprecision?(rcvd, check, epsilon)(src_set) AND
        uniformly_enabled?(rcvd, check)(src_set) AND
        enabled_within?(rcvd, check)(src_set) 

    all_single_imprecision?(rcvd, check, epsilon): bool = 
      single_imprecision?(rcvd, check, epsilon)(enabled?(rcvd, check))


    % Useful intermediate result for proofs of agreement propagation and 
    % agreement convergence

    % The separation of values from good sources may be bounded.  

    diameter?(sent, delta)(src_set): bool =
      FORALL s1, s2: 
          src_set(s1) AND 
          src_set(s2) 
        IMPLIES
          abs(sent(s1) - sent(s2)) <= delta

    rcvd_diameter?(rcvd, check, delta)(src_set): bool =
      FORALL d1, d2, s1, s2:
          src_set(s1) AND enabled(rcvd, check)(d1)(s1) AND
          src_set(s2) AND enabled(rcvd, check)(d2)(s2) 
        IMPLIES
          abs((rcvd(d1)(s1) - rcvd(d2)(s2))) <= delta

    rcvd_diameter: LEMMA 
        correct_imprecision?(sent, rcvd, check, epsilon)(correct_set) AND
        diameter?(sent, delta)(src_set) AND
        enabled_within?(rcvd, check)(src_set)
      IMPLIES
        rcvd_diameter?(rcvd, check, delta + epsilon)(correct_set)

  END inexact_comm_stage


body:
  %
  %
  % Purpose: basic results for "reducing" the vector of quantities.  
  %
  %

  reduce_properties[
    N: posnat, 
    T: TYPE+, 
    <=: (total_order?[T])
  ]: THEORY

  BEGIN

    IMPORTING
      ordered_finite_sequences[T, <=],
      finite_sets@finite_sets_card_eq,
      node[N, T]

    default: VAR T
    nodes, eligible: VAR finite_set[below(N)]
    enabled:  VAR non_empty_finite_set[below(N)]
    v, v1, v2: VAR vec
    n: VAR below(N)
    i: VAR nat

    tau: VAR tau_type


    % set declarations for use in pigeonhole arguments for ordered finite sequences
    lowset(v, enabled, (i: below(card(enabled)))): finite_set[below(N)] =
      {j:below(N) | enabled(j) AND v(j) <= sort(vec2seq(v, enabled))`seq(i) }

    card_lower_leq_lowset: LEMMA
      FORALL (i: below(card(enabled))):
      card[below(card(enabled))](lower(vec2seq(v, enabled), card(enabled), i)) <=
        card[below(N)](lowset(v, enabled, i))

    card_lowset: LEMMA
      FORALL (i: below(card(enabled))):
        i+1 <= card(lowset(v, enabled, i)) 

    highset(v, enabled, (i: below(card(enabled)))): finite_set[below(N)] =
      {j:below(N) | enabled(j) AND sort(vec2seq(v, enabled))`seq(i) <= v(j)}

    card_upper_leq_highset: LEMMA
      FORALL (i: below(card(enabled))):
      card[below(card(enabled))](upper(vec2seq(v, enabled), card(enabled), i)) <=
        card[below(N)](highset(v, enabled, i))
    
    card_highset: LEMMA
      FORALL (i: below(card(enabled))):
        card(enabled) - i <= card(highset(v, enabled, i)) 

    % The function "reduce" takes a vector of values, filters out the
    % unenabled elements, sorts them, then removes the "tau" highest and 
    % "tau" lowest values.
    reduce(tau)(v, enabled): ne_seqs = 
      LET s = vec2seq(v, enabled) IN
      LET t = tau(s`length) IN 
              sort(s) ^ (t, s`length - (t + 1))

    min_reduce: LEMMA min(reduce(tau)(v, enabled)) = sort(vec2seq(v, enabled))`seq(tau(card(enabled)))

    max_reduce: LEMMA max(reduce(tau)(v, enabled)) = 
                        sort(vec2seq(v, enabled))`seq(card(enabled) - 1 - tau(card(enabled)))

    reduce_length: LEMMA reduce(tau)(v, enabled)`length = M(enabled, tau)

    reduce_rewrite: LEMMA
        i < M(enabled, tau)
      IMPLIES
        reduce(tau)(v, enabled)`seq(i) = sort(vec2seq(v, enabled))`seq(tau(card(enabled)) + i)

    reduce_overlap: LEMMA
         i < M(enabled, tau) 
      IMPLIES
        EXISTS n:
          enabled(n) AND
          v1(n) <= reduce(tau)(v1, enabled)`seq(i) AND
          reduce(tau)(v2, enabled)`seq(i) <= v2(n)

    reduce_agreement: LEMMA
        enabled_symmetric?(enabled, v1, v2)
      IMPLIES
        reduce(tau)(v1, enabled) = reduce(tau)(v2, enabled)

    % Validity results for the tau-reduced multiset
    min_validity: LEMMA
        quorum?(enabled, tau)(nodes)
      IMPLIES
        EXISTS n: nodes(n) AND enabled(n) AND v(n) <= min(reduce(tau)(v, enabled))

    max_validity: LEMMA
        quorum?(enabled, tau)(nodes)
      IMPLIES
        EXISTS n: nodes(n) AND enabled(n) AND max(reduce(tau)(v, enabled)) <= v(n)

    cf: VAR consensus_function

    % reduce_choice is a function to choose one value
    % from the sequence of values that came from reduce.
    reduce_choice(cf, eligible, v, tau, default): T =
      IF empty?[below(N)](eligible) 
        THEN default
        ELSE cf(reduce(tau)(v, eligible))
      ENDIF

    % reduce_choice2(tau, cf, default) HAS_TYPE node level choice function
    reduce_choice2(tau, cf, default)(v, eligible): T =
      IF empty?[below(N)](eligible) 
        THEN default
        ELSE cf(reduce(tau)(v, eligible))
      ENDIF

    choice_lower_validity: LEMMA
        quorum?(eligible, tau)(nodes)
      IMPLIES
        EXISTS n: nodes(n) AND eligible(n) AND 
          v(n) <= reduce_choice(cf, eligible, v, tau, default)

    choice_upper_validity: LEMMA
        quorum?(eligible, tau)(nodes)
      IMPLIES
        EXISTS n: nodes(n) AND eligible(n) AND 
          reduce_choice(cf, eligible, v, tau, default) <= v(n)

     
    choice_agreement_generation: LEMMA
        enabled_symmetric?(eligible, v1, v2)
      IMPLIES
        reduce_choice(cf, eligible, v1, tau, default) = 
          reduce_choice(cf, eligible, v2, tau, default)


  END reduce_properties

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

  % Subtype TCC generated (at line 32, column 71) for  i
      % expected type  below[sort(vec2seq(v, enabled))`length]
  lowset_TCC1: OBLIGATION
    FORALL (v: vec[N, T], enabled: non_empty_finite_set[below(N)],
            (i: below(card[below(N)](enabled))), j: below(N)):
      enabled(j) IMPLIES i < sort[T, <=](vec2seq[N, T](v, enabled))`length;

  % Subtype TCC generated (at line 36, column 58) for  card(enabled)
      % expected type  posnat
  card_lower_leq_lowset_TCC1: OBLIGATION
    FORALL (enabled: non_empty_finite_set[below(N)],
            i: below(card[below(N)](enabled))):
      card[below(N)](enabled) > 0;

  % Subtype TCC generated (at line 60, column 16) for  s`length
      % expected type  pn: posnat
  reduce_TCC1: OBLIGATION
    FORALL (v: vec[N, T], enabled: non_empty_finite_set[below(N)],
            s: ne_seqs[T]):
      s = vec2seq(v, enabled) IMPLIES s`length > 0;

  % Subtype TCC generated (at line 61, column 26) for  s`length - (t + 1)
      % expected type  nat
  reduce_TCC2: OBLIGATION
    FORALL (tau: tau_type, v: vec[N, T],
            enabled: non_empty_finite_set[below(N)], s: ne_seqs[T]):
      s = vec2seq(v, enabled) IMPLIES
       (FORALL (t: {t: nat | 2 * t < s`length}):
          t = tau(s`length) IMPLIES s`length - (t + 1) >= 0);

  % Subtype TCC generated (at line 61, column 12) for
      % sort(s) ^ (t, s`length - (t + 1))
      % expected type  ne_seqs[T]
  reduce_TCC3: OBLIGATION
    FORALL (tau: tau_type, v: vec[N, T],
            enabled: non_empty_finite_set[below(N)], s: ne_seqs[T]):
      s = vec2seq(v, enabled) IMPLIES
       (FORALL (t: {t: nat | 2 * t < s`length}):
          t = tau(s`length) IMPLIES
           length(^[T](sort[T, <=](s), (t, s`length - (t + 1)))) > 0);

  % Subtype TCC generated (at line 63, column 85) for  card(enabled)
      % expected type  pn: posnat
  min_reduce_TCC1: OBLIGATION
    FORALL (enabled: non_empty_finite_set[below(N)]):
      card[below(N)](enabled) > 0;

  % Subtype TCC generated (at line 63, column 81) for  tau(card(enabled))
      % expected type  below[sort(vec2seq(v, enabled))`length]
  min_reduce_TCC2: OBLIGATION
    FORALL (enabled: non_empty_finite_set[below(N)], tau: tau_type,
            v: vec[N, T]):
      tau(card[below(N)](enabled)) <
       sort[T, <=](vec2seq[N, T](v, enabled))`length;

  % Subtype TCC generated (at line 66, column 52) for
      % card(enabled) - 1 - tau(card(enabled))
      % expected type  below[sort(vec2seq(v, enabled))`length]
  max_reduce_TCC1: OBLIGATION
    FORALL (enabled: non_empty_finite_set[below(N)], tau: tau_type,
            v: vec[N, T]):
      card[below(N)](enabled) - 1 - tau(card[below(N)](enabled)) >= 0 AND
       card[below(N)](enabled) - 1 - tau(card[below(N)](enabled)) <
        sort[T, <=](vec2seq[N, T](v, enabled))`length;

  % Subtype TCC generated (at line 73, column 34) for  i
      % expected type  below[reduce(tau)(v, enabled)`length]
  reduce_rewrite_TCC1: OBLIGATION
    FORALL (enabled: non_empty_finite_set[below(N)], i: nat, tau: tau_type,
            v: vec[N, T]):
      i < M(enabled, tau) IMPLIES i < reduce(tau)(v, enabled)`length;

  % Subtype TCC generated (at line 73, column 69) for  tau(card(enabled)) + i
      % expected type  below[sort(vec2seq(v, enabled))`length]
  reduce_rewrite_TCC2: OBLIGATION
    FORALL (enabled: non_empty_finite_set[below(N)], i: nat, tau: tau_type,
            v: vec[N, T]):
      i < M(enabled, tau) IMPLIES
       tau(card[below(N)](enabled)) + i <
        sort[T, <=](vec2seq[N, T](v, enabled))`length;

  % Subtype TCC generated (at line 81, column 37) for  i
      % expected type  below[reduce(tau)(v2, enabled)`length]
  reduce_overlap_TCC1: OBLIGATION
    FORALL (enabled: non_empty_finite_set[below(N)], i: nat, tau: tau_type,
            v1, v2: vec[N, T]):
      i < M(enabled, tau) IMPLIES
       (FORALL (n):
          v1(n) <= reduce(tau)(v1, enabled)`seq(i) AND enabled(n) IMPLIES
           i < reduce(tau)(v2, enabled)`length);


body:
  %
  %
  % Purpose : A choice function that selects a specified element of
  %           a reduced vector when the enabled set is nonempty,
  %           and a default value otherwise.  
  %
  %

  reduce_choice[
    S: posnat,
    D: posnat,
    T: TYPE+,
    <=: (total_order?[T]),
    default: T
  ]: THEORY

    BEGIN

    IMPORTING
      fault_assumptions_stage[S, D, T],
      reduce_properties[S, T, <=]

    tau: VAR tau_type

    d, d1, d2: VAR below(D)
    s: VAR below(S)
    src_set: VAR finite_set[below(S)]

    check: VAR check_stage
    rcvd: VAR rcvd_matrix_stage

    cf: VAR consensus_function
    icf: VAR in_consensus_function

    reduce_choice(tau, cf)(rcvd, check)(d): T = 
      reduce_choice(cf, enabled(rcvd, check)(d), rcvd(d), tau, default)

  %  reduce_choice_stage: JUDGEMENT
  %     reduce_choice(tau, cf) HAS_TYPE choice_stage

    in_rcvd: LEMMA
        NOT empty?(enabled(rcvd, check)(d))
      IMPLIES
        EXISTS (s: below(S)):
          reduce_choice(tau, icf)(rcvd, check)(d) = rcvd(d)(s)

    min_reduce_choice: LEMMA
      reduce_choice(tau, min)(rcvd, check)(d) <= reduce_choice(tau, cf)(rcvd, check)(d)

    max_reduce_choice: LEMMA
      reduce_choice(tau, cf)(rcvd, check)(d) <= reduce_choice(tau, max)(rcvd, check)(d)

    reduce_overlap?(rcvd, check, tau)(src_set): bool = 
      FORALL d1, d2: 
        EXISTS s:
          src_set(s) AND
          enabled(rcvd, check)(d1)(s) AND
          enabled(rcvd, check)(d2)(s) AND
          min(reduce(tau)(rcvd(d1), enabled(rcvd, check)(d1))) <= rcvd(d1)(s) AND
          rcvd(d2)(s) <= max(reduce(tau)(rcvd(d2), enabled(rcvd, check)(d2)))

    M(rcvd, check, tau)(d): nat =
      IF empty?(enabled(rcvd, check)(d)) THEN 0
      ELSE M(enabled(rcvd, check)(d), tau)
      ENDIF

    IMPORTING finite_sets@finite_sets_minmax[nat, <=]

    max_length(rcvd, check, tau): nat =
      max(image(M(rcvd, check, tau), fullset[below(D)]))

    max_length_bound: LEMMA
      M(rcvd, check, tau)(d) <= max_length(rcvd, check, tau)

    END reduce_choice

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

  % Subtype TCC generated (at line 59, column 34) for
      % enabled(rcvd, check)(d1)
      % expected type  non_empty_finite_set[below(S)]
  reduce_overlap?_TCC1: OBLIGATION
    FORALL (rcvd: rcvd_matrix_stage[S, D, T], check: check_stage[S, D, T],
            src_set: finite_set[below(S)], d1, d2, s):
      enabled(rcvd, check)(d2)(s) AND
       enabled(rcvd, check)(d1)(s) AND src_set(s)
       IMPLIES NOT empty?[below(S)](enabled[S, D, T](rcvd, check)(d1));

  % Subtype TCC generated (at line 60, column 49) for
      % enabled(rcvd, check)(d2)
      % expected type  non_empty_finite_set[below(S)]
  reduce_overlap?_TCC2: OBLIGATION
    FORALL (rcvd: rcvd_matrix_stage[S, D, T], check: check_stage[S, D, T],
            tau: tau_type, src_set: finite_set[below(S)], d1, d2, s):
      min(reduce(tau)(rcvd(d1), enabled(rcvd, check)(d1))) <= rcvd(d1)(s) AND
       enabled(rcvd, check)(d2)(s) AND
        enabled(rcvd, check)(d1)(s) AND src_set(s)
       IMPLIES NOT empty?[below(S)](enabled[S, D, T](rcvd, check)(d2));

  % Subtype TCC generated (at line 70, column 8) for
      % image(M(rcvd, check, tau), fullset[below(D)])
      % expected type  SS: non_empty_finite_set[nat]
  max_length_TCC1: OBLIGATION
    FORALL (rcvd: rcvd_matrix_stage[S, D, T], check: check_stage[S, D, T],
            tau: tau_type):
      is_finite[nat]
          (image[below(D), nat](M(rcvd, check, tau), fullset[below(D)]))
       AND
       NOT empty?[nat]
               (image[below(D), nat](M(rcvd, check, tau), fullset[below(D)]));


body:
  %
  %
  % Purpose : the validity and agreement properties of a median select
  %           voter in the inexact communication case
  %
  %


  inexact_reduce_stage[
    S:    posnat,
    D:    posnat,
    error: real
  ]: THEORY  


    BEGIN

    IMPORTING 
      reduce_choice[S, D, real, <=, error],
      inexact_comm_stage[S, D]

    s, s1, s2: VAR below(S)
    d, d1, d2: VAR below(D)
    v: VAR real
    eps_l, eps_u, epsilon, delta: VAR nonneg_real

    sent: VAR sent_vec_stage
    rcvd: VAR rcvd_matrix_stage
    check: VAR check_stage

    src_set: VAR non_empty_finite_set[below(S)]
    dst_set: VAR non_empty_finite_set[below(D)]

    tau: VAR tau_type
    cf, cf1, cf2: VAR consensus_function
    ok?: VAR pred[ne_seqs]
    

    n, n1, n2: VAR nat
    k: VAR posnat

    reduce_lower_validity: LEMMA
        quorum_lower?(sent, rcvd, check, tau, eps_l)
      IMPLIES
        EXISTS s: enabled(rcvd, check)(d)(s) AND 
          sent(s) - eps_l <= reduce_choice(tau, cf)(rcvd, check)(d)

    reduce_upper_validity: LEMMA
        quorum_upper?(sent, rcvd, check, tau, eps_u)
      IMPLIES
        EXISTS s: enabled(rcvd, check)(d)(s) AND
          reduce_choice(tau, cf)(rcvd, check)(d) <= sent(s) + eps_u

    reduce_master_slave: COROLLARY
        quorum_accuracy?(sent, rcvd, check, tau, eps_l, eps_u) AND
        enabled_within?(rcvd, check)(src_set) AND
        diameter?(sent, delta)(src_set) AND
        src_set(s)
      IMPLIES
        abs(sent(s) - reduce_choice(tau, cf)(rcvd, check)(d)) <= delta + max(eps_l, eps_u)
   
    reduce_agreement_propagation: THEOREM
        quorum_imprecision?(sent, rcvd, check, tau, epsilon) AND
        diameter?(sent, delta)(src_set) AND
        enabled_within?(rcvd, check)(src_set)
      IMPLIES
        reduce_choice(tau, cf1)(rcvd, check)(d1) - reduce_choice(tau, cf2)(rcvd, check)(d2) <= delta + epsilon

    overlap_imprecision?(rcvd, check, tau, epsilon): bool =
      EXISTS (src_set: finite_set[below(S)]):
        reduce_overlap?(rcvd, check, tau)(src_set) AND
        single_imprecision?(rcvd, check, epsilon)(src_set)

    overlap?(rcvd, check, tau, epsilon): bool =
      FORALL d1, d2:  
        reduce_choice(tau, min)(rcvd, check)(d1) - reduce_choice(tau, max)(rcvd, check)(d2) <= epsilon

    convergence_overlap: LEMMA
        overlap_imprecision?(rcvd, check, tau, epsilon)
      IMPLIES
        overlap?(rcvd, check, tau, epsilon)

    reduce_convergence: THEOREM
        quorum_imprecision?(sent, rcvd, check, tau, epsilon) AND
        diameter?(sent, delta)(src_set) AND
        enabled_within?(rcvd, check)(src_set) AND
        overlap_imprecision?(rcvd, check, tau, epsilon) AND
        convergent?(cf, max_length(rcvd, check, tau), k)
      IMPLIES
        reduce_choice(tau, cf)(rcvd, check)(d1) 
          - reduce_choice(tau, cf)(rcvd, check)(d2) 
            <= delta * ((k - 1) / k) + epsilon

    reduce_agreement_generation: LEMMA
        all_symmetric?(rcvd, check, epsilon) AND
        inexact_consensus?(cf)
      IMPLIES
        reduce_choice(tau, cf)(rcvd, check)(d1) - reduce_choice(tau, cf)(rcvd, check)(d2) <= epsilon


    IMPORTING select_minmax[S, real, <=], select_minmax[D, real, <=]

    reduce_min_validity: LEMMA
        quorum_lower?(sent, rcvd, check, tau, eps_l) AND
        enabled_within?(rcvd, check)(src_set)
      IMPLIES
        v_min(sent, src_set) - eps_l <= v_min(reduce_choice(tau, cf)(rcvd, check), dst_set)

    reduce_max_validity: LEMMA
        quorum_upper?(sent, rcvd, check, tau, eps_u) AND
        enabled_within?(rcvd, check)(src_set)
      IMPLIES
        v_max(reduce_choice(tau, cf)(rcvd, check), dst_set) 
          <= v_max(sent, src_set) + eps_u

    minmax_diameter: LEMMA
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        diameter?(sent, delta)(src_set)

    agreement_propagation: LEMMA
        quorum_imprecision?(sent, rcvd, check, tau, epsilon) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(reduce_choice(tau, cf1)(rcvd, check), dst_set) -
        v_min(reduce_choice(tau, cf2)(rcvd, check), dst_set) <= delta + epsilon

    agreement_generation: LEMMA
        all_symmetric?(rcvd, check, epsilon) AND
        inexact_consensus?(cf)
      IMPLIES
        v_max(reduce_choice(tau, cf)(rcvd, check), dst_set) -
        v_min(reduce_choice(tau, cf)(rcvd, check), dst_set) <= epsilon

    convergence: LEMMA
        quorum_imprecision?(sent, rcvd, check, tau, epsilon) AND
        overlap_imprecision?(rcvd, check, tau, epsilon) AND
        convergent?(cf, max_length(rcvd, check, tau), k) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(reduce_choice(tau, cf)(rcvd, check), dst_set) -
          v_min(reduce_choice(tau, cf)(rcvd, check), dst_set) 
            <= delta * ((k - 1) / k) + epsilon

    END inexact_reduce_stage


body:
  %
  % Purpose : Provide overlap results for tau = |E| - floor(N'/2) - 1
  %
  weber_overlap[N: posnat, T: TYPE+, <=: (total_order?[T])]: THEORY 

    BEGIN

    IMPORTING
     reduce_properties[N, T, <=]

    src_set: VAR finite_set[below(N)]
    e, e1, e2 : var non_empty_finite_set[below(N)]
    v1, v2  : var [below(N) -> T]
    k: var below(N)

    tau(src_set): tau_type = weber(card(src_set))

    weber_overlap: LEMMA
        subset?(e1, src_set) AND
        subset?(e2, src_set) AND
        intersection_majority?(e1, e2, src_set)
      IMPLIES
        EXISTS k:
          src_set(k) AND
          e1(k) AND
          e2(k) AND
          min(reduce(tau(src_set))(v1, e1)) <= v1(k) AND
          v2(k) <= max(reduce(tau(src_set))(v2, e2))

    END weber_overlap


body:
  weber_stage 
  [
    S:    posnat,
    D:    posnat,
    error: real
  ]: THEORY  


    BEGIN

    IMPORTING 
      weber_overlap[S, real, <=],
      inexact_reduce_stage[S, D, error]

    d1, d2: VAR below(D)
    epsilon, delta: VAR nonneg_real
    cf: VAR consensus_function
    X: VAR posnat

    sent: VAR sent_vec_stage
    rcvd: VAR rcvd_matrix_stage
    check: VAR check_stage

    src_set: VAR non_empty_finite_set[below(S)]
    dst_set: VAR non_empty_finite_set[below(D)]

    overlap_imprecision: LEMMA
        enabled_within?(rcvd, check)(src_set) AND
        intersection_majority?(rcvd, check)(src_set) AND 
        single_imprecision?(rcvd, check, epsilon)(src_set)
      IMPLIES
        overlap_imprecision?(rcvd, check, tau(src_set), epsilon)

    weber_convergence: THEOREM
        quorum_imprecision?(sent, rcvd, check, tau(src_set), epsilon) AND
        intersection_majority?(rcvd, check)(src_set) AND 
        single_imprecision?(rcvd, check, epsilon)(src_set) AND
        convergent?(cf, max_length(rcvd, check, tau(src_set)), X) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(reduce_choice(tau(src_set), cf)(rcvd, check), dst_set) -
          v_min(reduce_choice(tau(src_set), cf)(rcvd, check), dst_set) 
            <= delta * ((X - 1) / X) + epsilon

    weber_mean_convergence: COROLLARY
        X = max_length(rcvd, check, tau(src_set)) AND
        quorum_imprecision?(sent, rcvd, check, tau(src_set), epsilon) AND
        intersection_majority?(rcvd, check)(src_set) AND 
        single_imprecision?(rcvd, check, epsilon)(src_set) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(reduce_choice(tau(src_set), mean)(rcvd, check), dst_set) -
          v_min(reduce_choice(tau(src_set), mean)(rcvd, check), dst_set) 
            <= delta * ((X - 1) / X) + epsilon

    weber_midpoint_convergence: COROLLARY
        quorum_imprecision?(sent, rcvd, check, tau(src_set), epsilon) AND
        intersection_majority?(rcvd, check)(src_set) AND 
        single_imprecision?(rcvd, check, epsilon)(src_set) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(reduce_choice(tau(src_set), midpoint)(rcvd, check), dst_set) -
          v_min(reduce_choice(tau(src_set), midpoint)(rcvd, check), dst_set) 
            <= delta / 2 + epsilon

    END weber_stage


body:
  pigeonhole_int: THEORY

    BEGIN

    IMPORTING
      pigeonhole[int]

    x, y, z : var int
    nat_set: TYPE = {N: finite_set[int] | FORALL (x:int): N(x) => x >= 0}
    negint_set: TYPE = {N : finite_set[int] |FORALL (x:int): N(x) => x < 0}

    A, B, C, 
    S, S1, S2: VAR nat_set

    X, Y, Z: VAR finite_set[int]

    A_bar: VAR negint_set

    disjoint1: LEMMA
      disjoint?(A, A_bar)

    disjoint2: LEMMA
      disjoint?(A_bar, A)

    complement(z): int = 0 - (1 + z)

    complement_complement: LEMMA
      complement(complement(z)) = z

    mirror(X): finite_set[int] = image(complement)(X)

    mirror_mirror: LEMMA
      mirror(mirror(X)) = X

    card_mirror: LEMMA
      card(mirror(X)) = card(X)

    subset_mirror: LEMMA
        subset?(X, Y)
      IMPLIES
        subset?(mirror(X), mirror(Y))

    mirror_nat: JUDGEMENT mirror(A) HAS_TYPE negint_set
    mirror_negint: JUDGEMENT mirror(A_bar) HAS_TYPE nat_set

    split(X, Y): finite_set[int] = 
      union(intersection(X, Y), mirror(difference(X, Y)))

    subset_split: LEMMA
        subset?(X, Y)
      IMPLIES
        subset?(split(X, Z), split(Y, Z))

    card_split: LEMMA
      card(split(A, C)) = card(A)

    two_thirds_split: LEMMA
        two_thirds_majority_subset?(A, S)
      IMPLIES
        two_thirds_majority_subset?(split(A, C), split(S, C))   
     
    two_thirds_overlap_lem: LEMMA
        two_thirds_majority_subset?(A, S1) AND
        two_thirds_majority_subset?(split(B, C), split(S2, C)) AND
        intersection_majority?(S1, split(S2, C))
      IMPLIES
        EXISTS x: A(x) AND B(x) AND C(x)
     

    fta_overlap_pigeonhole: LEMMA
        two_thirds_majority_subset?(A, S1) AND
        two_thirds_majority_subset?(B, S2) AND
        byzantine_intersection_majority?(S1, S2, C)
      IMPLIES
        EXISTS x: A(x) AND B(x) AND C(x)
     
    END pigeonhole_int

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

  % Subtype TCC generated (at line 30, column 31) for  image(complement)(X)
      % expected type  finite_set[int]
  mirror_TCC1: OBLIGATION
    FORALL (X: finite_set[int]):
      is_finite[int](image[int, int](complement)(X));

  % Judgement subtype TCC generated (at line 43, column 24) for  mirror(A)
      % expected type  negint_set
  mirror_nat: OBLIGATION FORALL (A, x: int): mirror(A)(x) => x < 0;

  % Judgement subtype TCC generated (at line 44, column 27) for  mirror(A_bar)
      % expected type  nat_set
  mirror_negint: OBLIGATION
    FORALL (A_bar, x: int): mirror(A_bar)(x) => x >= 0;


body:
  middle_third_pigeonhole[N: posnat]: THEORY

    BEGIN

    IMPORTING
      pigeonhole_int, pigeonhole[below(N)]

    A, B, C, S1, S2: VAR finite_set[below(N)]
    x: VAR below(N)

    middle_third_pigeonhole: LEMMA
        two_thirds_majority_subset?(A, S1) AND
        two_thirds_majority_subset?(B, S2) AND
        byzantine_intersection_majority?(S1, S2, C)
      IMPLIES
        EXISTS x: A(x) AND B(x) AND C(x)

    END middle_third_pigeonhole


body:
  %
  % Purpose      : Provide overlap results for tau(E) = floor(|E|/3)
  %
  middle_third_overlap[N: posnat, T: TYPE+, <=: (total_order?[T])]: THEORY

    BEGIN
    
    IMPORTING
      reduce_properties[N, T, <=],
      middle_third_pigeonhole[N]


    src_set: var finite_set[below(N)] % subsets of indices
    e1, e2 : var non_empty_finite_set[below(N)]
    v1, v2  : var [below(N) -> T]

    k: var below(N)

    middle_third_overlap: LEMMA
         byzantine_intersection_majority?(e1, e2, src_set)
      IMPLIES
        EXISTS k: 
          src_set(k) AND
          e1(k) AND 
          e2(k) AND 
          min(reduce(byz)(v1, e1)) <= v1(k) AND 
          v2(k) <= max(reduce(byz)(v2, e2))

    END middle_third_overlap


body:
  middle_third_stage[
    S:    posnat,
    D:    posnat,
    error: real
  ]: THEORY  


    BEGIN

    IMPORTING 
      inexact_reduce_stage[S, D, error],
      middle_third_overlap[S, real, <=]

    d1, d2: VAR below(D)
    epsilon, delta: VAR nonneg_real
    cf: VAR consensus_function
    X: VAR posnat

    sent: VAR sent_vec_stage
    rcvd: VAR rcvd_matrix_stage
    check: VAR check_stage

    src_set: VAR non_empty_finite_set[below(S)]
    dst_set: VAR non_empty_finite_set[below(D)]

    byz_overlap_imprecision?(rcvd, check, epsilon): bool = 
      EXISTS (src_set: finite_set[below(S)]):
        byzantine_intersection_majority?(rcvd, check)(src_set) AND 
        single_imprecision?(rcvd, check, epsilon)(src_set)

    byzantine_overlap: LEMMA
        byz_overlap_imprecision?(rcvd, check, epsilon)
      IMPLIES
        overlap_imprecision?(rcvd, check, byz, epsilon)

    middle_third_convergence: LEMMA
        quorum_imprecision?(sent, rcvd, check, byz, epsilon) AND
        byz_overlap_imprecision?(rcvd, check, epsilon) AND
        convergent?(cf, max_length(rcvd, check, byz), X) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(reduce_choice(byz, cf)(rcvd, check), dst_set) -
          v_min(reduce_choice(byz, cf)(rcvd, check), dst_set) 
            <= delta * ((X - 1) / X) + epsilon

    mean_convergence: COROLLARY
        X = max_length(rcvd, check, byz) AND
        quorum_imprecision?(sent, rcvd, check, byz, epsilon) AND
        byz_overlap_imprecision?(rcvd, check, epsilon) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(reduce_choice(byz, mean)(rcvd, check), dst_set) -
          v_min(reduce_choice(byz, mean)(rcvd, check), dst_set) 
            <= delta * ((X - 1) / X) + epsilon

    midpoint_convergence: COROLLARY
        quorum_imprecision?(sent, rcvd, check, byz, epsilon) AND
        byz_overlap_imprecision?(rcvd, check, epsilon) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(reduce_choice(byz, midpoint)(rcvd, check), dst_set) -
          v_min(reduce_choice(byz, midpoint)(rcvd, check), dst_set) 
            <= delta / 2 + epsilon

    END middle_third_stage


body:
  median_overlap[N: posnat, T: TYPE+, <=: (total_order?[T])]: THEORY

  BEGIN
    
    IMPORTING 
      reduce_properties[N, T, <=]

    e1, e2: VAR non_empty_finite_set[below(N)]
    v1, v2: VAR vec %[below(N) -> T]

    k: VAR below(N)

    median_overlap: LEMMA 
        card(union(e1, e2)) - card(intersection(e1, e2)) <= 1
      IMPLIES
        EXISTS k: 
          e1(k) AND 
          e2(k) AND 
          min(reduce(mid)(v1, e1)) <= v1(k) AND 
          v2(k) <= max(reduce(mid)(v2, e2))

  END median_overlap


body:
  median_stage[
    S:    posnat,
    D:    posnat,
    error: real
  ]: THEORY  


    BEGIN

    IMPORTING 
      inexact_reduce_stage[S, D, error],
      median_overlap[S, real, <=]

    d, d1, d2: VAR below(D)
    epsilon, delta: VAR nonneg_real

    sent: VAR sent_vec_stage
    rcvd: VAR rcvd_matrix_stage
    check: VAR check_stage

    src_set: VAR non_empty_finite_set[below(S)]
    dst_set: VAR non_empty_finite_set[below(D)]

    median: choice_stage = reduce_choice(mid, midpoint)
      
    one_asymmetric_ommission?(rcvd, check): bool = 
      FORALL d1, d2:
        card[below(S)](union(enabled(rcvd, check)(d1), enabled(rcvd, check)(d2))) -
          card[below(S)](intersection(enabled(rcvd, check)(d1), enabled(rcvd, check)(d2))) <= 1

    one_asymmetric_overlap: LEMMA
        enabled_nonempty?(rcvd, check) AND
        one_asymmetric_ommission?(rcvd, check) AND
        all_single_imprecision?(rcvd, check, epsilon)
      IMPLIES
        overlap_imprecision?(rcvd, check, mid, epsilon)

    median_convergence: THEOREM 
        quorum_imprecision?(sent, rcvd, check, mid, epsilon) AND
        one_asymmetric_ommission?(rcvd, check) AND
        all_single_imprecision?(rcvd, check, epsilon) AND
        enabled_within?(rcvd, check)(src_set) AND
        v_max(sent, src_set) - v_min(sent, src_set) <= delta
      IMPLIES
        v_max(median(rcvd, check), dst_set) - v_min(median(rcvd, check), dst_set) <= (delta / 2) + epsilon

    END median_stage


body:
  convergence_top: THEORY

  BEGIN

    IMPORTING 
      median_stage,
      middle_third_stage,
      weber_stage

  END convergence_top


body:
  %
  %
  % Purpose : types for the functions that operate in a node
  %
  %

  node_functions
  [
      N   : [nat -> posnat],  % Number of source nodes at each stage
      T   : TYPE+
  ]: THEORY

  BEGIN

    i: VAR nat

    IMPORTING node_functions_stage

    choice_function:  TYPE = [i:nat -> choice_stage[N(i), N(i+1), T]]
    choice_system:    TYPE = [i:nat -> choice_stage_alt[N(i), N(i+1), T]]
    check_function:   TYPE = [i:nat -> check_stage[N(i), N(i+1), T]]
    check_system:     TYPE = [i:nat -> check_stage_alt[N(i), N(i+1), T]]
    compute_function: TYPE = [i:nat -> compute_stage[N(i), T]]

    sent_vec: TYPE = [i:nat -> sent_vec_stage[N(i), N(i+1), T]]
    rcvd_matrix: TYPE = [i:nat -> rcvd_matrix_stage[N(i), N(i+1), T]]


    filter_system: TYPE = [i:nat -> filter_stage[N(i),N(i+1),T]]

    nominal_filter(i): filter_stage[N(i), N(i+1), T] = nominal_filter[N(i),N(i+1),T]


  END node_functions


body:
  %
  %
  % Purpose : choice functions with ordered values (exact or
  %           inexact); definition of a middle value voter; definition
  %           of min and max (as compute functions).
  %
  %

  k_ordered
  [
      N   : [nat -> posnat],  % Number of source nodes at each stage
      T   : TYPE+,
      <=  : (total_order?[T]),              
      error: [nat -> T]
  ]: THEORY

    BEGIN

    IMPORTING
      reduce_choice,
      node_functions[N, T],
      select_minmax

    j: VAR nat
    node_set: VAR [j : nat -> non_empty_finite_set[below(N(j))]] 
    sent:  VAR sent_vec 
    local: VAR sent_vec 

    v_min(sent, node_set)(j) : T = v_min[N(j), T, <=](sent(j), node_set(j))
    v_max(sent, node_set)(j) : T = v_max[N(j), T, <=](sent(j), node_set(j))


    k_consensus_function: TYPE = [j:nat -> consensus_function[T,<=]]
    cf: VAR k_consensus_function
    tau: VAR [j:nat -> tau_type]

    reduce_choice(tau, cf): choice_function = 
      LAMBDA j: reduce_choice[N(j), N(j+1), T, <=, error(j)](tau(j), cf(j))


  END k_ordered


body:
  %
  %
  % Purpose : Build the messages that a destination sends, given
  %           the messages it receives.
  %
  %

  protocol  
  [
      N   : [nat -> posnat],  % Number of source nodes at each stage
      T   : TYPE+
  ]: THEORY

  BEGIN

    i, j, k: VAR nat

    IMPORTING node_functions[N, T]

    sent:   VAR sent_vec
    rcvd:   VAR rcvd_matrix

    check:  VAR check_function
    choice: VAR choice_function
    compute:VAR compute_function

    %
    % Models of protocol for stages j..k
    %

    % no computation after the choice
    protocol(choice, sent, rcvd, check, j, k) : bool = 
      FORALL i : j <= i AND i < k IMPLIES
        sent(i + 1) = choice(i)(rcvd(i), check(i))

    % arbitrary compute function after choice.  The function can
    % be different in each stage and different for each node
    % in the stage.  This means that the function can be based
    % on information that is local only to the node.
    protocol(compute, choice, sent, rcvd, check, j, k) : bool = 
      FORALL i : j <= i AND i < k IMPLIES 
        sent(i + 1) = compute(i+1)(choice(i)(rcvd(i), check(i)))



  %  identity: compute_function = LAMBDA j: id[vec[N(j), T]]

  %  identity_compute_same: LEMMA
  %    protocol(identity, choice, sent, rcvd, check, j, k) 
  %      IFF protocol(choice, sent, rcvd, check, j, k)


    %
    % Models of protocol for stages 0..k
    %


    % no computation after the choice
    protocol(sent, rcvd, check, choice, k) : bool = 
      FORALL i : i < k IMPLIES
        sent(i + 1) = choice(i)(rcvd(i), check(i))

    % arbitrary compute function after choice.  The function can
    % be different in each stage and different for each node
    % in the stage.  This means that the function can be based
    % on information that is local only to the node.
  %  protocol(sent, rcvd, check, choice, compute, k) : bool = 
  %    FORALL i : i < k IMPLIES 
  %      sent(i + 1) = compute(i+1)(choice(i)(rcvd(i), check(i)))

    % correspondence results
    protocol_rw: LEMMA
      protocol(sent, rcvd, check, choice, k) 
        = protocol(choice, sent, rcvd, check, 0, k) 

  %  protocol_compute_rw: LEMMA
  %    protocol(sent, rcvd, check, choice, compute, k) 
  %      = protocol(compute, choice, sent, rcvd, check, 0, k) 

  END protocol


body:
  %
  % Purpose: properties of inexact communication through 
  %          multiple-stages
  %
  %

  inexact_comm
  [
      N   : [nat -> posnat]
  ] : THEORY

    BEGIN

    IMPORTING
      node_functions[N, real],
      inexact_comm_stage

    i, j, k: VAR nat

    sources: VAR [j : nat -> finite_set[below(N(j))]] 

    sent:  VAR sent_vec
    rcvd:  VAR rcvd_matrix
    check: VAR check_function
    epsilon: VAR [nat -> nonneg_real]
    tau: VAR [i: nat -> tau_type]
    cf: VAR [nat -> consensus_function]


    %
    % Abstracted fault assumptions
    %

    % same predicate is in exact_comm
    enabled_within?(rcvd, check, j, k)(sources): bool = 
      FORALL i : j <= i AND i < k IMPLIES
        enabled_within?[N(i), N(i + 1), real](rcvd(i), check(i))(sources(i))
    
    % (simple) majority

    majority_lower?(sent, rcvd, check, epsilon, j, k): bool =
      FORALL i : j <= i AND i < k IMPLIES
        majority_lower?[N(i), N(i + 1)](sent(i), rcvd(i), check(i), epsilon(i))

    majority_upper?(sent, rcvd, check, epsilon, j, k): bool =
      FORALL i : j <= i AND i < k IMPLIES
        majority_upper?[N(i), N(i + 1)](sent(i), rcvd(i), check(i), epsilon(i))

    majority_imprecision?(sent, rcvd, check, epsilon, j, k): bool =
      FORALL i : j <= i AND i < k IMPLIES
        majority_imprecision?[N(i), N(i + 1)](sent(i), rcvd(i), check(i), epsilon(i))

    exists_all_symmetric?(sent, rcvd, check, epsilon, cf, j, k): bool =
      EXISTS i: j <= i AND i < k AND
        inexact_consensus?(cf(i)) AND
        all_symmetric?(rcvd(i), check(i), epsilon(i)) AND
        majority_imprecision?(sent, rcvd, check, epsilon, i + 1, k)

    % quorum, a generalized majority (from simple to consensus to unamimous)

    quorum_lower?(sent, rcvd, check, tau, epsilon, j, k): bool =
      FORALL i : j <= i AND i < k IMPLIES
        quorum_lower?[N(i), N(i + 1)](sent(i), rcvd(i), check(i), tau(i), epsilon(i))

    quorum_upper?(sent, rcvd, check, tau, epsilon, j, k): bool =
      FORALL i : j <= i AND i < k IMPLIES
        quorum_upper?[N(i), N(i + 1)](sent(i), rcvd(i), check(i), tau(i), epsilon(i))

    quorum_imprecision?(sent, rcvd, check, tau, epsilon, j, k): bool =
      FORALL i : j <= i AND i < k IMPLIES
        quorum_imprecision?[N(i), N(i + 1)](sent(i), rcvd(i), check(i), tau(i), epsilon(i))

    exists_all_symmetric?(sent, rcvd, check, tau, epsilon, cf, j, k): bool =
      EXISTS i: j <= i AND i < k AND
        inexact_consensus?(cf(i)) AND
        all_symmetric?(rcvd(i), check(i), epsilon(i)) AND
        quorum_imprecision?(sent, rcvd, check, tau, epsilon, i + 1, k)


  END inexact_comm


body:
  %
  %
  % Purpose : validity and agreement properties for a multi-stage inexact 
  %           exchange with the results-based fault model.
  %
  %


  inexact_reduce
  [
      N   : [nat -> posnat],  
      error: [nat -> real]
  ] : THEORY

    BEGIN

    IMPORTING
      inexact_comm[N],
      protocol[N, real],
      k_ordered[N, real, <=, error],
      inexact_reduce_stage,
      reals@sigma_nat

    i, j, k: VAR nat
    v: VAR real

    sent:  VAR sent_vec
    rcvd:  VAR rcvd_matrix
    check: VAR check_function

    epsilon, eps_u, eps_l, eps: VAR [nat -> nonneg_real]
    delta : VAR nonneg_real

    node_set: VAR [i: nat -> non_empty_finite_set[below(N(i))]] 

    tau: VAR [j: nat -> tau_type]
    idx: VAR [nat -> nat]
    cf: VAR k_consensus_function


  % Main results
    lower_validity: THEOREM
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        quorum_lower?(sent, rcvd, check, tau, eps_l, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set)
      IMPLIES
        v_min(sent, node_set)(j) - sigma(j, j + k - 1, eps_l) <= v_min(sent, node_set)(j + k)

    upper_validity: THEOREM
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        quorum_upper?(sent, rcvd, check, tau, eps_u, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set)
      IMPLIES
        v_max(sent, node_set)(j + k) <= v_max(sent, node_set)(j) + sigma(j, j + k - 1, eps_u)

    agreement_propagation: THEOREM
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        quorum_imprecision?(sent, rcvd, check, tau, epsilon, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set) AND
        v_max(sent, node_set)(j) - v_min(sent, node_set)(j) <= delta
      IMPLIES
        v_max(sent, node_set)(j + k) - v_min(sent, node_set)(j + k) 
          <= delta + sigma(j, j + k - 1, epsilon)

    X: VAR posnat

    convergent_stage?(rcvd, check, tau, epsilon, cf, X, j, k): bool = 
      EXISTS i: j <= i AND i < k AND
        overlap_imprecision?[N(i), N(i + 1), error(i)](rcvd(i), check(i), tau(i), epsilon(i)) AND
        convergent?(cf(i), max_length[N(i), N(i + 1), real, <=, error(i)](rcvd(i), check(i), tau(i)), X)

    convergence: THEOREM
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        quorum_imprecision?(sent, rcvd, check, tau, epsilon, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set) AND
        convergent_stage?(rcvd, check, tau, epsilon, cf, X, j, j + k) AND
        v_max(sent, node_set)(j) - v_min(sent, node_set)(j) <= delta
      IMPLIES
        v_max(sent, node_set)(j + k) - v_min(sent, node_set)(j + k) 
          <= delta * ((X - 1) / X) + sigma(j, j + k - 1, epsilon)

    agreement_generation: THEOREM
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        exists_all_symmetric?(sent, rcvd, check, tau, epsilon, cf, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set)
      IMPLIES
        v_max(sent, node_set)(j + k) - v_min(sent, node_set)(j + k) <= sigma(j, j + k - 1, epsilon)

  END inexact_reduce

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

  % Subtype TCC generated (at line 47, column 39) for  j
      % expected type  T_low[nat]
  lower_validity_TCC1: OBLIGATION
    FORALL (cf: k_consensus_function[N, real, <=, error],
            check: check_function[N, real], eps_l: [nat -> nonneg_real],
            j, k: nat,
            node_set: [i: nat -> non_empty_finite_set[below(N(i))]],
            rcvd: rcvd_matrix[N, real], sent: sent_vec[N, real],
            tau: [j: nat -> tau_type]):
      enabled_within?(rcvd, check, j, j + k)(node_set) AND
       quorum_lower?(sent, rcvd, check, tau, eps_l, j, j + k) AND
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k)
       IMPLIES j >= 0 OR (EXISTS (j_1: nat): j_1 <= j);

  % Subtype TCC generated (at line 47, column 42) for  j + k - 1
      % expected type  T_high[nat]
  lower_validity_TCC2: OBLIGATION
    FORALL (cf: k_consensus_function[N, real, <=, error],
            check: check_function[N, real], eps_l: [nat -> nonneg_real],
            j, k: nat,
            node_set: [i: nat -> non_empty_finite_set[below(N(i))]],
            rcvd: rcvd_matrix[N, real], sent: sent_vec[N, real],
            tau: [j: nat -> tau_type]):
      enabled_within?(rcvd, check, j, j + k)(node_set) AND
       quorum_lower?(sent, rcvd, check, tau, eps_l, j, j + k) AND
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k)
       IMPLIES j + k - 1 >= 0 OR (EXISTS (j_1: nat): j + k - 1 <= j_1);

  % Subtype TCC generated (at line 54, column 71) for  j
      % expected type  T_low[nat]
  upper_validity_TCC1: OBLIGATION
    FORALL (cf: k_consensus_function[N, real, <=, error],
            check: check_function[N, real], eps_u: [nat -> nonneg_real],
            j, k: nat,
            node_set: [i: nat -> non_empty_finite_set[below(N(i))]],
            rcvd: rcvd_matrix[N, real], sent: sent_vec[N, real],
            tau: [j: nat -> tau_type]):
      enabled_within?(rcvd, check, j, j + k)(node_set) AND
       quorum_upper?(sent, rcvd, check, tau, eps_u, j, j + k) AND
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k)
       IMPLIES j >= 0 OR (EXISTS (j_1: nat): j_1 <= j);

  % Subtype TCC generated (at line 54, column 74) for  j + k - 1
      % expected type  T_high[nat]
  upper_validity_TCC2: OBLIGATION
    FORALL (cf: k_consensus_function[N, real, <=, error],
            check: check_function[N, real], eps_u: [nat -> nonneg_real],
            j, k: nat,
            node_set: [i: nat -> non_empty_finite_set[below(N(i))]],
            rcvd: rcvd_matrix[N, real], sent: sent_vec[N, real],
            tau: [j: nat -> tau_type]):
      enabled_within?(rcvd, check, j, j + k)(node_set) AND
       quorum_upper?(sent, rcvd, check, tau, eps_u, j, j + k) AND
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k)
       IMPLIES j + k - 1 >= 0 OR (EXISTS (j_1: nat): j + k - 1 <= j_1);

  % Subtype TCC generated (at line 63, column 25) for  j
      % expected type  T_low[nat]
  agreement_propagation_TCC1: OBLIGATION
    FORALL (cf: k_consensus_function[N, real, <=, error],
            check: check_function[N, real], delta: nonneg_real,
            epsilon: [nat -> nonneg_real], j, k: nat,
            node_set: [i: nat -> non_empty_finite_set[below(N(i))]],
            rcvd: rcvd_matrix[N, real], sent: sent_vec[N, real],
            tau: [j: nat -> tau_type]):
      v_max(sent, node_set)(j) - v_min(sent, node_set)(j) <= delta AND
       enabled_within?(rcvd, check, j, j + k)(node_set) AND
        quorum_imprecision?(sent, rcvd, check, tau, epsilon, j, j + k) AND
         protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k)
       IMPLIES j >= 0 OR (EXISTS (j_1: nat): j_1 <= j);

  % Subtype TCC generated (at line 63, column 28) for  j + k - 1
      % expected type  T_high[nat]
  agreement_propagation_TCC2: OBLIGATION
    FORALL (cf: k_consensus_function[N, real, <=, error],
            check: check_function[N, real], delta: nonneg_real,
            epsilon: [nat -> nonneg_real], j, k: nat,
            node_set: [i: nat -> non_empty_finite_set[below(N(i))]],
            rcvd: rcvd_matrix[N, real], sent: sent_vec[N, real],
            tau: [j: nat -> tau_type]):
      v_max(sent, node_set)(j) - v_min(sent, node_set)(j) <= delta AND
       enabled_within?(rcvd, check, j, j + k)(node_set) AND
        quorum_imprecision?(sent, rcvd, check, tau, epsilon, j, j + k) AND
         protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k)
       IMPLIES j + k - 1 >= 0 OR (EXISTS (j_1: nat): j + k - 1 <= j_1);

  % Subtype TCC generated (at line 87, column 75) for  j
      % expected type  T_low[nat]
  agreement_generation_TCC1: OBLIGATION
    FORALL (cf: k_consensus_function[N, real, <=, error],
            check: check_function[N, real], epsilon: [nat -> nonneg_real],
            j, k: nat,
            node_set: [i: nat -> non_empty_finite_set[below(N(i))]],
            rcvd: rcvd_matrix[N, real], sent: sent_vec[N, real],
            tau: [j: nat -> tau_type]):
      enabled_within?(rcvd, check, j, j + k)(node_set) AND
       exists_all_symmetric?(sent, rcvd, check, tau, epsilon, cf, j, j + k)
        AND protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k)
       IMPLIES j >= 0 OR (EXISTS (j_1: nat): j_1 <= j);

  % Subtype TCC generated (at line 87, column 78) for  j + k - 1
      % expected type  T_high[nat]
  agreement_generation_TCC2: OBLIGATION
    FORALL (cf: k_consensus_function[N, real, <=, error],
            check: check_function[N, real], epsilon: [nat -> nonneg_real],
            j, k: nat,
            node_set: [i: nat -> non_empty_finite_set[below(N(i))]],
            rcvd: rcvd_matrix[N, real], sent: sent_vec[N, real],
            tau: [j: nat -> tau_type]):
      enabled_within?(rcvd, check, j, j + k)(node_set) AND
       exists_all_symmetric?(sent, rcvd, check, tau, epsilon, cf, j, j + k)
        AND protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k)
       IMPLIES j + k - 1 >= 0 OR (EXISTS (j_1: nat): j + k - 1 <= j_1);


body:
  %
  %
  % Purpose : integration fault model with mapping to the 
  %           results-based fault model.
  %
  %

  integration_fault_model[N:posnat]: THEORY

    BEGIN
    IMPORTING 
       finite_sets_below_extra[N]

    p : VAR below(N)

    % the fault types for the integration fault model
    fault_class: TYPE =
      {good,                     
       omissive_symmetric,       
       omissive_asymmetric,
       transmissive_symmetric, 
       single_error_asymmetric,
       transmissive_asymmetric}

    fcl : var fault_class

    correct_denotation?(fcl) : bool =
      good?(fcl) OR omissive_symmetric?(fcl) OR omissive_asymmetric?(fcl)

    symmetric_denotation?(fcl) : bool = 
      good?(fcl) OR omissive_symmetric?(fcl) OR transmissive_symmetric?(fcl)

    single_denotation?(fcl) : bool =    
      NOT transmissive_asymmetric?(fcl)


    node_status: TYPE = [below(N) -> fault_class]

    status: VAR node_status

    good(status) : finite_set[below(N)] = {p | good?(status(p))}
    omissive_symmetric(status) : finite_set[below(N)] =
      {p | omissive_symmetric?(status(p))}
    omissive_asymmetric(status) : finite_set[below(N)] =
      {p | omissive_asymmetric?(status(p))}
    transmissive_symmetric(status)   : finite_set[below(N)] =
      {p | transmissive_symmetric?(status(p))}
    single_error_asymmetric(status)  : finite_set[below(N)] =
      {p | single_error_asymmetric?(status(p))}
    transmissive_asymmetric(status)  : finite_set[below(N)] =
      {p | transmissive_asymmetric?(status(p))}

    correct_denotation(status) : finite_set[below(N)] = 
       {p | correct_denotation?(status(p))}
    symmetric_denotation(status): finite_set[below(N)] = 
       {p | symmetric_denotation?(status(p))}
    single_denotation(status): finite_set[below(N)] = 
       {p | single_denotation?(status(p))}


    symmetric_single_denotation: LEMMA
      subset?(symmetric_denotation(status), single_denotation(status))


  END integration_fault_model

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

  fault_class_ord_defaxiom: AXIOM
         fault_class_ord(good) = 0 AND fault_class_ord(omissive_symmetric) = 1
     AND fault_class_ord(omissive_asymmetric) = 2
     AND fault_class_ord(transmissive_symmetric) = 3
     AND fault_class_ord(single_error_asymmetric) = 4
     AND fault_class_ord(transmissive_asymmetric) = 5;

  fault_class_inclusive: AXIOM
    FORALL (fault_class_var: fault_class):
          good?(fault_class_var) OR omissive_symmetric?(fault_class_var)
       OR omissive_asymmetric?(fault_class_var)
       OR transmissive_symmetric?(fault_class_var)
       OR single_error_asymmetric?(fault_class_var)
       OR transmissive_asymmetric?(fault_class_var);

  fault_class_induction: AXIOM
    FORALL (p: [fault_class -> boolean]):
           p(good) AND p(omissive_symmetric) AND p(omissive_asymmetric)
       AND p(transmissive_symmetric) AND p(single_error_asymmetric)
       AND p(transmissive_asymmetric)
       IMPLIES (FORALL (fault_class_var: fault_class): p(fault_class_var));

  fault_class_well_founded: AXIOM strict_well_founded?[fault_class](<<);

  fault_class: TYPE

  good?: [fault_class -> boolean]

  omissive_symmetric?: [fault_class -> boolean]

  omissive_asymmetric?: [fault_class -> boolean]

  transmissive_symmetric?: [fault_class -> boolean]

  single_error_asymmetric?: [fault_class -> boolean]

  transmissive_asymmetric?: [fault_class -> boolean]

  fault_class_ord: [fault_class -> upto(5)]

  ord(x: fault_class): [fault_class -> upto(5)] =
      CASES x
        OF good: 0,
           omissive_symmetric: 1,
           omissive_asymmetric: 2,
           transmissive_symmetric: 3,
           single_error_asymmetric: 4,
           transmissive_asymmetric: 5
        ENDCASES

  subterm(x: fault_class, y: fault_class):  boolean = x = y;

  good: (good?)

  omissive_symmetric: (omissive_symmetric?)

  omissive_asymmetric: (omissive_asymmetric?)

  transmissive_symmetric: (transmissive_symmetric?)

  single_error_asymmetric: (single_error_asymmetric?)

  transmissive_asymmetric: (transmissive_asymmetric?)

  <<:  (strict_well_founded?[fault_class]) =
      LAMBDA (x, y: fault_class): FALSE;


body:
  %
  %
  % Purpose : This theory introduces error terms for various
  %           sources of temporal imprecision in a communication
  %           network.  It assumes that a pair of communicating
  %           nodes have a common clock frequency, but are driven
  %           by independent oscillators.  One contributor to the
  %           imprecision is due to the discretization of a
  %           realtime event that can only be observed at discrete
  %           intervals (i.e. on an edge of the destination
  %           clock). The bound on this error is at least one tick
  %           (as measured by the destination's clock).  An event that
  %           happens immediately after a destination clock edge will
  %           not be recorded until the following edge. Another
  %           (small) contributor to imprecision is the relative
  %           drift rate of the two clocks.  At this level of
  %           granularity, the relative drift may safely be
  %           neglected (it will be overwhelmed by clock
  %           jitter). However, we include it for completeness.
  %           Finally, this theory addresses imprecision due to
  %           differences in wire lengths.  If a single source
  %           sends to two different destinations, the difference in
  %           time of observation may be affected by the different
  %           communication delays.  
  %
  %

  timing_imprecision
  [
     rho     : nonneg_real, % Bound on drift for a good oscillator
     min_latency   : nonneg_real, % minimum real time latency (in ticks
                            % of real time) of the communication link
                            % determined by things like length of wire, speed
                            % of light, and clock rate.
     var_latency: nonneg_real
                            % Max variation (in ticks of real 
                            % time) caused by both wire length 
                            % differences and clock jitter.  
  ]: THEORY

    BEGIN

    IMPORTING inverse_clocks[rho]

    y: VAR nonneg_real
    skew: VAR nonneg_real

    ev, ev1, ev2, ev1r, ev2r: VAR real  % the real time this event occurs
    c, c1, c2: VAR good_clock 

    T : VAR integer

    epsilon: posreal = 1 + rho + var_latency 
    max_latency: posreal   = min_latency + epsilon
    mid_latency: posreal   = min_latency + epsilon / 2 % = (min_latency + max_latency) / 2

    mid_latency_ge_one_half :LEMMA mid_latency >= 1 / 2 % for W tccs

    % W is the expected Clocktime latency for a point to point communication.
    W: posint =
      IF fractional(mid_latency) < 1 / 2 THEN floor(mid_latency) ELSE ceiling(mid_latency) ENDIF

    % Results for tcc proofs
    drift_relation_alt: LEMMA y / rate <= y AND y <= y * rate
    W_bound:         LEMMA min_latency < W        AND W <= max_latency 
    W_bound_alt:     LEMMA min_latency < W * rate AND W / rate <= max_latency

    % 
    % Terms denoting imprecision in the communication link
    %
    epsilon_l: posreal = W * rate - min_latency
    epsilon_u: nnreal  = max_latency - W / rate
    max_error: posreal = max(epsilon_l, epsilon_u)

    epsilon_relation: LEMMA epsilon_l + epsilon_u = epsilon + drift * W


    %
    % The timestamp of event ev as observed by a process governed by
    % good_clock c is the earliest marked Clocktime after the event.
    % A timestamp can be thought of as the earliest clock time that 
    % the event can be recognized.
    %

    Timestamp(c,ev): integer = C(c)(ev) + 1

    event_observation_error: LEMMA
       ev < c(Timestamp(c, ev)) AND c(Timestamp(c, ev)) <= ev + 1 + rho

    % the possible range of reception times of a message 'ev' from a good source.
    good_range(ev): set[real] =
      {t: real | ev + min_latency <= t & t <= ev + min_latency + var_latency}


    % Temporal validity for a message from a good source
    link_lower_range: LEMMA
        good_range(c1(T - W))(ev2)
      IMPLIES
        c1(T) - epsilon_l <= c2(Timestamp(c2, ev2))

    link_upper_range: LEMMA
        good_range(c1(T - W))(ev2)
      IMPLIES
        c2(Timestamp(c2, ev2)) <= c1(T) + epsilon_u

    link_abs_bound: LEMMA
        good_range(c1(T - W))(ev2)
      IMPLIES
        abs(c2(Timestamp(c2, ev2)) - c1(T)) <= max_error


    % the transmission delay difference caused by differences in wire lengths
    % is bounded by epsilon. This is the basis of agreement propagation.
    link_relative_range: LEMMA
        good_range(ev1)(ev1r) AND
        good_range(ev2)(ev2r)
      IMPLIES  
        abs(c1(Timestamp(c1, ev1r)) - c2(Timestamp(c2, ev2r)) - ev1 + ev2) <= epsilon

    link_relative_symmetry: COROLLARY
        good_range(ev)(ev1) AND
        good_range(ev)(ev2) 
      IMPLIES
        abs(c1(Timestamp(c1, ev1)) - c2(Timestamp(c2, ev2))) <= epsilon
      

    % Two events that are in the good range of the same event differ by
    % at most "var_latency".
    good_range_bounded: LEMMA
        good_range(ev)(ev1) AND
        good_range(ev)(ev2) 
      IMPLIES
        abs(ev1 - ev2) <= var_latency

    link_symmetry: LEMMA
        abs(ev1 - ev2) <= var_latency 
      IMPLIES
        abs(c1(Timestamp(c1, ev1)) - c2(Timestamp(c2, ev2))) <= epsilon

  END timing_imprecision

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

  % Subtype TCC generated (at line 61, column 44) for  floor(mid_latency)
      % expected type  posint
  W_TCC1: OBLIGATION
    fractional(mid_latency) < 1 / 2 IMPLIES floor(mid_latency) > 0;

  % Subtype TCC generated (at line 61, column 68) for  ceiling(mid_latency)
      % expected type  posint
  W_TCC2: OBLIGATION
    NOT fractional(mid_latency) < 1 / 2 IMPLIES ceiling(mid_latency) > 0;

  % Subtype TCC generated (at line 71, column 23) for  W * rate - min_latency
      % expected type  posreal
  epsilon_l_TCC1: OBLIGATION
    W * rate[rho] - min_latency >= 0 AND W * rate[rho] - min_latency > 0;

  % Subtype TCC generated (at line 72, column 23) for  max_latency - W / rate
      % expected type  nnreal
  epsilon_u_TCC1: OBLIGATION max_latency - W / rate[rho] >= 0;

  % Subtype TCC generated (at line 73, column 23) for
      % max(epsilon_l, epsilon_u)
      % expected type  posreal
  max_error_TCC1: OBLIGATION max(epsilon_l, epsilon_u) > 0;


body:
  %
  %
  % Purpose : properties of a check in the time domain.  A check
  %   in the time domain can be considered as answering the 
  %   question does an event fall within a timing window.
  %                
  %
  %

  timing_window[
     rho     : nonneg_real, % Bound on drift for a good oscillator
     min_latency   : nonneg_real, % minimum real time latency (in ticks
                            % of real time) of the communication link
                            % determined by things like length of wire, speed
                            % of light, and clock rate.
     var_latency: nonneg_real
                            % Max variation (in ticks of real 
                            % time) caused by both wire length 
                            % differences and clock jitter.  
  ]: THEORY

  BEGIN

    IMPORTING timing_imprecision[rho, min_latency, var_latency]

    skew: VAR nonneg_real
    ev, ev1, ev2: VAR real
    c, c1, c2: VAR good_clock 
    T : VAR integer

    Delta_max(skew): nat = floor(rate * (skew + max_error))

    % The Timestamped event ev at the destination falls within the
    % reception window for time T of destination clock c.
    timing_conforms?(c, T, skew)(ev): bool = 
      c(T - Delta_max(skew)) <= ev & ev <= c(T + Delta_max(skew))

    % The timing check can also be expressed as a property on
    % Clocktimes. This is the basis for its implementation.
    timing_conforms_def: LEMMA
        timing_conforms?(c, T, skew)(c(Timestamp(c, ev)))
      IFF
        abs(Timestamp(c, ev) - T) <= Delta_max(skew)

    inner_window?(c, T, skew)(ev): bool = 
      timing_conforms?(c, T, skew)(c(Timestamp(c, ev)))

    outer_window?(c, T, skew)(ev): bool =
      NOT timing_conforms?(c, T, skew)(c(Timestamp(c, ev)))

    good_range_always_conforms: LEMMA
        good_range(c1(T - W))(ev) AND
        abs(c1(T) - c2(T)) <= skew 
      IMPLIES
        timing_conforms?(c2, T, skew)(c2(Timestamp(c2, ev)))

    good_range_inner_window: LEMMA
        good_range(c1(T - W))(ev) AND
        abs(c1(T) - c2(T)) <= skew 
      IMPLIES
        inner_window?(c2, T, skew)(ev)


  END timing_window


body:
  %
  %
  % Purpose: Models the temporal correlation of send and receive
  %          events (aka communication) under the integration (hybrid) 
  %          fault model and the message filter in the time domain.
  %
  %

  timing_integration_stage
  [
     rho     : nonneg_real, % Bound on drift for a good oscillator
     min_latency   : nonneg_real, % Minimum real time latency (in ticks
                            % of real time) of the communication link
                            % determined by things like length of wire, speed
                            % of light, and clock rate.
     var_latency: nonneg_real, % Max variation (in ticks of real 
                            % time) caused by both wire length 
                            % differences and clock jitter.  
     S   : posnat,          % Number of sending nodes
     D   : posnat           % Number of destination nodes
  ] : THEORY

    BEGIN

    IMPORTING
      timing_window[rho, min_latency, var_latency],
      integration_fault_model[S],
      inexact_comm_stage[S, D],
      finite_sets@finite_sets_minmax[real, <=],
      finite_sets@finite_sets_below[D]

    s, s1, s2: VAR below(S)
    d, d1, d2: VAR below(D)
    status:    VAR node_status[S]

    tau: VAR tau_type

    check: VAR check_stage

    common_check: VAR finite_set[below(S)] % who is supposed to send
   
    T:  VAR integer
    ev: VAR real
    pi: VAR nonneg_real

    c_src: VAR [below(S) -> good_clock]
    c_dst: VAR [below(D) -> good_clock]

    t_of(c_dst, T)(d): real = c_dst(d)(T)

    t_min(c_dst, T): real = min(image(t_of(c_dst, T),fullset[below(D)]))

    c: VAR good_clock
    f: VAR [below(D) -> real]


    uniformly_good_range?(c, T)(f): bool =
      FORALL d: good_range(c(T-W))(f(d))

    uniformly_inner_window?(c_dst, T, pi)(f): bool =
      FORALL d: inner_window?(c_dst(d), T, pi)(f(d))

    uniformly_outer_window?(c_dst, T, pi)(f): bool =
      FORALL d: outer_window?(c_dst(d), T, pi)(f(d))

    uniformly_outer_exists: LEMMA
      EXISTS f: uniformly_outer_window?(c_dst, T, pi)(f)

    single_denotation_timing?(c_dst, T, pi)(f): bool =
      FORALL d1, d2: 
          inner_window?(c_dst(d1), T, pi)(f(d1)) AND
          inner_window?(c_dst(d2), T, pi)(f(d2))
        IMPLIES
          abs(f(d1) - f(d2)) <= var_latency

    symmetric_timing_conforms?(c_dst, T, pi)(f): bool =
      FORALL d1, d2:
        inner_window?(c_dst(d1), T, pi)(f(d1))
      IMPLIES
        inner_window?(c_dst(d2), T, pi)(f(d2))

    symmetric_timing_uniform: LEMMA
        symmetric_timing_conforms?(c_dst, T, pi)(f)
      IFF
        (uniformly_inner_window?(c_dst, T, pi)(f) OR
         uniformly_outer_window?(c_dst, T, pi)(f))

    uniformly_outer_single_denotation: LEMMA
        uniformly_outer_window?(c_dst, T, pi)(f)
      IMPLIES
        single_denotation_timing?(c_dst, T, pi)(f)
    
    % The message of good source s sent at Clocktime T-W is received in the
    % interval [c_src(s)(T-W) + min_latency, c_src(s)(T-W) + min_latency + var_latency].
    good_send(c_src, T, s)(d): (good_range(c_src(s)(T-W)))

    % The message of a ommissive symmetric source is either received like 
    % that of a good source by all destinations or falls in the outer 
    % window of all destinations.
    osym_send(c_src, c_dst, T, pi, s):
      (union(uniformly_good_range?(c_src(s), T),
             uniformly_outer_window?(c_dst, T, pi)))

    % The message of an omissive asymmetric source may either be received
    % like that of a good source or may fall in the outer window.
    oasym_send(c_src, c_dst, T, pi, s, d):
      (union(good_range(c_src(s)(T-W)), outer_window?(c_dst(d), T, pi)))

    % Reception of the message of a transmissive symmetric source is constrained
    % only as follows:
    % 1) the message falls in the inner window of all recipients or it
    % falls in the outside window of all recipients;
    % 2) if they fall in the inner window, the messages differ at most by
    % "var_latency".

    tsym_send(c_dst, T, pi, s) : 
      (union(intersection(uniformly_inner_window?(c_dst, T, pi),
                          single_denotation_timing?(c_dst, T, pi)),
             uniformly_outer_window?(c_dst, T, pi)))

    sv_send(c_dst, T, pi, s) : (single_denotation_timing?(c_dst, T, pi))

    tsym_single_denotation: LEMMA
      single_denotation_timing?(c_dst, T, pi)(tsym_send(c_dst, T, pi, s))

    % An asymmetrically faulty source may generate an unrestricted, potentially
    % distinct event at each destination.
    tasym_send(c_dst, T, pi, s, d): real

    % The time the message is received which was sent by source s at Clocktime
    % T-W.
    % This includes corruption by the given fault of the source, and the
    % uncertain delay caused by the wire and clock jitter.
    send(c_src, c_dst, T, pi, status)(d)(s): real =
      CASES status(s) OF 
        good                     : good_send(c_src, T, s)(d),
        omissive_symmetric       : osym_send(c_src, c_dst, T, pi, s)(d),
        omissive_asymmetric      : oasym_send(c_src, c_dst, T, pi, s, d),
        transmissive_symmetric   : tsym_send(c_dst, T, pi, s)(d),
        single_error_asymmetric  : sv_send(c_dst, T, pi, s)(d),
        transmissive_asymmetric  : tasym_send(c_dst, T, pi, s, d) 
      ENDCASES

    % Source and destination clocks have bounded skew. This implicitly assumes
    % that all sources have good clocks. The clock events of bad sources are
    % not observable through the network.
    clock_relation?(T, c_src, c_dst, pi): bool = 
      FORALL s, d: abs(c_src(s)(T) - c_dst(d)(T)) <= pi

    % the event of timestamping the received message happens within the
    % reception window around clocktime T of the destination clock,
    % and the source passes both the local_check and common_check.
    check(c_dst, T, common_check, pi)(d)(s)(ev): bool =
      timing_conforms?(c_dst(d), T, pi)(ev) AND common_check(s)


    sent(c_src, T)(s): real = c_src(s)(T-W)
    nominal(c_src, T)(s): real = c_src(s)(T)

    % the Timestamped reception of the message sent by the source at time T-W
    received(c_dst, c_src, T, status, pi)(d)(s): real =
      c_dst(d)(Timestamp(c_dst(d), send(c_src, c_dst, T, pi, status)(d)(s)))

    received_clock_edge: LEMMA
      clock_edge?(c_dst(d), received(c_dst, c_src, T, status, pi)(d)(s))

    enabled_within_stage: LEMMA
      enabled_within?(
        received(c_dst, c_src, T, status, pi),
        check(c_dst, T, common_check, pi))
          (common_check)

    % The message sent by a correct_denotation s at Clocktime T-W is received either
    % in the good range or in the outer window.
    correct_denotation_send: LEMMA
        correct_denotation?(status(s))
      IMPLIES
        good_range(c_src(s)(T-W))(send(c_src, c_dst, T, pi, status)(d)(s)) OR
        outer_window?(c_dst(d), T, pi)(send(c_src, c_dst, T, pi, status)(d)(s))

    % The message sent by a correct_denotation s at Clocktime T-W, if it conforms,
    % is received in the good range.
    conforming_correct_denotation_send: LEMMA
        clock_relation?(T, c_src, c_dst, pi) AND
        correct_denotation(status)(s) AND
        enabled(received(c_dst, c_src, T, status, pi), 
                check(c_dst, T, common_check, pi))(d)(s)
      IMPLIES
        good_range(c_src(s)(T-W))(send(c_src, c_dst, T, pi, status)(d)(s))

    single_denotation_send: LEMMA
        single_denotation?(status(s)) AND
        clock_relation?(T, c_src, c_dst, pi)
      IMPLIES
        single_denotation_timing?(c_dst, T, pi)(transpose(send(c_src, c_dst, T, pi, status))(s))

    symmetric_send: COROLLARY
        symmetric_denotation?(status(s)) AND
        clock_relation?(T, c_src, c_dst, pi)
      IMPLIES
        single_denotation_timing?(c_dst, T, pi)(transpose(send(c_src, c_dst, T, pi, status))(s))

    symmetric_timing_conforms: LEMMA
        symmetric_denotation?(status(s)) AND
        clock_relation?(T, c_src, c_dst, pi)
      IMPLIES
        symmetric_timing_conforms?(c_dst, T, pi)(transpose(send(c_src, c_dst, T, pi, status))(s))


    % "received" satisfies the inexact comm properties wrt. "sent" and
    % "nominal".

    correct_lower_timing: LEMMA
        clock_relation?(T, c_src, c_dst, pi)
      IMPLIES
        correct_lower_inaccuracy?(
          nominal(c_src, T),
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, common_check, pi),
          epsilon_l)
            (correct_denotation(status))

    correct_quorum_lower: LEMMA
         clock_relation?(T, c_src, c_dst, pi) AND
         quorum?(received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi), tau)
             (correct_denotation(status))
       IMPLIES
         quorum_lower?(        
           nominal(c_src, T),
           received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi),
           tau,
           epsilon_l)

    correct_majority_lower: LEMMA
         clock_relation?(T, c_src, c_dst, pi) AND
         majority?(received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi))
             (correct_denotation(status))
       IMPLIES
         majority_lower?(        
           nominal(c_src, T),
           received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi),
           epsilon_l)


    correct_upper_timing: LEMMA
        clock_relation?(T, c_src, c_dst, pi)
      IMPLIES
        correct_upper_inaccuracy?(
          nominal(c_src, T),
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, common_check, pi),
          epsilon_u)
            (correct_denotation(status))

    correct_majority_upper: LEMMA
         clock_relation?(T, c_src, c_dst, pi) AND
         majority?(received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi))
             (correct_denotation(status))
       IMPLIES
         majority_upper?(        
           nominal(c_src, T),
           received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi),
           epsilon_u)

    correct_quorum_upper: LEMMA
         clock_relation?(T, c_src, c_dst, pi) AND
         quorum?(received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi), tau)
             (correct_denotation(status))
       IMPLIES
         quorum_upper?(        
           nominal(c_src, T),
           received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi),
           tau,
           epsilon_u)

    correct_accuracy_timing: LEMMA
         clock_relation?(T, c_src, c_dst, pi) AND
         majority?(received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi))
             (correct_denotation(status))
       IMPLIES
         majority_accuracy?(        
           nominal(c_src, T),
           received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi),
           epsilon_l,
           epsilon_u)

    correct_imprecision_timing: LEMMA
        clock_relation?(T, c_src, c_dst, pi) 
      IMPLIES
        correct_imprecision?(
          sent(c_src, T),
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, common_check, pi), 
          epsilon)
            (correct_denotation(status)) 

    quorum_imprecision: LEMMA
         clock_relation?(T, c_src, c_dst, pi) AND
         quorum?(received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi), tau)
             (correct_denotation(status))
       IMPLIES
         quorum_imprecision?(        
           sent(c_src, T),
           received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi),
           tau,
           epsilon)

    majority_imprecision: LEMMA
         clock_relation?(T, c_src, c_dst, pi) AND
         majority?(received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi))
             (correct_denotation(status))
       IMPLIES
         majority_imprecision?(        
           sent(c_src, T),
           received(c_dst, c_src, T, status, pi),
           check(c_dst, T, common_check, pi),
           epsilon)

    % the Timestamped received message of a symmetric source is either
    % conforming at all destinations and the received events vary by at most
    % "var_latency", or it is non-conforming at all destinations.

    single_imprecision_timing: LEMMA
        clock_relation?(T, c_src, c_dst, pi) 
      IMPLIES
        single_imprecision?(
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, common_check, pi),
          epsilon)
            (single_denotation(status))

    uniformly_enabled: LEMMA
        clock_relation?(T, c_src, c_dst, pi) 
      IMPLIES
        uniformly_enabled?(
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, common_check, pi))
            (symmetric_denotation(status))

    symmetric_imprecision_timing: LEMMA
        clock_relation?(T, c_src, c_dst, pi) 
      IMPLIES
        single_imprecision?(
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, common_check, pi),
          epsilon)
            (symmetric_denotation(status))

  %  enabled_symmetric?(c_src, c_dst, T, common_check, status, pi)

    all_symmetric_timing: LEMMA
        clock_relation?(T, c_src, c_dst, pi) AND
        enabled_within?(
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, common_check, pi))
           (symmetric_denotation(status))
      IMPLIES
        all_symmetric?(
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, common_check, pi), 
          epsilon)
      

    % Synchronization fault assumptions
    majority_synch?(status, c_src, c_dst, T, common_check, pi): bool =
      majority?(
        received(c_dst, c_src, T, status, pi),
        check(c_dst, T, common_check, pi)
         )(correct_denotation(status))

    quorum_synch?(status, c_src, c_dst, T, common_check, tau, pi): bool =
      quorum?(
        received(c_dst, c_src, T, status, pi),
        check(c_dst, T, common_check, pi),
        tau
         )(correct_denotation(status))

    all_symmetric_synch?(status, c_src, c_dst, T, common_check, pi): bool =
      enabled_within?(
        received(c_dst, c_src, T, status, pi),
        check(c_dst, T, common_check, pi))(symmetric_denotation(status)) AND
      enabled_nonempty?(
        received(c_dst, c_src, T, status, pi),         
        check(c_dst, T, common_check, pi))



  END timing_integration_stage

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

  % Subtype TCC generated (at line 51, column 30) for
      % image(t_of(c_dst, T), fullset[below(D)])
      % expected type  SS: non_empty_finite_set[real]
  t_min_TCC1: OBLIGATION
    FORALL (c_dst: [below(D) -> good_clock[rho]], T: integer):
      is_finite[real]
          (image[below(D), real](t_of(c_dst, T), fullset[below(D)]))
       AND
       NOT empty?[real]
               (image[below(D), real](t_of(c_dst, T), fullset[below(D)]));

  % Existence TCC generated (at line 95, column 2) for
      % good_send(c_src, T, s)(d): (good_range(c_src(s)(T - W)))
  good_send_TCC1: OBLIGATION
    EXISTS (x:
              [d1: [[below(S) -> good_clock[rho]], integer, below(S)] ->
                 [below(D) ->
                    (good_range[rho, min_latency, var_latency]
                         (d1`1
                              (d1`3)
                              (d1`2 - W[rho, min_latency, var_latency])))]]):
      TRUE;

  % Existence TCC generated (at line 100, column 2) for
      % osym_send(c_src, c_dst, T, pi, s):
      %       (union(uniformly_good_range?(c_src(s), T),
      %              uniformly_outer_window?(c_dst, T, pi)))
  osym_send_TCC1: OBLIGATION
    EXISTS (x:
              [d:
                 [[below(S) -> good_clock[rho]],
                  [below(D) -> good_clock[rho]], integer, nonneg_real,
                  below(S)] ->
                 (union[[below(D) -> real]]
                      (uniformly_good_range?(d`1(d`5), d`3),
                       uniformly_outer_window?(d`2, d`3, d`4)))]):
      TRUE;

  % Existence TCC generated (at line 106, column 2) for
      % oasym_send(c_src, c_dst, T, pi, s, d):
      %       (union(good_range(c_src(s)(T - W)),
      %              outer_window?(c_dst(d), T, pi)))
  oasym_send_TCC1: OBLIGATION
    EXISTS (x:
              [d1:
                 [[below(S) -> good_clock[rho]],
                  [below(D) -> good_clock[rho]], integer, nonneg_real,
                  below(S), below(D)] ->
                 (union[real]
                      (good_range[rho, min_latency, var_latency]
                           (d1`1
                                (d1`5)
                                (d1`3 - W[rho, min_latency, var_latency])),
                       outer_window?[rho, min_latency, var_latency]
                           (d1`2(d1`6), d1`3, d1`4)))]):
      TRUE;

  % Existence TCC generated (at line 116, column 2) for
      % tsym_send(c_dst, T, pi, s):
      %       (union(intersection(uniformly_inner_window?(c_dst, T, pi),
      %                           single_denotation_timing?(c_dst, T, pi)),
      %              uniformly_outer_window?(c_dst, T, pi)))
  tsym_send_TCC1: OBLIGATION
    EXISTS (x:
              [d:
                 [[below(D) -> good_clock[rho]], integer, nonneg_real,
                  below(S)] ->
                 (union[[below(D) -> real]]
                      (intersection[[below(D) -> real]]
                           (uniformly_inner_window?(d`1, d`2, d`3),
                            single_denotation_timing?(d`1, d`2, d`3)),
                       uniformly_outer_window?(d`1, d`2, d`3)))]):
      TRUE;

  % Existence TCC generated (at line 121, column 2) for
      % sv_send(c_dst, T, pi, s): (single_denotation_timing?(c_dst, T, pi))
  sv_send_TCC1: OBLIGATION
    EXISTS (x:
              [d:
                 [[below(D) -> good_clock[rho]], integer, nonneg_real,
                  below(S)] ->
                 (single_denotation_timing?(d`1, d`2, d`3))]):
      TRUE;


body:
  %
  %
  % Purpose : Results to derive relationships between clocks,
  %           especially to show that two clocks share the same oscillator.
  %
  %

  clock_shift[ rho:nonneg_real, N: posnat]: THEORY

    BEGIN

    IMPORTING inverse_clocks[rho]

    c, c1, c2: VAR [below(N) -> good_clock]
    T, T1, T2: VAR integer
    X: VAR nat

    n, n1, n2: VAR below(N)
    
    local_event, le1, le2: VAR [below(N) -> real]

    all_clock_edge?(c, local_event): bool = FORALL n: clock_edge?(c(n), local_event(n))

    offset(c, T)(local_event)(n): real = offset(c(n), T)(local_event(n))

    same_edges?(c1, c2): bool = FORALL n: offset_clocks?(c1(n), c2(n))

    offset_left_edge: LEMMA
        clock_edge?(c(n), local_event(n)) AND
        0 <= T 
      IMPLIES
        T / rate <= offset(c, T)(local_event)(n) - local_event(n)

    offset_left: LEMMA
        X / rate < offset(c, X)(local_event)(n) - local_event(n) + rate

    offset_right_edge: LEMMA
        clock_edge?(c(n), local_event(n)) AND
        0 <= T 
      IMPLIES
        offset(c, T)(local_event)(n) - local_event(n) <= rate * T

    offset_right: LEMMA
         offset(c, X)(local_event)(n) - local_event(n) <= rate * X

    offset_zero: LEMMA
        all_clock_edge?(c, local_event)
      IMPLIES
        offset(c, 0)(local_event) = local_event

    offset_drift: LEMMA
        offset(c, X)(local_event)(n2) - offset(c, X)(local_event)(n1)
          < local_event(n2) - local_event(n1) + drift * X + rate

    offset_nondecreasing: LEMMA
      le1(n) <= le2(n) IMPLIES offset(c, T)(le1)(n) <= offset(c, T)(le2)(n)

    offset_drift_edge: LEMMA
        clock_edge?(c(n1), le1(n1)) AND
        clock_edge?(c(n2), le2(n2)) 
      IMPLIES
        offset(c, X)(le2)(n2) - offset(c, X)(le1)(n1)
          <= le2(n2) - le1(n1) + drift * X

    double_offset: LEMMA
      offset(c, T1)(offset(c, T2)(local_event)) = offset(c, T1 + T2)(local_event)

    offset_same: LEMMA
        same_edges?(c1, c2)
      IMPLIES
        (offset(c1, T1 + T2)(le1) = offset(c2, T1 + T2)(le2) IFF offset(c1, T2)(le1) = offset(c2, T2)(le2))

    offset_same2: LEMMA
        same_edges?(c1, c2) AND
        all_clock_edge?(c1, le1) AND
        all_clock_edge?(c2, le2)
      IMPLIES
        (offset(c1, T1)(le1) = offset(c2, T1)(le2) IFF le1 = le2)

    END clock_shift


body:
  %
  %
  % Purpose : a choice function for a single stage inexact communication
  %           specifically adapted for synchronization properties
  %
  %

  reduce_synch_stage 
  [
     rho     : nonneg_real, % Bound on drift for a good oscillator
     min_latency   : nonneg_real, % Minimum real time latency (in ticks
                            % of real time) of the communication link
                            % determined by things like length of wire, speed
                            % of light, and clock rate.
     var_latency: nonneg_real, % Max variation (in ticks of real 
                            % time) caused by both wire length 
                            % differences and clock jitter.  
     S   : posnat,          % Number of sending nodes
     D   : posnat           % Number of destination nodes
  ]: THEORY


    BEGIN
      IMPORTING
        clock_shift[rho, D],
        timing_integration_stage[rho, min_latency, var_latency, S, D], 
        inexact_reduce_stage[S, D, 0]

    s, s1, s2: VAR below(S)
    d, d1, d2: VAR below(D)
    c_src: VAR [below(S) -> good_clock]
    c_dst: VAR [below(D) -> good_clock]
    status:    VAR node_status[S]

    src_set: VAR non_empty_finite_set[below[S]] % who is supposed to send
    dst_set: VAR non_empty_finite_set[below(D)]

    T : VAR integer
    N, N1, N2 : VAR nat
    delta, pi: VAR nonneg_real

    t_at : VAR [below(D) -> real]
   
    tau: VAR tau_type
    cf: VAR consensus_function
    icf: VAR in_consensus_function



    synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi)(d): real =
      offset(c_dst, N)(reduce_choice(tau, cf)(
                        received(c_dst, c_src, T, status, pi),
                        check(c_dst, T, src_set, pi)))(d)

    synch_stage_offset: LEMMA
      synch_stage(status, c_src, c_dst, T, N1 + N2, src_set, tau, cf, pi)
        = offset(c_dst, N1)(synch_stage(status, c_src, c_dst, T, N2, src_set, tau, cf, pi))


    lower_synch_validity: LEMMA
        quorum_synch?(status, c_src, c_dst, T, src_set, tau, pi) AND
        clock_relation?(T, c_src, c_dst, pi)
      IMPLIES
        v_min(nominal(c_src, T), src_set) + N/rate - epsilon_l
        <= v_min(synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi), dst_set)
    
    upper_synch_validity: LEMMA
        quorum_synch?(status, c_src, c_dst, T, src_set, tau, pi) AND
        clock_relation?(T, c_src, c_dst, pi)
      IMPLIES
        v_max(synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi), dst_set)
          <= v_max(nominal(c_src, T), src_set) + epsilon_u + N * rate

    synch_master_slave: COROLLARY
        quorum_synch?(status, c_src, c_dst, T, src_set, tau, pi) AND
        clock_relation?(T, c_src, c_dst, pi) AND
        v_max(nominal(c_src, T), src_set) -
          v_min(nominal(c_src, T), src_set) <= delta AND
        src_set(s) AND
        dst_set(d)
      IMPLIES
        abs(nominal(c_src, T)(s) - synch_stage(status, c_src, c_dst, T, 0, src_set, tau, cf, pi)(d)) 
                 <= delta + max(epsilon_l, epsilon_u)

    synch_agreement_propagation: LEMMA
        quorum_synch?(status, c_src, c_dst, T, src_set, tau, pi) AND
        clock_relation?(T, c_src, c_dst, pi) AND
        v_max(sent(c_src, T), src_set) -
          v_min(sent(c_src, T), src_set) <= delta
      IMPLIES
        v_max(synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi), dst_set)
          - v_min(synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi), dst_set)
         <= delta + epsilon + drift * N

    overlap_synch?(status, c_src, c_dst, T, src_set, tau, pi): bool = 
      reduce_overlap?(
        received(c_dst, c_src, T, status, pi),
        check(c_dst, T, src_set, pi), tau)
       (single_denotation(status))

    overlap_imprecision: LEMMA
        clock_relation?(T, c_src, c_dst, pi) AND
        overlap_synch?(status, c_src, c_dst, T, src_set, tau, pi)
      IMPLIES
        overlap_imprecision?(      
          received(c_dst, c_src, T, status, pi),
          check(c_dst, T, src_set, pi), 
          tau, epsilon)

    max_length(status, c_src, c_dst, T, src_set, tau, pi): nat =
      max_length(received(c_dst, c_src, T, status, pi), check(c_dst, T, src_set, pi), tau)

    k: VAR posnat

    synch_convergence: LEMMA
        quorum_synch?(status, c_src, c_dst, T, src_set, tau, pi) AND
        clock_relation?(T, c_src, c_dst, pi) AND
        overlap_synch?(status, c_src, c_dst, T, src_set, tau, pi) AND
        convergent?(cf, max_length(status, c_src, c_dst, T, src_set, tau, pi), k) AND
        v_max(sent(c_src, T), src_set) -
          v_min(sent(c_src, T), src_set) <= delta
      IMPLIES
        v_max(synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi), dst_set)
          - v_min(synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi), dst_set)
        <= delta * ((k - 1) / k) + epsilon + drift * N + rate

    synch_agreement_generation: LEMMA
        all_symmetric_synch?(status, c_src, c_dst, T, src_set, pi) AND
        clock_relation?(T, c_src, c_dst, pi) AND
        inexact_consensus?(cf)
      IMPLIES
        v_max(synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi), dst_set)
          - v_min(synch_stage(status, c_src, c_dst, T, N, src_set, tau, cf, pi), dst_set)
         <= epsilon + drift * N + rate

    synch_agreement_generation_edge: LEMMA
        all_symmetric_synch?(status, c_src, c_dst, T, src_set, pi) AND
        clock_relation?(T, c_src, c_dst, pi) AND
        inexact_consensus?(icf)
      IMPLIES
        v_max(synch_stage(status, c_src, c_dst, T, N, src_set, tau, icf, pi), dst_set)
          - v_min(synch_stage(status, c_src, c_dst, T, N, src_set, tau, icf, pi), dst_set)
         <= epsilon + drift * N

   
    END reduce_synch_stage


body:
  %
  %
  % Purpose : timing aspects of communication with a multi-stage integration
  %           fault model. 
  %    
  %           Proofs that the explicit broadcast timing model satisfies the 
  %           inexact sampling properties, provided that the source and 
  %           destination clocks are within a known precision "pi"
  %
  %


  timing_integration
  [
    rho: nonneg_real,      % Bound on drift for a good oscillator
    min_latency: [nat -> nonneg_real], 
                           % Minimum real time latency (in ticks
                           % of real time) of the communication link
                           % between stage i and i+1
                           % determined by things like length of wire, speed
                           % of light, and clock rate.
    var_latency: [nat -> nonneg_real], 
                           % Max variation (in ticks of real 
                           % time) between stage i and i+1
                           % caused by both wire length 
                           % differences and clock jitter.  
    stage: [nat -> posnat] % Number of nodes in a given stage
  ] : THEORY

    BEGIN


    IMPORTING
      timing_integration_stage,
      inexact_comm[stage]

    i, j, k: VAR nat

    clk, c_src, c_dst: VAR [j:nat -> [below(stage(j)) -> good_clock[rho]]]
    Schedule: VAR [nat -> integer] % The nominal message send time for the given stage
    pi: VAR [nat -> nonneg_real]
    cf: VAR [nat -> consensus_function]
    tau: VAR [nat -> tau_type]

    status: VAR [j:nat -> node_status[stage(j)]]
    common_check: VAR [j:nat -> non_empty_finite_set[below(stage(j))]]
    sent: VAR [j:nat -> [below(stage(j)) -> real]]

    received(c_dst, c_src, Schedule, status, pi)(i): 
      [below(stage(i+1)) -> [below(stage(i)) -> real]] =
      received[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
        (c_dst(i+1), c_src(i), Schedule(i), status(i), pi(i))

    check(c_dst, Schedule, common_check, pi)(i):
      [below(stage(i+1)) -> [below(stage(i)) -> [real -> bool]]] =
      check[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
        (c_dst(i+1), Schedule(i), common_check(i), pi(i))

    correct_denotation(status)(j): finite_set[below(stage(j))] = correct_denotation(status(j))
    symmetric_denotation(status)(j): finite_set[below(stage(j))] = symmetric_denotation(status(j))
    single_denotation(status)(j): finite_set[below(stage(j))] = single_denotation(status(j))

    sent(c_src, Schedule)(i): [below(stage(i)) -> real] = 
      sent[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)](c_src(i), Schedule(i))
    nominal(c_src, Schedule)(i): [below(stage(i)) -> real] = 
      nominal[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)](c_src(i), Schedule(i))


    % The clocks of stage i, are within pi of the clocks in stage i+1, for all i
    clock_relation?(Schedule, c_src, c_dst, pi, j, k): bool = 
      FORALL i: j <= i AND i < k IMPLIES
        clock_relation?[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
                  (Schedule(i), c_src(i), c_dst(i+1), pi(i))

    epsilon_lower(i):nonneg_real = epsilon_l[rho,min_latency(i),var_latency(i)]
    epsilon_upper(i):nonneg_real = epsilon_u[rho,min_latency(i),var_latency(i)]
    epsilon_total(i):nonneg_real = epsilon[rho,min_latency(i),var_latency(i)]

    enabled_within_timing: LEMMA
      enabled_within?(
        received(c_dst, c_src, Schedule, status, pi), 
        check(c_dst, Schedule, common_check, pi), j, k)(common_check)

    % Synchronization fault assumptions
    majority_synch?(status, c_src, c_dst, Schedule, common_check, pi, j, k): bool =
      FORALL i: j <= i AND i < k IMPLIES
        majority_synch?[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
          (status(i), c_src(i), c_dst(i + 1), Schedule(i), common_check(i), pi(i))

    quorum_synch?(status, c_src, c_dst, Schedule, common_check, tau, pi, j, k): bool =
      FORALL i: j <= i AND i < k IMPLIES
        quorum_synch?[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
          (status(i), c_src(i), c_dst(i + 1), Schedule(i), common_check(i), tau(i), pi(i))

    exists_symmetric_synch_stage?(status, c_src, c_dst, Schedule, common_check, pi, cf, j, k): bool =
      EXISTS i: j <= i AND i < k AND
        all_symmetric_synch?[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
          (status(i), c_src(i), c_dst(i + 1), Schedule(i), common_check(i), pi(i)) AND
        inexact_consensus?(cf(i)) AND
        majority_synch?(status, c_src, c_dst, Schedule, common_check, pi, i + 1, k)

    exists_symmetric_synch_stage?(status, c_src, c_dst, Schedule, common_check, tau, pi, cf, j, k): bool =
      EXISTS i: j <= i AND i < k AND
        all_symmetric_synch?[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
          (status(i), c_src(i), c_dst(i + 1), Schedule(i), common_check(i), pi(i)) AND
        inexact_consensus?(cf(i)) AND
        quorum_synch?(status, c_src, c_dst, Schedule, common_check, tau, pi, i + 1, k)

  END timing_integration


body:
  %
  %
  % Purpose : a specific instantiation of an inexact middle-value 
  %          multi-stage exchange adapted for synchronization properties
  %
  %


  reduce_synch
  [
    rho: nonneg_real,      % Bound on drift for a good oscillator
    min_latency: [nat -> nonneg_real], 
                           % Minimum real time latency (in ticks
                           % of real time) of the communication link
                           % between stage i and i+1
                           % determined by things like length of wire, speed
                           % of light, and clock rate.
    var_latency: [nat -> nonneg_real], 
                           % Max variation (in ticks of real 
                           % time) between stage i and i+1
                           % caused by both wire length 
                           % differences and clock jitter.  
    stage: [nat -> posnat] % Number of nodes in a given stage
  ] : THEORY

    BEGIN

    i, j, k: VAR nat

    source_error(i): MACRO real = 0

    IMPORTING
      reals@sigma_nat,
      reals@real_fun_ops,
      timing_integration[rho, min_latency, var_latency, stage],
      k_ordered[stage, real, <=, source_error],
      protocol[stage, real],
      reduce_synch_stage

    c_src: VAR [i: nat -> [below(stage(i)) -> good_clock[rho]]]
    c_dst: VAR [i: nat -> [below(stage(i)) -> good_clock[rho]]]
    clk: VAR [i: nat -> [below(stage(i)) -> good_clock[rho]]]
    tau: VAR [nat -> tau_type]
    Lag, Schedule: VAR [nat -> integer]
    pi: VAR [nat -> nonneg_real]
    delta: VAR nonneg_real

    cf: VAR k_consensus_function
    icf: VAR [nat -> in_consensus_function]

    status: VAR [i: nat -> node_status[stage(i)]]
    src_set: VAR [i: nat -> non_empty_finite_set[below(stage(i))]] 
    local_check:  VAR [i: nat -> [below(stage(i+1)) -> finite_set[below(stage(i))]]] 

    same_clock?(c_src, c_dst, j, k): bool = 
      FORALL i: j <= i AND i < k IMPLIES
        same_edges?[rho, stage(i+1)](c_src(i+1), c_dst(i+1))

    W(i): nat = W[rho, min_latency(i), var_latency(i)]

    feasible?(Schedule): bool = FORALL i:  Schedule(i) <= Schedule(i+1) - W(i+1) 

    Sched :VAR (feasible?)

    Delay(Sched)(i): nat = Sched(i + 1) - Sched(i)

    Del(Sched)(i): nat = Sched(i) - Sched(pred(i))

    Del_Delay: LEMMA Del(Sched)(i + 1) = Delay(Sched)(i)

    Lag(Sched)(i): nat = Delay(Sched)(i) - W(i+1)

    Delay_Lag: LEMMA
      Delay(Sched)(i) = W(i+1) + Lag(Sched)(i)

    offset_sent_nominal: LEMMA
      nominal(clk, Schedule)(i) = offset[rho, stage(i)](clk(i), W(i))(sent(clk, Schedule)(i)) 


    %used only for correspondence to protocol
    offset(clk, Schedule)(i): compute_stage[stage(i), real] 
      = offset[rho, stage(i)](clk(i), Schedule(i))

    synch_protocol(status, c_src, c_dst, Sched, src_set, tau, cf, pi, j, k): bool = 
        FORALL i: j <= i AND i < k IMPLIES
          nominal(c_src, Sched)(i+1) = 
            synch_stage[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
              (status(i), c_src(i), c_dst(i+1), Sched(i), Delay(Sched)(i), src_set(i), tau(i), cf(i), pi(i))

    synch_protocol_sent: LEMMA
        feasible?(Schedule)AND
        same_clock?(c_src, c_dst, j, k) AND
        synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, cf, pi, j, k)
      IMPLIES
        FORALL i: j <= i AND i < k IMPLIES
          sent(c_src, Schedule)(i+1) = 
            synch_stage[rho, min_latency(i), var_latency(i), stage(i), stage(i+1)]
              (status(i), c_src(i), c_dst(i+1), Schedule(i), Lag(Schedule)(i), src_set(i), tau(i), cf(i), pi(i))

    protocol_synch(status, c_src, c_dst, Sched, src_set, tau, cf, pi, j, k): bool = 
      protocol(offset(c_dst, Del(Sched)), reduce_choice(tau, cf), 
        nominal(c_src, Sched), 
        received(c_dst, c_src, Sched, status, pi),
        check(c_dst, Sched, src_set, pi), j, k)

  %  offset_transform(clk, Schedule, cf)(i): consensus_function
  %    = LAMBDA (s:ne_seqs):offset[rho, stage(i)](clk(i), Schedule(i)) o cf(i)

  %  protocol_synch2(status, c_src, c_dst, Sched, src_set, tau, cf, pi, j, k): bool = 
  %    protocol(reduce_choice(tau, offset_transform(c_dst, Del(Sched), cf)), 
  %      nominal(c_src, Sched), 
  %      received(c_dst, c_src, Sched, status, pi),
  %      check(c_dst, Sched, src_set, pi), j, k)

    % correspondence result
    k_stage_synch: LEMMA 
      protocol_synch(status, c_src, c_dst, Sched, src_set, tau, cf, pi, j, k) IFF 
        synch_protocol(status, c_src, c_dst, Sched, src_set, tau, cf, pi, j, k)


    % Synchronization protocol guarantees
    lower_validity: THEOREM
        feasible?(Schedule) AND
        synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, cf, pi, j, j + k) AND
        quorum_synch?(status, c_src, c_dst, Schedule, src_set, tau, pi, j, j + k) AND
        clock_relation?(Schedule, c_src, c_dst, pi, j, j + k)
      IMPLIES
        v_min(nominal(c_src, Schedule), src_set)(j) 
          - sigma(j, j + k - 1, epsilon_lower - ((1/rate[rho]) * Delay(Schedule)))
          <= v_min(nominal(c_src, Schedule), src_set)(j + k)

    upper_validity: THEOREM
        feasible?(Schedule) AND
        synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, cf, pi, j, j + k) AND
        quorum_synch?(status, c_src, c_dst, Schedule, src_set, tau, pi, j, j + k) AND
        clock_relation?(Schedule, c_src, c_dst, pi, j, j + k)
      IMPLIES
          v_max(nominal(c_src, Schedule), src_set)(j + k) 
            <= v_max(nominal(c_src, Schedule), src_set)(j) 
                 + sigma(j, j + k - 1, epsilon_upper + rate[rho] * Delay(Schedule)) 

    agreement_propagation: LEMMA
        feasible?(Schedule) AND
        synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, cf, pi, j, j + k) AND
        quorum_synch?(status, c_src, c_dst, Schedule, src_set, tau, pi, j, j + k) AND
        clock_relation?(Schedule, c_src, c_dst, pi, j, j + k) AND
        v_max(sent(c_src, Schedule), src_set)(j) 
          - v_min(sent(c_src, Schedule), src_set)(j) <= delta AND
        same_clock?(c_src, c_dst, j, j + k)
      IMPLIES
        v_max(sent(c_src, Schedule), src_set)(j + k) 
          - v_min(sent(c_src, Schedule), src_set)(j + k) 
            <= delta + sigma(j, j + k - 1, epsilon_total + drift[rho] * Lag(Schedule))

    X: VAR posnat

    convergent_stage?(status, c_src, c_dst, Schedule, src_set, tau, cf, X, pi, j, k): bool =
      EXISTS i: j <= i AND i < k AND
        overlap_synch?[rho, min_latency(i), var_latency(i), stage(i), stage(i + 1)]
           (status(i), c_src(i), c_dst(i + 1), Schedule(i), src_set(i), tau(i), pi(i)) AND
        convergent?(cf(i), 
          max_length[rho, min_latency(i), var_latency(i), stage(i), stage(i + 1)]
            (status(i), c_src(i), c_dst(i + 1), Schedule(i), src_set(i), tau(i), pi(i)), X)


    convergence: LEMMA
        feasible?(Schedule)AND
        synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, cf, pi, j, j + k) AND
        quorum_synch?(status, c_src, c_dst, Schedule, src_set, tau, pi, j, j + k) AND
        clock_relation?(Schedule, c_src, c_dst, pi, j, j + k) AND
        convergent_stage?(status, c_src, c_dst, Schedule, src_set, tau, cf, X, pi, j, j + k) AND
        v_max(sent(c_src, Schedule), src_set)(j) 
          - v_min(sent(c_src, Schedule), src_set)(j) <= delta AND
        same_clock?(c_src, c_dst, j, j + k)
      IMPLIES
        v_max(sent(c_src, Schedule), src_set)(j + k) 
          - v_min(sent(c_src, Schedule), src_set)(j + k) 
            <= delta * ((X - 1) / X) + sigma(j, j + k - 1, epsilon_total + drift[rho] * Lag(Schedule)) + rate[rho]

    agreement_generation: THEOREM
        feasible?(Schedule)AND
        synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, cf, pi, j, j + k) AND
        exists_symmetric_synch_stage?(status, c_src, c_dst, Schedule, src_set, tau, pi, cf, j, j + k) AND
        clock_relation?(Schedule, c_src, c_dst, pi, j, j + k) AND
        same_clock?(c_src, c_dst, j, j + k)
      IMPLIES
        v_max(sent(c_src, Schedule), src_set)(j + k) 
          - v_min(sent(c_src, Schedule), src_set)(j + k) 
            <= sigma(j, j + k - 1, epsilon_total + drift[rho] * Lag(Schedule)) + rate[rho]

    agreement_generation_edge: THEOREM
        feasible?(Schedule)AND
        synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, icf, pi, j, j + k) AND
        exists_symmetric_synch_stage?(status, c_src, c_dst, Schedule, src_set, tau, pi, icf, j, j + k) AND
        clock_relation?(Schedule, c_src, c_dst, pi, j, j + k) AND
        same_clock?(c_src, c_dst, j, j + k)
      IMPLIES
        v_max(sent(c_src, Schedule), src_set)(j + k) 
          - v_min(sent(c_src, Schedule), src_set)(j + k) 
            <= sigma(j, j + k - 1, epsilon_total + drift[rho] * Lag(Schedule))

  END reduce_synch

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

  % Subtype TCC generated (at line 65, column 25) for  Sched(i + 1) - Sched(i)
      % expected type  nat
  Delay_TCC1: OBLIGATION
    FORALL (Sched: (feasible?), i: nat): Sched(i + 1) - Sched(i) >= 0;

  % Subtype TCC generated (at line 67, column 23) for
      % Sched(i) - Sched(pred(i))
      % expected type  nat
  Del_TCC1: OBLIGATION
    FORALL (Sched: (feasible?), i: nat): Sched(i) - Sched(pred(i)) >= 0;

  % Subtype TCC generated (at line 71, column 23) for
      % Delay(Sched)(i) - W(i + 1)
      % expected type  nat
  Lag_TCC1: OBLIGATION
    FORALL (Sched: (feasible?), i: nat): Delay(Sched)(i) - W(i + 1) >= 0;

  % Subtype TCC generated (at line 129, column 19) for  j + k - 1
      % expected type  T_high[nat]
  lower_validity_TCC1: OBLIGATION
    FORALL (Schedule: [nat -> integer],
            c_dst, c_src: [i: nat -> [below(stage(i)) -> good_clock[rho]]],
            cf: k_consensus_function[stage, real, <=, LAMBDA (i): 0],
            j, k: nat, pi: [nat -> nonneg_real],
            src_set: [i: nat -> non_empty_finite_set[below(stage(i))]],
            status: [i: nat -> node_status[stage(i)]],
            tau: [nat -> tau_type]):
      clock_relation?(Schedule, c_src, c_dst, pi, j, j + k) AND
       quorum_synch?(status, c_src, c_dst, Schedule, src_set, tau, pi, j,
                     j + k)
        AND
        synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, cf, pi,
                       j, j + k)
         AND feasible?(Schedule)
       IMPLIES j + k - 1 >= 0 OR (EXISTS (j_1: nat): j + k - 1 <= j_1);

  % Subtype TCC generated (at line 189, column 22) for  j + k - 1
      % expected type  T_high[nat]
  agreement_generation_TCC1: OBLIGATION
    FORALL (Schedule: [nat -> integer],
            c_dst, c_src: [i: nat -> [below(stage(i)) -> good_clock[rho]]],
            cf: k_consensus_function[stage, real, <=, LAMBDA (i): 0],
            j, k: nat, pi: [nat -> nonneg_real],
            src_set: [i: nat -> non_empty_finite_set[below(stage(i))]],
            status: [i: nat -> node_status[stage(i)]],
            tau: [nat -> tau_type]):
           same_clock?(c_src, c_dst, j, j + k)
       AND clock_relation?(Schedule, c_src, c_dst, pi, j, j + k)
       AND exists_symmetric_synch_stage?(status,
                                         c_src,
                                         c_dst,
                                         Schedule,
                                         src_set,
                                         tau,
                                         pi,
                                         cf,
                                         j,
                                         j + k)
       AND synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, cf,
                          pi, j, j + k)
       AND feasible?(Schedule)
       IMPLIES j + k - 1 >= 0 OR (EXISTS (j_1: nat): j + k - 1 <= j_1);

  % Subtype TCC generated (at line 200, column 22) for  j + k - 1
      % expected type  T_high[nat]
  agreement_generation_edge_TCC1: OBLIGATION
    FORALL (Schedule: [nat -> integer],
            c_dst, c_src: [i: nat -> [below(stage(i)) -> good_clock[rho]]],
            icf: [nat -> in_consensus_function[real]], j, k: nat,
            pi: [nat -> nonneg_real],
            src_set: [i: nat -> non_empty_finite_set[below(stage(i))]],
            status: [i: nat -> node_status[stage(i)]],
            tau: [nat -> tau_type]):
           same_clock?(c_src, c_dst, j, j + k)
       AND clock_relation?(Schedule, c_src, c_dst, pi, j, j + k)
       AND exists_symmetric_synch_stage?(status,
                                         c_src,
                                         c_dst,
                                         Schedule,
                                         src_set,
                                         tau,
                                         pi,
                                         icf,
                                         j,
                                         j + k)
       AND synch_protocol(status, c_src, c_dst, Schedule, src_set, tau, icf,
                          pi, j, j + k)
       AND feasible?(Schedule)
       IMPLIES j + k - 1 >= 0 OR (EXISTS (j_1: nat): j + k - 1 <= j_1);


body:
  %
  %
  % Purpose : Describe properties about exact communication in 
  %           relation to the results-based fault model.
  %
  %

  exact_comm_stage 
  [
      S   : posnat,  % Number of sources 
      D   : posnat,  % Number of destinations
      T   : TYPE+    % Message type
  ] : THEORY

    BEGIN

    IMPORTING
      fault_assumptions_stage[S, D, T]

    t: VAR T

    s, s1, s2: VAR below(S)
    d, d1, d2: VAR below(D)

    src_set, correct_set: VAR finite_set[below(S)]

    sent: VAR sent_vec_stage
    rcvd: VAR rcvd_matrix_stage
    check: VAR check_stage

    % this predicate asserts that all sources in src_set are 
    % correctly denoted sources
    exact_correct_denotation?(sent, rcvd, check)(src_set): bool =
      FORALL d, s: 
          src_set(s) AND 
          enabled(rcvd, check)(d)(s) 
        IMPLIES
          rcvd(d)(s) = sent(s)

    % this predicate asserts that all sources in src_set are 
    % singly denoted sources
    exact_single_denotation?(rcvd, check)(src_set): bool =
      FORALL d1, d2, s:
          src_set(s) AND
          enabled(rcvd, check)(d1)(s) AND
          enabled(rcvd, check)(d2)(s)
        IMPLIES
          rcvd(d1)(s) = rcvd(d2)(s)

    % if all nodes in a given set are enabled;
    % all conforming correct_denotation sources send genuine values;
    % and the sent values of all nodes in the given set agree:
    % then the received values from enabled correct_denotation sources agree.
    correct_uniform: LEMMA
        enabled_within?(rcvd, check)(src_set) AND
        exact_correct_denotation?(sent, rcvd, check)(correct_set) AND
        uniform?(sent, t)(src_set)
      IMPLIES
        uniform?(rcvd(d), t)(intersection(correct_set, enabled(rcvd, check)(d)))

    correct_uniform_alt: LEMMA
        enabled_within?(rcvd, check)(src_set) AND
        exact_correct_denotation?(sent, rcvd, check)(correct_set) AND
        uniform?(sent, t)(enabled?(rcvd, check))
      IMPLIES
        uniform?(rcvd(d), t)(intersection(correct_set, enabled(rcvd, check)(d)))

    tau: VAR tau_type
   
    % Quorum is a generalized type of majority.  tau=0 means unamimous, tau=mid
    % means a (simple) majority.

    quorum_correct?(sent, rcvd, check, tau): bool =
      EXISTS src_set:
        exact_correct_denotation?(sent, rcvd, check)(src_set) AND
        quorum?(rcvd, check, tau)(src_set)

    majority_correct?(sent, rcvd, check): bool = 
      EXISTS src_set:
        exact_correct_denotation?(sent, rcvd, check)(src_set) AND
        majority?(rcvd, check)(src_set)

    majority_correct_rw: LEMMA
      majority_correct?(sent, rcvd, check) = quorum_correct?(sent, rcvd, check, mid)
   
    all_symmetric?(rcvd, check): bool = 
      EXISTS src_set: 
        exact_single_denotation?(rcvd, check)(src_set) AND
        uniformly_enabled?(rcvd, check)(src_set) AND
        enabled_within?(rcvd, check)(src_set) 

    % The following were added to enable diagnostic results for majority

    majority_correct_element?(sent, rcvd, check)(s): bool = 
      EXISTS src_set:
        src_set(s) AND
        exact_correct_denotation?(sent, rcvd, check)(src_set) AND
        majority?(rcvd, check)(src_set)

    symmetric_source?(rcvd, check)(s): bool = 
      EXISTS src_set:
        src_set(s) AND
        exact_single_denotation?(rcvd, check)(src_set) AND
        uniformly_enabled?(rcvd, check)(src_set) AND
        enabled_within?(rcvd, check)(src_set)

  END exact_comm_stage


