# TheoryBodies

body:
  %------------------------------------------------------------------------------
  % gs_circle.pvs
  % ACCoRD v.1.0
  %
  % Ground speed circle solutions satisfy the following equations:
  %   sq(s+v*t) = sq(D)       [2D]
  %   v = l*vo - vi           [2D]
  %   abs((s+v*t)`z) = H
  %
  % It is shown that ground speed circle solutions are ground speed only 
  % solutions for the ownship.
  %
  % The sign value dir determines horizontal direction (Entry/Exit).
  % The sign value irt determines two possible ground speed circle solutions.  
  %------------------------------------------------------------------------------

  gs_circle[D,H: posreal] : THEORY
  BEGIN
    
     IMPORTING gs_only[D],
               circle_solutions[D,H],
               vertical_criterion[D,H]

    s,nvo     : VAR Vect3
    sp        : VAR Sp2_vect3
    vo,vi     : VAR Nzv2_vect3 
    dir,irt,
    epsh,epsv : VAR Sign

    %------------%
    % ALGORITHMS %
    %------------%

    % vectors_2D.zero indicates no ground speed solution

    gs_circle(s,vo,vi,dir,irt): {nvo | nz_vect2?(nvo) => gs_only_3D?(vo)(nvo)} =
      IF vo`z = vi`z THEN zero
      ELSE
        LET t = Theta_H(s`z,vo`z-vi`z,-dir) IN
        IF t > 0 THEN
          LET nvo2 = gs_only_circle(s,vo,vi,t,dir,irt) IN
            nvo2 WITH [z |-> vo`z] 
        ELSE
           zero
        ENDIF
      ENDIF

    gs_circle?(s,vo,vi,dir)(nvo) : bool =
      nz_vect2?(nvo) AND
      EXISTS (irt): nvo = gs_circle(s,vo,vi,dir,irt)

    gs_circle?(s,vo,vi)(nvo) : MACRO bool =
      EXISTS (dir): gs_circle?(s,vo,vi,dir)(nvo)

    gs_vertical(s,vo,vi,epsh,epsv): {nvo | nz_vect2?(nvo) => 
                                           gs_only_3D?(vo)(nvo)} =
      IF vo`z = vi`z THEN zero
      ELSE LET v = vo-vi,
               dir:Sign = IF abs(s`z) >= H THEN epsv*sign(s`z) ELSE Entry ENDIF,
               t = Theta_H(s`z,v`z,-dir) IN
        IF t > 0 AND epsv = sign(s`z + t*v`z) THEN
          LET nvo2 = gs_only_vertical(s,vo,vi,t,dir) IN
            IF horizontal_los?(s) OR horizontal_criterion?(s,epsh)(nvo2-vo) THEN
              nvo2 WITH [z |-> vo`z] 
            ELSE
              zero
            ENDIF
        ELSE
           zero
        ENDIF
      ENDIF

    gs_vertical?(s,vo,vi,epsh,epsv)(nvo) : bool =
      nz_vect2?(nvo) AND
      nvo = gs_vertical(s,vo,vi,epsh,epsv)

    %------------%
    % LEMMAS     %
    %------------%

    gs_circle_nzvz : LEMMA
      gs_circle?(s,vo,vi,dir)(nvo) IMPLIES
      vo`z /= vi`z 

    gs_circle_solution_2D : LEMMA
      gs_circle?(s,vo,vi,dir)(nvo) IMPLIES
        circle_solution_2D?(s,nvo-vi,Theta_H(s`z,vo`z-vi`z,-dir),dir)

    gs_circle_solution : LEMMA
      gs_circle?(s,vo,vi,dir)(nvo) IMPLIES
        circle_solution?(s,nvo-vi,Theta_H(s`z,vo`z-vi`z,-dir),dir)

    gs_circle_independence: THEOREM
      gs_circle?(s,vo,vi,dir)(nvo) IMPLIES
        NOT conflict_ever?(s,nvo-vi)

    gs_circle_complete: THEOREM
      vo`z /= vi`z AND
      gs_only_3D?(vo)(nvo) AND
      circle_solution?(s,nvo-vi,Theta_H(s`z,vo`z-vi`z,-dir),dir)
      IMPLIES
        gs_circle?(s,vo,vi,dir)(nvo)

    gs_vertical_meets_horizontal_criterion : THEOREM
      gs_vertical?(sp,vo,vi,epsh,epsv)(nvo) IMPLIES
      horizontal_criterion?(sp,epsh)(nvo-vo)

    gs_vertical_meets_vertical_criterion : THEOREM
      gs_vertical?(s,vo,vi,epsh,epsv)(nvo) IMPLIES
      vertical_criterion?(epsv)(s,vo-vi)(nvo-vi)

  END gs_circle

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

  % Subtype TCC generated (at line 37, column 24) for  zero
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           gs_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  gs_circle_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z = vi`z IMPLIES
       vect2(zero) /= zero =>
        gs_only?(vect2(vo))(vect2(zero)) AND vo`z = zero`z;

  % Subtype TCC generated (at line 39, column 26) for  vo`z - vi`z
      % expected type  nzreal
  gs_circle_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3):
      NOT vo`z = vi`z IMPLIES vo`z - vi`z /= 0;

  % Subtype TCC generated (at line 41, column 42) for  t
      % expected type  posreal
  gs_circle_TCC3: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, dir: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (t: real):
          t > 0 AND t = Theta_H(s`z, vo`z - vi`z, -dir) IMPLIES t >= 0);

  % Subtype TCC generated (at line 42, column 10) for  nvo2 WITH [z |-> vo`z]
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           gs_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  gs_circle_TCC4: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, dir: Sign, irt: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (t: real):
          t > 0 AND t = Theta_H(s`z, vo`z - vi`z, -dir) IMPLIES
           (FORALL (nvo2: {nvo | nvo /= zero => gs_only?(vect2(vo))(nvo)}):
              nvo2 =
               gs_only_circle(vect2(s), vect2(vo), vect2(vi), t, dir, irt)
               IMPLIES
               vect2((nvo2 WITH [z |-> vo`z])) /= zero =>
                gs_only?(vect2(vo))(vect2((nvo2 WITH [z |-> vo`z])))));

  % Subtype TCC generated (at line 44, column 9) for  zero
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           gs_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  gs_circle_TCC5: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, dir: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (t: real):
          NOT t > 0 AND t = Theta_H(s`z, vo`z - vi`z, -dir) IMPLIES
           vect2(zero) /= zero =>
            gs_only?(vect2(vo))(vect2(zero)) AND vo`z = zero`z);

  % Subtype TCC generated (at line 60, column 29) for  v`z
      % expected type  nzreal
  gs_vertical_TCC1: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsv: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (v: Vector):
          v = vo - vi IMPLIES
           (FORALL (dir: Sign):
              dir = IF abs(s`z) >= H THEN epsv * sign(s`z) ELSE -1 ENDIF
               IMPLIES v`z /= 0));

  % Subtype TCC generated (at line 62, column 44) for  t
      % expected type  posreal
  gs_vertical_TCC2: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsv: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (v: Vector):
          v = vo - vi IMPLIES
           (FORALL (dir: Sign):
              dir = IF abs(s`z) >= H THEN epsv * sign(s`z) ELSE -1 ENDIF
               IMPLIES
               (FORALL (t: real):
                  t > 0 AND
                   epsv = sign(s`z + t * v`z) AND t = Theta_H(s`z, v`z, -dir)
                   IMPLIES t >= 0)));

  % Subtype TCC generated (at line 63, column 57) for  vect2(s)
      % expected type  Sp_vect2[D]
  gs_vertical_TCC3: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsv: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (v: Vector):
          v = vo - vi IMPLIES
           (FORALL (dir: Sign):
              dir = IF abs(s`z) >= H THEN epsv * sign(s`z) ELSE -1 ENDIF
               IMPLIES
               (FORALL (t: real):
                  t > 0 AND
                   epsv = sign(s`z + t * v`z) AND t = Theta_H(s`z, v`z, -dir)
                   IMPLIES
                   (FORALL (nvo2:
                              {nvo |
                                       nvo /= zero
                                       =>
                                       gs_only?(vect2(vo))(nvo)}):
                      NOT sqv(vect2(s)) < sq(D) AND
                       nvo2 =
                        gs_only_vertical(vect2(s),
                                         vect2(vo),
                                         vect2(vi),
                                         t,
                                         dir)
                       IMPLIES sqv(vect2(s)) >= sq(D)))));

  % Subtype TCC generated (at line 64, column 12) for  nvo2 WITH [z |-> vo`z]
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           gs_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  gs_vertical_TCC4: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsh: Sign,
            epsv: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (v: Vector):
          v = vo - vi IMPLIES
           (FORALL (dir: Sign):
              dir = IF abs(s`z) >= H THEN epsv * sign(s`z) ELSE -1 ENDIF
               IMPLIES
               (FORALL (t: real):
                  t > 0 AND
                   epsv = sign(s`z + t * v`z) AND t = Theta_H(s`z, v`z, -dir)
                   IMPLIES
                   (FORALL (nvo2:
                              {nvo |
                                       nvo /= zero
                                       =>
                                       gs_only?(vect2(vo))(nvo)}):
                      (sqv(vect2(s)) < sq(D) OR
                        horizontal_criterion?(vect2(s), epsh)
                                             (nvo2 - vect2(vo)))
                       AND
                       nvo2 =
                        gs_only_vertical(vect2(s),
                                         vect2(vo),
                                         vect2(vi),
                                         t,
                                         dir)
                       IMPLIES
                       vect2((nvo2 WITH [z |-> vo`z])) /= zero =>
                        gs_only?(vect2(vo))
                                (vect2((nvo2 WITH [z |-> vo`z])))))));

  % Subtype TCC generated (at line 66, column 12) for  zero
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           gs_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  gs_vertical_TCC5: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsh: Sign,
            epsv: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (v: Vector):
          v = vo - vi IMPLIES
           (FORALL (dir: Sign):
              dir = IF abs(s`z) >= H THEN epsv * sign(s`z) ELSE -1 ENDIF
               IMPLIES
               (FORALL (t: real):
                  t > 0 AND
                   epsv = sign(s`z + t * v`z) AND t = Theta_H(s`z, v`z, -dir)
                   IMPLIES
                   (FORALL (nvo2:
                              {nvo |
                                       nvo /= zero
                                       =>
                                       gs_only?(vect2(vo))(nvo)}):
                      NOT sqv(vect2(s)) < sq(D) AND
                       NOT horizontal_criterion?(vect2(s), epsh)
                                                (nvo2 - vect2(vo))
                        AND
                        nvo2 =
                         gs_only_vertical(vect2(s),
                                          vect2(vo),
                                          vect2(vi),
                                          t,
                                          dir)
                       IMPLIES
                       vect2(zero) /= zero =>
                        gs_only?(vect2(vo))(vect2(zero)) AND
                         vo`z = zero`z))));

  % Subtype TCC generated (at line 69, column 9) for  zero
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           gs_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  gs_vertical_TCC6: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsv: Sign):
      NOT vo`z = vi`z IMPLIES
       (FORALL (v: Vector):
          v = vo - vi IMPLIES
           (FORALL (dir: Sign):
              dir = IF abs(s`z) >= H THEN epsv * sign(s`z) ELSE -1 ENDIF
               IMPLIES
               (FORALL (t: real):
                  NOT (t > 0 AND epsv = sign(s`z + t * v`z)) AND
                   t = Theta_H(s`z, v`z, -dir)
                   IMPLIES
                   vect2(zero) /= zero =>
                    gs_only?(vect2(vo))(vect2(zero)) AND vo`z = zero`z)));

  % Subtype TCC generated (at line 87, column 47) for  vo`z - vi`z
      % expected type  nzreal
  gs_circle_solution_2D_TCC1: OBLIGATION
    FORALL (dir: Sign, nvo, s: Vect3, vi, vo: Nzv2_vect3):
      gs_circle?(s, vo, vi, dir)(nvo) IMPLIES vo`z - vi`z /= 0;


body:
  %------------------------------------------------------------------------------
  % vs_only.pvs
  % ACCoRD v1.0
  %
  % This theory proposes criteria for vertical only resolutions. Circle solutions 
  % solve the following equation on vz:
  %
  %   sz+t*vz = eps*H,
  %   
  % where t = Theta_D(s,v,epsp), and eps determines the bottom
  %   eps =  1: top circle
  %   eps = -1: bottom circle
  %------------------------------------------------------------------------------

  vs_only[D,H: posreal] : THEORY
  BEGIN

    IMPORTING circle_criterion[D,H]

    ss         : VAR Ss2_vect3    % Horizontally separated
    vgs        : VAR Nzv2_vect3   % Ground speed is non-zero 
    s,v        : VAR Vect3
    eps        : VAR Sign
    nnt        : VAR nnreal
    t,vz       : VAR real
    v2         : VAR Vect2

    %------------%
    % ALGORITHMS %
    %------------%

    % If first projection is true, the second projection is a relative vertical 
    % only resolution maneuver.

    vs_only(s,v2,t,eps) : [bool,real] =
      IF eps*s`z < H AND strict_horizontal_sep?(s) AND Delta(s,v2) > 0 THEN  
        (true,vs_at(s`z,Theta_D(s,v2,Entry),eps))
      ELSIF eps*s`z >= H AND t > 0 THEN
        (true,vs_at(s`z,t,eps))
      ELSE
        (false,0)
      ENDIF

    %------------%
    % LEMMAS     %
    %------------%

    circle_vs_only_ge : LEMMA
      LET signsz = sign(s`z+nnt*vz) IN
      circle_criterion_at?(s,v WITH [z := vz],nnt,eps) AND
      (eps = Exit IMPLIES signsz*v`z <= 0) AND
      signsz*v`z >= signsz*vz
      IMPLIES
        circle_criterion_at?(s,v,nnt,eps)

    vs_entry_meets_circle_criterion : LEMMA
       horizontal_conflict?(ss,vgs) AND
       eps*ss`z < H AND
       eps*vgs`z >= eps*vs_at(ss`z,Theta_D(ss,vgs,Entry),eps)
       IMPLIES
         circle_criterion_at?(ss,vgs,Theta_D(ss,vgs,Entry),Entry)

    vs_exit_meets_circle_criterion : LEMMA
      eps*s`z >= H AND
      horizontal_conflict?(s,vgs) AND
      vgs`z = vs_at(s`z,Theta_D(s,vgs,Exit),eps)
      IMPLIES
        circle_criterion_at?(s,vgs,Theta_D(s,vgs,Exit),Exit)

  END vs_only

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

  % Subtype TCC generated (at line 37, column 32) for  v2
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  vs_only_TCC1: OBLIGATION
    FORALL (s: Vect3, v2: Vect2, eps: Sign):
      eps * s`z < H AND sqv(vect2(s)) > sq(D) AND Delta(vect2(s), v2) > 0
       IMPLIES v2 /= zero AND Delta[D](vect2(s), v2) >= 0;

  % Subtype TCC generated (at line 37, column 22) for
      % Theta_D(vect2(s), v2, -1)
      % expected type  nzreal
  vs_only_TCC2: OBLIGATION
    FORALL (s: Vect3, v2: Vect2, eps: Sign):
      eps * s`z < H AND sqv(vect2(s)) > sq(D) AND Delta(vect2(s), v2) > 0
       IMPLIES Theta_D[D](vect2(s), v2, -1) /= 0;

  % Subtype TCC generated (at line 39, column 22) for  t
      % expected type  nzreal
  vs_only_TCC3: OBLIGATION
    FORALL (s: Vect3, v2: Vect2, t: real, eps: Sign):
      eps * s`z >= H AND
       t > 0 AND
        NOT (eps * s`z < H AND
              sqv(vect2(s)) > sq(D) AND Delta(vect2(s), v2) > 0)
       IMPLIES t /= 0;

  % Subtype TCC generated (at line 59, column 44) for  vect2(vgs)
      % expected type  {nzv | Delta(vect2(ss), nzv) >= 0}
  vs_entry_meets_circle_criterion_TCC1: OBLIGATION
    FORALL (eps: Sign, ss: Ss2_vect3[D, H], vgs: Nzv2_vect3):
      horizontal_conflict?(vect2(ss), vect2(vgs)) AND eps * ss`z < H IMPLIES
       Delta[D](vect2(ss), vect2(vgs)) >= 0;

  % Subtype TCC generated (at line 59, column 33) for
      % Theta_D(vect2(ss), vect2(vgs), -1)
      % expected type  nzreal
  vs_entry_meets_circle_criterion_TCC2: OBLIGATION
    FORALL (eps: Sign, ss: Ss2_vect3[D, H], vgs: Nzv2_vect3):
      horizontal_conflict?(vect2(ss), vect2(vgs)) AND eps * ss`z < H IMPLIES
       Theta_D[D](vect2(ss), vect2(vgs), -1) /= 0;

  % Subtype TCC generated (at line 66, column 32) for  vect2(vgs)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  vs_exit_meets_circle_criterion_TCC1: OBLIGATION
    FORALL (eps: Sign, s: Vect3, vgs: Nzv2_vect3):
      eps * s`z >= H AND horizontal_conflict?(vect2(s), vect2(vgs)) IMPLIES
       Delta[D](vect2(s), vect2(vgs)) >= 0;

  % Subtype TCC generated (at line 66, column 22) for
      % Theta_D(vect2(s), vect2(vgs), 1)
      % expected type  nzreal
  vs_exit_meets_circle_criterion_TCC2: OBLIGATION
    FORALL (eps: Sign, s: Vect3, vgs: Nzv2_vect3):
      eps * s`z >= H AND horizontal_conflict?(vect2(s), vect2(vgs)) IMPLIES
       Theta_D[D](vect2(s), vect2(vgs), 1) /= 0;


body:
  %------------------------------------------------------------------------------
  % vs_circle.pvs
  % ACCoRD v.1.0
  %
  % Computes a resolution that only changes the vertical speed.
  %
  %------------------------------------------------------------------------------

  vs_circle[D,H: posreal] : THEORY
  BEGIN

    IMPORTING vs_only[D,H],
              circle_solutions[D,H],
  	    vertical_criterion[D,H]
    
    sp         : VAR Sp_vect3     % 3-D separation
    s,v,w,
    nvo,nvi,
    nvo1,nvo2 : VAR Vect3
    eps,dir   : VAR Sign
    t         : VAR posreal
    vo,vi     : VAR Nzv2_vect3
    b,bt	    : VAR nnreal

    %------------%
    % ALGORITHMS %
    %------------%

    % vectors_2D.zero indicates no ground speed solution

    vs_circle(s,vo,vi,eps) : {nvo | nz_vect2?(nvo) IMPLIES vs_only?(vo)(nvo)} =
      LET v = vo-vi IN
      IF zero_vect2?(v) AND eps=sign(s`z) THEN vo WITH [z:=vi`z]
      ELSIF Delta(s,v) > 0 THEN
         LET (res,vz) = vs_only(s,v,Theta_D(s,v,Exit),eps) IN
         IF res THEN vo WITH [z := vi`z+vz]
         ELSE zero
         ENDIF
      ELSE zero
      ENDIF

    vs_circle?(s,vo,vi,eps)(nvo) : bool =
      nz_vect2?(nvo) AND
      nvo = vs_circle(s,vo,vi,eps)

    vs_circle?(s,vo,vi)(nvo) : MACRO bool =
      EXISTS (eps): vs_circle?(s,vo,vi,eps)(nvo)

    %------------%
    % LEMMAS     %
    %------------%

    vs_circle_meets_vertical_criterion: LEMMA
      horizontal_conflict?(sp,vo-vi) AND
      vs_circle?(sp,vo,vi,eps)(nvo) IMPLIES
      vertical_criterion?(eps)(sp,vo-vi)(nvo-vi)

    vs_only_vs_criterion_ge_vz: LEMMA
      vertical_criterion?(eps)(s,v)(nvo1-vi) AND  
      vs_only?(nvo1)(nvo2) AND
      eps*nvo2`z >= eps*nvo1`z IMPLIES
      vertical_criterion?(eps)(s,v)(nvo2-vi)

    %--------------------------%
    % THEOREM: Independence    %
    %--------------------------%

    vs_circle_independence : THEOREM
      horizontal_conflict?(sp,vo-vi) AND
      vs_circle?(sp,vo,vi,eps)(nvo) 
      IMPLIES
        NOT conflict?(sp,nvo-vi)

    %--------------------------%
    % THEOREM: Coordination    %
    %--------------------------%

    vs_circle_coordination : THEOREM
      conflict?(sp,vo-vi) AND
      vs_circle?(sp,vo,vi,eps)(nvo) AND
      vs_circle?(-sp,vi,vo,-eps)(nvi)
      IMPLIES
        NOT conflict?(sp,nvo-nvi)

  END vs_circle

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

  % Subtype TCC generated (at line 33, column 45) for  vo WITH [z := vi`z]
      % expected type  {nvo | vect2(nvo) /= zero IMPLIES vs_only?(vo)(nvo)}
  vs_circle_TCC1: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, eps: Sign, v: Vect3):
      vect2(v) = zero AND eps = sign(s`z) AND v = vo - vi IMPLIES
       vect2((vo WITH [z := vi`z])) /= zero IMPLIES
        vs_only?(vo)((vo WITH [z := vi`z]));

  % Subtype TCC generated (at line 35, column 44) for  vect2(v)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  vs_circle_TCC2: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, eps: Sign, v: Vect3):
      Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND eps = sign(s`z)) AND v = vo - vi
       IMPLIES vect2(v) /= zero AND Delta[D](vect2(s), vect2(v)) >= 0;

  % Subtype TCC generated (at line 36, column 19) for
      % vo WITH [z := vi`z + vz]
      % expected type  {nvo | vect2(nvo) /= zero IMPLIES vs_only?(vo)(nvo)}
  vs_circle_TCC3: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, eps: Sign, v: Vect3):
      Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND eps = sign(s`z)) AND v = vo - vi
       IMPLIES
       (FORALL (res: bool, vz: real):
          res AND
           vz = vs_only(s, vect2(v), Theta_D(vect2(s), vect2(v), 1), eps)`2
            AND
            res = vs_only(s, vect2(v), Theta_D(vect2(s), vect2(v), 1), eps)`1
           IMPLIES
           vect2((vo WITH [z := vi`z + vz])) /= zero IMPLIES
            vs_only?(vo)((vo WITH [z := vi`z + vz])));

  % Subtype TCC generated (at line 37, column 12) for  zero
      % expected type  {nvo | vect2(nvo) /= zero IMPLIES vs_only?(vo)(nvo)}
  vs_circle_TCC4: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, eps: Sign, v: Vect3):
      Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND eps = sign(s`z)) AND v = vo - vi
       IMPLIES
       (FORALL (res: bool, vz: real):
          NOT res AND
           vz = vs_only(s, vect2(v), Theta_D(vect2(s), vect2(v), 1), eps)`2
            AND
            res = vs_only(s, vect2(v), Theta_D(vect2(s), vect2(v), 1), eps)`1
           IMPLIES vect2(zero) /= zero IMPLIES vs_only?(vo)(zero));

  % Subtype TCC generated (at line 39, column 9) for  zero
      % expected type  {nvo | vect2(nvo) /= zero IMPLIES vs_only?(vo)(nvo)}
  vs_circle_TCC5: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, eps: Sign, v: Vect3):
      NOT Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND eps = sign(s`z)) AND v = vo - vi
       IMPLIES vect2(zero) /= zero IMPLIES vs_only?(vo)(zero);


body:
  %------------------------------------------------------------------------------
  % vertical_cr.pvs
  % ACCoRD v.1.0
  % Vertical resolution algorithm
  %------------------------------------------------------------------------------

  vertical_cr[D,H: posreal] : THEORY
  BEGIN

    IMPORTING vs_circle[D,H],
              gs_circle[D,H],
              trk_circle[D,H],
              opt_vertical[D,H]

    sp        : VAR Sp_vect3 % 3-D separation
    nvo       : VAR Vect3
    vo,vi     : VAR Nzv2_vect3
    epsh,epsv : VAR Sign

    %------------%
    % ALGORITHMS %
    %------------%

    hor_circle?(sp,vo,vi,epsh,epsv)(nvo) : bool =
      gs_vertical?(sp,vo,vi,epsh,epsv)(nvo) OR
      trk_vertical?(sp,vo,vi,epsh,epsv)(nvo) OR
      opt_vertical?(sp,vo,vi,epsh,epsv)(nvo)

    hor_circle_horizontal_only : LEMMA
      hor_circle?(sp,vo,vi,epsh,epsv)(nvo) IMPLIES
        horizontal_only?(vo)(nvo)

    vertical_cr?(sp,vo,vi,epsh,epsv)(nvo) : bool = 
      vs_circle?(sp,vo,vi,epsv)(nvo) OR
      hor_circle?(sp,vo,vi,epsh,epsv)(nvo)

    vertical_cr_meets_vertical_criterion: THEOREM
      horizontal_conflict?(sp,vo-vi) AND
      vertical_cr?(sp,vo,vi,epsh,epsv)(nvo)
      IMPLIES 
        vertical_criterion?(epsv)(sp,vo-vi)(nvo-vi)

    hor_circle_meets_horizontal_criterion: THEOREM
      horizontal_sep?(sp) AND
      hor_circle?(sp,vo,vi,epsh,epsv)(nvo)
      IMPLIES 
        horizontal_criterion?(sp,epsh)(nvo-vo)

  END vertical_cr


body:
  %------------------------------------------------------------------------------
  % opt_line.pvs
  % ACCoRD v.1.0
  %
  % Optimal lines solutions are ground speed/track optimal solutions that are 
  % tangent to the protected zone.
  %------------------------------------------------------------------------------

  opt_line[D: posreal] : THEORY
  BEGIN
    
    IMPORTING opt_trk_gs[D],
              tangent_line[D]

    sp      : VAR Sp_vect2
    eps     : VAR Sign
    vo,vi,
    nvo     : VAR Vect2

    %------------%
    % ALGORITHMS %
    %------------%

    % zero indicates no optimal horizontal solution

    opt_line_eps(sp,vo,vi,eps): {nvo:Vect2 | nz_vect2?(nvo) => 
                                             optimal?(vo,tangent_line(sp,eps))(nvo)} =
      LET (k,nvo) = opt_trk_gs_line(tangent_line(sp,eps),vo,vi) IN
      IF k >= 0 THEN
        nvo
      ELSE
        zero 
      ENDIF


    opt_line_eps?(sp,vo,vi,eps)(nvo) : bool =
      nz_vect2?(nvo) AND
      nvo = opt_line_eps(sp,vo,vi,eps)

    %----------%
    % LEMMAS   %
    %----------%

    opt_line_eps_tangent_line: LEMMA 
      opt_line_eps?(sp,vo,vi,eps)(nvo) 
      IMPLIES
        tangent_line?(sp,nvo-vi,eps)  

    opt_line_is_line_solution: LEMMA 
      opt_line_eps?(sp,vo,vi,eps)(nvo) 
      IMPLIES
        line_solution?(sp,nvo-vi,eps)              

  END opt_line

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

  % Subtype TCC generated (at line 30, column 6) for  nvo
      % expected type  {nvo: Vect2 |
                     %          nvo /= zero =>
                     %           optimal?(vo, tangent_line(sp, eps))(nvo)}
  opt_line_eps_TCC1: OBLIGATION
    FORALL (sp: Sp_vect2[D], vo: Vect2, vi: Vect2, eps: Sign, k: real,
            nvo: (optimal?(vo, tangent_line[D](sp, eps)))):
      k >= 0 AND
       nvo = opt_trk_gs_line(tangent_line(sp, eps), vo, vi)`2 AND
        k = opt_trk_gs_line(tangent_line(sp, eps), vo, vi)`1
       IMPLIES nvo /= zero => optimal?(vo, tangent_line[D](sp, eps))(nvo);

  % Subtype TCC generated (at line 32, column 6) for  zero
      % expected type  {nvo: Vect2 |
                     %          nvo /= zero =>
                     %           optimal?(vo, tangent_line(sp, eps))(nvo)}
  opt_line_eps_TCC2: OBLIGATION
    FORALL (sp: Sp_vect2[D], vo: Vect2, vi: Vect2, eps: Sign, k: real,
            nvo: (optimal?(vo, tangent_line[D](sp, eps)))):
      NOT k >= 0 AND
       nvo = opt_trk_gs_line(tangent_line(sp, eps), vo, vi)`2 AND
        k = opt_trk_gs_line(tangent_line(sp, eps), vo, vi)`1
       IMPLIES zero /= zero => optimal?(vo, tangent_line[D](sp, eps))(zero);


body:
  %------------------------------------------------------------------------------
  % horizontal_cr.pvs
  % ACCoRD v.1.0
  % Horizontal resolution algorithms
  %------------------------------------------------------------------------------

  horizontal_cr[D:posreal] : THEORY

  BEGIN

    IMPORTING gs_line[D], 
              trk_line[D], 
              opt_line[D]

    sp      : VAR Sp_vect2
    vo,vi,
    nvo     : VAR Vect2
    eps     : VAR Sign

    %------------%
    % ALGORITHMS %
    %------------%

    horizontal_cr?(sp,vo,vi,eps)(nvo) : bool =
      gs_line_eps?(sp,vo,vi,eps)(nvo) OR
      trk_line_eps?(sp,vo,vi,eps)(nvo) OR
      opt_line_eps?(sp,vo,vi,eps)(nvo) 

    %--------------------------%
    % LEMMAS                   %
    %--------------------------%

    horizontal_cr_is_line_solution: THEOREM
      horizontal_cr?(sp,vo,vi,eps)(nvo)
      IMPLIES 
        line_solution?(sp,nvo-vi,eps)

  END horizontal_cr


body:
  %------------------------------------------------------------------------------
  % cr3d.pvs
  % ACCoRD v.1.0
  % Conflict resolution correctness
  %------------------------------------------------------------------------------

  cr3d[D,H:posreal] : THEORY
  BEGIN

    IMPORTING horizontal_cr[D],
              vertical_cr[D,H],
              criteria_3D[D,H]

    sp        : VAR Sp_vect3 % 3-D separation
    nvo,nvi   : VAR Vect3
    vo,vi     : VAR Nzv2_vect3
    hst       : VAR Horizontal_Strategy
    vst       : VAR Vertical_Strategy
    epsh,epsv : VAR Sign

    cr?(sp,vo,vi,hst,vst)(nvo) : bool =
      horizontal_sep?(sp) AND horizontal_cr?(sp,vo,vi,hst(sp,vo-vi))(nvo) OR
      vertical_cr?(sp,vo,vi,hst(sp,vo-vi),vst(sp,vo-vi))(nvo)

    cr_satifies_criterion_3D : THEOREM
      conflict?(sp,vo-vi) AND
      cr?(sp,vo,vi,hst,vst)(nvo) IMPLIES
      criterion_3D?(sp,vo-vi,hst(sp,vo-vi),vst(sp,vo-vi))(nvo-vi)

    cr3d?(sp,vo,vi)(nvo) : bool =
      cr?(sp,vo,vi,horizontalCoordination,verticalCoordinationConflict)(nvo)

    cr3d_satifies_criterion_3D : THEOREM
      conflict?(sp,vo-vi) AND
      cr3d?(sp,vo,vi)(nvo) IMPLIES
      criterion_3D?(sp,vo-vi,horizontalCoordination(sp,vo-vi),verticalCoordinationConflict(sp,vo-vi))(nvo-vi)

    %--------------------------%
    % THEOREM: Independence    %
    %--------------------------%

    cr_independence: THEOREM
      conflict?(sp,vo-vi) AND
      cr?(sp,vo,vi,hst,vst)(nvo)
      IMPLIES 
        NOT conflict?(sp,nvo-vi)

    cr3d_independence: THEOREM
      conflict?(sp,vo-vi) AND
      cr3d?(sp,vo,vi)(nvo)
      IMPLIES 
        NOT conflict?(sp,nvo-vi)

    %--------------------------%
    % THEOREM: Coordination    %
    %--------------------------%

    cr_coordination: THEOREM
      conflict?(sp,vo-vi) AND
      cr?(sp,vo,vi,hst,vst)(nvo) AND
      cr?(-sp,vi,vo,hst,vst)(nvi)
      IMPLIES 
        NOT conflict?(sp,nvo-nvi)

    cr3d_coordination: THEOREM
      conflict?(sp,vo-vi) AND
      cr3d?(sp,vo,vi)(nvo) AND
      cr3d?(-sp,vi,vo)(nvi)
      IMPLIES 
        NOT conflict?(sp,nvo-nvi)

  END cr3d


body:
  % ----------------------------------------------------------%
  % tca_3D - Time of closest approach for cylindrical distance
  % between the two aircraft.
  % ----------------------------------------------------------% 

  tca_3D[D,H:posreal]  : THEORY 
  BEGIN

    IMPORTING circle_criterion[D,H],
    	    cd_vertical,
              omega_2D,
  	    util,
  	    analysis@metric_space_real_fun[real,real_dist],
  	    analysis@real_fun_continuity_equiv,
  	    analysis@continuity_of_max_min[real,real_dist]

    s,v 	    : VAR Vect3       
    t,t1,t2,r,
    B1,B2	    : VAR real
    eps	    : VAR Sign
    nnt,pt    : VAR nnreal

  cyl_norm_sq(s): nnreal = max(sqv(vect2(s))/sq(D),sq(s`z)/sq(H))

  cyl_norm_sq_diff_cont: LEMMA
  		       continuous?(LAMBDA (t:real): (sqv(vect2(s) + t*vect2(v))/sq(D) - sq(s`z+t*v`z)/sq(H)),fullset[real])

  cyl_norm_sq_IVT1: LEMMA cyl_norm_sq(s+t1*v) = sqv(vect2(s)+t1*vect2(v))/sq(D) AND cyl_norm_sq(s+t2*v) /= sqv(vect2(s)+t2*vect2(v))/sq(D)
  		  IMPLIES (EXISTS (t:real): ((t1<=t AND t<=t2) OR (t2<=t AND t<=t1)) AND sqv(vect2(s)+t*vect2(v))/sq(D) = sq(s`z+t*v`z)/sq(H))

  cyl_norm_sq_IVT2: LEMMA cyl_norm_sq(s+t1*v) = sq(s`z+t1*v`z)/sq(H) AND cyl_norm_sq(s+t2*v) /= sq(s`z+t2*v`z)/sq(H)
  		  IMPLIES (EXISTS (t:real): ((t1<=t AND t<=t2) OR (t2<=t AND t<=t1)) AND sqv(vect2(s)+t*vect2(v))/sq(D) = sq(s`z+t*v`z)/sq(H))

  cyl_norm_sq_fun(s,v)(t) : nnreal = cyl_norm_sq(s+t*v)

  cyl_norm_sq_fun_convex: LEMMA convex?(cyl_norm_sq_fun(s,v))

  cyl_norm_sq_fun_cont: LEMMA continuous?(cyl_norm_sq_fun(s,v),fullset[real])

  cyl_norm_min_exists: LEMMA B1<=B2 IMPLIES (EXISTS (t:real): B1<=t AND t<=B2 AND (FORALL (r:real): B1<=r AND r<=B2 IMPLIES cyl_norm_sq_fun(s,v)(r) >= cyl_norm_sq_fun(s,v)(t)))

  cyl_norm_min_exists_inf: LEMMA EXISTS (tz: nnreal): FORALL (nnt:nnreal): cyl_norm_sq_fun(s,v)(nnt) >= cyl_norm_sq_fun(s,v)(tz)

  conflict_at_cyl_norm_sq: LEMMA
  		      conflict_at?(s,v,t) IFF cyl_norm_sq(s+t*v) < 1

  Min_Info: TYPE = [# min_time : nnreal , min_dist : nnreal #]

  info(s,v,nnt): Min_Info = (# min_time := nnt, min_dist := cyl_norm_sq(s+nnt*v) #)

  MI1,MI2 : VAR Min_Info

  minimum_info(MI1,MI2): {MI : Min_Info | (MI = MI1 OR MI = MI2) AND MI`min_dist <= MI1`min_dist AND MI`min_dist <= MI2`min_dist}
  		       = IF MI1`min_dist <= MI2`min_dist THEN MI1
  		         ELSE MI2 ENDIF

  horizontal_min_info(s,v) : {MI : Min_Info | MI`min_dist <= info(s,v,0)`min_dist AND 
  			       	 	  (vect2(v) /= zero AND horizontal_tca(s,v)>=0 IMPLIES MI`min_dist<=info(s,v,horizontal_tca(s,v))`min_dist)}=
  			 IF vect2(v) = zero OR (vect2(v) /= zero AND horizontal_tca(s,v) <= 0) THEN
  			    info(s,v,0)
  			 ELSE minimum_info(info(s,v,horizontal_tca(s,v)),info(s,v,0))
  			 ENDIF

  horiz_vert_min_info(s,v) : {MI : Min_Info | MI`min_dist <= info(s,v,0)`min_dist AND 
  			       	 	  (vect2(v) /= zero AND horizontal_tca(s,v)>=0 IMPLIES MI`min_dist<=info(s,v,horizontal_tca(s,v))`min_dist)
  					  AND (v`z/=0 AND -s`z/v`z>=0 IMPLIES MI`min_dist <= info(s,v,-s`z/v`z)`min_dist)} =
  			 IF v`z = 0 OR (v`z /= 0 AND -s`z/v`z <= 0) THEN
  			    horizontal_min_info(s,v)
  			 ELSE
  				minimum_info(horizontal_min_info(s,v),info(s,v,-s`z/v`z))
  			 ENDIF

  cyl_intersect_time(s,v,eps) : real = 
  			LET
  				a = sqv(vect2(v))/sq(D) - sq(v`z)/sq(H),
  				b = vect2(s)*vect2(v)/sq(D) - s`z*v`z/sq(H),
  				c = sqv(vect2(s))/sq(D) - sq(s`z)/sq(H)
  			IN
  				IF a = 0 AND b = 0 THEN 0
  				ELSIF a = 0 THEN -c/(2*b)
  				ELSIF discr2b(a,b,c) < 0 THEN 0
  				ELSE root2b(a,b,c,sign(a)*eps) ENDIF % This uses sign(a)*eps instead of just eps, so that the LT lemma will prove

  cyl_intersect_time_lt: LEMMA
  		       cyl_intersect_time(s,v,-1) <= cyl_intersect_time(s,v,1)

  cyl_intersect_time_id : LEMMA
  		      (EXISTS (t1:real): sqv(vect2(s+t1*v))/sq(D) /= sq((s+t1*v)`z)/sq(H))
  		      AND
  		      sqv(vect2(s + t*v))/sq(D) = sq((s+t*v)`z)/sq(H) IMPLIES
  		      (EXISTS (eps): t = cyl_intersect_time(s,v,eps))

  cyl_intersect_min_info(s,v) : {MI : Min_Info | FORALL (eps:Sign): cyl_intersect_time(s,v,eps)>0 IMPLIES
  			    MI`min_dist<=info(s,v,cyl_intersect_time(s,v,eps))`min_dist} =
  			  LET
  			    mt1 = cyl_intersect_time(s,v,-1),
  			    mt2 = cyl_intersect_time(s,v,1)
  			  IN
  			    IF mt2 <= 0 THEN horizontal_min_info(s,v)
  			    ELSIF mt1 <=0 THEN (# min_time := mt2, min_dist := cyl_norm_sq(s+mt2*v) #)
  			    ELSE
  			    minimum_info((# min_time := mt1, min_dist := cyl_norm_sq(s+mt1*v) #),
  			    		    (# min_time := mt2, min_dist := cyl_norm_sq(s+mt2*v) #))
  			    ENDIF

  tca_3D(s,v) : nnreal = minimum_info(horiz_vert_min_info(s,v),cyl_intersect_min_info(s,v))`min_time

  tca_3D_id : LEMMA nnt = 0 OR (vect2(v) /= zero AND nnt = -(vect2(s)*vect2(v))/sqv(vect2(v))) OR (v`z /= 0 AND nnt = -(s`z*v`z)/sq(v`z))
  	  OR sqv(vect2(s+nnt*v))/sq(D) = sq((s+nnt*v)`z)/sq(H) IMPLIES
  	  cyl_norm_sq(s + nnt*v) >= cyl_norm_sq(s+tca_3D(s,v)*v)

  tca_3D_vect2_zero: LEMMA vect2(v)=zero AND cyl_norm_sq_fun(s,v)(nnt) = sqv(vect2(s+nnt*v))/sq(D) IMPLIES
  		   cyl_norm_sq_fun(s,v)(nnt) >= cyl_norm_sq_fun(s,v)(tca_3D(s,v))

  tca_3D_vz_zero: LEMMA v`z=0 AND cyl_norm_sq_fun(s,v)(nnt) = sq((s+nnt*v)`z)/sq(H) IMPLIES
  		   cyl_norm_sq_fun(s,v)(nnt) >= cyl_norm_sq_fun(s,v)(tca_3D(s,v))

  tca_3D_def: LEMMA cyl_norm_sq(s + nnt*v) >= cyl_norm_sq(s+tca_3D(s,v)*v)

  tca_3D_conflict: LEMMA conflict?(s,v) IFF cyl_norm_sq(s + tca_3D(s,v)*v) < 1

  tca_3D_conflict_at: LEMMA conflict?(s,v) IFF conflict_at?(s,v,tca_3D(s,v))

  % for nonnegative times, cyl_norm_sq_fun is decreasing to the left of tca_3D
  % and increasing to the right.

  tca_3D_left_decreasing: LEMMA nnt<=pt AND pt<=tca_3D(s,v) IMPLIES
  			cyl_norm_sq_fun(s,v)(nnt)>=cyl_norm_sq_fun(s,v)(pt)

  tca_3D_right_increasing: LEMMA tca_3D(s,v)<=nnt AND nnt<=pt IMPLIES
  			cyl_norm_sq_fun(s,v)(nnt)<=cyl_norm_sq_fun(s,v)(pt)








  END tca_3D

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

  % Assuming TCC generated (at line 13, column 5) for
      % analysis@metric_space_real_fun[real, real_dist]
      % generated from assumption metric_space_real_fun.fullset_metric_space
  IMP_metric_space_real_fun_TCC1: OBLIGATION
    metric_space?[real, real_dist](fullset[real]);

  % Subtype TCC generated (at line 54, column 48) for  MI1
      % expected type  {MI: Min_Info |
                     %          (MI = MI1 OR MI = MI2) AND
                     %           MI`min_dist <= MI1`min_dist AND
                     %            MI`min_dist <= MI2`min_dist}
  minimum_info_TCC1: OBLIGATION
    FORALL (MI1: Min_Info, MI2: Min_Info):
      MI1`min_dist <= MI2`min_dist IMPLIES
       MI1`min_dist <= MI1`min_dist AND MI1`min_dist <= MI2`min_dist;

  % Subtype TCC generated (at line 55, column 16) for  MI2
      % expected type  {MI: Min_Info |
                     %          (MI = MI1 OR MI = MI2) AND
                     %           MI`min_dist <= MI1`min_dist AND
                     %            MI`min_dist <= MI2`min_dist}
  minimum_info_TCC2: OBLIGATION
    FORALL (MI1: Min_Info, MI2: Min_Info):
      NOT MI1`min_dist <= MI2`min_dist IMPLIES
       MI2`min_dist <= MI1`min_dist AND MI2`min_dist <= MI2`min_dist;

  % Subtype TCC generated (at line 60, column 7) for  info(s, v, 0)
      % expected type  {MI: Min_Info |
                     %          MI`min_dist <= info(s, v, 0)`min_dist AND
                     %           (vect2(v) /= zero AND
                     %             horizontal_tca(vect2(s), vect2(v)) >= 0
                     %             IMPLIES
                     %             MI`min_dist <=
                     %              info(s,
                     %                   v,
                     %                   horizontal_tca
                     %                   (vect2(s), vect2(v)))`min_dist)}
  horizontal_min_info_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      vect2(v) = zero OR
       (vect2(v) /= zero AND horizontal_tca(vect2(s), vect2(v)) <= 0)
       IMPLIES
       info(s, v, 0)`min_dist <= info(s, v, 0)`min_dist AND
        (vect2(v) /= zero AND horizontal_tca(vect2(s), vect2(v)) >= 0 IMPLIES
          info(s, v, 0)`min_dist <=
           info(s, v, horizontal_tca(vect2(s), vect2(v)))`min_dist);

  % Subtype TCC generated (at line 61, column 48) for  vect2(v)
      % expected type  Nz_vect2
  horizontal_min_info_TCC2: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT vect2(v) = zero AND
       NOT (vect2(v) /= zero AND horizontal_tca(vect2(s), vect2(v)) <= 0)
       IMPLIES vect2(v) /= zero;

  % Subtype TCC generated (at line 61, column 31) for
      % horizontal_tca(vect2(s), vect2(v))
      % expected type  nnreal
  horizontal_min_info_TCC3: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT vect2(v) = zero AND
       NOT (vect2(v) /= zero AND horizontal_tca(vect2(s), vect2(v)) <= 0)
       IMPLIES horizontal_tca(vect2(s), vect2(v)) >= 0;

  % Subtype TCC generated (at line 61, column 9) for
      % minimum_info(info(s, v, horizontal_tca(vect2(s), vect2(v))),
      %              info(s, v, 0))
      % expected type  {MI: Min_Info |
                     %          MI`min_dist <= info(s, v, 0)`min_dist AND
                     %           (vect2(v) /= zero AND
                     %             horizontal_tca(vect2(s), vect2(v)) >= 0
                     %             IMPLIES
                     %             MI`min_dist <=
                     %              info(s,
                     %                   v,
                     %                   horizontal_tca
                     %                   (vect2(s), vect2(v)))`min_dist)}
  horizontal_min_info_TCC4: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT vect2(v) = zero AND
       NOT (vect2(v) /= zero AND horizontal_tca(vect2(s), vect2(v)) <= 0)
       IMPLIES
       minimum_info(info(s, v, horizontal_tca(vect2(s), vect2(v))),
                    info(s, v, 0))`min_dist
        <= info(s, v, 0)`min_dist
        AND
        (vect2(v) /= zero AND horizontal_tca(vect2(s), vect2(v)) >= 0 IMPLIES
          minimum_info(info(s, v, horizontal_tca(vect2(s), vect2(v))),
                       info(s, v, 0))`min_dist
           <= info(s, v, horizontal_tca(vect2(s), vect2(v)))`min_dist);

  % Subtype TCC generated (at line 68, column 7) for
      % horizontal_min_info(s, v)
      % expected type  {MI: Min_Info |
                     %          MI`min_dist <= info(s, v, 0)`min_dist AND
                     %           (vect2(v) /= zero AND
                     %             horizontal_tca(vect2(s), vect2(v)) >= 0
                     %             IMPLIES
                     %             MI`min_dist <=
                     %              info(s,
                     %                   v,
                     %                   horizontal_tca
                     %                   (vect2(s), vect2(v)))`min_dist)
                     %            AND
                     %            (v`z /= 0 AND -s`z / v`z >= 0 IMPLIES
                     %              MI`min_dist <=
                     %               info(s, v, -s`z / v`z)`min_dist)}
  horiz_vert_min_info_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      v`z = 0 OR (v`z /= 0 AND -s`z / v`z <= 0) IMPLIES
       horizontal_min_info(s, v)`min_dist <= info(s, v, 0)`min_dist AND
        (vect2(v) /= zero AND horizontal_tca(vect2(s), vect2(v)) >= 0 IMPLIES
          horizontal_min_info(s, v)`min_dist <=
           info(s, v, horizontal_tca(vect2(s), vect2(v)))`min_dist)
         AND
         (v`z /= 0 AND -s`z / v`z >= 0 IMPLIES
           horizontal_min_info(s, v)`min_dist <=
            info(s, v, -s`z / v`z)`min_dist);

  % Subtype TCC generated (at line 70, column 56) for  v`z
      % expected type  nznum
  horiz_vert_min_info_TCC2: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT v`z = 0 AND NOT (v`z /= 0 AND -s`z / v`z <= 0) IMPLIES v`z /= 0;

  % Subtype TCC generated (at line 70, column 51) for  -s`z / v`z
      % expected type  nnreal
  horiz_vert_min_info_TCC3: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT v`z = 0 AND NOT (v`z /= 0 AND -s`z / v`z <= 0) IMPLIES
       -s`z / v`z >= 0;

  % Subtype TCC generated (at line 70, column 4) for
      % minimum_info(horizontal_min_info(s, v), info(s, v, -s`z / v`z))
      % expected type  {MI: Min_Info |
                     %          MI`min_dist <= info(s, v, 0)`min_dist AND
                     %           (vect2(v) /= zero AND
                     %             horizontal_tca(vect2(s), vect2(v)) >= 0
                     %             IMPLIES
                     %             MI`min_dist <=
                     %              info(s,
                     %                   v,
                     %                   horizontal_tca
                     %                   (vect2(s), vect2(v)))`min_dist)
                     %            AND
                     %            (v`z /= 0 AND -s`z / v`z >= 0 IMPLIES
                     %              MI`min_dist <=
                     %               info(s, v, -s`z / v`z)`min_dist)}
  horiz_vert_min_info_TCC4: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT v`z = 0 AND NOT (v`z /= 0 AND -s`z / v`z <= 0) IMPLIES
       minimum_info(horizontal_min_info(s, v),
                    info(s, v, -s`z / v`z))`min_dist
        <= info(s, v, 0)`min_dist
        AND
        (vect2(v) /= zero AND horizontal_tca(vect2(s), vect2(v)) >= 0 IMPLIES
          minimum_info(horizontal_min_info(s, v),
                       info(s, v, -s`z / v`z))`min_dist
           <= info(s, v, horizontal_tca(vect2(s), vect2(v)))`min_dist)
         AND
         (v`z /= 0 AND -s`z / v`z >= 0 IMPLIES
           minimum_info(horizontal_min_info(s, v),
                        info(s, v, -s`z / v`z))`min_dist
            <= info(s, v, -s`z / v`z)`min_dist);

  % Subtype TCC generated (at line 80, column 25) for  (2 * b)
      % expected type  nznum
  cyl_intersect_time_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3, a: real):
      a = sqv(vect2(v)) / sq(D) - sq(v`z) / sq(H) IMPLIES
       (FORALL (b: real):
          b = vect2(s) * vect2(v) / sq(D) - s`z * v`z / sq(H) IMPLIES
           (FORALL (c: real):
              a = 0 AND
               NOT (a = 0 AND b = 0) AND
                c = sqv(vect2(s)) / sq(D) - sq(s`z) / sq(H)
               IMPLIES (2 * b) /= 0));

  % Subtype TCC generated (at line 81, column 18) for  a
      % expected type  nzreal
  cyl_intersect_time_TCC2: OBLIGATION
    FORALL (s: Vect3, v: Vect3, a: real):
      a = sqv(vect2(v)) / sq(D) - sq(v`z) / sq(H) IMPLIES
       (FORALL (b: real):
          b = vect2(s) * vect2(v) / sq(D) - s`z * v`z / sq(H) IMPLIES
           (FORALL (c: real):
              NOT a = 0 AND
               NOT (a = 0 AND b = 0) AND
                c = sqv(vect2(s)) / sq(D) - sq(s`z) / sq(H)
               IMPLIES a /= 0));

  % Subtype TCC generated (at line 82, column 20) for  c
      % expected type  {c: real | discr2b(a, b, c) >= 0}
  cyl_intersect_time_TCC3: OBLIGATION
    FORALL (s: Vect3, v: Vect3, a: real):
      a = sqv(vect2(v)) / sq(D) - sq(v`z) / sq(H) IMPLIES
       (FORALL (b: real):
          b = vect2(s) * vect2(v) / sq(D) - s`z * v`z / sq(H) IMPLIES
           (FORALL (c: real):
              NOT discr2b(a, b, c) < 0 AND
               NOT a = 0 AND
                NOT (a = 0 AND b = 0) AND
                 c = sqv(vect2(s)) / sq(D) - sq(s`z) / sq(H)
               IMPLIES discr2b(a, b, c) >= 0));

  % Subtype TCC generated (at line 94, column 29) for
      % cyl_intersect_time(s, v, eps)
      % expected type  nnreal
  cyl_intersect_min_info_TCC1: OBLIGATION
    FORALL (s, v, eps: Sign):
      cyl_intersect_time(s, v, eps) > 0 IMPLIES
       cyl_intersect_time(s, v, eps) >= 0;

  % Subtype TCC generated (at line 99, column 24) for
      % horizontal_min_info(s, v)
      % expected type  {MI: Min_Info |
                     %          FORALL (eps: Sign):
                     %            cyl_intersect_time(s, v, eps) > 0 IMPLIES
                     %             MI`min_dist <=
                     %              info(s,
                     %                   v,
                     %                   cyl_intersect_time
                     %                   (s, v, eps))`min_dist}
  cyl_intersect_min_info_TCC2: OBLIGATION
    FORALL (s, v: Vect3, mt1: real):
      mt1 = cyl_intersect_time(s, v, -1) IMPLIES
       (FORALL (mt2: real):
          mt2 <= 0 AND mt2 = cyl_intersect_time(s, v, 1) IMPLIES
           (FORALL (eps: Sign):
              cyl_intersect_time(s, v, eps) > 0 IMPLIES
               horizontal_min_info(s, v)`min_dist <=
                info(s, v, cyl_intersect_time(s, v, eps))`min_dist));

  % Subtype TCC generated (at line 100, column 41) for  mt2
      % expected type  nnreal
  cyl_intersect_min_info_TCC3: OBLIGATION
    FORALL (s, v: Vect3, mt1: real):
      mt1 = cyl_intersect_time(s, v, -1) IMPLIES
       (FORALL (mt2: real):
          mt1 <= 0 AND NOT mt2 <= 0 AND mt2 = cyl_intersect_time(s, v, 1)
           IMPLIES mt2 >= 0);

  % Subtype TCC generated (at line 100, column 26) for
      % (# min_time := mt2, min_dist := cyl_norm_sq(s + mt2 * v) #)
      % expected type  {MI: Min_Info |
                     %          FORALL (eps: Sign):
                     %            cyl_intersect_time(s, v, eps) > 0 IMPLIES
                     %             MI`min_dist <=
                     %              info(s,
                     %                   v,
                     %                   cyl_intersect_time
                     %                   (s, v, eps))`min_dist}
  cyl_intersect_min_info_TCC4: OBLIGATION
    FORALL (s, v: Vect3, mt1: real):
      mt1 = cyl_intersect_time(s, v, -1) IMPLIES
       (FORALL (mt2: real):
          mt1 <= 0 AND NOT mt2 <= 0 AND mt2 = cyl_intersect_time(s, v, 1)
           IMPLIES
           (FORALL (eps: Sign):
              cyl_intersect_time(s, v, eps) > 0 IMPLIES
               cyl_norm_sq(s + mt2 * v) <=
                info(s, v, cyl_intersect_time(s, v, eps))`min_dist));

  % Subtype TCC generated (at line 102, column 35) for  mt1
      % expected type  nnreal
  cyl_intersect_min_info_TCC5: OBLIGATION
    FORALL (s, v: Vect3, mt1: real):
      mt1 = cyl_intersect_time(s, v, -1) IMPLIES
       (FORALL (mt2: real):
          NOT mt1 <= 0 AND NOT mt2 <= 0 AND mt2 = cyl_intersect_time(s, v, 1)
           IMPLIES mt1 >= 0);

  % Subtype TCC generated (at line 103, column 28) for  mt2
      % expected type  nnreal
  cyl_intersect_min_info_TCC6: OBLIGATION
    FORALL (s, v: Vect3, mt1: real):
      mt1 = cyl_intersect_time(s, v, -1) IMPLIES
       (FORALL (mt2: real):
          NOT mt1 <= 0 AND NOT mt2 <= 0 AND mt2 = cyl_intersect_time(s, v, 1)
           IMPLIES mt2 >= 0);

  % Subtype TCC generated (at line 102, column 7) for
      % minimum_info((# min_time := mt1,
      %                 min_dist := cyl_norm_sq(s + mt1 * v) #),
      %              (# min_time := mt2,
      %                 min_dist := cyl_norm_sq(s + mt2 * v) #))
      % expected type  {MI: Min_Info |
                     %          FORALL (eps: Sign):
                     %            cyl_intersect_time(s, v, eps) > 0 IMPLIES
                     %             MI`min_dist <=
                     %              info(s,
                     %                   v,
                     %                   cyl_intersect_time
                     %                   (s, v, eps))`min_dist}
  cyl_intersect_min_info_TCC7: OBLIGATION
    FORALL (s, v: Vect3, mt1: real):
      mt1 = cyl_intersect_time(s, v, -1) IMPLIES
       (FORALL (mt2: real):
          NOT mt1 <= 0 AND NOT mt2 <= 0 AND mt2 = cyl_intersect_time(s, v, 1)
           IMPLIES
           (FORALL (eps: Sign):
              cyl_intersect_time(s, v, eps) > 0 IMPLIES
               minimum_info((# min_time := mt1,
                               min_dist := cyl_norm_sq(s + mt1 * v) #),
                            (# min_time := mt2,
                               min_dist
                                 := cyl_norm_sq(s + mt2 * v) #))`min_dist
                <= info(s, v, cyl_intersect_time(s, v, eps))`min_dist));

  % Subtype TCC generated (at line 108, column 78) for  sqv(vect2(v))
      % expected type  nznum
  tca_3D_id_TCC1: OBLIGATION
    FORALL (nnt: nnreal, v: Vect3):
      NOT nnt = 0 AND vect2(v) /= zero IMPLIES sqv(vect2(v)) /= 0;

  % Subtype TCC generated (at line 108, column 127) for  sq(v`z)
      % expected type  nznum
  tca_3D_id_TCC2: OBLIGATION
    FORALL (nnt: nnreal, s, v: Vect3):
      NOT nnt = 0 AND
       NOT (vect2(v) /= zero AND
             nnt = -(vect2(s) * vect2(v)) / sqv(vect2(v)))
        AND v`z /= 0
       IMPLIES sq(v`z) /= 0;


body:
  % ----------------------------------------------------------%
  % tca_3D_interval - Time of closest approach for cylindrical distance
  % between the two aircraft during a time interval [B,T]
  % ----------------------------------------------------------% 

  tca_3D_interval[D,H:posreal,B:nnreal,T: {AB: posreal|AB>B}]  : THEORY 
  BEGIN

    IMPORTING tca_3D[D,H],
    	    cd3d[D,H,B,T]

    s,v 	    : VAR Vect3       
    t,t1,t2,r : VAR Lookahead[B,T]
    B1,B2	    : VAR real
    eps	    : VAR Sign
    nnt	    : VAR nnreal

    tca_3D_interval(s,v): Lookahead[B,T] = 
    			LET tca = tca_3D(s,v)
  			IN
  			    IF B<=tca AND tca<=T THEN tca
  			    ELSIF tca<B THEN B
  			    ELSE T
  			    ENDIF

    tca_3D_interval_def: LEMMA cyl_norm_sq(s + t*v) >= cyl_norm_sq(s+tca_3D_interval(s,v)*v)

    tca_3D_interval_conflict: LEMMA conflict_3D?(s,v) IFF cyl_norm_sq(s + tca_3D_interval(s,v)*v) < 1

    tca_3D_interval_conflict_at: LEMMA conflict_3D?(s,v) IFF conflict_at?(s,v,tca_3D_interval(s,v))







  END tca_3D_interval

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

  % Subtype TCC generated (at line 21, column 33) for  tca
      % expected type  Lookahead[B, T]
  tca_3D_interval_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3, tca: nnreal):
      B <= tca AND tca <= T AND tca = tca_3D(s, v) IMPLIES
       B <= tca AND tca <= T;

  % Subtype TCC generated (at line 22, column 24) for  B
      % expected type  Lookahead[B, T]
  tca_3D_interval_TCC2: OBLIGATION
    FORALL (s: Vect3, v: Vect3, tca: nnreal):
      tca < B AND NOT (B <= tca AND tca <= T) AND tca = tca_3D(s, v) IMPLIES
       B <= B AND B <= T;

  % Subtype TCC generated (at line 23, column 12) for  T
      % expected type  Lookahead[B, T]
  tca_3D_interval_TCC3: OBLIGATION
    FORALL (s: Vect3, v: Vect3, tca: nnreal):
      NOT tca < B AND NOT (B <= tca AND tca <= T) AND tca = tca_3D(s, v)
       IMPLIES B <= T AND T <= T;


body:
  delay_3D[D,H:posreal]  : THEORY 

  % Shows that if the max delay will result in a conflict free maneuver
  % with a given new velocity, then any turn off to that velocity before
  % then will also be conflict free.

  BEGIN

    IMPORTING cd3d

    nnt: VAR posreal % conflict time
    rt : VAR posreal % future resolution time


    s,v,nv,so,si,vo,vi,nvo,nvi: VAR Vect3


    delay_conflict_free_rel: LEMMA
      nnt <= rt AND
      conflict?[D,H](s,v) AND
      (NOT conflict_3D?[D,H,0,rt](s,v)) AND
      (NOT conflict?[D,H](s + rt*v,nv))
      IMPLIES
      (NOT conflict_3D?[D,H,0,nnt](s,v))
      AND
      (NOT conflict?[D,H](s+nnt*v,nv))

    delay_conflict_free: LEMMA
      nnt <= rt AND
      conflict?[D,H](so-si,vo-vi) AND
      (NOT conflict_3D?[D,H,0,rt](so-si,vo-vi)) AND
      (NOT conflict?[D,H]((so+rt*vo)-(si+rt*vi),nvo-vi))
      IMPLIES
      (NOT conflict_3D?[D,H,0,nnt](so-si,vo-vi))
      AND
      (NOT conflict?[D,H]((so+nnt*vo)-(si+nnt*vi),nvo-vi))


  END delay_3D


body:
  %------------------------------------------------------------------------------
  % cd_sphere
  %
  % Correctness and completeness of 3-D conflict (ever) detection algorithm for
  % a spherical protection zone.
  %------------------------------------------------------------------------------

  cd_sphere  : THEORY 
  BEGIN

    IMPORTING reals@sign,
              reals@quadratic_2b,
  	    reals@quad_minmax,
              vectors@vectors_3D

    s,v   : VAR Vect3
    D	: VAR posreal     


    conflict_sphere_ever(D,s,v) : bool =
      EXISTS (t:nnreal): norm(s+t*v)<D

    cd_sphere(D,s,v): bool =
      IF   s*v < 0 THEN (sq(s*v)-sqv(v)*(sqv(s)-sq(D)) > 0)
      ELSE (sqv(s) < sq(D))
      ENDIF

    cd_sphere_def: LEMMA cd_sphere(D,s,v) IFF conflict_sphere_ever(D,s,v)



  END cd_sphere


body:
  %------------------------------------------------------------------------------
  % cd2d_inf.pvs
  % ACCoRD v1.0
  %
  % Correctness and completeness of 2-D conflict detection algorithm for infinite
  % lookahead time
  %   D : Horizontal separation
  %------------------------------------------------------------------------------

  cd2d_inf[D:posreal]  : THEORY 
  BEGIN

    IMPORTING horizontal[D],
    	    vect_analysis@vect_cont_2D,
  	    vect_analysis@vect2_cont_dot[real],
              vectors@det_2D,
   	    tangent_line[D]

    s,v   : VAR Vect2     
    sp    : VAR Sp_vect2
    ss    : VAR Ss_vect2
    nzv   : VAR Nz_vect2  
    t	: VAR nnreal


    detection_2D_inf(s,nzv) : [nnreal,nnreal] =
      IF Delta(s,nzv) > 0 THEN
        LET tin  = Theta_D(s,nzv,Entry),
            tout = Theta_D(s,nzv,Exit) IN
          (max(tin,0),max(tout,0))
      ELSE
        (0,0)
      ENDIF

    detection_2D_inf_correct : THEOREM
      LET (tin,tout) = detection_2D_inf(s,nzv) IN
       tin < t AND t < tout IMPLIES horizontal_los?(s+t*nzv)

    detection_2D_inf_complete : THEOREM
      LET (tin,tout) = detection_2D_inf(s,nzv) IN
        horizontal_los?(s+t*nzv) IMPLIES tin <= t AND t <= tout AND tin < tout

    conflict_detection_2D_inf : THEOREM
      LET (tin,tout) = detection_2D_inf(s,nzv) IN
      horizontal_conflict?(s,nzv) IFF tin < tout

    %-----------------------------------------------%
    % 2-D Conflict Detection (cd2d_inf)                 %
    %-----------------------------------------------%

    cd2d_inf?(s,v) : bool =
      horizontal_los?(s) OR
      (Delta(s,v) > 0 AND s*v < 0)

    %-----------------------------------------------%
    % THEOREM: cd2d_inf is correct and complete         %
    %-----------------------------------------------%

    cd2d_inf : THEOREM 
      horizontal_conflict?(s,v)
      IFF
      cd2d_inf?(s,v)

  END cd2d_inf

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

  % Subtype TCC generated (at line 28, column 27) for  nzv
      % expected type  {nzv | Delta(s, nzv) >= 0}
  detection_2D_inf_TCC1: OBLIGATION
    FORALL (s: Vect2, nzv: Nz_vect2):
      Delta(s, nzv) > 0 IMPLIES Delta[D](s, nzv) >= 0;


body:
  %------------------------------------------------------------------------------
  % cd3d_inf.pvs
  % ACCoRD v1.0
  %
  % Correctness and completeness of 3-D conflict detection algorithm for infinite
  % lookahead time
  %   D : Horizontal separation
  %   H : Vertical separation
  %------------------------------------------------------------------------------

  cd3d_inf[D,H:posreal]  : THEORY 
  BEGIN

    IMPORTING circle_criterion[D,H],
    	    omega_2D,
              cd2d,
  	    util,
  	    cd2d_inf[D]

    s,v : VAR Vect3       
    t   : VAR nnreal
    nzv : VAR Nz_vect3

    conflict_3D_2D_inf_stable: LEMMA v`z/=0 AND max(-H-sign(v`z)*s`z,0) < H-sign(v`z)*s`z
      IMPLIES
      (conflict?(s,v) IFF 
      conflict_2D?[D*abs(v`z),max(-H-sign(v`z)*s`z,0),H-sign(v`z)*s`z](abs(v`z)*s,v))

    conflict_vz_swap: LEMMA conflict?(s,v) IFF conflict?(s WITH [z:=-(s`z)],v WITH [z:=-(v`z)])

    conflict_on_open_interval: LEMMA conflict?(s,v) IFF
      EXISTS (topen: posreal): sqv(vect2(s)+topen*vect2(v))<sq(D) AND abs(s`z + topen*v`z) < H

    %-----------------------------------------------%
    % 3-D Conflict interval detection [tin,tout]    %
    %     (tin,tout) is the conflict interval       %
    %-----------------------------------------------%  
   
    detection_inf(s,nzv) : [nnreal,nnreal] =
      IF zero_vect2?(nzv) AND horizontal_los?(s) THEN
          (max(Theta_H(s`z,nzv`z,Entry),0),max(Theta_H(s`z,nzv`z,Exit),0))
      ELSIF Delta(s,nzv) > 0 THEN
        LET td1 = Theta_D(s,nzv,Entry),
            td2 = Theta_D(s,nzv,Exit) IN
        IF nzv`z /= 0 THEN
          LET tin  = max(td1,Theta_H(s`z,nzv`z,Entry)),
              tout = min(td2,Theta_H(s`z,nzv`z,Exit)) IN      
          (max(tin,0),max(tout,0))
        ELSIF vertical_los?(s`z) THEN
          (max(td1,0),max(td2,0))
        ELSE
          (0,0)
        ENDIF
      ELSE
        (0,0)
      ENDIF
   
    detection_inf_correct : THEOREM
      LET (tin,tout) = detection_inf(s,nzv) IN
       tin < t AND t < tout IMPLIES conflict_at?(s,nzv,t)

    detection_inf_complete : THEOREM
      LET (tin,tout) = detection_inf(s,nzv) IN
        conflict_at?(s,nzv,t) IMPLIES tin <= t AND t <= tout AND tin < tout

    conflict_detection_inf : THEOREM
      LET (tin,tout) = detection_inf(s,nzv) IN
      conflict?(s,nzv) IFF tin < tout

    %-----------------------------------------------%
    % 3-D Conflict Detection_inf (cd3d_inf)                 %
    %-----------------------------------------------%

    cd3d_inf?(s,v) : bool =
      IF v`z = 0 AND abs(s`z)<H 
         THEN cd2d_inf?[D](s,v)
      ELSIF v`z /= 0 AND max(-H-sign(v`z)*s`z,0) < H-sign(v`z)*s`z
         THEN cd2d?[D*abs(v`z),max(-H-sign(v`z)*s`z,0),H-sign(v`z)*s`z](abs(v`z)*s,v)
      ELSE
         FALSE
      ENDIF

    cd3d_inf_rewrite: LEMMA cd3d_inf?(s,v) IFF 
      IF v`z = 0 AND abs(s`z)<H 
         THEN cd2d_inf?[D](s,v)
      ELSIF v`z /= 0 AND max(Theta_H(s`z,v`z,Entry),0) < Theta_H(s`z,v`z,Exit)
         THEN cd2d?[D,max(Theta_H(s`z,v`z,Entry),0),Theta_H(s`z,v`z,Exit)](s,v)
      ELSE
         FALSE
      ENDIF

    cd3d_inf_correct : THEOREM
      cd3d_inf?(s,v) IMPLIES
      conflict?(s,v)

    cd3d_inf_complete : THEOREM 
      conflict?(s,v)
      IMPLIES
      cd3d_inf?(s,v)

    %-----------------------------------------------%
    % THEOREM: cd3d_inf is correct and complete         %
    %-----------------------------------------------%

    cd3d_inf : THEOREM
      conflict?(s,v) IFF
      cd3d_inf?(s,v) 


  END cd3d_inf

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

  % Subtype TCC generated (at line 27, column 17) for  D * abs(v`z)
      % expected type  posreal
  conflict_3D_2D_inf_stable_TCC1: OBLIGATION
    FORALL (s, v: Vect3):
      max(-H - sign(v`z) * s`z, 0) < H - sign(v`z) * s`z AND v`z /= 0 IMPLIES
       D * abs(v`z) > 0;

  % Subtype TCC generated (at line 27, column 28) for
      % max(-H - sign(v`z) * s`z, 0)
      % expected type  nnreal
  conflict_3D_2D_inf_stable_TCC2: OBLIGATION
    FORALL (s, v: Vect3):
      max(-H - sign(v`z) * s`z, 0) < H - sign(v`z) * s`z AND v`z /= 0 IMPLIES
       max(-H - sign(v`z) * s`z, 0) >= 0;

  % Subtype TCC generated (at line 27, column 52) for  H - sign(v`z) * s`z
      % expected type  {AB: posreal | AB > max(-H - sign(v`z) * s`z, 0)}
  conflict_3D_2D_inf_stable_TCC3: OBLIGATION
    FORALL (s, v: Vect3):
      max(-H - sign(v`z) * s`z, 0) < H - sign(v`z) * s`z AND v`z /= 0 IMPLIES
       H - sign(v`z) * s`z >= 0 AND
        H - sign(v`z) * s`z > 0 AND
         H - sign(v`z) * s`z > max(-H - sign(v`z) * s`z, 0);

  % Subtype TCC generated (at line 41, column 25) for  nzv`z
      % expected type  nzreal
  detection_inf_TCC1: OBLIGATION
    FORALL (s: Vect3, nzv: Nz_vect3):
      vect2(nzv) = zero AND sqv(vect2(s)) < sq(D) IMPLIES nzv`z /= 0;

  % Subtype TCC generated (at line 41, column 9) for
      % max(Theta_H(s`z, nzv`z, -1), 0)
      % expected type  nnreal
  detection_inf_TCC2: OBLIGATION
    FORALL (s: Vect3, nzv: Nz_vect3):
      vect2(nzv) = zero AND sqv(vect2(s)) < sq(D) IMPLIES
       max(Theta_H[H](s`z, nzv`z, -1), 0) >= 0;

  % Subtype TCC generated (at line 41, column 41) for
      % max(Theta_H(s`z, nzv`z, 1), 0)
      % expected type  nnreal
  detection_inf_TCC3: OBLIGATION
    FORALL (s: Vect3, nzv: Nz_vect3):
      vect2(nzv) = zero AND sqv(vect2(s)) < sq(D) IMPLIES
       max(Theta_H[H](s`z, nzv`z, 1), 0) >= 0;

  % Subtype TCC generated (at line 43, column 26) for  vect2(nzv)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  detection_inf_TCC4: OBLIGATION
    FORALL (s: Vect3, nzv: Nz_vect3):
      Delta(vect2(s), vect2(nzv)) > 0 AND
       NOT (vect2(nzv) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES vect2(nzv) /= zero AND Delta[D](vect2(s), vect2(nzv)) >= 0;

  % Subtype TCC generated (at line 48, column 9) for  max(tin, 0)
      % expected type  nnreal
  detection_inf_TCC5: OBLIGATION
    FORALL (s: Vect3, nzv: Nz_vect3):
      Delta(vect2(s), vect2(nzv)) > 0 AND
       NOT (vect2(nzv) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (td1: real):
          td1 = Theta_D(vect2(s), vect2(nzv), -1) IMPLIES
           (FORALL (td2: real):
              nzv`z /= 0 AND td2 = Theta_D(vect2(s), vect2(nzv), 1) IMPLIES
               (FORALL (tin:
                          {p: real |
                                   p >= td1 AND
                                    p >= Theta_H[H](s`z, nzv`z, -1)}):
                  tin = max(td1, Theta_H(s`z, nzv`z, -1)) IMPLIES
                   (FORALL (tout:
                              {p: real |
                                       p <= td2
                                       AND
                                       p <= Theta_H[H](s`z, nzv`z, 1)}):
                      tout = min(td2, Theta_H(s`z, nzv`z, 1)) IMPLIES
                       max(tin, 0) >= 0))));

  % Subtype TCC generated (at line 48, column 20) for  max(tout, 0)
      % expected type  nnreal
  detection_inf_TCC6: OBLIGATION
    FORALL (s: Vect3, nzv: Nz_vect3):
      Delta(vect2(s), vect2(nzv)) > 0 AND
       NOT (vect2(nzv) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (td1: real):
          td1 = Theta_D(vect2(s), vect2(nzv), -1) IMPLIES
           (FORALL (td2: real):
              nzv`z /= 0 AND td2 = Theta_D(vect2(s), vect2(nzv), 1) IMPLIES
               (FORALL (tin:
                          {p: real |
                                   p >= td1 AND
                                    p >= Theta_H[H](s`z, nzv`z, -1)}):
                  tin = max(td1, Theta_H(s`z, nzv`z, -1)) IMPLIES
                   (FORALL (tout:
                              {p: real |
                                       p <= td2
                                       AND
                                       p <= Theta_H[H](s`z, nzv`z, 1)}):
                      tout = min(td2, Theta_H(s`z, nzv`z, 1)) IMPLIES
                       max(tout, 0) >= 0))));

  % Subtype TCC generated (at line 87, column 20) for
      % max(Theta_H(s`z, v`z, -1), 0)
      % expected type  nnreal
  cd3d_inf_rewrite_TCC1: OBLIGATION
    FORALL (s, v: Vect3):
      NOT (v`z = 0 AND abs(s`z) < H) AND
       max(Theta_H(s`z, v`z, -1), 0) < Theta_H(s`z, v`z, 1) AND v`z /= 0
       IMPLIES max(Theta_H[H](s`z, v`z, -1), 0) >= 0;

  % Subtype TCC generated (at line 87, column 50) for  Theta_H(s`z, v`z, 1)
      % expected type  {AB: posreal | AB > max(Theta_H(s`z, v`z, -1), 0)}
  cd3d_inf_rewrite_TCC2: OBLIGATION
    FORALL (s, v: Vect3):
      NOT (v`z = 0 AND abs(s`z) < H) AND
       max(Theta_H(s`z, v`z, -1), 0) < Theta_H(s`z, v`z, 1) AND v`z /= 0
       IMPLIES
       Theta_H[H](s`z, v`z, 1) >= 0 AND
        Theta_H[H](s`z, v`z, 1) > 0 AND
         Theta_H[H](s`z, v`z, 1) > max(Theta_H[H](s`z, v`z, -1), 0);


body:
  horizontal_sq_dtca[D:posreal] : THEORY
  BEGIN

    IMPORTING vect_analysis@vect_deriv_2D[real],
              tangent_line[D]

    V    : VAR (differentiable_rv?)
    a,r  : VAR real
    s    : VAR Vect2
    ss   : VAR Ss_vect2
    pm   : VAR Sign

    horizontal_sq_dtca_diff : LEMMA
      (FORALL (a):nz_vect2?(V(a))) IMPLIES
      derivable?[real](LAMBDA (r: real): horizontal_sq_dtca(s, V(r)), r)

    horizontal_sq_dtca_deriv : LEMMA
      (FORALL (a):nz_vect2?(V(a))) IMPLIES
      deriv(LAMBDA(r:real):horizontal_sq_dtca(s,V(r)),r) = 
      LET v = V(r),
          w = deriv_rv(V)(r) IN
      (2*sqv(v)*det(s,v)*det(s,w)-2*sq(det(s,v))*(v*w))/sq(sqv(v))

    horizontal_sq_dtca_deriv_simpl : LEMMA
      (FORALL (a):nz_vect2?(V(a))) IMPLIES
      LET v = V(r),
          w = deriv_rv(V)(r) IN
      (2*sqv(v)*det(s,v)*det(s,w)-2*sq(det(s,v))*(v*w))/sq(sqv(v)) =
      2*det(s,v)*det(V(r),w)*(s*V(r))/sq(sqv(v))

    horizontal_sq_dtca_deriv_sign : LEMMA 
      (FORALL (a):nz_vect2?(V(a))) AND
      line_solution?(ss,V(r)) IMPLIES
      (pm*deriv(LAMBDA(r:real):horizontal_sq_dtca(ss,V(r)),r) > 0 IFF
       LET v   = V(r),
           w   = deriv_rv(V)(r),
           eps = eps_line(ss,v) IN
       pm*(Q(ss,eps)*w) > 0) 
    
  END horizontal_sq_dtca

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

  % Assuming TCC generated (at line 4, column 12) for
      % vect_analysis@vect_deriv_2D[real]
      % generated from assumption vect_deriv_2D.deriv_domain
  IMP_vect_deriv_2D_TCC1: OBLIGATION deriv_domain?[real];

  % Assuming TCC generated (at line 4, column 12) for
      % vect_analysis@vect_deriv_2D[real]
      % generated from assumption vect_deriv_2D.not_one_element
  IMP_vect_deriv_2D_TCC2: OBLIGATION not_one_element?[real];

  % Subtype TCC generated (at line 15, column 61) for  V(r)
      % expected type  Nz_vect2
  horizontal_sq_dtca_diff_TCC1: OBLIGATION
    FORALL (V: (LAMBDA (V: [real -> Vect2]): derivable_rv?(V))):
      (FORALL (a): V(a) /= zero) IMPLIES (FORALL (r: real): V(r) /= zero);

  % Subtype TCC generated (at line 19, column 52) for  r
      % expected type  {x |
                     %          derivable?(LAMBDA
                     %                     (r: real):
                     %                     horizontal_sq_dtca(s, V(r)),
                     %                     x)}
  horizontal_sq_dtca_deriv_TCC1: OBLIGATION
    FORALL (V: (LAMBDA (V: [real -> Vect2]): derivable_rv?(V)), r1: real,
            s: Vect2):
      (FORALL (a): V(a) /= zero) IMPLIES
       derivable?[real](LAMBDA (r: real): horizontal_sq_dtca(s, V(r)), r1);

  % Subtype TCC generated (at line 22, column 54) for  sq(sqv(v))
      % expected type  nznum
  horizontal_sq_dtca_deriv_TCC2: OBLIGATION
    FORALL (V: (LAMBDA (V: [real -> Vect2]): derivable_rv?(V)), r: real):
      (FORALL (a): V(a) /= zero) IMPLIES
       (FORALL (v: Vect2):
          v = V(r) IMPLIES
           (FORALL (w: Vect2): w = deriv_rv(V)(r) IMPLIES sq(sqv(v)) /= 0));

  % Subtype TCC generated (at line 34, column 57) for  r
      % expected type  {x |
                     %          derivable?(LAMBDA
                     %                     (r: real):
                     %                     horizontal_sq_dtca(ss, V(r)),
                     %                     x)}
  horizontal_sq_dtca_deriv_sign_TCC1: OBLIGATION
    FORALL (V: (LAMBDA (V: [real -> Vect2]): derivable_rv?(V)), r1: real,
            ss: Ss_vect2[D]):
      ((EXISTS (eps: Sign): line_solution?(ss, V(r1), eps)) AND
        (FORALL (a): V(a) /= zero))
       IMPLIES
       derivable?[real](LAMBDA (r: real): horizontal_sq_dtca(ss, V(r)), r1);


body:
  %------------------------------------------------------------------------------
  % cd2d_ever
  %
  % Correctness and completeness of 3-D conflict (ever) detection algorithm for
  % a spherical protection zone.
  %------------------------------------------------------------------------------

  cd2d_ever  : THEORY 
  BEGIN

    IMPORTING reals@sign,
              reals@quadratic_2b,
  	    reals@quad_minmax,
  	    vectors@vectors_2D,
  	    horizontal

    s,v   : VAR Vect2
    D	: VAR posreal  

    cd2d_ever(D,s,v): bool =
      IF   s*v < 0 THEN (sq(s*v)-sqv(v)*(sqv(s)-sq(D)) > 0)
      ELSE (sqv(s) < sq(D))
      ENDIF

    cd2d_ever_def: LEMMA 
      cd2d_ever(D,s,v) IFF horizontal_conflict?[D](s,v)

  END cd2d_ever


body:
  %------------------------------------------------------------------------------
  % cd3d_ever.pvs
  %
  % Authors: Anthony Narkawicz
  % 	   Cesar Munoz
  %	   NASA Langley
  %------------------------------------------------------------------------------

  cd3d_ever[D,H:posreal]  : THEORY 
  BEGIN

    IMPORTING cd2d_ever,
              omega_2D,
  	    space_3D[D,H],
  	    util

    s,v : VAR Vect3       
    t   : VAR nnreal


    conflict_2D_stable: LEMMA v`z/=0 AND max(-H-sign(v`z)*s`z,0) < H-sign(v`z)*s`z
      IMPLIES
      (conflict?(s,v) IFF 
      conflict_2D?[D*abs(v`z),max(-H-sign(v`z)*s`z,0),H-sign(v`z)*s`z](abs(v`z)*s,v))

    conflict_vz_swap: LEMMA conflict?(s,v) IFF conflict?(s WITH [z:=-(s`z)],v WITH [z:=-(v`z)])

    conflict_on_open_interval: LEMMA conflict?(s,v) IFF
      EXISTS (topen: posreal): sqv(vect2(s)+topen*vect2(v))<sq(D) AND abs(s`z + topen*v`z) < H

    %-----------------------------------------------%
    % 3-D Conflict Detection (cd3d_ever)                 %
    %-----------------------------------------------%

    cd3d_ever?(s,v) : bool =
      IF v`z = 0 AND abs(s`z)<H 
         THEN cd2d_ever(D,s,v)
      ELSIF v`z /= 0 AND max(-H-sign(v`z)*s`z,0) < H-sign(v`z)*s`z
         THEN cd2d?[D*abs(v`z),max(-H-sign(v`z)*s`z,0),H-sign(v`z)*s`z](abs(v`z)*s,v)
      ELSE
         FALSE
      ENDIF

    cd3d_ever_rewrite: LEMMA cd3d_ever?(s,v) IFF 
      IF v`z = 0 AND abs(s`z)<H 
         THEN cd2d_ever(D,s,v)
      ELSIF v`z /= 0 AND max(Theta_H(s`z,v`z,Entry),0) < Theta_H(s`z,v`z,Exit)
         THEN cd2d?[D,max(Theta_H(s`z,v`z,Entry),0),Theta_H(s`z,v`z,Exit)](s,v)
      ELSE
         FALSE
      ENDIF

    cd3d_ever_correct : THEOREM
      cd3d_ever?(s,v) IMPLIES
      conflict?(s,v)

     cd3d_ever_complete : THEOREM 
      conflict?(s,v)
      IMPLIES
      cd3d_ever?(s,v)

    %-----------------------------------------------%
    % THEOREM: cd3d_ever is correct and complete    %
    %-----------------------------------------------%

    cd3d_ever : THEOREM
      conflict?(s,v) IFF
      cd3d_ever?(s,v) 


  END cd3d_ever

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

  % Subtype TCC generated (at line 24, column 17) for  D * abs(v`z)
      % expected type  posreal
  conflict_2D_stable_TCC1: OBLIGATION
    FORALL (s, v: Vect3):
      max(-H - sign(v`z) * s`z, 0) < H - sign(v`z) * s`z AND v`z /= 0 IMPLIES
       D * abs(v`z) > 0;

  % Subtype TCC generated (at line 24, column 28) for
      % max(-H - sign(v`z) * s`z, 0)
      % expected type  nnreal
  conflict_2D_stable_TCC2: OBLIGATION
    FORALL (s, v: Vect3):
      max(-H - sign(v`z) * s`z, 0) < H - sign(v`z) * s`z AND v`z /= 0 IMPLIES
       max(-H - sign(v`z) * s`z, 0) >= 0;

  % Subtype TCC generated (at line 24, column 52) for  H - sign(v`z) * s`z
      % expected type  {AB: posreal | AB > max(-H - sign(v`z) * s`z, 0)}
  conflict_2D_stable_TCC3: OBLIGATION
    FORALL (s, v: Vect3):
      max(-H - sign(v`z) * s`z, 0) < H - sign(v`z) * s`z AND v`z /= 0 IMPLIES
       H - sign(v`z) * s`z >= 0 AND
        H - sign(v`z) * s`z > 0 AND
         H - sign(v`z) * s`z > max(-H - sign(v`z) * s`z, 0);

  % Subtype TCC generated (at line 48, column 20) for
      % max(Theta_H(s`z, v`z, -1), 0)
      % expected type  nnreal
  cd3d_ever_rewrite_TCC1: OBLIGATION
    FORALL (s, v: Vect3):
      NOT (v`z = 0 AND abs(s`z) < H) AND
       max(Theta_H(s`z, v`z, -1), 0) < Theta_H(s`z, v`z, 1) AND v`z /= 0
       IMPLIES max(Theta_H[H](s`z, v`z, -1), 0) >= 0;

  % Subtype TCC generated (at line 48, column 50) for  Theta_H(s`z, v`z, 1)
      % expected type  {AB: posreal | AB > max(Theta_H(s`z, v`z, -1), 0)}
  cd3d_ever_rewrite_TCC2: OBLIGATION
    FORALL (s, v: Vect3):
      NOT (v`z = 0 AND abs(s`z) < H) AND
       max(Theta_H(s`z, v`z, -1), 0) < Theta_H(s`z, v`z, 1) AND v`z /= 0
       IMPLIES
       Theta_H[H](s`z, v`z, 1) >= 0 AND
        Theta_H[H](s`z, v`z, 1) > 0 AND
         Theta_H[H](s`z, v`z, 1) > max(Theta_H[H](s`z, v`z, -1), 0);


body:
  %------------------------------------------------------------------------------
  %    Loss of Separation Criterion: Vertical
  %
  %    Authors: Anthony Narkawicz
  %    	      Cesar Munoz
  %   
  %------------------------------------------------------------------------------
  vertical_los_criterion[D,H: posreal] : THEORY                        
  BEGIN

    IMPORTING vertical[H],
    	    space_3D[D,H]

    vo,vi,
    nvi,nvo,
    v,nv,
    s,so,si : VAR Vect3
    t,t1,t2,
    tm      : VAR real
    tr      : VAR posreal %% Parameter that specifies maximum time to recover
    eps	  : VAR Sign
    tn	  : VAR nnreal
    sz,vz,
    nvz,
    voz,viz,
    nvoz,
    nviz,
    soz,siz : VAR real
    MinRelVertSpeed,
    MinRelVertSpeedo,
    MinRelVertSpeedi: VAR posreal

    vertical_sep_after(sz,vz)(tm): bool = 
      FORALL (t): t>=tm IMPLIES
      vertical_sep_at?(sz,vz,t)

    vs_bound_crit?(s,v,eps)(nv): bool =
      IF eps*v`z>0
        THEN (eps*nv`z>=eps*v`z) AND eps*v`z*(vect2(nv)*vect2(s)) - eps*nv`z*(vect2(v)*vect2(s)) >= 0
      ELSE eps*nv`z>=0
      ENDIF


    %% This criterion is not proven. It's intended to be used in kinematic/iterative code
    %% as opposed to vertical_los_criterion?, which should only used in state-based/instantaneous
    %% maneuver algorithms. This criterion is like vs_bound_crit? but removes the else branch
    %% that restricts some vertical maneuvers [CAM]
    horizontal_new_repulsive_criterion?(s,v,eps)(nv): bool =
      (eps*nv`z>=eps*v`z) AND eps*v`z*(vect2(nv)*vect2(s)) - eps*nv`z*(vect2(v)*vect2(s)) >= 0

    %%% vs_bound_crit? can be described as follows. There is a plane that contains v
    %%% and the vector (perpR(vect2(v)),0) (i.e. (v`y,-v`x,0)). This plane has equation
    %%% (v`x*v`z, v`y*v`z, -sqv(v))*nv = 0. So nv is in the eps-direction above/below
    %%% this plane if -eps*v`z*(vect2(nv)*vect2(v)) + eps*nv`z*sqv(vect2(v)) >=0.

    time_vertical_exit_by(sz,vz,eps,MinRelVertSpeed): {x:real | MinRelVertSpeed>0 AND abs(sz)<H IMPLIES x>0} =
      IF eps*vz <= 0 THEN Theta_H(sz,eps*MinRelVertSpeed,1)
      ELSE min(Theta_H(sz,eps*MinRelVertSpeed,1),Theta_H(sz,vz,1))
      ENDIF

    time_vertical_exit_by_symm: LEMMA time_vertical_exit_by(-sz,-vz,-eps,MinRelVertSpeed) =
    			            time_vertical_exit_by(sz,vz,eps,MinRelVertSpeed)

    %%% minimum speed for exiting, considering current speed.

    min_rel_vert_speed(sz,vz,eps,MinRelVertSpeed): {x:nnreal | abs(sz)<H IMPLIES x>0} =
      IF eps*vz <=0 THEN MinRelVertSpeed
      ELSE max(MinRelVertSpeed,abs(vz)) ENDIF

    min_rel_vert_speed_symm: LEMMA min_rel_vert_speed(-sz,-vz,-eps,MinRelVertSpeed) =
    			   	 min_rel_vert_speed(sz,vz,eps,MinRelVertSpeed)

    vs_bound_crit_indep: LEMMA
      vs_bound_crit?(s,v,eps)(nv) AND
      vect2(s)*vect2(v) < 0 AND vect2(s)*vect2(nv) < 0 IMPLIES
      norm(vect2(s+horizontal_tca(s,nv)*nv)) > norm(vect2(s+horizontal_tca(s,v)*v)) OR
      eps*(s+horizontal_tca(s,nv)*nv)`z >= eps*(s+horizontal_tca(s,v)*v)`z
      
    vs_bound_crit_coord: LEMMA
      vs_bound_crit?(so-si,vo-vi,eps)(nvo-vi) AND
      vs_bound_crit?(si-so,vi-vo,-eps)(nvi-vo) IMPLIES
      vs_bound_crit?(so-si,vo-vi,eps)(nvo-nvi)

    vs_bound_dir: LEMMA
      vs_bound_crit?(s,v,eps)(nv) IMPLIES
      eps*nv`z>=0

    vertical_los_criterion?(s,v,eps,MinRelVertSpeed)(nv): bool =
        abs(s`z)<H AND
        vs_bound_crit?(s,v,eps)(nv) AND
        eps*nv`z >= min_rel_vert_speed(s`z,v`z,eps,MinRelVertSpeed)

    vertical_los_criterion_coord: LEMMA
      vertical_los_criterion?(s,vo-vi,eps,MinRelVertSpeedo)(nvo-vi) AND
      vertical_los_criterion?(-s,vi-vo,-eps,MinRelVertSpeedi)(nvi-vo) IMPLIES
      vertical_los_criterion?(s,vo-vi,eps,max(MinRelVertSpeedo,MinRelVertSpeedi))(nvo-nvi)

    vertical_sep_after_def: LEMMA
      abs(sz)<H AND vertical_sep_at?(sz,vz,tr)
      IMPLIES
      vertical_sep_after(sz,vz)(tr)

    z_los_vertical_sep: LEMMA
      vertical_los_criterion?(s,v,eps,MinRelVertSpeed)(nv)
      IMPLIES
      LET teb = time_vertical_exit_by(s`z,v`z,eps,MinRelVertSpeed)
      IN  vertical_sep_after(s`z,nv`z)(teb)

  END vertical_los_criterion

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

  % Subtype TCC generated (at line 57, column 24) for
      % Theta_H(sz, eps * MinRelVertSpeed, 1)
      % expected type  {x: real |
                     %          MinRelVertSpeed > 0 AND abs(sz) < H IMPLIES
                     %           x > 0}
  time_vertical_exit_by_TCC1: OBLIGATION
    FORALL (sz: real, vz: real, eps: Sign, MinRelVertSpeed: posreal):
      eps * vz <= 0 IMPLIES
       MinRelVertSpeed > 0 AND abs(sz) < H IMPLIES
        Theta_H[H](sz, eps * MinRelVertSpeed, 1) > 0;

  % Subtype TCC generated (at line 58, column 58) for  vz
      % expected type  nzreal
  time_vertical_exit_by_TCC2: OBLIGATION
    FORALL (vz: real, eps: Sign): NOT eps * vz <= 0 IMPLIES vz /= 0;

  % Subtype TCC generated (at line 58, column 9) for
      % min(Theta_H(sz, eps * MinRelVertSpeed, 1), Theta_H(sz, vz, 1))
      % expected type  {x: real |
                     %          MinRelVertSpeed > 0 AND abs(sz) < H IMPLIES
                     %           x > 0}
  time_vertical_exit_by_TCC3: OBLIGATION
    FORALL (sz: real, vz: real, eps: Sign, MinRelVertSpeed: posreal):
      NOT eps * vz <= 0 IMPLIES
       MinRelVertSpeed > 0 AND abs(sz) < H IMPLIES
        min(Theta_H[H](sz, eps * MinRelVertSpeed, 1), Theta_H[H](sz, vz, 1))
         > 0;

  % Subtype TCC generated (at line 67, column 23) for  MinRelVertSpeed
      % expected type  {x: nnreal | abs(sz) < H IMPLIES x > 0}
  min_rel_vert_speed_TCC1: OBLIGATION
    FORALL (sz: real, vz: real, eps: Sign, MinRelVertSpeed: posreal):
      eps * vz <= 0 IMPLIES abs(sz) < H IMPLIES MinRelVertSpeed > 0;

  % Subtype TCC generated (at line 68, column 9) for
      % max(MinRelVertSpeed, abs(vz))
      % expected type  {x: nnreal | abs(sz) < H IMPLIES x > 0}
  min_rel_vert_speed_TCC2: OBLIGATION
    FORALL (sz: real, vz: real, eps: Sign, MinRelVertSpeed: posreal):
      NOT eps * vz <= 0 IMPLIES
       abs(sz) < H IMPLIES max(MinRelVertSpeed, abs(vz)) > 0;

  % Subtype TCC generated (at line 76, column 34) for  vect2(nv)
      % expected type  Nz_vect2
  vs_bound_crit_indep_TCC1: OBLIGATION
    FORALL (eps: Sign, nv, s, v: Vect3):
      vect2(s) * vect2(nv) < 0 AND
       vect2(s) * vect2(v) < 0 AND vs_bound_crit?(s, v, eps)(nv)
       IMPLIES vect2(nv) /= zero;

  % Subtype TCC generated (at line 76, column 75) for  vect2(v)
      % expected type  Nz_vect2
  vs_bound_crit_indep_TCC2: OBLIGATION
    FORALL (eps: Sign, nv, s, v: Vect3):
      vect2(s) * vect2(nv) < 0 AND
       vect2(s) * vect2(v) < 0 AND vs_bound_crit?(s, v, eps)(nv)
       IMPLIES vect2(v) /= zero;


body:
  %------------------------------------------------------------------------------
  %    Loss of Separation Criterion: Vertical
  %    
  %    This criterion allows for a backup system that performs
  %    Collision Avoidance in the Event of A Near Collision (E.g. TCAS).
  %    The collision avoidance system is assumed to activate when a cylinder
  %    around the intruder of radius caD and height caH is expected to be 
  %    entered by the ownship within time caTime.
  %------------------------------------------------------------------------------
  vertical_los_crit_CA[D,H,caD,caH,caTime: posreal,
           ( IMPORTING definitions_3D )
           break_vz_symm:[Vect3 ->  Sign] %% Break symmetry when v`z = 0
        ] : THEORY                        
  BEGIN

    ASSUMING

      break_vz_symm_comm : ASSUMPTION
        FORALL (s:Vect3):
          s /= zero IMPLIES
          break_vz_symm(-s) = -break_vz_symm(s)

      break_vz_symm_sz : ASSUMPTION
        FORALL (s:Vect3):
          s`z /= 0 IMPLIES 
          break_vz_symm(s) = sign(s`z)

      % Future work: continuity of break symmetry

    ENDASSUMING

    IMPORTING vertical_los_criterion[D,H],
  	    cd3d[caD,caH,0,caTime],
  	    cd3d_ever[caD,caH]

    vo,vi,
    nvi,nvo,
    v,nv    : VAR Vect3
    s	: VAR Vect3
    t,t1,t2,
    tm      : VAR real
    tr      : VAR posreal %% Parameter that specifies maximum time to recover
    eps	  : VAR Sign
    tn	  : VAR nnreal
    sz,vz,
    nvz,
    voz,viz,
    nvoz,
    nviz,
    soz,siz    : VAR real
    MinRelVertSpeed,
    MinRelVertSpeedo,
    MinRelVertSpeedi: VAR posreal

    %%% This file implements a specific element of the type EpsChooser,
    %%% which is defined in vertical_los_generic. It then constructs the
    %%% associated criterion with the function vertical_los_crit_epschooser?
    %%% that is defined in that file.

    %%% Recall from vertical_los_generic that EpsChooser picks an epsilon
    %%% (-1 or 1) (up or down). A decision vector is a function that takes
    %%% s, vo, and vi and returns another vector on which the decision
    %%% of epsilon will be made.

    Decision_Vector : TYPE+ = {f:[[Vect3,Vect3]->Vect3]| FORALL (s,v): 
      (s /= zero OR v/=zero) => (f(s,v)/=zero AND f(-s,-v)=-f(s,v))}

    dv: VAR Decision_Vector

    dv_to_ec(dv)(s,v): Sign =
      break_vz_symm(dv(s,v))

    dv_to_ec_antisymmetric: JUDGEMENT
      dv_to_ec(dv) HAS_TYPE Vertical_Strategy[D,H]

    %%% The interior cylinder where CA applies:

    CA_applies?(s,v): bool = cd3d?[caD,caH,0,caTime](s,v)

    CA_cyl_conflict_ever?(s,v): bool =
      cd3d_ever?[caD,caH](s,v)

    %%% A specific decision vector for the new criterion:

    vertical_decision_vect(s,v): {vq: Vect3 | (s /= zero OR v/=zero) IMPLIES vq/=zero} =
      IF (s/=zero AND CA_cyl_conflict_ever?(s,v)) OR (s/=zero AND v`z=0) THEN
         (IF s`z /= 0 OR sqv(v)=0 THEN s ELSE v ENDIF)
      ELSIF vect2(v) = zero OR s = zero THEN
         v
      ELSIF vect2(s)*vect2(v) <= 0 THEN
         s + horizontal_tca(s,v)*v
      ELSE
         s
      ENDIF

    vertical_decision_vect_antisymmetric: JUDGEMENT
      vertical_decision_vect HAS_TYPE Decision_Vector

    %%% The new criterion:

    vertical_los_crit_CA?(s,v,MinRelVertSpeed)(nv) : bool =
      vertical_los_criterion?(s,v,dv_to_ec(vertical_decision_vect)(s,v),MinRelVertSpeed)(nv)

    % It is coordinated:

    vertical_los_crit_CA_independent: LEMMA
      LET eps: Sign = dv_to_ec(vertical_decision_vect)(s, v)
      IN 
          s/=zero AND
  	vertical_los_crit_CA?(s,v,MinRelVertSpeed)(nv) AND
  	vect2(s)*vect2(v) < 0 AND vect2(s)*vect2(nv) < 0 AND
  	norm(vect2(s+horizontal_tca(s,nv)*nv)) <= norm(vect2(s+horizontal_tca(s,v)*(v)))
  	IMPLIES
  	eps*(s+horizontal_tca((s),nv)*nv)`z >= eps*(s+horizontal_tca((s),v)*(v))`z

    vertical_los_crit_CA_independent_strong: LEMMA
      	s/=zero AND
  	vertical_los_crit_CA?(s,v,MinRelVertSpeed)(nv) AND
  	vect2(s)*vect2(v) < 0 AND vect2(s)*vect2(nv) < 0 AND
  	norm(vect2(s+horizontal_tca(s,nv)*nv)) <= norm(vect2(s+horizontal_tca(s,v)*(v)))
  	IMPLIES
  	((v`z=0 OR CA_cyl_conflict_ever?(s,v)) AND 
  	  sign(s`z)/=sign(v`z) AND abs((s+horizontal_tca((s),nv)*nv)`z) >= abs(s`z))
  	OR
  	abs((s+horizontal_tca((s),nv)*nv)`z) >= abs((s+horizontal_tca((s),v)*(v))`z)

    vertical_los_crit_CA_independent_vspeed: LEMMA
      s/=zero AND
        vertical_los_crit_CA?(s,v,MinRelVertSpeed)(nv)
        IMPLIES
        break_vz_symm(vertical_decision_vect(s,v))*(nv`z)>=MinRelVertSpeed

    vertical_los_crit_CA_coordinated_vspeed: LEMMA
        s/=zero AND
        vertical_los_crit_CA?(s,vo-vi,MinRelVertSpeedo)(nvo-vi) AND
        vertical_los_crit_CA?(-s,vi-vo,MinRelVertSpeedi)(nvi-vo)
        IMPLIES
        break_vz_symm(vertical_decision_vect(s,vo-vi))*(nvo`z-nvi`z)>=max(MinRelVertSpeedo,MinRelVertSpeedi)

    vertical_los_crit_CA_coordinated: LEMMA
        s/=zero AND
        vertical_los_crit_CA?(s,vo-vi,MinRelVertSpeedo)(nvo-vi) AND
        vertical_los_crit_CA?(-s,vi-vo,MinRelVertSpeedi)(nvi-vo)
        IMPLIES
        vertical_los_crit_CA?(s,vo-vi,max(MinRelVertSpeedo,MinRelVertSpeedi))(nvo-nvi)

    vertical_los_crit_CA_coordinated_strong: LEMMA
        LET v = vo-vi, nv = nvo-nvi IN
        s/=zero AND
        vertical_los_crit_CA?(s,vo-vi,MinRelVertSpeedo)(nvo-vi) AND
        vertical_los_crit_CA?(-s,vi-vo,MinRelVertSpeedi)(nvi-vo) AND
        vect2(s)*vect2(v) < 0
        IMPLIES
        vect2(s)*vect2(nv) >= 0 OR
        norm(vect2(s+horizontal_tca(s,nv)*nv)) > norm(vect2(s+horizontal_tca(s,v)*(v))) OR
        ((v`z=0 OR CA_cyl_conflict_ever?(s,v)) AND 
           sign(s`z)/=sign(v`z) AND abs((s+horizontal_tca((s),nv)*nv)`z) >= abs(s`z)) OR
        abs((s+horizontal_tca((s),nv)*nv)`z) >= abs((s+horizontal_tca((s),v)*(v))`z)

  END vertical_los_crit_CA

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

  % Existence TCC generated (at line 65, column 2) for
      % Decision_Vector: TYPE+ =
      %       {f: [[Vect3, Vect3] -> Vect3] |
      %                FORALL (s, v):
      %                  (s /= zero OR v /= zero) =>
      %                   (f(s, v) /= zero AND f(-s, -v) = -f(s, v))}
  Decision_Vector_TCC1: OBLIGATION
    EXISTS (x:
              {f: [[Vect3, Vect3] -> Vect3] |
                       FORALL (s, v):
                         (s /= zero OR v /= zero) =>
                          (f(s, v) /= zero AND f(-s, -v) = -f(s, v))}):
      TRUE;

  % Judgement subtype TCC generated (at line 74, column 4) for  dv_to_ec(dv)
      % expected type  Vertical_Strategy[D, H]
  dv_to_ec_antisymmetric: OBLIGATION
    FORALL (dv, s, v):
      (s /= zero OR v /= zero) => dv_to_ec(dv)(-s, -v) = -dv_to_ec(dv)(s, v);

  % Subtype TCC generated (at line 87, column 37) for  s
      % expected type  {vq: Vect3 |
                     %          (s /= zero OR v /= zero) IMPLIES vq /= zero}
  vertical_decision_vect_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      (s`z /= 0 OR sqv(v) = 0) AND
       ((s /= zero AND CA_cyl_conflict_ever?(s, v)) OR
         (s /= zero AND v`z = 0))
       IMPLIES (s /= zero OR v /= zero) IMPLIES s /= zero;

  % Subtype TCC generated (at line 87, column 44) for  v
      % expected type  {vq: Vect3 |
                     %          (s /= zero OR v /= zero) IMPLIES vq /= zero}
  vertical_decision_vect_TCC2: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT s`z /= 0 AND
       NOT sqv(v) = 0 AND
        ((s /= zero AND CA_cyl_conflict_ever?(s, v)) OR
          (s /= zero AND v`z = 0))
       IMPLIES (s /= zero OR v /= zero) IMPLIES v /= zero;

  % Subtype TCC generated (at line 89, column 7) for  v
      % expected type  {vq: Vect3 |
                     %          (s /= zero OR v /= zero) IMPLIES vq /= zero}
  vertical_decision_vect_TCC3: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      (vect2(v) = zero OR s = zero) AND
       NOT (s /= zero AND CA_cyl_conflict_ever?(s, v)) AND
        NOT (s /= zero AND v`z = 0)
       IMPLIES (s /= zero OR v /= zero) IMPLIES v /= zero;

  % Subtype TCC generated (at line 91, column 28) for  vect2(v)
      % expected type  Nz_vect2
  vertical_decision_vect_TCC4: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
           vect2(s) * vect2(v) <= 0 AND NOT vect2(v) = zero AND NOT s = zero
       AND NOT (s /= zero AND CA_cyl_conflict_ever?(s, v))
       AND NOT (s /= zero AND v`z = 0)
       IMPLIES vect2(v) /= zero;

  % Subtype TCC generated (at line 91, column 7) for
      % s + horizontal_tca(vect2(s), vect2(v)) * v
      % expected type  {vq: Vect3 |
                     %          (s /= zero OR v /= zero) IMPLIES vq /= zero}
  vertical_decision_vect_TCC5: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
           vect2(s) * vect2(v) <= 0 AND NOT vect2(v) = zero AND NOT s = zero
       AND NOT (s /= zero AND CA_cyl_conflict_ever?(s, v))
       AND NOT (s /= zero AND v`z = 0)
       IMPLIES
       (s /= zero OR v /= zero) IMPLIES
        s + horizontal_tca(vect2(s), vect2(v)) * v /= zero;

  % Subtype TCC generated (at line 93, column 7) for  s
      % expected type  {vq: Vect3 |
                     %          (s /= zero OR v /= zero) IMPLIES vq /= zero}
  vertical_decision_vect_TCC6: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
           NOT vect2(s) * vect2(v) <= 0 AND NOT vect2(v) = zero
       AND NOT s = zero AND NOT (s /= zero AND CA_cyl_conflict_ever?(s, v))
       AND NOT (s /= zero AND v`z = 0)
       IMPLIES (s /= zero OR v /= zero) IMPLIES s /= zero;

  % Judgement subtype TCC generated (at line 97, column 4) for
      % vertical_decision_vect
      % expected type  Decision_Vector
  vertical_decision_vect_antisymmetric: OBLIGATION
    FORALL (s, v):
      (s /= zero OR v /= zero) =>
       (vertical_decision_vect(s, v) /= zero AND
         vertical_decision_vect(-s, -v) = -vertical_decision_vect(s, v));

  % Subtype TCC generated (at line 112, column 31) for  vect2(nv)
      % expected type  Nz_vect2
  vertical_los_crit_CA_independent_TCC1: OBLIGATION
    FORALL (MinRelVertSpeed: posreal, nv, s, v: Vect3, eps: Sign):
           vect2(s) * vect2(nv) < 0 AND vect2(s) * vect2(v) < 0
       AND vertical_los_crit_CA?(s, v, MinRelVertSpeed)(nv) AND s /= zero
       AND eps = dv_to_ec(vertical_decision_vect)(s, v)
       IMPLIES vect2(nv) /= zero;

  % Subtype TCC generated (at line 112, column 73) for  vect2(v)
      % expected type  Nz_vect2
  vertical_los_crit_CA_independent_TCC2: OBLIGATION
    FORALL (MinRelVertSpeed: posreal, nv, s, v: Vect3, eps: Sign):
           vect2(s) * vect2(nv) < 0 AND vect2(s) * vect2(v) < 0
       AND vertical_los_crit_CA?(s, v, MinRelVertSpeed)(nv) AND s /= zero
       AND eps = dv_to_ec(vertical_decision_vect)(s, v)
       IMPLIES vect2(v) /= zero;

  % Subtype TCC generated (at line 120, column 31) for  vect2(nv)
      % expected type  Nz_vect2
  vertical_los_crit_CA_independent_strong_TCC1: OBLIGATION
    FORALL (MinRelVertSpeed: posreal, nv, s, v: Vect3):
      s /= zero AND
       vertical_los_crit_CA?(s, v, MinRelVertSpeed)(nv) AND
        vect2(s) * vect2(v) < 0 AND vect2(s) * vect2(nv) < 0
       IMPLIES vect2(nv) /= zero;

  % Subtype TCC generated (at line 120, column 73) for  vect2(v)
      % expected type  Nz_vect2
  vertical_los_crit_CA_independent_strong_TCC2: OBLIGATION
    FORALL (MinRelVertSpeed: posreal, nv, s, v: Vect3):
      s /= zero AND
       vertical_los_crit_CA?(s, v, MinRelVertSpeed)(nv) AND
        vect2(s) * vect2(v) < 0 AND vect2(s) * vect2(nv) < 0
       IMPLIES vect2(v) /= zero;

  % Subtype TCC generated (at line 155, column 36) for  vect2(nv)
      % expected type  Nz_vect2
  vertical_los_crit_CA_coordinated_strong_TCC1: OBLIGATION
    FORALL (MinRelVertSpeedi, MinRelVertSpeedo: posreal,
            nvi, nvo, s, vi, vo, v: Vect3):
      v = vo - vi IMPLIES
       (FORALL (nv: Vect3):
               NOT vect2(s) * vect2(nv) >= 0 AND s /= zero
           AND vertical_los_crit_CA?(s, vo - vi, MinRelVertSpeedo)(nvo - vi)
           AND vertical_los_crit_CA?(-s, vi - vo, MinRelVertSpeedi)(nvi - vo)
           AND vect2(s) * vect2(v) < 0 AND nv = nvo - nvi
           IMPLIES vect2(nv) /= zero);

  % Subtype TCC generated (at line 155, column 77) for  vect2(v)
      % expected type  Nz_vect2
  vertical_los_crit_CA_coordinated_strong_TCC2: OBLIGATION
    FORALL (MinRelVertSpeedi, MinRelVertSpeedo: posreal,
            nvi, nvo, s, vi, vo, v: Vect3):
      v = vo - vi IMPLIES
       (FORALL (nv: Vect3):
               NOT vect2(s) * vect2(nv) >= 0 AND s /= zero
           AND vertical_los_crit_CA?(s, vo - vi, MinRelVertSpeedo)(nvo - vi)
           AND vertical_los_crit_CA?(-s, vi - vo, MinRelVertSpeedi)(nvi - vo)
           AND vect2(s) * vect2(v) < 0 AND nv = nvo - nvi
           IMPLIES vect2(v) /= zero);


body:
  wedge_optimum_2D: THEORY
  %------------------------------------------------------------------------------
  %  This file defines an algorithm that finds the point on a line
  %  with the largest norm such that it lies between two half planes 
  %  that are inputs
  %
  %             /-half plane 1
  %           /
  %         / |  
  %       /   | 
  %     0     |   
  %       \   | 
  %	  \ X-point    
  %	    \   
  %	      \
  %	        \
  %
  %------------------------------------------------------------------------------

  BEGIN

     IMPORTING vectors@vectors_2D,
     	     horizontal,
  	     vectors@law_cos_pos_2D,
  	     vectors@basis_2D,
  	     analysis@interm_value_thm,
  	     analysis@continuous_lambda,
  	     reals@quad_minmax

     v,u,w,c,p,s	: VAR Vect2
     e1,e2 	: VAR Nz_vect2
     R,k	  	: VAR posreal
     t	  	: VAR nnreal
     a,b		: VAR real

    intersects_segment?(p,w,v,a,b,e1,e2): bool =
      EXISTS (t:real): a<=t AND t<=b AND
      	   	     (w+t*v-p)*e1>=0 AND
  		     (w+t*v-p)*e2>=0

    intersects_segment_fun?(p,w,v,a,b,e1,e2): bool =
      LET
        tlow1  = IF v*e1>0 THEN ((p-w)*e1)/(v*e1) ELSIF v*e1 = 0 AND (w-p)*e1<0 THEN b+1 ELSE a ENDIF,
        thigh1 = IF v*e1<0 THEN ((p-w)*e1)/(v*e1) ELSIF v*e1 = 0 AND (w-p)*e1<0 THEN a-1 ELSE b ENDIF,
        tlow2  = IF v*e2>0 THEN ((p-w)*e2)/(v*e2) ELSIF v*e2 = 0 AND (w-p)*e2<0 THEN b+2 ELSE a ENDIF,
        thigh2 = IF v*e2<0 THEN ((p-w)*e2)/(v*e2) ELSIF v*e2 = 0 AND (w-p)*e2<0 THEN a-2 ELSE b ENDIF,
        tlow   = max(max(tlow1,tlow2),a),
        thigh  = min(min(thigh1,thigh2),b)
      IN (tlow <= thigh)

    intersects_segment_fun_def: LEMMA
      intersects_segment_fun? = intersects_segment?

    on_segment?(w,v,a,b)(s): bool = 
      EXISTS (t:real): a<=t AND t<=b AND
      	   	     s = w+t*v

    on_segment_in_wedge?(p,w,v,a,b,e1,e2)(s): bool = 
      EXISTS (t:real): a<=t AND t<=b AND
      	   	     s = w+t*v AND
  		     (s-p)*e1>=0 AND
  		     (s-p)*e2>=0

    intersects_segment_sym: LEMMA
      intersects_segment?(p,w,v,a,b,e2,e1) IFF
      intersects_segment?(p,w,v,a,b,e1,e2)

    on_segment_in_wedge_sym: LEMMA
      on_segment_in_wedge?(p,w,v,a,b,e2,e1) =
      on_segment_in_wedge?(p,w,v,a,b,e1,e2)


    %%% The line segment is w+tv, where t is in [a,b]

    max_segment_point_in_slice(p,w,v,a,b,e1,e2): Vect2 =
      LET
        tlow1  = IF v*e1>0 THEN ((p-w)*e1)/(v*e1) ELSIF v*e1 = 0 AND (w-p)*e1<0 THEN b+1 ELSE a ENDIF,
        thigh1 = IF v*e1<0 THEN ((p-w)*e1)/(v*e1) ELSIF v*e1 = 0 AND (w-p)*e1<0 THEN a-1 ELSE b ENDIF,
        tlow2  = IF v*e2>0 THEN ((p-w)*e2)/(v*e2) ELSIF v*e2 = 0 AND (w-p)*e2<0 THEN b+2 ELSE a ENDIF,
        thigh2 = IF v*e2<0 THEN ((p-w)*e2)/(v*e2) ELSIF v*e2 = 0 AND (w-p)*e2<0 THEN a-2 ELSE b ENDIF,
        tlow   = max(max(tlow1,tlow2),a),
        thigh  = min(min(thigh1,thigh2),b),
        aa     = sqv(v),
        bb     = 2*(v*(w-p)),
        cc     = sqv(w-p),
        qmint  = IF v = zero THEN 0 ELSE -bb/(2*aa) ENDIF,
        maxt   = IF aa*tlow^2 + bb*tlow <= aa*thigh^2+bb*thigh THEN thigh
        	       ELSE tlow ENDIF
      IN w + maxt*v

    % max_segment_point_in_slice_symm: LEMMA
    %   max_segment_point_in_slice(p,w,v,a,b,e1,e2) =
    %   max_segment_point_in_slice(p,w,v,a,b,e2,e1)

    max_segment_point_in_slice_def: LEMMA
      Let s = max_segment_point_in_slice(p,w,v,a,b,e1,e2) IN
      (intersects_segment?(p,w,v,a,b,e1,e2)
      IMPLIES on_segment_in_wedge?(p,w,v,a,b,e1,e2)(s)) AND
      (FORALL (u): on_segment_in_wedge?(p,w,v,a,b,e1,e2)(u)
      	    	 IMPLIES norm(u-p) <= norm(s-p))

    max_segment_point_in_slice_complete: LEMMA 
      LET s = max_segment_point_in_slice(p,w,v,a,b,e1,e2) IN
      FORALL (u): on_segment_in_wedge?(p,w,v,a,b,e1,e2)(u)
      	   	IMPLIES
  		on_segment_in_wedge?(p,w,v,a,b,e1,e2)(s)



  END wedge_optimum_2D

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

  % Subtype TCC generated (at line 43, column 42) for  (v * e1)
      % expected type  nznum
  intersects_segment_fun?_TCC1: OBLIGATION
    FORALL (v: Vect2, e1: Nz_vect2, e2: Nz_vect2):
      v * e1 > 0 IMPLIES (v * e1) /= 0;

  % Subtype TCC generated (at line 44, column 42) for  (v * e1)
      % expected type  nznum
  intersects_segment_fun?_TCC2: OBLIGATION
    FORALL (p: Vect2, w: Vect2, v: Vect2, a: real, b: real, e1: Nz_vect2,
            e2: Nz_vect2, tlow1: real):
      v * e1 < 0 AND
       tlow1 =
        IF v * e1 > 0 THEN ((p - w) * e1) / (v * e1)
        ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN b + 1
        ELSE a
        ENDIF
       IMPLIES (v * e1) /= 0;

  % Subtype TCC generated (at line 45, column 42) for  (v * e2)
      % expected type  nznum
  intersects_segment_fun?_TCC3: OBLIGATION
    FORALL (p: Vect2, w: Vect2, v: Vect2, a: real, b: real, e1: Nz_vect2,
            e2: Nz_vect2, tlow1: real):
      tlow1 =
       IF v * e1 > 0 THEN ((p - w) * e1) / (v * e1)
       ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN b + 1
       ELSE a
       ENDIF
       IMPLIES
       (FORALL (thigh1: real):
          v * e2 > 0 AND
           thigh1 =
            IF v * e1 < 0 THEN ((p - w) * e1) / (v * e1)
            ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN a - 1
            ELSE b
            ENDIF
           IMPLIES (v * e2) /= 0);

  % Subtype TCC generated (at line 46, column 42) for  (v * e2)
      % expected type  nznum
  intersects_segment_fun?_TCC4: OBLIGATION
    FORALL (p: Vect2, w: Vect2, v: Vect2, a: real, b: real, e1: Nz_vect2,
            e2: Nz_vect2, tlow1: real):
      tlow1 =
       IF v * e1 > 0 THEN ((p - w) * e1) / (v * e1)
       ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN b + 1
       ELSE a
       ENDIF
       IMPLIES
       (FORALL (thigh1: real):
          thigh1 =
           IF v * e1 < 0 THEN ((p - w) * e1) / (v * e1)
           ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN a - 1
           ELSE b
           ENDIF
           IMPLIES
           (FORALL (tlow2: real):
              v * e2 < 0 AND
               tlow2 =
                IF v * e2 > 0 THEN ((p - w) * e2) / (v * e2)
                ELSIF v * e2 = 0 AND (w - p) * e2 < 0 THEN b + 2
                ELSE a
                ENDIF
               IMPLIES (v * e2) /= 0));

  % Subtype TCC generated (at line 86, column 44) for  (2 * aa)
      % expected type  nznum
  max_segment_point_in_slice_TCC1: OBLIGATION
    FORALL (p: Vect2, w: Vect2, v: Vect2, a: real, b: real, e1: Nz_vect2,
            e2: Nz_vect2, tlow1: real):
      tlow1 =
       IF v * e1 > 0 THEN ((p - w) * e1) / (v * e1)
       ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN b + 1
       ELSE a
       ENDIF
       IMPLIES
       (FORALL (thigh1: real):
          thigh1 =
           IF v * e1 < 0 THEN ((p - w) * e1) / (v * e1)
           ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN a - 1
           ELSE b
           ENDIF
           IMPLIES
           (FORALL (tlow2: real):
              tlow2 =
               IF v * e2 > 0 THEN ((p - w) * e2) / (v * e2)
               ELSIF v * e2 = 0 AND (w - p) * e2 < 0 THEN b + 2
               ELSE a
               ENDIF
               IMPLIES
               (FORALL (thigh2: real):
                  thigh2 =
                   IF v * e2 < 0 THEN ((p - w) * e2) / (v * e2)
                   ELSIF v * e2 = 0 AND (w - p) * e2 < 0 THEN a - 2
                   ELSE b
                   ENDIF
                   IMPLIES
                   (FORALL (tlow:
                              {p_1: real |
                                       p_1 >= max(tlow1, tlow2)
                                       AND
                                       p_1 >= a}):
                      tlow = max(max(tlow1, tlow2), a) IMPLIES
                       (FORALL (thigh:
                                  {p_1: real |
                                           p_1 <= min(thigh1, thigh2)
                                           AND
                                           p_1 <= b}):
                          thigh = min(min(thigh1, thigh2), b) IMPLIES
                           (FORALL (aa: nnreal):
                              aa = sqv(v) IMPLIES
                               (FORALL (bb: real):
                                  bb = 2 * (v * (w - p)) IMPLIES
                                   (FORALL (cc: nnreal):
                                      NOT v = zero AND cc = sqv(w - p)
                                      IMPLIES
                                      (2 * aa) /= 0))))))));

  % Subtype TCC generated (at line 87, column 26) for  2
      % expected type  {i: int | tlow /= 0 OR i >= 0}
  max_segment_point_in_slice_TCC2: OBLIGATION
    FORALL (p: Vect2, w: Vect2, v: Vect2, a: real, b: real, e1: Nz_vect2,
            e2: Nz_vect2, tlow1: real):
      tlow1 =
       IF v * e1 > 0 THEN ((p - w) * e1) / (v * e1)
       ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN b + 1
       ELSE a
       ENDIF
       IMPLIES
       (FORALL (thigh1: real):
          thigh1 =
           IF v * e1 < 0 THEN ((p - w) * e1) / (v * e1)
           ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN a - 1
           ELSE b
           ENDIF
           IMPLIES
           (FORALL (tlow2: real):
              tlow2 =
               IF v * e2 > 0 THEN ((p - w) * e2) / (v * e2)
               ELSIF v * e2 = 0 AND (w - p) * e2 < 0 THEN b + 2
               ELSE a
               ENDIF
               IMPLIES
               (FORALL (thigh2: real):
                  thigh2 =
                   IF v * e2 < 0 THEN ((p - w) * e2) / (v * e2)
                   ELSIF v * e2 = 0 AND (w - p) * e2 < 0 THEN a - 2
                   ELSE b
                   ENDIF
                   IMPLIES
                   (FORALL (tlow:
                              {p_1: real |
                                       p_1 >= max(tlow1, tlow2)
                                       AND
                                       p_1 >= a}):
                      tlow = max(max(tlow1, tlow2), a) IMPLIES
                       (FORALL (thigh:
                                  {p_1: real |
                                           p_1 <= min(thigh1, thigh2)
                                           AND
                                           p_1 <= b}):
                          thigh = min(min(thigh1, thigh2), b) IMPLIES
                           (FORALL (aa: nnreal):
                              aa = sqv(v) IMPLIES
                               (FORALL (bb: real):
                                  bb = 2 * (v * (w - p)) IMPLIES
                                   (FORALL (cc: nnreal):
                                      cc = sqv(w - p)
                                      IMPLIES
                                      (FORALL
                                       (qmint: real):
                                       qmint
                                       =
                                       IF v = zero
                                       THEN 0
                                       ELSE -bb / (2 * aa)
                                       ENDIF
                                       IMPLIES
                                       tlow /= 0 OR 2 >= 0)))))))));

  % Subtype TCC generated (at line 87, column 50) for  2
      % expected type  {i: int | thigh /= 0 OR i >= 0}
  max_segment_point_in_slice_TCC3: OBLIGATION
    FORALL (p: Vect2, w: Vect2, v: Vect2, a: real, b: real, e1: Nz_vect2,
            e2: Nz_vect2, tlow1: real):
      tlow1 =
       IF v * e1 > 0 THEN ((p - w) * e1) / (v * e1)
       ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN b + 1
       ELSE a
       ENDIF
       IMPLIES
       (FORALL (thigh1: real):
          thigh1 =
           IF v * e1 < 0 THEN ((p - w) * e1) / (v * e1)
           ELSIF v * e1 = 0 AND (w - p) * e1 < 0 THEN a - 1
           ELSE b
           ENDIF
           IMPLIES
           (FORALL (tlow2: real):
              tlow2 =
               IF v * e2 > 0 THEN ((p - w) * e2) / (v * e2)
               ELSIF v * e2 = 0 AND (w - p) * e2 < 0 THEN b + 2
               ELSE a
               ENDIF
               IMPLIES
               (FORALL (thigh2: real):
                  thigh2 =
                   IF v * e2 < 0 THEN ((p - w) * e2) / (v * e2)
                   ELSIF v * e2 = 0 AND (w - p) * e2 < 0 THEN a - 2
                   ELSE b
                   ENDIF
                   IMPLIES
                   (FORALL (tlow:
                              {p_1: real |
                                       p_1 >= max(tlow1, tlow2)
                                       AND
                                       p_1 >= a}):
                      tlow = max(max(tlow1, tlow2), a) IMPLIES
                       (FORALL (thigh:
                                  {p_1: real |
                                           p_1 <= min(thigh1, thigh2)
                                           AND
                                           p_1 <= b}):
                          thigh = min(min(thigh1, thigh2), b) IMPLIES
                           (FORALL (aa: nnreal):
                              aa = sqv(v) IMPLIES
                               (FORALL (bb: real):
                                  bb = 2 * (v * (w - p)) IMPLIES
                                   (FORALL (cc: nnreal):
                                      cc = sqv(w - p)
                                      IMPLIES
                                      (FORALL
                                       (qmint: real):
                                       qmint
                                       =
                                       IF v = zero
                                       THEN 0
                                       ELSE -bb / (2 * aa)
                                       ENDIF
                                       IMPLIES
                                       thigh /= 0 OR 2 >= 0)))))))));


body:
  circle_optimum_2D: THEORY
  %------------------------------------------------------------------------------
  %  This file defines an algorithm that finds the point on a circle
  %  with the largest norm such that it lies between two half planes 
  %  that are inputs
  %
  %  Anthony N
  %
  %             /-half plane 1
  %           /\
  %         /   \
  %       /      \ -circle
  %     0         \
  %       \	 |
  %	  \      |
  %	    \   /
  %	      \X-point
  %	        \- half plane 2
  %
  %  This function uses Theta_D, which is defined in ACCoRD.
  %------------------------------------------------------------------------------

  BEGIN

     IMPORTING vectors@vectors_2D,
     	     horizontal,
  	     vectors@law_cos_pos_2D,
  	     vectors@basis_2D,
  	     analysis@interm_value_thm,
  	     analysis@continuous_lambda

     v,u,w,c,p        : VAR Vect2
     e1,e2 	: VAR Nz_vect2
     R,k	  	: VAR posreal
     t	  	: VAR nnreal

    circle?(c,R)(w): bool = norm(w-c) = R
    segment?(v)(w): bool  = EXISTS (t): w = t*v
    
    % First, a function to compute the maximum norm of a point that lies both in the
    % circle and along the vector v from the origin.

    intersects_circle_fun?(v,c,R): bool = (v/=zero AND Delta[R](-c,v)>=0 AND (c*v >=0 OR sqv(-c)<=sq(R)))
    				      	OR
  					(v =zero AND sqv(c) = sq(R))

    intersects_circle_fun_scal: LEMMA intersects_circle_fun?(v,c,R) IFF
      			           intersects_circle_fun?(k*v,c,R)

    intersects_circle_fun_def: LEMMA intersects_circle_fun?(v,c,R) IFF
      			       (EXISTS (w): circle?(c,R)(w) AND segment?(v)(w))

    intersects_circle_fun_inc: LEMMA v/=zero AND u/=zero AND intersects_circle_fun?(v,c,R) AND
      ^(v)*c<=^(u)*c IMPLIES intersects_circle_fun?(u,c,R)

    inter_circle_max_time(v,c,R): nnreal =
      IF v/=zero AND intersects_circle_fun?(v,c,R) THEN Theta_D[R](-c,v,1)
      ELSE 0 ENDIF

    inter_circle_max_time_scal: LEMMA
      FORALL (pt:posreal): inter_circle_max_time(pt*v,c,R) = (1/pt)*inter_circle_max_time(v,c,R)

    inter_circle_max_time_def: LEMMA
      LET t = inter_circle_max_time(v,c,R) IN
      	(intersects_circle_fun?(v,c,R) IMPLIES
    	circle?(c,R)(t*v)) AND
    	(FORALL (nnt:nnreal): circle?(c,R)(nnt*v) IMPLIES
    	       norm(nnt*v) <= norm(t*v) AND
    	       (nnt /= t AND v/=zero IMPLIES norm(nnt*v) < norm(t*v)))

    inter_circle_max_norm(v,c,R): nnreal = 
          IF intersects_circle_fun?(v,c,R) THEN inter_circle_max_time(v,c,R)*norm(v)
          ELSE 0 ENDIF

    inter_circle_max_norm_scal: LEMMA
      FORALL (pt:posreal): inter_circle_max_norm(pt*v,c,R) = inter_circle_max_norm(v,c,R)

    % inter_circle_max_norm_def: LEMMA
    %   LET maxnorm = inter_circle_max_norm(v,c,R) IN
    %     FORALL (nnt:nnreal): circle?(c,R)(nnt*v) IMPLIES norm(nnt*v) <= maxnorm

    max_norm_increasing: LEMMA
      (v/=zero AND u/=zero AND ^(v)*c<=^(u)*c) OR
      ((v=zero OR u=zero) AND norm(v)<=norm(u))
      IMPLIES
      inter_circle_max_norm(v,c,R) <= inter_circle_max_norm(u,c,R)

    %%%%%%% An algorithm that computes the point x with (1/norm(x))*x*c maximal such that
    %%%%%%% x*e1 >= k1 AND x*e2 >= k2

    %%%%%%% An algorithm that computes the point x on a circle of radius R around a point c
    %%%%%%% that is the maximal point from p satisfying (x-p)*e1>=0 AND (x-p)*e2>=0

    max_circle_point_in_slice(p,c,R,e1,e2): Vect2 =
      IF    c = p AND perpR(e1)*e2>=0 
          THEN p + (R/norm(e1))*perpR(e1)
      ELSIF c = p
          THEN p - (R/norm(e1))*perpR(e1)
      ELSIF (c-p)*e1 >= 0 AND (c-p)*e2 >= 0
          THEN p + (1+R/norm(c-p))*(c-p)
      ELSE
          LET e1perp = IF perpR(e1)*e2 >= 0 THEN perpR(e1) ELSE -perpR(e1) ENDIF,
  	    e2perp = IF (-sign(e1*e2))*(perpR(e2)*e1) >= 0 THEN (-sign(e1*e2))*perpR(e2) ELSE sign(e1*e2)*perpR(e2) ENDIF,
  	    e1vect = p + inter_circle_max_time(e1perp,c-p,R)*e1perp,
  	    e2vect = p + inter_circle_max_time(e2perp,c-p,R)*e2perp
  	IN
  	    IF (e2perp/=zero AND e1perp/=zero AND ^(e2perp)*(c-p)<=^(e1perp)*(c-p)) OR
      	       ((e2perp=zero OR e1perp=zero) AND norm(e2vect-p)<=norm(e1vect-p))
  	    THEN 
  	       e1vect
  	    ELSE
  	       e2vect
  	    ENDIF
      ENDIF

    % max_circle_point_in_slice_composition: LEMMA
    %   LET vv = max_circle_point_in_slice(p,c,R,e1,e2),
    %   	ww = max_circle_point_in_slice(p,c,R,e2,e3),
    % 	zz = max_circle_point_in_slice(p,c,R,e1,e3)
    %   IN intersects_circle_fun?(vv-p,c-p,R) AND
    %      intersects_circle_fun?(ww-p,c-p,R) AND
         
    %      IMPLIES
    %      intersects_circle_fun?(ww-p,c-p,R)

    lem1: LEMMA FORALL (v1,v2:Vect2): norm(v1) = 1 AND norm(v2) = 1
      IMPLIES ((v1*v2>=0 IFF norm(v1-v2)<=sqrt(2)) AND
      	    (v1*v2> 0 IFF norm(v1-v2)<sqrt(2)))

    lem2: LEMMA FORALL (v1,v2,v3:Vect2): norm(v1) = 1 AND norm(v2) = 1 AND
    	      	     		       norm(v3) = 1
      IMPLIES ((v1*v3 <= v2*v3) IFF norm(v1-v3)>=norm(v2-v3)) AND
      	    ((v1*v3 < v2*v3) IFF norm(v1-v3)>norm(v2-v3))



    max_circle_point_in_slice_intersection: LEMMA
      FORALL (aa, bb, cc, dd, ap, bp, cp, dp, h, g: Nz_vect2):
               orthonormal?(aa, ap) AND orthonormal?(bb, bp)
           AND orthonormal?(cc, cp) AND orthonormal?(dd, dp) AND norm(h) = 1 and norm(g) = 1
           AND bp * aa >= 0 AND ap * bb >= 0 AND cp * dd >= 0 AND dp * cc >= 0
           AND (aa = bb IMPLIES ap/=bp)
  	 AND h * aa > 0 AND h * bb > 0
           AND h * cc > 0 AND h * dd > 0 AND g*cc>0 AND g*dd>0 AND (NOT (g*aa>=0 AND g*bb>=0))
           IMPLIES
           (ap * cc > 0 AND ap * dd > 0) OR
            (bp * cc > 0 AND bp * dd > 0)

    max_circle_point_in_slice_union: LEMMA
      FORALL (aa, bb, cc, dd, ap, bp, cp, dp, h, g: Nz_vect2):
               orthonormal?(aa, ap) AND orthonormal?(bb, bp)
           AND orthonormal?(cc, cp) AND orthonormal?(dd, dp) AND norm(h) = 1 and norm(g) = 1
           AND bp * aa >= 0 AND ap * bb >= 0 AND cp * dd >= 0 AND dp * cc >= 0
           AND (aa = bb IMPLIES ap/=bp)
  	 AND h * aa > 0 AND h * bb > 0 AND g*cc = g*dd
           AND (h * cc > 0 OR h * dd > 0) AND (g*cc>0 OR g*dd>0) AND (NOT (g*aa>=0 AND g*bb>=0))
           IMPLIES
           (ap * cc > 0 OR ap * dd > 0) OR
            (bp * cc > 0 OR bp * dd > 0)

    dot_gt_dot_equals_slice_intersection: LEMMA 
      FORALL (g,rp:Vect2): rp*g>=0 AND norm(g) = 1 AND norm(rp) = 1
          IMPLIES  (EXISTS (vv1, vv2: Nz_vect2): norm(vv1) = 1 AND norm(vv2) = 1 AND
  	   g*vv1 = g*vv2 AND
             (FORALL (ww: Nz_vect2): norm(ww) = 1 IMPLIES
                 (ww * g > rp * g IFF (ww * vv1 > 0 AND ww * vv2 > 0))))

    dot_gt_dot_equals_slice_union: LEMMA 
      FORALL (g,rp:Vect2): rp*g<0 AND norm(g) = 1 AND norm(rp) = 1 AND rp/=-g
          IMPLIES  (EXISTS (vv1, vv2: Nz_vect2): norm(vv1) = 1 AND norm(vv2) = 1 AND
             g * vv1 = g * vv2 AND
  	   (FORALL (ww: Nz_vect2): norm(ww) = 1 IMPLIES
                 (ww * g > rp * g IFF (ww * vv1 > 0 OR ww * vv2 > 0))))

    max_circle_point_in_slice_lem: LEMMA
       (FORALL (r, s, g, h, rp, sp: Vect2):
               norm(r) = 1 AND norm(s) = 1 AND norm(g) = 1 AND norm(h) = 1
           AND norm(rp) = 1 AND norm(sp) = 1
           AND (NOT (g * r >= 0 AND g * s >= 0)) AND sp * g <= rp * g
           AND h * r >= 0 AND h * s >= 0 AND orthonormal?(r, rp)
           AND orthonormal?(s, sp) AND rp * s >= 0 AND sp * r >= 0 AND (r=s IMPLIES rp/=sp)
  	 AND (NOT (sp * g <= 0 AND r = -s AND rp = sp AND h = -sp))
           IMPLIES h * g <= rp * g)

    max_circle_point_in_slice_lem_eq: LEMMA
       (FORALL (r, s, g, h, rp, sp: Vect2):
               norm(r) = 1 AND norm(s)  = 1 AND norm(g) = 1 AND norm(h) = 1
           AND norm(rp) = 1 AND norm(sp) = 1
           AND (NOT (g * r >= 0 AND g * s >= 0)) AND sp * g <= rp * g
           AND h * r >= 0 AND h * s >= 0 AND orthonormal?(r, rp)
           AND orthonormal?(s, sp) AND rp * s >= 0 AND sp * r >= 0 AND r=s and		rp = -sp
           IMPLIES h * g <= rp * g)

    max_circle_point_in_slide_sym_lem: LEMMA FORALL (vv:Vect2,e1perp,e2perp:Nz_vect2):
       vv = p + inter_circle_max_time(e1perp, c - p, R) * e1perp AND circle?(c, R)(w) AND 
       (w - p) * e1 >= 0 AND  (w - p) * e2 >= 0 AND  orthogonal?(e1, e1perp)
       AND  orthogonal?(e2, e2perp) AND  e1perp * e2 >= 0 AND  e2perp * e1 >= 0
       AND ((e2perp /= zero AND e1perp /= zero AND ^(e2perp) * (c - p) <= ^(e1perp) * (c - p) AND
            (c-p/=zero AND (NOT (^(c - p) * ^(e1) >= 0 AND ^(c - p) * ^(e2) >= 0)) AND
         ^(e1) = ^(e2) AND ^(e1perp) = -^(e2perp) OR (c-p/=zero AND NOT (^(c - p) * ^(e1) >= 0 AND ^(c - p) * ^(e2) >= 0)) AND
         (^(e1) = ^(e2) IMPLIES ^(e1perp) /= ^(e2perp)) AND
          (NOT (^(e2perp) * ^(c - p) <= 0 AND
                 ^(e1) = -^(e2) AND
                  ^(e1perp) = ^(e2perp) AND w-p /= zero AND ^(w - p) = -^(e2perp))))) 
       OR ((e2perp = zero OR e1perp = zero) AND norm(perpR(e2)) <= norm(perpR(e1))))
       IMPLIES  (((c - p) * e1 >= 0 AND (c - p) * e2 >= 0) OR norm(w - p) <= norm(vv - p) OR c = p)

    max_circle_point_in_slice_def: LEMMA
      LET vv = max_circle_point_in_slice(p,c,R,e1,e2) IN
      (intersects_circle_fun?(vv-p,c-p,R)
      IMPLIES circle?(c,R)(vv) AND
      (vv-p)*e1 >= 0 AND
      (vv-p)*e2 >= 0) AND
      (FORALL (w): circle?(c,R)(w) AND (w-p)*e1 >= 0 AND (w-p)*e2 >= 0
      	    	 IMPLIES norm(w-p) <= norm(vv-p))

    max_circle_point_in_slice_complete: LEMMA 
      LET vv = max_circle_point_in_slice(p,c,R,e1,e2) IN
      FORALL (w): circle?(c,R)(w) AND (w-p)*e1 >= 0 AND (w-p)*e2 >= 0
      	   	IMPLIES
  		intersects_circle_fun?(vv-p,c-p,R)



  END circle_optimum_2D

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

  % Subtype TCC generated (at line 57, column 68) for  v
      % expected type  {nzv | Delta[R](-c, nzv) >= 0}
  inter_circle_max_time_TCC1: OBLIGATION
    FORALL (v: Vect2, c: Vect2, R: posreal):
      v /= zero AND intersects_circle_fun?(v, c, R) IMPLIES
       Delta[R](-c, v) >= 0;

  % Subtype TCC generated (at line 57, column 54) for  Theta_D[R](-c, v, 1)
      % expected type  nnreal
  inter_circle_max_time_TCC2: OBLIGATION
    FORALL (v: Vect2, c: Vect2, R: posreal):
      v /= zero AND intersects_circle_fun?(v, c, R) IMPLIES
       Theta_D[R](-c, v, 1) >= 0;

  % Subtype TCC generated (at line 100, column 22) for  norm(c - p)
      % expected type  nznum
  max_circle_point_in_slice_TCC1: OBLIGATION
    FORALL (p: Vect2, c: Vect2, e1: Nz_vect2, e2: Nz_vect2):
      (c - p) * e1 >= 0 AND
       (c - p) * e2 >= 0 AND
        NOT c = p AND NOT (c = p AND perpR(e1) * e2 >= 0)
       IMPLIES norm(c - p) /= 0;


body:
  %------------------------------------------------------------------------------
  % horizontal_los_criterion.pvs
  %
  % Criterion for horizontal recovery of Loss of Separation.
  % The criterion is based on the fact that s*v > 0 implies that v diverges 
  % from the origin of the coordinate system.
  %
  % This criteria is no longer used in Chorus. This criteria ensures divergence.
  % In the code, we are now using repulsive criteria instead. See repulsive.pvs.
  %------------------------------------------------------------------------------

  old_horiz_los_criterion : THEORY
  BEGIN

    IMPORTING definitions,
    	    predicate_coordination_2D

    s,
    v,vo,vi,
    nvo,nvi,
    w,nv,nw    : VAR Vect2
    T,T1,T2,
    Tmax,Tmin  : VAR posreal
    MinRelSpeed,
    MinRelSpeedo,
    MinRelSpeedi: VAR nnreal
    eps : VAR Sign

    horizontal_los_crit?(s,MinRelSpeed,eps)(v): bool =
        s*v>=0 AND
        eps*det(s,v)<=0 AND
        norm(v)>=MinRelSpeed


    horizontal_los_crit_symm: LEMMA
        horizontal_los_crit?(s,MinRelSpeed,eps)(v) IFF
        horizontal_los_crit?(-s,MinRelSpeed,eps)(-v)

    horizontal_los_crit_independent: LEMMA
        nvo-vi /= zero AND
        horizontal_los_crit?(s,MinRelSpeed,eps)(nvo-vi) IMPLIES
        divergent?(s,nvo-vi) AND
        eps*det(s,nvo-vi)<=0 AND
        norm(nvo-vi)>=MinRelSpeed

    horizontal_los_crit_coordinated: LEMMA
        horizontal_los_crit?(s,MinRelSpeedo,eps)(nvo-vi) AND
        horizontal_los_crit?(-s,MinRelSpeedi,eps)(nvi-vo) AND
        s*(vo-vi)<0 IMPLIES
        divergent?(s,nvo-nvi)
        
  END old_horiz_los_criterion


body:
  %------------------------------------------------------------------------------
  % horizontal_los.pvs
  % ACCoRD v.1.0
  %
  % Algorithms to horizontally recover from Loss of Separation 
  %------------------------------------------------------------------------------

  horizontal_los[D: posreal] : THEORY
  BEGIN

    IMPORTING vectors@perpendicular_2D,
    	    horizontal[D],            
  	    old_horiz_los_criterion,
              gs_only[D],
              trk_only[D],
              opt_trk_gs[D],
  	    circle_optimum_2D,
  	    wedge_optimum_2D
    
    s         : VAR LoS_vect2
    vo,vi     : VAR Nz_vect2
    v,nvo,nvi : VAR Vect2
    t,ti,to   : VAR posreal % Upper bound to time to recover separation
    irt       : VAR Sign
    MinRelSpeed,
    MinGS,MaxGS,
    MinRelSpeedo,
    MinGSo,MaxGSo,
    MinRelSpeedi,
    MinGSi,MaxGSi: VAR posreal

    %------------%
    % ALGORITHMS %
    %------------%

    sDs(s): posreal = norm(s)*D-sqv(s)

    gs_los(s,vo,vi,MinGS,MaxGS,MinRelSpeed,irt): {nvo | nz_vect2?(nvo) => 
                                   gs_only?(vo)(nvo) AND MinGS <= norm(nvo) AND norm(nvo) <= MaxGS} =
      LET nv = max_segment_point_in_slice(zero,-vi,(1/norm(vo))*vo,MinGS,MaxGS,s,irt*perpR(s))
      IN
        IF intersects_segment_fun?(zero,-vi,(1/norm(vo))*vo,MinGS,MaxGS,s,irt*perpR(s)) AND norm(nv)>=MinRelSpeed THEN
          nv+vi
        ELSE
          zero
        ENDIF

    gs_los_def: LEMMA LET nvo = gs_los(s,vo,vi,MinGS,MaxGS,MinRelSpeed,irt) IN
      (nvo/=zero IMPLIES
        gs_only?(vo)(nvo) AND 
        MinGS <= norm(nvo) AND 
        norm(nvo) <= MaxGS AND
        s*(nvo-vi)>=0 AND
        norm(nvo-vi)>=MinRelSpeed AND
        ((nvo-vi/=zero OR MinRelSpeed>0) IMPLIES divergent?(s,nvo-vi)) AND
        irt*det(s,nvo-vi)<=0) AND
          (FORALL (nvo2:Vect2):
  	  gs_only?(vo)(nvo2) AND 
        	  MinGS <= norm(nvo2) AND 
        	  norm(nvo2) <= MaxGS AND
  	  divergent?(s,nvo2-vi) AND
  	  irt*det(s,nvo2-vi)<=0 AND
  	  norm(nvo2-vi)>=MinRelSpeed IMPLIES
  	  norm(nvo2-vi)<=norm(nvo-vi)
  	  AND
  	  nvo/=zero)

    gs_los?(s,vo,vi,MinGS,MaxGS,MinRelSpeed)(nvo) : bool =
      nz_vect2?(nvo) AND
      EXISTS (irt): nvo = gs_los(s,vo,vi,MinGS,MaxGS,MinRelSpeed,irt)

    trk_los(s,vo,vi,MinRelSpeed,irt): {nvo | nz_vect2?(nvo) => 
                                   trk_only?(vo)(nvo)} =
      LET nv = max_circle_point_in_slice(zero,-vi,norm(vo),s,irt*perpR(s))
      IN
        IF intersects_circle_fun?(nv,-vi,norm(vo)) AND norm(nv)>=MinRelSpeed THEN
          nv+vi
        ELSE 
          zero
        ENDIF

    trk_los_def: LEMMA LET nvo = trk_los(s,vo,vi,MinRelSpeed,irt) IN
      (nvo/=zero IMPLIES
        norm(nvo) = norm(vo) AND
        s*(nvo-vi)>=0 AND
        norm(nvo-vi)>=MinRelSpeed AND
        ((nvo-vi/=zero OR MinRelSpeed>0) IMPLIES divergent?(s,nvo-vi)) AND
        irt*det(s,nvo-vi)<=0) AND
          (FORALL (nvo2:Vect2):
  	  norm(nvo2) = norm(vo) AND
  	  divergent?(s,nvo2-vi) AND
  	  irt*det(s,nvo2-vi)<=0 AND
  	  norm(nvo2-vi)>=MinRelSpeed IMPLIES
  	  norm(nvo2-vi)<=norm(nvo-vi)
  	  AND
  	  nvo/=zero)

    trk_los?(s,vo,vi,MinRelSpeed)(nvo) : bool =
      nz_vect2?(nvo) AND
      EXISTS (irt) : nvo = trk_los(s,vo,vi,MinRelSpeed,irt)

    % opt_los(s,vo,vi,t): {nvo | nz_vect2?(nvo) => 
    %                            optimal?(vo,Vdir(s,vo-vi))(nvo)} =
    %   LET v = vo-vi IN
    %   IF t*(s*v) < sDs(s) THEN
    %     opt_trk_gs_dot(s,vo,vi,sDs(s)/t)
    %   ELSE
    %     vo
    %   ENDIF

    % opt_los?(s,vo,vi,t)(nvo) : bool =
    %   nz_vect2?(nvo) AND
    %   nvo = opt_los(s,vo,vi,t)

    los_recovery?(s,vo,vi,MinRelSpeed,MinGS,MaxGS,MinRelSpeed)(nvo) : bool =
      gs_los?(s,vo,vi,MinGS,MaxGS,MinRelSpeed)(nvo) OR
      trk_los?(s,vo,vi,MinRelSpeed)(nvo)

    %----------%
    % LEMMAS   %
    %----------%

    los_recovery_meets_criteria : LEMMA
      los_recovery?(s,vo,vi,MinRelSpeed,MinGS,MaxGS,MinRelSpeed)(nvo)
      IMPLIES
        horizontal_los_crit?(s,MinRelSpeed,-sign(det(s,nvo-vi)))(nvo-vi)

    %-------------------------%
    % THEOREM: Independence   %
    %-------------------------%

    los_recovery_independence : THEOREM
      los_recovery?(s,vo,vi,MinRelSpeed,MinGS,MaxGS,MinRelSpeed)(nvo)
      IMPLIES
        divergent?(s,nvo-vi) AND
        norm(nvo-vi)>=MinRelSpeed

    %-------------------------%
    % THEOREM: Coordination   %
    %-------------------------%

    los_recovery_coordination : THEOREM
      los_recovery?(s,vo,vi,MinRelSpeedo,MinGSo,MaxGSo,MinRelSpeedo)(nvo) AND
      los_recovery?(-s,vi,vo,MinRelSpeedi,MinGSi,MaxGSi,MinRelSpeedi)(nvi)  AND
      horizontal_entry?(s,vo-vi)
      IMPLIES
        (divergent?(s,nvo-nvi) OR nvo-nvi=zero)

    %%%

  END horizontal_los

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

  % Subtype TCC generated (at line 36, column 20) for  norm(s) * D - sqv(s)
      % expected type  posreal
  sDs_TCC1: OBLIGATION
    FORALL (s: LoS_vect2[D]):
      norm(s) * D - sqv(s) >= 0 AND norm(s) * D - sqv(s) > 0;

  % Subtype TCC generated (at line 43, column 8) for  nv + vi
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           gs_only?(vo)(nvo) AND
                     %            MinGS <= norm(nvo) AND norm(nvo) <= MaxGS}
  gs_los_TCC1: OBLIGATION
    FORALL (s: LoS_vect2[D], vo: Nz_vect2, vi: Nz_vect2, MinGS: posreal,
            MaxGS: posreal, MinRelSpeed: posreal, irt: Sign, nv: Vect2):
      intersects_segment_fun?(zero, -vi, (1 / norm(vo)) * vo, MinGS, MaxGS,
                              s, irt * perpR(s))
       AND
       norm(nv) >= MinRelSpeed AND
        nv =
         max_segment_point_in_slice(zero, -vi, (1 / norm(vo)) * vo, MinGS,
                                    MaxGS, s, irt * perpR(s))
       IMPLIES
       nv + vi /= zero =>
        gs_only?(vo)(nv + vi) AND
         MinGS <= norm(nv + vi) AND norm(nv + vi) <= MaxGS;

  % Subtype TCC generated (at line 45, column 8) for  zero
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           gs_only?(vo)(nvo) AND
                     %            MinGS <= norm(nvo) AND norm(nvo) <= MaxGS}
  gs_los_TCC2: OBLIGATION
    FORALL (s: LoS_vect2[D], vo: Nz_vect2, vi: Nz_vect2, MinGS: posreal,
            MaxGS: posreal, MinRelSpeed: posreal, irt: Sign, nv: Vect2):
      NOT (intersects_segment_fun?(zero, -vi, (1 / norm(vo)) * vo, MinGS,
                                   MaxGS, s, irt * perpR(s))
            AND norm(nv) >= MinRelSpeed)
       AND
       nv =
        max_segment_point_in_slice(zero, -vi, (1 / norm(vo)) * vo, MinGS,
                                   MaxGS, s, irt * perpR(s))
       IMPLIES
       zero /= zero =>
        gs_only?(vo)(zero) AND MinGS <= norm(zero) AND norm(zero) <= MaxGS;

  % Subtype TCC generated (at line 77, column 8) for  nv + vi
      % expected type  {nvo | nvo /= zero => trk_only?(vo)(nvo)}
  trk_los_TCC1: OBLIGATION
    FORALL (s: LoS_vect2[D], vo: Nz_vect2, vi: Nz_vect2,
            MinRelSpeed: posreal, irt: Sign, nv: Vect2):
      intersects_circle_fun?(nv, -vi, norm(vo)) AND
       norm(nv) >= MinRelSpeed AND
        nv =
         max_circle_point_in_slice(zero, -vi, norm(vo), s, irt * perpR(s))
       IMPLIES nv + vi /= zero => trk_only?(vo)(nv + vi);

  % Subtype TCC generated (at line 79, column 8) for  zero
      % expected type  {nvo | nvo /= zero => trk_only?(vo)(nvo)}
  trk_los_TCC2: OBLIGATION
    FORALL (s: LoS_vect2[D], vo: Nz_vect2, vi: Nz_vect2,
            MinRelSpeed: posreal, irt: Sign, nv: Vect2):
      NOT (intersects_circle_fun?(nv, -vi, norm(vo)) AND
            norm(nv) >= MinRelSpeed)
       AND
       nv = max_circle_point_in_slice(zero, -vi, norm(vo), s, irt * perpR(s))
       IMPLIES zero /= zero => trk_only?(vo)(zero);

  % Subtype TCC generated (at line 144, column 18) for  -s
      % expected type  LoS_vect2[D]
  los_recovery_coordination_TCC1: OBLIGATION
    FORALL (MaxGSo, MinGSo, MinRelSpeedo: posreal, nvo: Vect2,
            s: LoS_vect2[D], vi, vo: Nz_vect2):
      los_recovery?(s, vo, vi, MinRelSpeedo, MinGSo, MaxGSo, MinRelSpeedo)
                   (nvo)
       IMPLIES sqv(-s) < sq(D);


body:
  %------------------------------------------------------------------------------
  % horizontal_los_criterion.pvs
  %
  %------------------------------------------------------------------------------

  horizontal_los_criterion : THEORY
  BEGIN

    IMPORTING repulsive

    s,
    vo,vi,
    nvo,nvi : VAR Nz_vect2
    eps : VAR Sign

    horizontal_los_criterion(s, vo, vi, nvo, eps): MACRO bool = repulsive_criteria(s,vo-vi,eps)(nvo-vi)

    horizontal_los_criterion_repulsive: LEMMA
      horizontal_los_criterion(s,vo,vi,nvo,eps)
      IMPLIES
      repulsive?(s,vo-vi)(nvo-vi)

    horizontal_los_criterion_coordinately_repulsive: LEMMA
      horizontal_los_criterion(s,vo,vi,nvo,eps) AND
      horizontal_los_criterion(-s,vi,vo,nvi,eps)
      IMPLIES
      repulsive?(s,vo-vi)(nvo-nvi)
        
  END horizontal_los_criterion


body:
  %% examples.pvs

  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 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:
  top : THEORY
  BEGIN

    IMPORTING time_fun,
              pathname,
              pvsio_checker,
              is_prime,
              prime_check

  END top


body:
  % Naive primality test
  is_prime : THEORY
  BEGIN

    is_prime?(n:nat) : bool =
      n > 1 AND (n = 2 OR FORALL (j:subrange(2,n-1)) : mod(n,j) /= 0)

  END is_prime

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

  % Subtype TCC generated (at line 6, column 59) for  j
      % expected type  nonzero_integer
  is_prime?_TCC1: OBLIGATION
    FORALL (n: nat):
      NOT n = 2 AND n > 1 IMPLIES (FORALL (j: subrange(2, n - 1)): j /= 0);


body:
  pathname : THEORY
  BEGIN

    pathname_path(name:string) : list[string]

    pathname_name(name:string) : string
   
    pathname_type(name:string) :string

    pathname_dir(name:string) : string =
      LET path = pathname_path(name) IN
      IF null?(path) THEN ""
      ELSIF car(path) = "/" THEN
        format("/~{~a/~}",{|cdr(path)|})
      ELSE
        format("~{~a/~}",{|path|})
      ENDIF

  END pathname

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

  % Subtype TCC generated (at line 13, column 14) for  path
      % expected type  (cons?[string])
  pathname_dir_TCC1: OBLIGATION
    FORALL (name: string, path: list[string]):
      NOT null?(path) AND path = pathname_path(name) IMPLIES
       cons?[string](path);


body:
  time_fun : THEORY
  BEGIN

    real_time : nat
    run_time  : nat
    internal_time_units : posreal

    Stamp : Global[[nat,nat],(0,0)]  % (realtime,runtime)

    tic : void =
      set[[nat,nat]](Stamp,(real_time,run_time))

    toc : [real,real] = 
      LET (ret,rut) = (real_time,run_time),
          (re0,ru0) = val[[nat,nat]](Stamp) IN
        ((ret-re0)/internal_time_units,(rut-ru0)/internal_time_units)

    % t is in secods; returns formatted string in the form "<h>h:<m>m:<s>s"
    hms(t:real) : string =
      LET ts = floor(t),
          ms = t-ts,
          h = floor(ts/3600),
          m = floor(mod(ts,3600)/60),
          s = mod(mod(ts,3600),60)+ms IN
      format("~ah:~am:~,3fs",(h,m,s))

    str_toc : string =
      format("Real time: ~a. Run time: ~,3f sec",(hms(toc`1),toc`2))

  END time_fun

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

  % Existence TCC generated (at line 25, column 4) for  format
  hms_TCC1: OBLIGATION
    FORALL (t: real, ts: {i | i <= t & t < 1 + i}):
      ts = floor(t) IMPLIES
       (FORALL (ms: real):
          ms = t - ts IMPLIES
           (FORALL (h: {i | i <= ts / 3600 & ts / 3600 < 1 + i}):
              h = floor(ts / 3600) IMPLIES
               (FORALL (m:
                          {i |
                                   i <= mod(ts, 3600) / 60 &
                                    mod(ts, 3600) / 60 < 1 + i}):
                  m = floor(mod(ts, 3600) / 60) IMPLIES
                   (FORALL (s: real):
                      s = mod(mod(ts, 3600), 60) + ms IMPLIES
                       (EXISTS (x:
                                  [{i | i <= ts / 3600 & ts / 3600 < 1 + i},
                                   {i |
                                            i <= mod(ts, 3600) / 60
                                            &
                                            mod(ts, 3600) / 60 < 1 + i},
                                   real]):
                          TRUE)))));


body:
  pvsio_checker : THEORY
  BEGIN

    IMPORTING time_fun,
              pathname

    % Global variables

    Records     : Global[nat,0]
    Fails       : Global[nat,0]
    CurrentLine : Global[nat,0]
    Frequency   : Global[posnat,10]
    Precision   : Global[nnreal,0.001]

    % Generic checker: 
    % Iterates check on a file until maxr (or end of file if maxr = 0)

    safe_div(m,n:real):real =
      IF n = 0 THEN 0 ELSE m/n ENDIF

    print_etc(fin:IStream,maxr:nat) : void =
      IF mod(val[nat](Records),val[posnat](Frequency)) = 0 THEN
        LET is   = IF maxr = 0 THEN safe_div(flength(fin),fgetpos(fin))
                   ELSE safe_div(maxr,val[nat](Records)) ENDIF,
            per  = floor(100*safe_div(1,is)),
            time = toc`1*(is-1) IN
          printf("[~d% - Line: ~d, Records: ~a] Estimated Time of Completion: ~a~%",
                (per,val(CurrentLine),val(Records),hms(time)))
      ELSE
        skip
      ENDIF 

    checker(file:string,check:[[IStream,OStream]->bool],maxr:nat) : void =
      IF file = "" OR fexists(file) THEN
        LET fin     = IF file = "" THEN stdin ELSE fopenin(file) ENDIF,
            nameout = IF maxr = 0 THEN format("~a~a.out",
                                             (pathname_dir(file),pathname_name(file))) 
                      ELSE format("~a~a-~a.out",
                                 (pathname_dir(file),pathname_name(file),maxr)) ENDIF,
            fout    = IF file = "" THEN stdout ELSE fopenout(create,nameout) ENDIF IN
          IF file /= "" THEN 
            printf("Reading: ~a. Writing: ~a~%",(file,nameout)) &
   	  fprintf(fout,"Date: ~a~%",date) &
            fprintf(fout,"Input file: ~a~%",file) 
          ELSE skip ENDIF &
          set[nat](Records,0) &
          set[nat](Fails,0) &
  	set[nat](CurrentLine,0) &
  	tic &
          while(NOT eof?(fin) AND maxr <= 0 OR val[nat](Records) < maxr,
                set[nat](Records,val[nat](Records)+1) &
                IF check(fin,fout) THEN skip ELSE set[nat](Fails,val[nat](Fails)+1) ENDIF &
                IF file /= "" THEN print_etc(fin,maxr) ELSE skip ENDIF) &
          LET msg = format("~a~%Lines: ~a. Records: ~a. Fails: ~a~%",
                          (str_toc,val[nat](CurrentLine),val[nat](Records),val[nat](Fails))) IN
          printf(msg) & 
  	IF file /= "" THEN fprintf(fout,msg) ELSE skip ENDIF &
          fclose(fin) &
          fclose(fout) 
      ELSE
        printf("File ~a doesn't exist",file)
      ENDIF

    empty_line(line:string) : bool =
      LET trln = trim(line) IN
        trln = "" OR strfind("%",trln) = 0

    readln_checker(fin:IStream):string =
      LET lvar = ref[string]("") IN
        prog(while (NOT eof?(fin) AND empty_line(val(lvar)),
               set[nat](CurrentLine,val[nat](CurrentLine)+1) &
               set[string](lvar,fread_line(fin))),
             val(lvar))

    almost_equal_prec?(r1,r2:real,prec:nnreal) : bool =
      abs(r1-r2) <= prec

    almost_equal?(r1,r2:real) : bool =
      almost_equal_prec?(r1,r2,val(Precision))

    check_real_prec(fout:OStream,msg:string,pvs,io:real,prec:nnreal) : bool =
      IF NOT almost_equal_prec?(pvs,io,prec) THEN
        fprintf(fout,"*** ERROR~a. Line: ~a. Record: ~a. PVS: ~,8f vs. Input: ~,8f~%",
               (msg,val(CurrentLine),val(Records),pvs,io)) &
        FALSE
      ELSE
        TRUE
      ENDIF

    check_real(fout:OStream,msg:string,pvs,io:real) : bool =
      check_real_prec(fout,msg,io,pvs,val(Precision))

    check_bool(fout:OStream,msg:string,pvs,io:bool) : bool =
      IF pvs /= io THEN
        fprintf(fout,"*** ERROR~a. Line: ~a. Record: ~a. PVS: ~a vs. Input: ~a~%",
               (msg,val(CurrentLine),val(Records),pvs,io)) &
        FALSE
      ELSE
        TRUE
      ENDIF

    check_int(fout:OStream,msg:string,pvs,io:int) : bool =
      IF pvs /= io THEN
        fprintf(fout,"*** ERROR~a. Line: ~a. Record: ~a. PVS: ~a vs. Input: ~a~%",
               (msg,val(CurrentLine),val(Records),pvs,io)) &
        FALSE
      ELSE
        TRUE
      ENDIF

    IMPORTING reals@sqrt

  END pvsio_checker

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

  % Subtype TCC generated (at line 19, column 27) for  n
      % expected type  nznum
  safe_div_TCC1: OBLIGATION FORALL (n: real): NOT n = 0 IMPLIES n /= 0;

  % Existence TCC generated (at line 7024, column 10) for  format
  print_etc_TCC1: OBLIGATION
    FORALL (fin: IStream, maxr: nat):
      mod(val[nat](Records), val[posnat](Frequency)) = 0 IMPLIES
       (FORALL (is: real):
          is =
           IF maxr = 0 THEN safe_div(flength(fin), fgetpos(fin))
           ELSE safe_div(maxr, val[nat](Records))
           ENDIF
           IMPLIES
           (FORALL (per:
                      {i |
                               i <= 100 * safe_div(1, is) &
                                100 * safe_div(1, is) < 1 + i}):
              per = floor(100 * safe_div(1, is)) IMPLIES
               (FORALL (time: real):
                  time = toc`1 * (is - 1) IMPLIES
                   (EXISTS (x:
                              [{i |
                                        i <= 100 * safe_div(1, is)
                                        &
                                        100 * safe_div(1, is) < 1 + i},
                               nat, nat, string]):
                      TRUE))));


body:
  prime_check : 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 =
      %set[posnat](Frequency,n) &    % Set frequency (in number of records) to print estimated time of completion
      %set[posreal](Precision,r) &   % Set precision to almost_equal
      checker(file,check?,records)

  END prime_check


body:
  top: THEORY
  BEGIN

   IMPORTING compute_sturm,
  	   gcd_coeff,
  	   number_sign_changes,
  	   polynomial_division,
  	   polynomial_pseudo_divide,
  	   remainder_sequence,
  	   sturm,
  	   sturmsquarefree,
             polylist,
  	   poly_strategy,
  	   strategies,
             examples

  END top


body:
  clear_denominators: THEORY
  BEGIN

    IMPORTING ints@gcd

  x,y : VAR posrat
  i   : VAR int
  n   : VAR nat
  pn  : VAR posnat

  PosRatPair: TYPE = [# num:posnat,den:posnat #]

  prp,prp1,prp2: VAR PosRatPair

  posratpair_convert(prp): posrat = prp`num/prp`den;

  +(prp1,prp2):PosRatPair = (# num:=prp1`num*prp2`den+prp2`num*prp1`den,
  			     den:=prp1`den*prp2`den #);

  posratpair_plus: LEMMA posratpair_convert(prp1)+posratpair_convert(prp2)=
  		       posratpair_convert(prp1+prp2);

  /(prp1,prp2):PosRatPair = (# num:=prp1`num*prp2`den,
  			     den:=prp1`den*prp2`num #);

  posratpair_div: LEMMA posratpair_convert(prp1)/posratpair_convert(prp2)=
  		       posratpair_convert(prp1/prp2);

  PosRatSet(x): set[posnat]= {N:posnat | EXISTS (pn1,pn2:posnat):
  		      		   x=pn1/pn2 AND N=pn1+pn2}

  PosRatSet_nonempty: LEMMA nonempty?(PosRatSet(x))

  PosRatSet_glb_posnat: LEMMA EXISTS (pn:posnat):
    PosRatSet(x)(pn) AND
    pn = glb(PosRatSet(x))

  PosRatMeas(x): nat =
    LET mp:posnat = glb(PosRatSet(x)) IN
      IF x<1 THEN 10^mp ELSE 10^mp - 1 ENDIF

  PosRatMeas_increasing: LEMMA
    (EXISTS (pn:(PosRatSet(x))): FORALL (pm:(PosRatSet(y))): pn<pm)
    IMPLIES PosRatMeas(x)<PosRatMeas(y)

  PosRatMeas_glb_minus_posnat: LEMMA x>pn IMPLIES
    glb(PosRatSet(x-pn)) <= glb(PosRatSet(x))-pn

  compute_posratpair(x:posrat): RECURSIVE {prp | posratpair_convert(prp)=x} =
    IF floor(x)=x THEN (# num:=floor(x),den:=1 #)
    ELSIF x>1 THEN (# num:=floor(x),den:=1 #) + compute_posratpair(x-floor(x))
    ELSE (# num:=1,den:=1 #)/compute_posratpair(1/x)
    ENDIF MEASURE PosRatMeas(x)


  aq: VAR [nat->rat]


  rat_poly_to_int_rec(aq,n): RECURSIVE {ans:[# newpoly:[nat->rat],currgcd:posnat #] |
    (EXISTS (cp:posrat): FORALL (j:nat): ans`newpoly(j) = cp*aq(j)) AND
    (FORALL (j:upto(n)): rational_pred(ans`newpoly(j)) AND
    	  	       integer_pred(ans`newpoly(j)) AND
  		       divides(ans`currgcd,ans`newpoly(j)))} =
    IF n = 0 AND aq(0)=0 THEN (# newpoly:=aq,currgcd:=1 #)
    ELSIF n = 0 THEN 
      LET thisden = compute_posratpair(abs(aq(0)))`den IN
        (# newpoly:= (LAMBDA (i:nat): thisden*aq(i)),
           currgcd:= abs(thisden*aq(0)) #)
    ELSIF aq(n) = 0 THEN rat_poly_to_int_rec(aq,n-1)
    ELSE
      LET currpoly = rat_poly_to_int_rec(aq,n-1),
  	thisden = compute_posratpair(abs(currpoly`newpoly(n)))`den
      IN  (# newpoly:=(LAMBDA (i:nat): thisden*(currpoly`newpoly(i))),
      	   currgcd:=compute_gcd(thisden*currpoly`newpoly(n),
  	                                  currpoly`currgcd) #)
    ENDIF MEASURE n

  rat_poly_to_int(aq,n): {ai:[nat->int] | EXISTS (cp:posrat):
  		       FORALL (j:upto(n)): ai(j) = cp*aq(j) } =
    LET rptir = rat_poly_to_int_rec(aq,n),
        ppoly = rptir`newpoly,
        mgcd  = rptir`currgcd
    IN (LAMBDA (i:nat): IF i<=n THEN ppoly(i)/mgcd ELSE 0 ENDIF)

  END clear_denominators

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

  % Subtype TCC generated (at line 36, column 11) for
      % extend[real, posnat, bool, FALSE](PosRatSet(x))
      % expected type  SB: (bounded_below?)
  PosRatSet_glb_posnat_TCC1: OBLIGATION
    FORALL (x: posrat, pn: posnat):
      PosRatSet(x)(pn) IMPLIES
       nonempty?[real](extend[real, posnat, bool, FALSE](PosRatSet(x))) AND
        bounded_below?(extend[real, posnat, bool, FALSE](PosRatSet(x)));

  % Subtype TCC generated (at line 39, column 22) for
      % extend[real, posnat, bool, FALSE](PosRatSet(x))
      % expected type  SB: (bounded_below?)
  PosRatMeas_TCC1: OBLIGATION
    FORALL (x: posrat):
      nonempty?[real](extend[real, posnat, bool, FALSE](PosRatSet(x))) AND
       bounded_below?(extend[real, posnat, bool, FALSE](PosRatSet(x)));

  % Subtype TCC generated (at line 39, column 18) for
      % glb(extend[real, posnat, bool, FALSE](PosRatSet(x)))
      % expected type  posnat
  PosRatMeas_TCC2: OBLIGATION
    FORALL (x: posrat):
      rational_pred(glb(extend[real, posnat, bool, FALSE](PosRatSet(x)))) AND
       integer_pred(glb(extend[real, posnat, bool, FALSE](PosRatSet(x)))) AND
        glb(extend[real, posnat, bool, FALSE](PosRatSet(x))) >= 0 AND
         glb(extend[real, posnat, bool, FALSE](PosRatSet(x))) > 0;

  % Subtype TCC generated (at line 40, column 27) for  10 ^ mp - 1
      % expected type  nat
  PosRatMeas_TCC3: OBLIGATION
    FORALL (x: posrat, mp: posnat):
      NOT x < 1 AND mp = glb(extend[real, posnat, bool, FALSE](PosRatSet(x)))
       IMPLIES 10 ^ mp - 1 >= 0;

  % Subtype TCC generated (at line 47, column 16) for  x - pn
      % expected type  posrat
  PosRatMeas_glb_minus_posnat_TCC1: OBLIGATION
    FORALL (pn: posnat, x: posrat): x > pn IMPLIES x - pn >= 0 AND x - pn > 0;

  % Subtype TCC generated (at line 47, column 6) for
      % extend[real, posnat, bool, FALSE](PosRatSet(x - pn))
      % expected type  SB: (bounded_below?)
  PosRatMeas_glb_minus_posnat_TCC2: OBLIGATION
    FORALL (pn: posnat, x: posrat):
      x > pn IMPLIES
       nonempty?[real](extend[real, posnat, bool, FALSE](PosRatSet(x - pn)))
        AND
        bounded_below?(extend[real, posnat, bool, FALSE](PosRatSet(x - pn)));

  % Subtype TCC generated (at line 50, column 29) for  floor(x)
      % expected type  posnat
  compute_posratpair_TCC1: OBLIGATION
    FORALL (x: posrat): floor(x) = x IMPLIES floor(x) > 0;

  % Subtype TCC generated (at line 50, column 21) for
      % (# num := floor(x), den := 1 #)
      % expected type  {prp | posratpair_convert(prp) = x}
  compute_posratpair_TCC2: OBLIGATION
    FORALL (x: posrat):
      floor(x) = x IMPLIES
       posratpair_convert((# num := floor(x), den := 1 #)) = x;

  % Subtype TCC generated (at line 51, column 25) for  floor(x)
      % expected type  posnat
  compute_posratpair_TCC3: OBLIGATION
    FORALL (x: posrat): x > 1 AND NOT floor(x) = x IMPLIES floor(x) > 0;

  % Subtype TCC generated (at line 51, column 65) for  x - floor(x)
      % expected type  x: posrat
  compute_posratpair_TCC4: OBLIGATION
    FORALL (x: posrat):
      x > 1 AND NOT floor(x) = x IMPLIES
       x - floor(x) >= 0 AND x - floor(x) > 0;

  % Termination TCC generated (at line 51, column 46) for
      % compute_posratpair(x - floor(x))
  compute_posratpair_TCC5: OBLIGATION
    FORALL (x: posrat):
      x > 1 AND NOT floor(x) = x IMPLIES
       PosRatMeas(x - floor(x)) < PosRatMeas(x);

  % Subtype TCC generated (at line 51, column 17) for
      % (# num := floor(x), den := 1 #) + compute_posratpair(x - floor(x))
      % expected type  {prp | posratpair_convert(prp) = x}
  compute_posratpair_TCC6: OBLIGATION
    FORALL (x: posrat,
            v:
              [x1: {z: posrat | PosRatMeas(z) < PosRatMeas(x)} ->
                 {prp | posratpair_convert(prp) = x1}]):
      x > 1 AND NOT floor(x) = x IMPLIES
       posratpair_convert((# num := floor(x), den := 1 #) + v(x - floor(x)))
        = x;

  % Termination TCC generated (at line 52, column 27) for
      % compute_posratpair(1 / x)
  compute_posratpair_TCC7: OBLIGATION
    FORALL (x: posrat):
      NOT x > 1 AND NOT floor(x) = x IMPLIES
       PosRatMeas(1 / x) < PosRatMeas(x);

  % Subtype TCC generated (at line 52, column 7) for
      % (# num := 1, den := 1 #) / compute_posratpair(1 / x)
      % expected type  {prp | posratpair_convert(prp) = x}
  compute_posratpair_TCC8: OBLIGATION
    FORALL (x: posrat,
            v:
              [x1: {z: posrat | PosRatMeas(z) < PosRatMeas(x)} ->
                 {prp | posratpair_convert(prp) = x1}]):
      NOT x > 1 AND NOT floor(x) = x IMPLIES
       posratpair_convert((# num := 1, den := 1 #) / v(1 / x)) = x;

  % Subtype TCC generated (at line 64, column 28) for
      % (# newpoly := aq, currgcd := 1 #)
      % expected type  {ans: [# newpoly: [nat -> rat], currgcd: posnat #] |
                     %          (EXISTS (cp: posrat):
                     %             FORALL (j: nat):
                     %               ans`newpoly(j) = cp * aq(j))
                     %           AND
                     %           (FORALL (j: upto(n)):
                     %              integer_pred(ans`newpoly(j)) AND
                     %               divides(ans`currgcd, ans`newpoly(j)))}
  rat_poly_to_int_rec_TCC1: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat):
      n = 0 AND aq(0) = 0 IMPLIES
       (EXISTS (cp: posrat): FORALL (j: nat): aq(j) = cp * aq(j)) AND
        (FORALL (j: upto(n)): integer_pred(aq(j)) AND divides(1, aq(j)));

  % Subtype TCC generated (at line 68, column 19) for  abs(thisden * aq(0))
      % expected type  posnat
  rat_poly_to_int_rec_TCC2: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat):
      n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       (FORALL (thisden: posnat):
          thisden = compute_posratpair(abs(aq(0)))`den IMPLIES
           abs(thisden * aq(0)) > 0 AND
            abs(thisden * aq(0)) >= 0 AND integer_pred(abs(thisden * aq(0))));

  % Subtype TCC generated (at line 67, column 6) for
      % (# newpoly := (LAMBDA (i: nat): thisden * aq(i)),
      %    currgcd := abs(thisden * aq(0)) #)
      % expected type  {ans: [# newpoly: [nat -> rat], currgcd: posnat #] |
                     %          (EXISTS (cp: posrat):
                     %             FORALL (j: nat):
                     %               ans`newpoly(j) = cp * aq(j))
                     %           AND
                     %           (FORALL (j: upto(n)):
                     %              integer_pred(ans`newpoly(j)) AND
                     %               divides(ans`currgcd, ans`newpoly(j)))}
  rat_poly_to_int_rec_TCC3: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat):
      n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       (FORALL (thisden: posnat):
          thisden = compute_posratpair(abs(aq(0)))`den IMPLIES
           (EXISTS (cp: posrat):
              FORALL (j: nat): thisden * aq(j) = cp * aq(j))
            AND
            (FORALL (j: upto(n)):
               integer_pred(thisden * aq(j)) AND
                divides(abs(thisden * aq(0)), thisden * aq(j))));

  % Subtype TCC generated (at line 66, column 37) for  abs(aq(0))
      % expected type  x: posrat
  rat_poly_to_int_rec_TCC4: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat):
      n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES abs(aq(0)) > 0;

  % Subtype TCC generated (at line 69, column 46) for  n - 1
      % expected type  nat
  rat_poly_to_int_rec_TCC5: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat):
      aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       n - 1 >= 0;

  % Termination TCC generated (at line 69, column 23) for
      % rat_poly_to_int_rec(aq, n - 1)
  rat_poly_to_int_rec_TCC6: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat):
      aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 69, column 23) for
      % rat_poly_to_int_rec(aq, n - 1)
      % expected type  {ans: [# newpoly: [nat -> rat], currgcd: posnat #] |
                     %          (EXISTS (cp: posrat):
                     %             FORALL (j: nat):
                     %               ans`newpoly(j) = cp * aq(j))
                     %           AND
                     %           (FORALL (j: upto(n)):
                     %              integer_pred(ans`newpoly(j)) AND
                     %               divides(ans`currgcd, ans`newpoly(j)))}
  rat_poly_to_int_rec_TCC7: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat,
            v:
              [d1: {z: [[nat -> rat], nat] | z`2 < n} ->
                 {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                          (EXISTS (cp: posrat):
                             FORALL (j: nat): ans`newpoly(j) = cp * d1`1(j))
                           AND
                           (FORALL (j: upto(d1`2)):
                              integer_pred(ans`newpoly(j)) AND
                               divides(ans`currgcd, ans`newpoly(j)))}]):
      aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       (EXISTS (cp: posrat):
          FORALL (j: nat): v(aq, n - 1)`newpoly(j) = cp * aq(j))
        AND
        (FORALL (j: upto(n)):
           integer_pred(v(aq, n - 1)`newpoly(j)) AND
            divides(v(aq, n - 1)`currgcd, v(aq, n - 1)`newpoly(j)));

  % Subtype TCC generated (at line 72, column 30) for
      % abs(currpoly`newpoly(n))
      % expected type  x: posrat
  rat_poly_to_int_rec_TCC8: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat,
            v:
              [d1: {z: [[nat -> rat], nat] | z`2 < n} ->
                 {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                          (EXISTS (cp: posrat):
                             FORALL (j: nat): ans`newpoly(j) = cp * d1`1(j))
                           AND
                           (FORALL (j: upto(d1`2)):
                              integer_pred(ans`newpoly(j)) AND
                               divides(ans`currgcd, ans`newpoly(j)))}]):
      NOT aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       (FORALL (currpoly:
                  {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                           (EXISTS (cp: posrat):
                              FORALL (j: nat): ans`newpoly(j) = cp * aq(j))
                            AND
                            (FORALL (j: upto(n - 1)):
                               integer_pred(ans`newpoly(j)) AND
                                divides(ans`currgcd, ans`newpoly(j)))}):
          currpoly = v(aq, n - 1) IMPLIES abs(currpoly`newpoly(n)) > 0);

  % Subtype TCC generated (at line 74, column 29) for
      % thisden * currpoly`newpoly(n)
      % expected type  int
  rat_poly_to_int_rec_TCC9: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat,
            v:
              [d1: {z: [[nat -> rat], nat] | z`2 < n} ->
                 {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                          (EXISTS (cp: posrat):
                             FORALL (j: nat): ans`newpoly(j) = cp * d1`1(j))
                           AND
                           (FORALL (j: upto(d1`2)):
                              integer_pred(ans`newpoly(j)) AND
                               divides(ans`currgcd, ans`newpoly(j)))}]):
      NOT aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       (FORALL (currpoly:
                  {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                           (EXISTS (cp: posrat):
                              FORALL (j: nat): ans`newpoly(j) = cp * aq(j))
                            AND
                            (FORALL (j: upto(n - 1)):
                               integer_pred(ans`newpoly(j)) AND
                                divides(ans`currgcd, ans`newpoly(j)))}):
          currpoly = v(aq, n - 1) IMPLIES
           (FORALL (thisden: posnat):
              thisden = compute_posratpair(abs(currpoly`newpoly(n)))`den
               IMPLIES integer_pred(thisden * currpoly`newpoly(n))));

  % Subtype TCC generated (at line 75, column 35) for  currpoly`currgcd
      % expected type  {jj: int |
                     %          thisden * currpoly`newpoly(n) = 0 => jj /= 0}
  rat_poly_to_int_rec_TCC10: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat,
            v:
              [d1: {z: [[nat -> rat], nat] | z`2 < n} ->
                 {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                          (EXISTS (cp: posrat):
                             FORALL (j: nat): ans`newpoly(j) = cp * d1`1(j))
                           AND
                           (FORALL (j: upto(d1`2)):
                              integer_pred(ans`newpoly(j)) AND
                               divides(ans`currgcd, ans`newpoly(j)))}]):
      NOT aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       (FORALL (currpoly:
                  {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                           (EXISTS (cp: posrat):
                              FORALL (j: nat): ans`newpoly(j) = cp * aq(j))
                            AND
                            (FORALL (j: upto(n - 1)):
                               integer_pred(ans`newpoly(j)) AND
                                divides(ans`currgcd, ans`newpoly(j)))}):
          currpoly = v(aq, n - 1) IMPLIES
           (FORALL (thisden: posnat):
              thisden = compute_posratpair(abs(currpoly`newpoly(n)))`den
               IMPLIES
               thisden * currpoly`newpoly(n) = 0 => currpoly`currgcd /= 0));

  % Subtype TCC generated (at line 73, column 8) for
      % (# newpoly := (LAMBDA (i: nat): thisden * (currpoly`newpoly(i))),
      %    currgcd
      %      := compute_gcd(thisden * currpoly`newpoly(n),
      %                     currpoly`currgcd) #)
      % expected type  {ans: [# newpoly: [nat -> rat], currgcd: posnat #] |
                     %          (EXISTS (cp: posrat):
                     %             FORALL (j: nat):
                     %               ans`newpoly(j) = cp * aq(j))
                     %           AND
                     %           (FORALL (j: upto(n)):
                     %              integer_pred(ans`newpoly(j)) AND
                     %               divides(ans`currgcd, ans`newpoly(j)))}
  rat_poly_to_int_rec_TCC11: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat,
            v:
              [d1: {z: [[nat -> rat], nat] | z`2 < n} ->
                 {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                          (EXISTS (cp: posrat):
                             FORALL (j: nat): ans`newpoly(j) = cp * d1`1(j))
                           AND
                           (FORALL (j: upto(d1`2)):
                              integer_pred(ans`newpoly(j)) AND
                               divides(ans`currgcd, ans`newpoly(j)))}]):
      NOT aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       (FORALL (currpoly:
                  {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                           (EXISTS (cp: posrat):
                              FORALL (j: nat): ans`newpoly(j) = cp * aq(j))
                            AND
                            (FORALL (j: upto(n - 1)):
                               integer_pred(ans`newpoly(j)) AND
                                divides(ans`currgcd, ans`newpoly(j)))}):
          currpoly = v(aq, n - 1) IMPLIES
           (FORALL (thisden: posnat):
              thisden = compute_posratpair(abs(currpoly`newpoly(n)))`den
               IMPLIES
               (EXISTS (cp: posrat):
                  FORALL (j: nat):
                    thisden * (currpoly`newpoly(j)) = cp * aq(j))
                AND
                (FORALL (j: upto(n)):
                   integer_pred(thisden * (currpoly`newpoly(j))) AND
                    divides(compute_gcd(thisden * currpoly`newpoly(n),
                                        currpoly`currgcd),
                            thisden * (currpoly`newpoly(j))))));

  % Subtype TCC generated (at line 71, column 42) for  n - 1
      % expected type  nat
  rat_poly_to_int_rec_TCC12: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat):
      NOT aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       n - 1 >= 0;

  % Termination TCC generated (at line 71, column 19) for
      % rat_poly_to_int_rec(aq, n - 1)
  rat_poly_to_int_rec_TCC13: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat):
      NOT aq(n) = 0 AND NOT n = 0 AND NOT (n = 0 AND aq(0) = 0) IMPLIES
       n - 1 < n;

  % Subtype TCC generated (at line 83, column 35) for  ppoly(i) / mgcd
      % expected type  int
  rat_poly_to_int_TCC1: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat,
            rptir:
              {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                       (EXISTS (cp: posrat):
                          FORALL (j: nat): ans`newpoly(j) = cp * aq(j))
                        AND
                        (FORALL (j: upto(n)):
                           integer_pred(ans`newpoly(j)) AND
                            divides(ans`currgcd, ans`newpoly(j)))}):
      rptir = rat_poly_to_int_rec(aq, n) IMPLIES
       (FORALL (ppoly: [nat -> rat]):
          ppoly = rptir`newpoly IMPLIES
           (FORALL (mgcd: posnat):
              mgcd = rptir`currgcd IMPLIES
               (FORALL (i: nat):
                  i <= n IMPLIES integer_pred(ppoly(i) / mgcd))));

  % Subtype TCC generated (at line 83, column 6) for
      % (LAMBDA (i: nat): IF i <= n THEN ppoly(i) / mgcd ELSE 0 ENDIF)
      % expected type  {ai: [nat -> int] |
                     %          EXISTS (cp: posrat):
                     %            FORALL (j: upto(n)): ai(j) = cp * aq(j)}
  rat_poly_to_int_TCC2: OBLIGATION
    FORALL (aq: [nat -> rat], n: nat,
            rptir:
              {ans: [# currgcd: posnat, newpoly: [nat -> rat] #] |
                       (EXISTS (cp: posrat):
                          FORALL (j: nat): ans`newpoly(j) = cp * aq(j))
                        AND
                        (FORALL (j: upto(n)):
                           integer_pred(ans`newpoly(j)) AND
                            divides(ans`currgcd, ans`newpoly(j)))}):
      rptir = rat_poly_to_int_rec(aq, n) IMPLIES
       (FORALL (ppoly: [nat -> rat]):
          ppoly = rptir`newpoly IMPLIES
           (FORALL (mgcd: posnat):
              mgcd = rptir`currgcd IMPLIES
               (EXISTS (cp: posrat):
                  FORALL (j: upto(n)):
                    IF j <= n THEN ppoly(j) / mgcd ELSE 0 ENDIF =
                     cp * aq(j))));


body:
  polynomial_division: THEORY
  BEGIN

    IMPORTING reals@polynomials,structures@array2list[real]

    g,h,qu,rm: VAR [nat->real]
    n,m,lastnonzero,i: VAR nat

    DivType : TYPE = [# quot: [nat->real],qdeg:nat,
    		      rem : [nat->real],rdeg :nat #]

    make_divtype(qu,n,rm,m): DivType = (# quot:=qu,qdeg:=n,rem:=rm,rdeg:=m #)

    poly_divide(g,n)(h,(m|h(m)/=0))(i): RECURSIVE DivType =
      IF m>n OR i>n-m THEN make_divtype(LAMBDA (j:nat): 0,0,g,n)
      ELSIF m = 0 THEN make_divtype((1/h(m))*g,n-m,LAMBDA (j:nat): 0,0)
      ELSE
        LET ldt = IF i=n-m THEN make_divtype(LAMBDA (j:nat): 0,n-m,g,n)
      	          ELSE poly_divide(g,n)(h,m)(i+1) ENDIF,
      	  thisterm = ldt`rem(ldt`rdeg)/h(m)
        IN  make_divtype(ldt`quot WITH [(i):=thisterm],
  	               n-m,LAMBDA (j:nat):
  		       	     IF j>m+i THEN 0
  			     ELSIF j<i THEN ldt`rem(j)
  			     ELSE ldt`rem(j)-thisterm*h(j-i) ENDIF,m+i-1)
      ENDIF
      MEASURE max(n-m-i+1,0)

    poly_divide_def: LEMMA
      h(m)/=0 IMPLIES
      LET pd = poly_divide(g,n)(h,m)(i) IN
          FORALL (x:real):
      	polynomial(g,n)(x) = 
  	  polynomial(pd`quot,pd`qdeg)(x)*polynomial(h,m)(x)
  	    + polynomial(pd`rem,pd`rdeg)(x)

    poly_divide_struct: LEMMA h(m)/=0 IMPLIES
      LET pd = poly_divide(g,n)(h,m)(0) IN
          (m=0 AND pd`rdeg = 0 AND pd`rem = (LAMBDA (i:nat): 0))
  	OR
  	(m>0 AND pd`rdeg < m)

    poly_divide_lengths: LEMMA h(m)/=0 IMPLIES
      LET pd = poly_divide(g,n)(h,m)(i) IN
      pd`qdeg = (IF i<=n-m THEN n-m ELSE 0 ENDIF) AND
      pd`rdeg = (IF i>n-m THEN n ELSIF m=0 THEN 0 ELSE m+i-1 ENDIF)

  END polynomial_division

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

  % Subtype TCC generated (at line 27, column 12) for  max(n - m - i + 1, 0)
      % expected type  naturalnumber
  poly_divide_TCC1: OBLIGATION
    FORALL (n: nat, h: [nat -> real], (m: nat | h(m) /= 0), i: nat):
      max(n - m - i + 1, 0) >= 0;

  % Subtype TCC generated (at line 16, column 37) for  h(m)
      % expected type  nznum
  poly_divide_TCC2: OBLIGATION
    FORALL (n: nat, h: [nat -> real], (m: nat | h(m) /= 0), i: nat):
      m = 0 AND NOT m > n AND NOT i > n - m IMPLIES h(m) /= 0;

  % Subtype TCC generated (at line 16, column 45) for  n - m
      % expected type  nat
  poly_divide_TCC3: OBLIGATION
    FORALL (n: nat, h: [nat -> real], (m: nat | h(m) /= 0), i: nat):
      m = 0 AND NOT m > n AND NOT i > n - m IMPLIES n - m >= 0;

  % Subtype TCC generated (at line 20, column 36) for  h(m)
      % expected type  nznum
  poly_divide_TCC4: OBLIGATION
    FORALL (g: [nat -> real], n: nat, h: [nat -> real], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [z: [[nat -> real], nat] ->
                 [z1: [h: [nat -> real], {m | h(m) /= 0}] ->
                    [{z2: nat |
                              max(1 - z2 - z1`2 + z`2, 0) <
                               max(1 + n - i - m, 0)} ->
                       DivType]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivType):
          ldt =
           IF i = n - m THEN make_divtype(LAMBDA (j: nat): 0, n - m, g, n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES h(m) /= 0);

  % Subtype TCC generated (at line 22, column 16) for  n - m
      % expected type  nat
  poly_divide_TCC5: OBLIGATION
    FORALL (g: [nat -> real], n: nat, h: [nat -> real], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [z: [[nat -> real], nat] ->
                 [z1: [h: [nat -> real], {m | h(m) /= 0}] ->
                    [{z2: nat |
                              max(1 - z2 - z1`2 + z`2, 0) <
                               max(1 + n - i - m, 0)} ->
                       DivType]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivType):
          ldt =
           IF i = n - m THEN make_divtype(LAMBDA (j: nat): 0, n - m, g, n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: real):
              thisterm = ldt`rem(ldt`rdeg) / h(m) IMPLIES n - m >= 0));

  % Subtype TCC generated (at line 25, column 35) for  j - i
      % expected type  nat
  poly_divide_TCC6: OBLIGATION
    FORALL (g: [nat -> real], n: nat, h: [nat -> real], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [z: [[nat -> real], nat] ->
                 [z1: [h: [nat -> real], {m | h(m) /= 0}] ->
                    [{z2: nat |
                              max(1 - z2 - z1`2 + z`2, 0) <
                               max(1 + n - i - m, 0)} ->
                       DivType]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivType):
          ldt =
           IF i = n - m THEN make_divtype(LAMBDA (j: nat): 0, n - m, g, n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: real):
              thisterm = ldt`rem(ldt`rdeg) / h(m) IMPLIES
               (FORALL (j1: nat):
                  NOT j1 < i AND NOT j1 > m + i IMPLIES j1 - i >= 0)));

  % Subtype TCC generated (at line 25, column 46) for  m + i - 1
      % expected type  nat
  poly_divide_TCC7: OBLIGATION
    FORALL (g: [nat -> real], n: nat, h: [nat -> real], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [z: [[nat -> real], nat] ->
                 [z1: [h: [nat -> real], {m | h(m) /= 0}] ->
                    [{z2: nat |
                              max(1 - z2 - z1`2 + z`2, 0) <
                               max(1 + n - i - m, 0)} ->
                       DivType]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivType):
          ldt =
           IF i = n - m THEN make_divtype(LAMBDA (j: nat): 0, n - m, g, n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: real):
              thisterm = ldt`rem(ldt`rdeg) / h(m) IMPLIES m + i - 1 >= 0));

  % Subtype TCC generated (at line 18, column 61) for  n - m
      % expected type  nat
  poly_divide_TCC8: OBLIGATION
    FORALL (n: nat, h: [nat -> real], (m: nat | h(m) /= 0), i: nat):
      i = n - m AND NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       n - m >= 0;

  % Termination TCC generated (at line 19, column 20) for
      % poly_divide(g, n)(h, m)(i + 1)
  poly_divide_TCC9: OBLIGATION
    FORALL (n: nat, h: [nat -> real], (m: nat | h(m) /= 0), i: nat):
      NOT i = n - m AND NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       max(n - m - (i + 1) + 1, 0) < max(n - m - i + 1, 0);


body:
  gcd_coeff: THEORY
  BEGIN

  IMPORTING reals@polynomials,reals@more_polynomial_props,reals@sign,
  	  polynomial_division,structures@more_list_props,ints@gcd,
            structures@listn[int],
  	  structures@array2list[int],
  	  sigma

    a,r : VAR [nat->real]
    p : VAR [nat->[nat->real]]
    n : VAR [nat->nat]
    d,m,i,j,k : VAR nat
    %m : VAR posnat
    x,y,c,b : VAR real
    l 	  : VAR list[int]

    gcd_coeff(ll:list[int]): RECURSIVE {m:nat| FORALL (ii:nat): 
    			  	    ii<length[int](ll) IMPLIES divides(m,nth[int](ll,ii))} =
      IF length[int](ll)=0 THEN 0
      ELSIF length[int](ll)=1 THEN abs(nth[int](ll,0))
      ELSE LET oldgcd = gcd_coeff(cdr[int](ll)) IN
        IF car[int](ll)=0 THEN oldgcd
        ELSIF oldgcd=1 THEN 1
        ELSE compute_gcd(car[int](ll),oldgcd) ENDIF
      ENDIF MEASURE length[int](ll)

    gcd_coeff_nonzero: LEMMA
      (EXISTS (i:below(length[int](l))): nth[int](l,i)/=0) IMPLIES gcd_coeff(l)/=0

    gcd_coeff_zero: LEMMA
      (FORALL (i:nat): i<length[int](l) IMPLIES nth[int](l,i)=0) IMPLIES gcd_coeff(l)=0

    descalarize_list(ll:list[int],(k:nzint|
        FORALL (ii:nat): ii<length[int](ll) IMPLIES 
          divides(k,nth[int](ll,ii)))): RECURSIVE {nl:list[int]|length[int](nl)=length[int](ll) AND
  	FORALL (i:below(length[int](ll))): nth[int](ll,i)=k*nth[int](nl,i)} =
  	IF null?(ll) THEN ll
  	ELSE cons[int](car[int](ll)/k,descalarize_list(cdr[int](ll),k)) ENDIF
  	MEASURE length[int](ll)

    primitize_list(ll:list[int]): list[int] =
      LET thisgcd = gcd_coeff(ll) IN
        IF thisgcd = 0 OR thisgcd = 1 THEN ll
        ELSE descalarize_list(ll,thisgcd) ENDIF

    primitize_list_def: LEMMA
      (EXISTS (i:below(length[int](l))): nth[int](l,i)/=0)
      IMPLIES
      length[int](l) = length[int](primitize_list(l)) AND
      LET thisgcd=gcd_coeff(l) IN
        thisgcd>0 AND FORALL (k:below(length[int](l))):
        nth[int](l,k) = thisgcd*nth[int](primitize_list(l),k)

    primitize_zero_list: LEMMA
      (FORALL (i:nat): i<length[int](l) IMPLIES nth[int](l,i)=0)
      IMPLIES
      primitize_list(l) = array2list[int](length[int](l))(LAMBDA (i:nat): 0)

    primitize_list_length: LEMMA
      length[int](primitize_list(l)) = length[int](l)

    nonzero_version_rec(ll:list[int]): RECURSIVE 
      {nl:list[int] | length[int](nl)<=length[int](ll) AND
        (FORALL (i:nat): i<length[int](ll) 
          IMPLIES nth[int](ll,i) = (IF i<length[int](ll)-length[int](nl) THEN 0 ELSE nth[int](nl,i-length[int](ll)+length[int](nl)) ENDIF))
         AND ((length[int](nl)>0 OR EXISTS (i:below(length[int](ll))):nth(ll,i)/=0) IMPLIES (length[int](nl)>0 AND car[int](nl)/=0))} =
      IF length[int](ll)=0 OR car[int](ll) /= 0 THEN ll
      ELSE nonzero_version_rec(cdr[int](ll)) ENDIF measure length[int](ll)

    nonzero_version_rec_length_nonzero: LEMMA
      FORALL (ll:list[int]):
        length[int](nonzero_version_rec(ll)) > 0
        IFF
        (length[int](ll)>0 AND EXISTS (i:below(length[int](ll))): nth(ll,i)/=0)

    nonzero_version_rec_def: LEMMA FORALL (ll:list[int]):
      LET L = nonzero_version_rec(ll) IN
        length[int](L) > 0 IMPLIES (car(L)/=0 AND FORALL (i:nat):
          i<length[int](ll)-length[int](L) IMPLIES nth[int](ll,i)=0)

    nonzero_version(ll:list[int]): list[int] =
      reverse[int](nonzero_version_rec(reverse(ll)))

    nonzero_version_def: LEMMA FORALL (ll:list[int]):
      LET L = nonzero_version(ll) IN
         length[int](L)<=length[int](ll) AND
         (FORALL (i:nat): i<length[int](ll) 
           IMPLIES nth[int](ll,i) = 
  	   (IF i<length[int](L) THEN 
  	   nth[int](L,i) ELSE 0 ENDIF)) AND 
         ((EXISTS (i:below(length[int](ll))):nth(ll,i)/=0) 
           IMPLIES (length[int](L)>0 AND nth(L,length[int](L)-1)/=0)) AND
         (length[int](L) > 0 IFF (length[int](ll)>0 AND 
           EXISTS (i:below(length[int](ll))): nth(ll,i)/=0)) AND
         (length[int](L) > 0 IMPLIES (nth[int](L,length[int](L)-1)/=0 AND FORALL (i:nat):
           i>length[int](L)-1 AND i<length[int](ll) IMPLIES nth[int](ll,i)=0))

    nonzero_version_length_nz: LEMMA FORALL (ll:list[int]):
      length(ll)>0 AND nth(ll,length(ll)-1)/=0 IMPLIES
      nonzero_version(ll) = ll

  END gcd_coeff

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

  % Subtype TCC generated (at line 20, column 30) for  0
      % expected type  {m: nat |
                     %          FORALL (ii: nat):
                     %            ii < length[int](ll) IMPLIES
                     %             divides(m, nth[int](ll, ii))}
  gcd_coeff_TCC1: OBLIGATION
    FORALL (ll: list[int]):
      length[int](ll) = 0 IMPLIES
       (FORALL (ii: nat):
          ii < length[int](ll) IMPLIES divides(0, nth[int](ll, ii)));

  % Subtype TCC generated (at line 21, column 49) for  0
      % expected type  below[length(ll)]
  gcd_coeff_TCC2: OBLIGATION
    FORALL (ll: list[int]):
      length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       0 < length[int](ll);

  % Subtype TCC generated (at line 21, column 33) for  abs(nth[int](ll, 0))
      % expected type  {m: nat |
                     %          FORALL (ii: nat):
                     %            ii < length[int](ll) IMPLIES
                     %             divides(m, nth[int](ll, ii))}
  gcd_coeff_TCC3: OBLIGATION
    FORALL (ll: list[int]):
      length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       (FORALL (ii: nat):
          ii < length[int](ll) IMPLIES
           divides(abs(nth[int](ll, 0)), nth[int](ll, ii)));

  % Subtype TCC generated (at line 23, column 18) for  ll
      % expected type  (cons?)
  gcd_coeff_TCC4: OBLIGATION
    FORALL (ll: list[int],
            v:
              [ll1: {z: list[int] | length[int](z) < length[int](ll)} ->
                 {m: nat |
                          FORALL (ii: nat):
                            ii < length[int](ll1) IMPLIES
                             divides(m, nth[int](ll1, ii))}]):
      NOT length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       (FORALL (oldgcd:
                  {m: nat |
                           FORALL (ii: nat):
                             ii < length[int](cdr[int](ll)) IMPLIES
                              divides(m, nth[int](cdr[int](ll), ii))}):
          oldgcd = v(cdr[int](ll)) IMPLIES cons?[int](ll));

  % Subtype TCC generated (at line 23, column 29) for  oldgcd
      % expected type  {m: nat |
                     %          FORALL (ii: nat):
                     %            ii < length[int](ll) IMPLIES
                     %             divides(m, nth[int](ll, ii))}
  gcd_coeff_TCC5: OBLIGATION
    FORALL (ll: list[int],
            v:
              [ll1: {z: list[int] | length[int](z) < length[int](ll)} ->
                 {m: nat |
                          FORALL (ii: nat):
                            ii < length[int](ll1) IMPLIES
                             divides(m, nth[int](ll1, ii))}]):
      NOT length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       (FORALL (oldgcd:
                  {m: nat |
                           FORALL (ii: nat):
                             ii < length[int](cdr[int](ll)) IMPLIES
                              divides(m, nth[int](cdr[int](ll), ii))}):
          car[int](ll) = 0 AND oldgcd = v(cdr[int](ll)) IMPLIES
           (FORALL (ii: nat):
              ii < length[int](ll) IMPLIES
               divides(oldgcd, nth[int](ll, ii))));

  % Subtype TCC generated (at line 24, column 26) for  1
      % expected type  {m: nat |
                     %          FORALL (ii: nat):
                     %            ii < length[int](ll) IMPLIES
                     %             divides(m, nth[int](ll, ii))}
  gcd_coeff_TCC6: OBLIGATION
    FORALL (ll: list[int],
            v:
              [ll1: {z: list[int] | length[int](z) < length[int](ll)} ->
                 {m: nat |
                          FORALL (ii: nat):
                            ii < length[int](ll1) IMPLIES
                             divides(m, nth[int](ll1, ii))}]):
      NOT length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       (FORALL (oldgcd:
                  {m: nat |
                           FORALL (ii: nat):
                             ii < length[int](cdr[int](ll)) IMPLIES
                              divides(m, nth[int](cdr[int](ll), ii))}):
          oldgcd = 1 AND NOT car[int](ll) = 0 AND oldgcd = v(cdr[int](ll))
           IMPLIES
           (FORALL (ii: nat):
              ii < length[int](ll) IMPLIES divides(1, nth[int](ll, ii))));

  % Subtype TCC generated (at line 25, column 36) for  oldgcd
      % expected type  {jj: int | car[int](ll) = 0 => jj /= 0}
  gcd_coeff_TCC7: OBLIGATION
    FORALL (ll: list[int],
            v:
              [ll1: {z: list[int] | length[int](z) < length[int](ll)} ->
                 {m: nat |
                          FORALL (ii: nat):
                            ii < length[int](ll1) IMPLIES
                             divides(m, nth[int](ll1, ii))}]):
      NOT length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       (FORALL (oldgcd:
                  {m: nat |
                           FORALL (ii: nat):
                             ii < length[int](cdr[int](ll)) IMPLIES
                              divides(m, nth[int](cdr[int](ll), ii))}):
          NOT oldgcd = 1 AND
           NOT car[int](ll) = 0 AND oldgcd = v(cdr[int](ll))
           IMPLIES car[int](ll) = 0 => oldgcd /= 0);

  % Subtype TCC generated (at line 25, column 11) for
      % compute_gcd(car[int](ll), oldgcd)
      % expected type  {m: nat |
                     %          FORALL (ii: nat):
                     %            ii < length[int](ll) IMPLIES
                     %             divides(m, nth[int](ll, ii))}
  gcd_coeff_TCC8: OBLIGATION
    FORALL (ll: list[int],
            v:
              [ll1: {z: list[int] | length[int](z) < length[int](ll)} ->
                 {m: nat |
                          FORALL (ii: nat):
                            ii < length[int](ll1) IMPLIES
                             divides(m, nth[int](ll1, ii))}]):
      NOT length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       (FORALL (oldgcd:
                  {m: nat |
                           FORALL (ii: nat):
                             ii < length[int](cdr[int](ll)) IMPLIES
                              divides(m, nth[int](cdr[int](ll), ii))}):
          NOT oldgcd = 1 AND
           NOT car[int](ll) = 0 AND oldgcd = v(cdr[int](ll))
           IMPLIES
           (FORALL (ii: nat):
              ii < length[int](ll) IMPLIES
               divides(compute_gcd(car[int](ll), oldgcd), nth[int](ll, ii))));

  % Subtype TCC generated (at line 22, column 41) for  ll
      % expected type  (cons?)
  gcd_coeff_TCC9: OBLIGATION
    FORALL (ll: list[int]):
      NOT length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       cons?[int](ll);

  % Termination TCC generated (at line 22, column 22) for
      % gcd_coeff(cdr[int](ll))
  gcd_coeff_TCC10: OBLIGATION
    FORALL (ll: list[int]):
      NOT length[int](ll) = 1 AND NOT length[int](ll) = 0 IMPLIES
       length[int](cdr[int](ll)) < length[int](ll);

  % Subtype TCC generated (at line 37, column 65) for  i
      % expected type  below[length(nl)]
  descalarize_list_TCC1: OBLIGATION
    FORALL (ll: list[int], nl: list[int]):
      length[int](nl) = length[int](ll) IMPLIES
       (FORALL (i: below(length[int](ll))): i < length[int](nl));

  % Subtype TCC generated (at line 38, column 19) for  ll
      % expected type  {nl: list[int] |
                     %          length[int](nl) = length[int](ll) AND
                     %           (FORALL (i: below(length[int](ll))):
                     %              nth[int](ll, i) = k * nth[int](nl, i))}
  descalarize_list_TCC2: OBLIGATION
    FORALL (ll: list[int],
            (k: nzint
                 | FORALL (ii: nat):
                     ii < length[int](ll) IMPLIES
                      divides(k, nth[int](ll, ii)))):
      null?(ll) IMPLIES
       (FORALL (i: below(length[int](ll))):
          nth[int](ll, i) = k * nth[int](ll, i));

  % Subtype TCC generated (at line 39, column 25) for  ll
      % expected type  (cons?)
  descalarize_list_TCC3: OBLIGATION
    FORALL (ll: list[int],
            (k: nzint
                 | FORALL (ii: nat):
                     ii < length[int](ll) IMPLIES
                      divides(k, nth[int](ll, ii)))):
      NOT null?(ll) IMPLIES cons?[int](ll);

  % Subtype TCC generated (at line 39, column 16) for  car[int](ll) / k
      % expected type  int
  descalarize_list_TCC4: OBLIGATION
    FORALL (ll: list[int],
            (k: nzint
                 | FORALL (ii: nat):
                     ii < length[int](ll) IMPLIES
                      divides(k, nth[int](ll, ii)))):
      NOT null?(ll) IMPLIES integer_pred(car[int](ll) / k);

  % Subtype TCC generated (at line 39, column 61) for  k
      % expected type  {k: nzint |
                     %          FORALL (ii: nat):
                     %            ii < length[int](cdr[int](ll)) IMPLIES
                     %             divides(k, nth[int](cdr[int](ll), ii))}
  descalarize_list_TCC5: OBLIGATION
    FORALL (ll: list[int],
            (k: nzint
                 | FORALL (ii: nat):
                     ii < length[int](ll) IMPLIES
                      divides(k, nth[int](ll, ii)))):
      NOT null?(ll) IMPLIES
       (FORALL (ii: nat):
          ii < length[int](cdr[int](ll)) IMPLIES
           divides(k, nth[int](cdr[int](ll), ii)));

  % Termination TCC generated (at line 39, column 31) for
      % descalarize_list(cdr[int](ll), k)
  descalarize_list_TCC6: OBLIGATION
    FORALL (ll: list[int],
            (k: nzint
                 | FORALL (ii: nat):
                     ii < length[int](ll) IMPLIES
                      divides(k, nth[int](ll, ii)))):
      NOT null?(ll) IMPLIES length[int](cdr[int](ll)) < length[int](ll);

  % Subtype TCC generated (at line 39, column 6) for
      % cons[int](car[int](ll) / k, descalarize_list(cdr[int](ll), k))
      % expected type  {nl: list[int] |
                     %          length[int](nl) = length[int](ll) AND
                     %           (FORALL (i: below(length[int](ll))):
                     %              nth[int](ll, i) = k * nth[int](nl, i))}
  descalarize_list_TCC7: OBLIGATION
    FORALL (ll: list[int],
            v:
              [d1:
                 {z:
                    [ll: list[int],
                     {k: nzint |
                              FORALL (ii: nat):
                                ii < length[int](ll) IMPLIES
                                 divides(k, nth[int](ll, ii))}] |
                          length[int](z`1) < length[int](ll)} ->
                 {nl: list[int] |
                          length[int](nl) = length[int](d1`1) AND
                           (FORALL (i: below(length[int](d1`1))):
                              nth[int](d1`1, i) = d1`2 * nth[int](nl, i))}],
            (k: nzint
                 | FORALL (ii: nat):
                     ii < length[int](ll) IMPLIES
                      divides(k, nth[int](ll, ii)))):
      NOT null?(ll) IMPLIES
       length[int](cons[int](car[int](ll) / k, v(cdr[int](ll), k))) =
        length[int](ll)
        AND
        (FORALL (i: below(length[int](ll))):
           nth[int](ll, i) =
            k * nth[int](cons[int](car[int](ll) / k, v(cdr[int](ll), k)), i));

  % Subtype TCC generated (at line 45, column 31) for  thisgcd
      % expected type  {k: nzint |
                     %          FORALL (ii: nat):
                     %            ii < length[int](ll) IMPLIES
                     %             divides(k, nth[int](ll, ii))}
  primitize_list_TCC1: OBLIGATION
    FORALL (ll: list[int],
            thisgcd:
              {m: nat |
                       FORALL (ii: nat):
                         ii < length[int](ll) IMPLIES
                          divides(m, nth[int](ll, ii))}):
      NOT thisgcd = 0 AND NOT thisgcd = 1 AND thisgcd = gcd_coeff(ll) IMPLIES
       thisgcd /= 0 AND
        (FORALL (ii: nat):
           ii < length[int](ll) IMPLIES divides(thisgcd, nth[int](ll, ii)));

  % Subtype TCC generated (at line 53, column 57) for  k
      % expected type  below[length(primitize_list(l))]
  primitize_list_def_TCC1: OBLIGATION
    FORALL (l: list[int]):
      (EXISTS (i: below(length[int](l))): nth[int](l, i) /= 0) AND
       length[int](l) = length[int](primitize_list(l))
       IMPLIES
       (FORALL (thisgcd:
                  {m: nat |
                           FORALL (ii: nat):
                             ii < length[int](l) IMPLIES
                              divides(m, nth[int](l, ii))}):
          thisgcd > 0 AND thisgcd = gcd_coeff(l) IMPLIES
           (FORALL (k: below(length[int](l))):
              k < length[int](primitize_list(l))));

  % Subtype TCC generated (at line 66, column 95) for
      % i - length[int](ll) + length[int](nl)
      % expected type  below[length(nl)]
  nonzero_version_rec_TCC1: OBLIGATION
    FORALL (ll: list[int], nl: list[int]):
      length[int](nl) <= length[int](ll) IMPLIES
       (FORALL (i: nat):
          NOT i < length[int](ll) - length[int](nl) AND i < length[int](ll)
           IMPLIES
           i - length[int](ll) + length[int](nl) >= 0 AND
            i - length[int](ll) + length[int](nl) < length[int](nl));

  % Subtype TCC generated (at line 67, column 122) for  nl
      % expected type  (cons?)
  nonzero_version_rec_TCC2: OBLIGATION
    FORALL (ll: list[int], nl: list[int]):
      length[int](nl) > 0 AND
       (length[int](nl) > 0 OR
         (EXISTS (i: below(length[int](ll))): nth(ll, i) /= 0))
        AND
        (FORALL (i: nat):
           i < length[int](ll) IMPLIES
            nth[int](ll, i) =
             (IF i < length[int](ll) - length[int](nl) THEN 0
              ELSE nth[int](nl, i - length[int](ll) + length[int](nl))
              ENDIF))
         AND length[int](nl) <= length[int](ll)
       IMPLIES cons?[int](nl);

  % Subtype TCC generated (at line 68, column 37) for  ll
      % expected type  (cons?)
  nonzero_version_rec_TCC3: OBLIGATION
    FORALL (ll: list[int]): NOT length[int](ll) = 0 IMPLIES cons?[int](ll);

  % Subtype TCC generated (at line 68, column 51) for  ll
      % expected type  {nl: list[int] |
                     %          length[int](nl) <= length[int](ll) AND
                     %           (FORALL (i: nat):
                     %              i < length[int](ll) IMPLIES
                     %               nth[int](ll, i) =
                     %                (IF i
                     %                    <
                     %                    length[int](ll) - length[int](nl)
                     %                 THEN 0
                     %                 ELSE nth[int]
                     %                      (nl,
                     %                       i + length[int](nl)
                     %                       -
                     %                       length[int](ll))
                     %                 ENDIF))
                     %            AND
                     %            ((length[int](nl) > 0 OR
                     %               (EXISTS
                     %                (i: below(length[int](ll))):
                     %                nth(ll, i) /= 0))
                     %              IMPLIES
                     %              (length[int](nl) > 0 AND
                     %                car[int](nl) /= 0))}
  nonzero_version_rec_TCC4: OBLIGATION
    FORALL (ll: list[int]):
      length[int](ll) = 0 OR car[int](ll) /= 0 IMPLIES
       length[int](ll) <= length[int](ll) AND
        (FORALL (i: nat):
           i < length[int](ll) IMPLIES
            nth[int](ll, i) =
             (IF i < length[int](ll) - length[int](ll) THEN 0
              ELSE nth[int](ll, i + length[int](ll) - length[int](ll))
              ENDIF))
         AND
         ((length[int](ll) > 0 OR
            (EXISTS (i: below(length[int](ll))): nth[int](ll, i) /= 0))
           IMPLIES (length[int](ll) > 0 AND car[int](ll) /= 0));

  % Termination TCC generated (at line 69, column 9) for
      % nonzero_version_rec(cdr[int](ll))
  nonzero_version_rec_TCC5: OBLIGATION
    FORALL (ll: list[int]):
      NOT length[int](ll) = 0 AND NOT car[int](ll) /= 0 IMPLIES
       length[int](cdr[int](ll)) < length[int](ll);

  % Subtype TCC generated (at line 69, column 9) for
      % nonzero_version_rec(cdr[int](ll))
      % expected type  {nl: list[int] |
                     %          length[int](nl) <= length[int](ll) AND
                     %           (FORALL (i: nat):
                     %              i < length[int](ll) IMPLIES
                     %               nth[int](ll, i) =
                     %                (IF i
                     %                    <
                     %                    length[int](ll) - length[int](nl)
                     %                 THEN 0
                     %                 ELSE nth[int]
                     %                      (nl,
                     %                       i + length[int](nl)
                     %                       -
                     %                       length[int](ll))
                     %                 ENDIF))
                     %            AND
                     %            ((length[int](nl) > 0 OR
                     %               (EXISTS
                     %                (i: below(length[int](ll))):
                     %                nth(ll, i) /= 0))
                     %              IMPLIES
                     %              (length[int](nl) > 0 AND
                     %                car[int](nl) /= 0))}
  nonzero_version_rec_TCC6: OBLIGATION
    FORALL (ll: list[int],
            v:
              [ll1: {z: list[int] | length[int](z) < length[int](ll)} ->
                 {nl: list[int] |
                          length[int](nl) <= length[int](ll1) AND
                           (FORALL (i: nat):
                              i < length[int](ll1) IMPLIES
                               nth[int](ll1, i) =
                                (IF i < length[int](ll1) - length[int](nl)
                                   THEN 0
                                 ELSE nth[int]
                                      (nl,
                                       i + length[int](nl)
                                       -
                                       length[int](ll1))
                                 ENDIF))
                            AND
                            ((length[int](nl) > 0 OR
                               (EXISTS (i: below(length[int](ll1))):
                                  nth(ll1, i) /= 0))
                              IMPLIES
                              (length[int](nl) > 0 AND
                                car[int](nl) /= 0))}]):
      NOT length[int](ll) = 0 AND NOT car[int](ll) /= 0 IMPLIES
       length[int](v(cdr[int](ll))) <= length[int](ll) AND
        (FORALL (i: nat):
           i < length[int](ll) IMPLIES
            nth[int](ll, i) =
             (IF i < length[int](ll) - length[int](v(cdr[int](ll))) THEN 0
              ELSE nth[int]
                       (v(cdr[int](ll)),
                        i + length[int](v(cdr[int](ll))) - length[int](ll))
              ENDIF))
         AND
         ((length[int](v(cdr[int](ll))) > 0 OR
            (EXISTS (i: below(length[int](ll))): nth[int](ll, i) /= 0))
           IMPLIES
           (length[int](v(cdr[int](ll))) > 0 AND
             car[int](v(cdr[int](ll))) /= 0));

  % Subtype TCC generated (at line 79, column 38) for  L
      % expected type  (cons?)
  nonzero_version_rec_def_TCC1: OBLIGATION
    FORALL (ll: list[int],
            L:
              {nl: list[int] |
                       length[int](nl) <= length[int](ll) AND
                        (FORALL (i: nat):
                           i < length[int](ll) IMPLIES
                            nth[int](ll, i) =
                             (IF i < length[int](ll) - length[int](nl) THEN 0
                              ELSE nth[int]
                                       (nl,
                                        i + length[int](nl)
                                        -
                                        length[int](ll))
                              ENDIF))
                         AND
                         ((length[int](nl) > 0 OR
                            (EXISTS (i: below(length[int](ll))):
                               nth[int](ll, i) /= 0))
                           IMPLIES
                           (length[int](nl) > 0 AND car[int](nl) /= 0))}):
      length[int](L) > 0 AND L = nonzero_version_rec(ll) IMPLIES
       cons?[real](L);

  % Subtype TCC generated (at line 80, column 61) for  i
      % expected type  below[length(ll)]
  nonzero_version_rec_def_TCC2: OBLIGATION
    FORALL (ll: list[int],
            L:
              {nl: list[int] |
                       length[int](nl) <= length[int](ll) AND
                        (FORALL (i: nat):
                           i < length[int](ll) IMPLIES
                            nth[int](ll, i) =
                             (IF i < length[int](ll) - length[int](nl) THEN 0
                              ELSE nth[int]
                                       (nl,
                                        i + length[int](nl)
                                        -
                                        length[int](ll))
                              ENDIF))
                         AND
                         ((length[int](nl) > 0 OR
                            (EXISTS (i: below(length[int](ll))):
                               nth[int](ll, i) /= 0))
                           IMPLIES
                           (length[int](nl) > 0 AND car[int](nl) /= 0))}):
      car(L) /= 0 AND length[int](L) > 0 AND L = nonzero_version_rec(ll)
       IMPLIES
       (FORALL (i: nat):
          i < length[int](ll) - length[int](L) IMPLIES i < length[int](ll));

  % Subtype TCC generated (at line 93, column 45) for  length[int](L) - 1
      % expected type  below[length(L)]
  nonzero_version_def_TCC1: OBLIGATION
    FORALL (ll: list[int], L: list[int]):
           length[int](L) > 0
       AND (EXISTS (i: below(length[int](ll))): nth(ll, i) /= 0)
       AND FORALL (i: nat):
             i < length[int](ll) IMPLIES
              nth[int](ll, i) =
               (IF i < length[int](L) THEN nth[int](L, i) ELSE 0 ENDIF)
       AND length[int](L) <= length[int](ll) AND L = nonzero_version(ll)
       IMPLIES
       length[int](L) - 1 >= 0 AND length[int](L) - 1 < length[int](L);

  % Subtype TCC generated (at line 96, column 47) for  length[int](L) - 1
      % expected type  below[length(L)]
  nonzero_version_def_TCC2: OBLIGATION
    FORALL (ll: list[int], L: list[int]):
           length[int](L) > 0
       AND length[int](L) > 0 IMPLIES
            (length[int](ll) > 0 AND
              (EXISTS (i: below(length[int](ll))): nth(ll, i) /= 0))
       AND (length[int](ll) > 0 AND
             (EXISTS (i: below(length[int](ll))): nth(ll, i) /= 0))
            IMPLIES length[int](L) > 0
       AND ((EXISTS (i: below(length[int](ll))): nth(ll, i) /= 0) IMPLIES
             (length[int](L) > 0 AND nth(L, length[int](L) - 1) /= 0))
       AND FORALL (i: nat):
             i < length[int](ll) IMPLIES
              nth[int](ll, i) =
               (IF i < length[int](L) THEN nth[int](L, i) ELSE 0 ENDIF)
       AND length[int](L) <= length[int](ll) AND L = nonzero_version(ll)
       IMPLIES
       length[int](L) - 1 >= 0 AND length[int](L) - 1 < length[int](L);

  % Subtype TCC generated (at line 100, column 28) for  length(ll) - 1
      % expected type  below[length(ll)]
  nonzero_version_length_nz_TCC1: OBLIGATION
    FORALL (ll: list[int]):
      length(ll) > 0 IMPLIES
       length[int](ll) - 1 >= 0 AND length[int](ll) - 1 < length[int](ll);


body:
  polynomial_pseudo_divide: THEORY
  BEGIN

    IMPORTING reals@polynomials ,structures@array2list[int],
    	    polynomial_division, gcd_coeff

    g,h,qu,rm: VAR [nat->int]
    n,m,lastnonzero,i: VAR nat

  %%%   Pseudo Remainders (Computable)   %%%

    DivListType : TYPE = [# quotl: list[int],qdegl:nat,
    		      reml : list[int],rdegl :nat #]

    qul,rml: VAR list[int]

    make_divlisttype(qul,n,rml,m): DivListType = (# quotl:=qul,qdegl:=n,reml:=rml,rdegl:=m #)

    pseudo_div(g,n)(h,(m|h(m)/=0))(i): RECURSIVE {DT: DivListType |
    					     	    (m>n OR i>n-m AND length(DT`reml)=n+1 AND DT`rdegl = n) OR
    						    (m=0 AND length(DT`reml)=0 AND DT`rdegl=0) OR 
  						    (m>0 AND length(DT`reml)=m+i AND length(DT`reml)=DT`rdegl+1)}=
      IF m>n OR i>n-m THEN make_divlisttype((::),0,array2list(n+1)(g),n)
      ELSIF m = 0 THEN make_divlisttype(array2list(n+1)(g),n,(::),0)
      ELSE
        LET ldt = IF i=n-m THEN make_divlisttype((::),n-m,array2list(n+1)(g),n)
      	          ELSE pseudo_div(g,n)(h,m)(i+1) ENDIF,
      	  thisterm = nth(ldt`reml,ldt`rdegl)
        IN  make_divlisttype(cons(thisterm,ldt`quotl),
    	               n-m,array2list(m+i)(LAMBDA (j:nat):
    		       	     IF j>m+i THEN 0
    			     ELSIF j<i THEN h(m)*nth(ldt`reml,j)
    			     ELSE h(m)*nth(ldt`reml,j)-thisterm*h(j-i) ENDIF),m+i-1)
      ENDIF
     MEASURE max(n-m-i+1,0)

    pseudo_div_lengths: LEMMA
      h(m)/=0 IMPLIES
      LET psd = pseudo_div(g,n)(h,m)(i),
      	pd  = poly_divide(g,n)(h,m)(i),
  	qlength = length(psd`quotl),
  	rlength = length(psd`reml)
      IN  psd`qdegl = pd`qdeg AND psd`rdegl = pd`rdeg AND psd`rdegl = max(rlength-1,0) AND
      	qlength = (IF i>n-m THEN 0 ELSIF m=0 THEN n-m+1 ELSE n-m-i+1 ENDIF)

    R,T : VAR nat

    Ka,Kn,Km,Ki: int
    Ca,Cn,Cm,Ci: int

    GG(k:nat,n,m,i,R,T): int = IF i>n-m THEN 0 ELSIF m=0 OR i = n-m OR k<i THEN 1 ELSE (1+(n-m-k)) ENDIF

    HH(k:nat,n,m,i,R,T): int =  IF i>n-m THEN 0 ELSIF m=0 OR i=n-m OR k>=i+m THEN 1 ELSE 1+(n-m-i) ENDIF

    HHGGLEM: LEMMA FORALL (k:nat):
      (k<=n-m AND i<=n-m) IMPLIES
      (GG(k,n,0,i,R,T)=1 AND
      (n-m>=0 IMPLIES GG(k,n,m,n-m,R,T)=1) AND
      (k<=n-m AND k>i IMPLIES GG(k,n,m,1+i,R,T)=GG(k,n,m,i,R,T)) AND
      HH(k,n,0,i,R,T)=1 AND
      (n-m>=0 IMPLIES HH(k,n,m,n-m,R,T)=1) AND
      (m/=0 IMPLIES HH(i+m,n,m,1+i,R,T)+1=GG(i,n,m,i,R,T)) AND
      (m/=0 AND k<i IMPLIES HH(k,n,m,i,R,T) = HH(k,n,m,1+i,R,T)+1) AND
      (m/=0 AND k>=i AND k<i+m IMPLIES (HH(k,n,m,i,R,T)=HH(k,n,m,1+i,R,T)+1 AND 
        HH(i+m,n,m,1+i,R,T)+1=HH(k,n,m,i,R,T) AND HH(i+m,n,m,1+i,R,T)=HH(k,n,m,1+i,R,T))))

    pseudo_div_def: LEMMA
      h(m)/=0 AND
      (FORALL (ii:nat): ii>n IMPLIES g(ii)=0) AND
      (FORALL (ii:nat): ii>m IMPLIES h(ii)=0) IMPLIES
      LET psd = pseudo_div(g,n)(h,m)(i),
      	pd  = poly_divide(g,n)(h,m)(i),
  	qlength = length(psd`quotl),
  	rlength = length(psd`reml)
      IN  pd`quot = (LAMBDA (k:nat): (1/h(m))^GG(k,n,m,i,R,T))
      		    *(LAMBDA (k:nat): IF k<=pd`qdeg AND 
  		  	  	   k>=pd`qdeg-qlength+1 
  				   THEN nth(psd`quotl,k-(pd`qdeg-qlength+1))      %n-m-pd`qdeg+j)
  		  	  	   ELSE 0 ENDIF) AND
  	pd`rem  = (LAMBDA (k:nat): (1/h(m))^HH(k,n,m,i,R,T))*(LAMBDA (k:nat): IF k<=pd`rdeg AND (i>n-m OR m>0) THEN nth(psd`reml,k) ELSE 0 ENDIF)

    poly_pseudo_remainder_def: LEMMA
      h(m)/=0 AND n>=m AND
      (FORALL (ii:nat): ii>n IMPLIES g(ii)=0) AND
      (FORALL (ii:nat): ii>m IMPLIES h(ii)=0) IMPLIES
      LET psd = pseudo_div(g,n)(h,m)(0),
      	pd  = poly_divide(g,n)(h,m)(0),
  	qlength = length(psd`quotl),
  	rlength = length(psd`reml)
      IN pd`rem = (1/h(m))^(n-m+1) * (LAMBDA (k:nat): IF k<=psd`rdegl AND m>0 THEN nth(psd`reml,k) ELSE 0 ENDIF)

    adjusted_remainder(g,n)(h,(m|h(m)/=0)): list[int] =
      LET ppd = pseudo_div(g,n)(h,m)(0),
      	thisrem = ppd`reml,
  	pseudosign:nzint = IF h(m)>0 OR mod(n-m+1,2)=0 OR m>n THEN 1 ELSE -1 ENDIF
      IN descalarize_list(nonzero_version(primitize_list(thisrem)),-pseudosign)

    adjusted_remainder_def: LEMMA
        h(m)/=0 AND
        (FORALL (ii:nat): ii>n IMPLIES g(ii)=0) AND
        (FORALL (ii:nat): ii>m IMPLIES h(ii)=0)
      IMPLIES
        LET thisrem  = adjusted_remainder(g,n)(h,m),
        	  pd       = poly_divide(g,n)(h,m)(0),
  	  thisdeg  = length[int](thisrem)-1,
  	  thispoly = (LAMBDA (i:nat): IF i<=thisdeg THEN nth(thisrem,i) ELSE 0 ENDIF)
        IN thisdeg>=0 IMPLIES ((EXISTS (cp:posreal):
          polynomial(thispoly,thisdeg) = polynomial(-cp*pd`rem,pd`rdeg)) AND
  	thispoly(thisdeg) /= 0)

    adjusted_remainder_length: LEMMA
      h(m)/=0 IMPLIES
      LET pr = adjusted_remainder(g,n)(h,m) IN
        length(pr)<=m

    adjusted_remainder_length2: LEMMA
      h(m)/=0 IMPLIES
      LET pr = adjusted_remainder(g,n)(h,m) IN
        length(pr)<=n+1

    adjusted_remainder_empty: LEMMA
      (FORALL (i:nat): i>n IMPLIES g(i)=0) AND
      (FORALL (i:nat): i>m IMPLIES h(i)=0) AND
      h(m)/=0 AND
      length(adjusted_remainder(g,n)(h,m))=0
      IMPLIES
      FORALL (j:nat): j<=poly_divide(g,n)(h,m)(0)`rdeg IMPLIES
             poly_divide(g,n)(h,m)(0)`rem(j)=0

    adjusted_remainder_test: LEMMA
      LET g = (LAMBDA (i:nat): IF i=0 THEN 1 ELSIF i=1 THEN 2
  			     ELSIF i=2 THEN 2 ELSIF i=3 THEN 5
  			     ELSIF i=5 THEN 2 ELSIF i=6 THEN -7 ELSE 0 ENDIF),
  	h = (LAMBDA (i:nat): IF i=0 THEN -4 ELSIF i=1 THEN -4
  			     ELSIF i=2 THEN 2 ELSIF i=3 THEN 5
  			     ELSIF i=4 THEN -2 ELSE 0 ENDIF)
      IN adjusted_remainder(g,6)(h,4) = (: -740, -996, -10, 887 :)

  END polynomial_pseudo_divide

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

  % Subtype TCC generated (at line 35, column 11) for  max(n - m - i + 1, 0)
      % expected type  naturalnumber
  pseudo_div_TCC1: OBLIGATION
    FORALL (n: nat, h: [nat -> int], (m: nat | h(m) /= 0), i: nat):
      max(n - m - i + 1, 0) >= 0;

  % Subtype TCC generated (at line 23, column 25) for
      % make_divlisttype((: :), 0, array2list(n + 1)(g), n)
      % expected type  {DT: DivListType |
                     %          (m > n OR
                     %            i > n - m AND
                     %             length(DT`reml) = 1 + n AND DT`rdegl = n)
                     %           OR
                     %           (m = 0 AND
                     %             length(DT`reml) = 0 AND DT`rdegl = 0)
                     %            OR
                     %            (m > 0 AND
                     %              length(DT`reml) = i + m AND
                     %               length(DT`reml) = 1 + DT`rdegl)}
  pseudo_div_TCC2: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat):
      m > n OR i > n - m IMPLIES
       (m > n OR
         i > n - m AND
          length[int]
              (make_divlisttype((: :), 0, array2list[int](n + 1)(g), n)`reml)
           = 1 + n
           AND
           make_divlisttype((: :), 0, array2list[int](n + 1)(g), n)`rdegl =
            n)
        OR
        (m = 0 AND
          length[int]
              (make_divlisttype((: :), 0, array2list[int](n + 1)(g), n)`reml)
           = 0
           AND
           make_divlisttype((: :), 0, array2list[int](n + 1)(g), n)`rdegl =
            0)
         OR
         (m > 0 AND
           length[int]
               (make_divlisttype((: :), 0, array2list[int](n + 1)(g),
                                 n)`reml)
            = i + m
            AND
            length[int]
                (make_divlisttype((: :), 0, array2list[int](n + 1)(g),
                                  n)`reml)
             =
             1 +
              make_divlisttype((: :), 0, array2list[int](n + 1)(g), n)`rdegl);

  % Subtype TCC generated (at line 24, column 21) for
      % make_divlisttype(array2list(n + 1)(g), n, (: :), 0)
      % expected type  {DT: DivListType |
                     %          (m > n OR
                     %            i > n - m AND
                     %             length(DT`reml) = 1 + n AND DT`rdegl = n)
                     %           OR
                     %           (m = 0 AND
                     %             length(DT`reml) = 0 AND DT`rdegl = 0)
                     %            OR
                     %            (m > 0 AND
                     %              length(DT`reml) = i + m AND
                     %               length(DT`reml) = 1 + DT`rdegl)}
  pseudo_div_TCC3: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat):
      m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (m > n OR
         i > n - m AND
          length[int]
              (make_divlisttype(array2list[int](n + 1)(g), n, (: :), 0)`reml)
           = 1 + n
           AND
           make_divlisttype(array2list[int](n + 1)(g), n, (: :), 0)`rdegl =
            n)
        OR
        (m = 0 AND
          length[int]
              (make_divlisttype(array2list[int](n + 1)(g), n, (: :), 0)`reml)
           = 0
           AND
           make_divlisttype(array2list[int](n + 1)(g), n, (: :), 0)`rdegl =
            0)
         OR
         (m > 0 AND
           length[int]
               (make_divlisttype(array2list[int](n + 1)(g), n, (: :),
                                 0)`reml)
            = i + m
            AND
            length[int]
                (make_divlisttype(array2list[int](n + 1)(g), n, (: :),
                                  0)`reml)
             =
             1 +
              make_divlisttype(array2list[int](n + 1)(g), n, (: :), 0)`rdegl);

  % Subtype TCC generated (at line 28, column 31) for  ldt`rdegl
      % expected type  below[length(ldt`reml)]
  pseudo_div_TCC4: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [d11: [[nat -> int], nat] ->
                 [d1: [h: [nat -> int], {m | h(m) /= 0}] ->
                    [i1:
                       {z: nat |
                                max(1 - z - d1`2 + d11`2, 0) <
                                 max(1 + n - i - m, 0)} ->
                       {DT: DivListType |
                                (d1`2 > d11`2 OR
                                  i1 > d11`2 - d1`2 AND
                                   length(DT`reml) = 1 + d11`2 AND
                                    DT`rdegl = d11`2)
                                 OR
                                 (d1`2 = 0 AND
                                   length(DT`reml) = 0 AND DT`rdegl = 0)
                                  OR
                                  (d1`2 > 0 AND
                                    length(DT`reml) = i1 + d1`2 AND
                                     length(DT`reml) = 1 + DT`rdegl)}]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivListType):
          ldt =
           IF i = n - m
             THEN make_divlisttype((: :), n - m, array2list(n + 1)(g), n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES ldt`rdegl < length[int](ldt`reml));

  % Subtype TCC generated (at line 30, column 18) for  n - m
      % expected type  nat
  pseudo_div_TCC5: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [d11: [[nat -> int], nat] ->
                 [d1: [h: [nat -> int], {m | h(m) /= 0}] ->
                    [i1:
                       {z: nat |
                                max(1 - z - d1`2 + d11`2, 0) <
                                 max(1 + n - i - m, 0)} ->
                       {DT: DivListType |
                                (d1`2 > d11`2 OR
                                  i1 > d11`2 - d1`2 AND
                                   length(DT`reml) = 1 + d11`2 AND
                                    DT`rdegl = d11`2)
                                 OR
                                 (d1`2 = 0 AND
                                   length(DT`reml) = 0 AND DT`rdegl = 0)
                                  OR
                                  (d1`2 > 0 AND
                                    length(DT`reml) = i1 + d1`2 AND
                                     length(DT`reml) = 1 + DT`rdegl)}]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivListType):
          ldt =
           IF i = n - m
             THEN make_divlisttype((: :), n - m, array2list(n + 1)(g), n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: int):
              thisterm = nth(ldt`reml, ldt`rdegl) IMPLIES n - m >= 0));

  % Subtype TCC generated (at line 32, column 43) for  j
      % expected type  below[length(ldt`reml)]
  pseudo_div_TCC6: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [d11: [[nat -> int], nat] ->
                 [d1: [h: [nat -> int], {m | h(m) /= 0}] ->
                    [i1:
                       {z: nat |
                                max(1 - z - d1`2 + d11`2, 0) <
                                 max(1 + n - i - m, 0)} ->
                       {DT: DivListType |
                                (d1`2 > d11`2 OR
                                  i1 > d11`2 - d1`2 AND
                                   length(DT`reml) = 1 + d11`2 AND
                                    DT`rdegl = d11`2)
                                 OR
                                 (d1`2 = 0 AND
                                   length(DT`reml) = 0 AND DT`rdegl = 0)
                                  OR
                                  (d1`2 > 0 AND
                                    length(DT`reml) = i1 + d1`2 AND
                                     length(DT`reml) = 1 + DT`rdegl)}]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivListType):
          ldt =
           IF i = n - m
             THEN make_divlisttype((: :), n - m, array2list(n + 1)(g), n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: int):
              thisterm = nth(ldt`reml, ldt`rdegl) IMPLIES
               (FORALL (j: nat):
                  j < i AND NOT j > m + i IMPLIES
                   j < length[int](ldt`reml))));

  % Subtype TCC generated (at line 33, column 33) for  j
      % expected type  below[length(ldt`reml)]
  pseudo_div_TCC7: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [d11: [[nat -> int], nat] ->
                 [d1: [h: [nat -> int], {m | h(m) /= 0}] ->
                    [i1:
                       {z: nat |
                                max(1 - z - d1`2 + d11`2, 0) <
                                 max(1 + n - i - m, 0)} ->
                       {DT: DivListType |
                                (d1`2 > d11`2 OR
                                  i1 > d11`2 - d1`2 AND
                                   length(DT`reml) = 1 + d11`2 AND
                                    DT`rdegl = d11`2)
                                 OR
                                 (d1`2 = 0 AND
                                   length(DT`reml) = 0 AND DT`rdegl = 0)
                                  OR
                                  (d1`2 > 0 AND
                                    length(DT`reml) = i1 + d1`2 AND
                                     length(DT`reml) = 1 + DT`rdegl)}]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivListType):
          ldt =
           IF i = n - m
             THEN make_divlisttype((: :), n - m, array2list(n + 1)(g), n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: int):
              thisterm = nth(ldt`reml, ldt`rdegl) IMPLIES
               (FORALL (j: nat):
                  NOT j < i AND NOT j > m + i IMPLIES
                   j < length[int](ldt`reml))));

  % Subtype TCC generated (at line 33, column 47) for  j - i
      % expected type  nat
  pseudo_div_TCC8: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [d11: [[nat -> int], nat] ->
                 [d1: [h: [nat -> int], {m | h(m) /= 0}] ->
                    [i1:
                       {z: nat |
                                max(1 - z - d1`2 + d11`2, 0) <
                                 max(1 + n - i - m, 0)} ->
                       {DT: DivListType |
                                (d1`2 > d11`2 OR
                                  i1 > d11`2 - d1`2 AND
                                   length(DT`reml) = 1 + d11`2 AND
                                    DT`rdegl = d11`2)
                                 OR
                                 (d1`2 = 0 AND
                                   length(DT`reml) = 0 AND DT`rdegl = 0)
                                  OR
                                  (d1`2 > 0 AND
                                    length(DT`reml) = i1 + d1`2 AND
                                     length(DT`reml) = 1 + DT`rdegl)}]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivListType):
          ldt =
           IF i = n - m
             THEN make_divlisttype((: :), n - m, array2list(n + 1)(g), n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: int):
              thisterm = nth(ldt`reml, ldt`rdegl) IMPLIES
               (FORALL (j: nat):
                  NOT j < i AND NOT j > m + i IMPLIES j - i >= 0)));

  % Subtype TCC generated (at line 33, column 59) for  m + i - 1
      % expected type  nat
  pseudo_div_TCC9: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [d11: [[nat -> int], nat] ->
                 [d1: [h: [nat -> int], {m | h(m) /= 0}] ->
                    [i1:
                       {z: nat |
                                max(1 - z - d1`2 + d11`2, 0) <
                                 max(1 + n - i - m, 0)} ->
                       {DT: DivListType |
                                (d1`2 > d11`2 OR
                                  i1 > d11`2 - d1`2 AND
                                   length(DT`reml) = 1 + d11`2 AND
                                    DT`rdegl = d11`2)
                                 OR
                                 (d1`2 = 0 AND
                                   length(DT`reml) = 0 AND DT`rdegl = 0)
                                  OR
                                  (d1`2 > 0 AND
                                    length(DT`reml) = i1 + d1`2 AND
                                     length(DT`reml) = 1 + DT`rdegl)}]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivListType):
          ldt =
           IF i = n - m
             THEN make_divlisttype((: :), n - m, array2list(n + 1)(g), n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: int):
              thisterm = nth(ldt`reml, ldt`rdegl) IMPLIES m + i - 1 >= 0));

  % Subtype TCC generated (at line 29, column 10) for
      % make_divlisttype(cons(thisterm, ldt`quotl), n - m,
      %                  array2list(m + i)
      %                            (LAMBDA (j: nat):
      %                               IF j > m + i
      %                               THEN 0
      %                               ELSIF j < i
      %                               THEN h(m) * nth(ldt`reml, j)
      %                               ELSE h(m) * nth(ldt`reml, j)
      %                                    -
      %                                    thisterm * h(j - i)
      %                               ENDIF),
      %                  m + i - 1)
      % expected type  {DT: DivListType |
                     %          (m > n OR
                     %            i > n - m AND
                     %             length(DT`reml) = 1 + n AND DT`rdegl = n)
                     %           OR
                     %           (m = 0 AND
                     %             length(DT`reml) = 0 AND DT`rdegl = 0)
                     %            OR
                     %            (m > 0 AND
                     %              length(DT`reml) = i + m AND
                     %               length(DT`reml) = 1 + DT`rdegl)}
  pseudo_div_TCC10: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            i: nat,
            v:
              [d11: [[nat -> int], nat] ->
                 [d1: [h: [nat -> int], {m | h(m) /= 0}] ->
                    [i1:
                       {z: nat |
                                max(1 - z - d1`2 + d11`2, 0) <
                                 max(1 + n - i - m, 0)} ->
                       {DT: DivListType |
                                (d1`2 > d11`2 OR
                                  i1 > d11`2 - d1`2 AND
                                   length(DT`reml) = 1 + d11`2 AND
                                    DT`rdegl = d11`2)
                                 OR
                                 (d1`2 = 0 AND
                                   length(DT`reml) = 0 AND DT`rdegl = 0)
                                  OR
                                  (d1`2 > 0 AND
                                    length(DT`reml) = i1 + d1`2 AND
                                     length(DT`reml) = 1 + DT`rdegl)}]]]):
      NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       (FORALL (ldt: DivListType):
          ldt =
           IF i = n - m
             THEN make_divlisttype((: :), n - m, array2list(n + 1)(g), n)
           ELSE v(g, n)(h, m)(i + 1)
           ENDIF
           IMPLIES
           (FORALL (thisterm: int):
              thisterm = nth(ldt`reml, ldt`rdegl) IMPLIES
               (m > n OR
                 i > n - m AND
                  length[int]
                      (make_divlisttype(cons[int](thisterm, ldt`quotl),
                                        n - m,
                                        array2list[int]
                                        (m + i)
                                        (LAMBDA
                                         (j: nat):
                                         IF j > m + i
                                         THEN 0
                                         ELSIF j < i
                                         THEN h(m) * nth[int](ldt`reml, j)
                                         ELSE h(m) * nth[int](ldt`reml, j)
                                              -
                                              thisterm * h(j - i)
                                         ENDIF),
                                        m + i - 1)`reml)
                   = 1 + n
                   AND
                   make_divlisttype(cons[int](thisterm, ldt`quotl), n - m,
                                    array2list[int]
                                        (m + i)
                                        (LAMBDA
                                         (j: nat):
                                         IF j > m + i
                                         THEN 0
                                         ELSIF j < i
                                         THEN h(m) * nth[int](ldt`reml, j)
                                         ELSE h(m) * nth[int](ldt`reml, j)
                                              -
                                              thisterm * h(j - i)
                                         ENDIF),
                                    m + i - 1)`rdegl
                    = n)
                OR
                (m = 0 AND
                  length[int]
                      (make_divlisttype(cons[int](thisterm, ldt`quotl),
                                        n - m,
                                        array2list[int]
                                        (m + i)
                                        (LAMBDA
                                         (j: nat):
                                         IF j > m + i
                                         THEN 0
                                         ELSIF j < i
                                         THEN h(m) * nth[int](ldt`reml, j)
                                         ELSE h(m) * nth[int](ldt`reml, j)
                                              -
                                              thisterm * h(j - i)
                                         ENDIF),
                                        m + i - 1)`reml)
                   = 0
                   AND
                   make_divlisttype(cons[int](thisterm, ldt`quotl), n - m,
                                    array2list[int]
                                        (m + i)
                                        (LAMBDA
                                         (j: nat):
                                         IF j > m + i
                                         THEN 0
                                         ELSIF j < i
                                         THEN h(m) * nth[int](ldt`reml, j)
                                         ELSE h(m) * nth[int](ldt`reml, j)
                                              -
                                              thisterm * h(j - i)
                                         ENDIF),
                                    m + i - 1)`rdegl
                    = 0)
                 OR
                 (m > 0 AND
                   length[int]
                       (make_divlisttype(cons[int](thisterm, ldt`quotl),
                                         n - m,
                                         array2list[int]
                                         (m + i)
                                         (LAMBDA
                                          (j: nat):
                                          IF j > m + i
                                          THEN 0
                                          ELSIF j < i
                                          THEN h(m) * nth[int](ldt`reml, j)
                                          ELSE h(m) * nth[int](ldt`reml, j)
                                               -
                                               thisterm * h(j - i)
                                          ENDIF),
                                         m + i - 1)`reml)
                    = i + m
                    AND
                    length[int]
                        (make_divlisttype(cons[int](thisterm, ldt`quotl),
                                          n - m,
                                          array2list[int]
                                          (m + i)
                                          (LAMBDA
                                           (j: nat):
                                           IF j > m + i
                                           THEN 0
                                           ELSIF j < i
                                           THEN h(m) * nth[int](ldt`reml, j)
                                           ELSE h(m) * nth[int](ldt`reml, j)
                                                -
                                                thisterm * h(j - i)
                                           ENDIF),
                                          m + i - 1)`reml)
                     =
                     1 +
                      make_divlisttype(cons[int](thisterm, ldt`quotl),
                                       n - m,
                                       array2list[int]
                                       (m + i)
                                       (LAMBDA
                                        (j: nat):
                                        IF j > m + i
                                        THEN 0
                                        ELSIF j < i
                                        THEN h(m) * nth[int](ldt`reml, j)
                                        ELSE h(m) * nth[int](ldt`reml, j)
                                             -
                                             thisterm * h(j - i)
                                        ENDIF),
                                       m + i - 1)`rdegl)));

  % Subtype TCC generated (at line 26, column 52) for  n - m
      % expected type  nat
  pseudo_div_TCC11: OBLIGATION
    FORALL (n: nat, h: [nat -> int], (m: nat | h(m) /= 0), i: nat):
      i = n - m AND NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       n - m >= 0;

  % Termination TCC generated (at line 27, column 20) for
      % pseudo_div(g, n)(h, m)(i + 1)
  pseudo_div_TCC12: OBLIGATION
    FORALL (n: nat, h: [nat -> int], (m: nat | h(m) /= 0), i: nat):
      NOT i = n - m AND NOT m = 0 AND NOT m > n AND NOT i > n - m IMPLIES
       max(n - m - (i + 1) + 1, 0) < max(n - m - i + 1, 0);

  % Subtype TCC generated (at line 78, column 26) for
      % k - (pd`qdeg - qlength + 1)
      % expected type  below[length(psd`quotl)]
  pseudo_div_def_TCC1: OBLIGATION
    FORALL (g, h: [nat -> int], i, m, n: nat):
      (FORALL (ii: nat): ii > m IMPLIES h(ii) = 0) AND
       (FORALL (ii: nat): ii > n IMPLIES g(ii) = 0) AND h(m) /= 0
       IMPLIES
       (FORALL (psd:
                  {DT: DivListType |
                           (m > n OR
                             i > n - m AND
                              length[int](DT`reml) = 1 + n AND DT`rdegl = n)
                            OR
                            (m = 0 AND
                              length[int](DT`reml) = 0 AND DT`rdegl = 0)
                             OR
                             (m > 0 AND
                               length[int](DT`reml) = i + m AND
                                length[int](DT`reml) = 1 + DT`rdegl)}):
          psd = pseudo_div(g, n)(h, m)(i) IMPLIES
           (FORALL (pd: DivType):
              pd = poly_divide(g, n)(h, m)(i) IMPLIES
               (FORALL (qlength: nat):
                  qlength = length(psd`quotl) IMPLIES
                   (FORALL (rlength: nat):
                      rlength = length(psd`reml) IMPLIES
                       (FORALL (k: nat):
                          k <= pd`qdeg AND k >= pd`qdeg - qlength + 1 IMPLIES
                           k - (pd`qdeg - qlength + 1) >= 0 AND
                            k - (pd`qdeg - qlength + 1) <
                             length[int](psd`quotl))))));

  % Subtype TCC generated (at line 80, column 122) for  k
      % expected type  below[length(psd`reml)]
  pseudo_div_def_TCC2: OBLIGATION
    FORALL (R, T: nat, g, h: [nat -> int], i, m, n: nat):
      (FORALL (ii: nat): ii > m IMPLIES h(ii) = 0) AND
       (FORALL (ii: nat): ii > n IMPLIES g(ii) = 0) AND h(m) /= 0
       IMPLIES
       (FORALL (psd:
                  {DT: DivListType |
                           (m > n OR
                             i > n - m AND
                              length[int](DT`reml) = 1 + n AND DT`rdegl = n)
                            OR
                            (m = 0 AND
                              length[int](DT`reml) = 0 AND DT`rdegl = 0)
                             OR
                             (m > 0 AND
                               length[int](DT`reml) = i + m AND
                                length[int](DT`reml) = 1 + DT`rdegl)}):
          psd = pseudo_div(g, n)(h, m)(i) IMPLIES
           (FORALL (pd: DivType):
              pd = poly_divide(g, n)(h, m)(i) IMPLIES
               (FORALL (qlength: nat):
                  qlength = length(psd`quotl) IMPLIES
                   (FORALL (rlength: nat):
                      (pd`quot =
                        (LAMBDA (k: nat): (1 / h(m)) ^ GG(k, n, m, i, R, T))
                         *
                         (LAMBDA (k: nat):
                            IF k <= pd`qdeg AND k >= pd`qdeg - qlength + 1
                              THEN nth(psd`quotl,
                                       k - (pd`qdeg - qlength + 1))
                            ELSE 0
                            ENDIF))
                       AND rlength = length(psd`reml)
                       IMPLIES
                       (FORALL (k1: nat):
                          k1 <= pd`rdeg AND (i > n - m OR m > 0) IMPLIES
                           k1 < length[int](psd`reml))))));

  % Subtype TCC generated (at line 90, column 94) for  k
      % expected type  below[length(psd`reml)]
  poly_pseudo_remainder_def_TCC1: OBLIGATION
    FORALL (g, h: [nat -> int], m, n: nat):
      (FORALL (ii: nat): ii > m IMPLIES h(ii) = 0) AND
       (FORALL (ii: nat): ii > n IMPLIES g(ii) = 0) AND n >= m AND h(m) /= 0
       IMPLIES
       (FORALL (psd:
                  {DT: DivListType |
                           (m > n OR
                             0 > n - m AND
                              length[int](DT`reml) = 1 + n AND DT`rdegl = n)
                            OR
                            (m = 0 AND
                              length[int](DT`reml) = 0 AND DT`rdegl = 0)
                             OR
                             (m > 0 AND
                               length[int](DT`reml) = m AND
                                length[int](DT`reml) = 1 + DT`rdegl)}):
          psd = pseudo_div(g, n)(h, m)(0) IMPLIES
           (FORALL (pd: DivType):
              pd = poly_divide(g, n)(h, m)(0) IMPLIES
               (FORALL (qlength: nat):
                  qlength = length(psd`quotl) IMPLIES
                   (FORALL (rlength: nat):
                      rlength = length(psd`reml) IMPLIES
                       (FORALL (k: nat):
                          k <= psd`rdegl AND m > 0 IMPLIES
                           k < length[int](psd`reml))))));

  % Subtype TCC generated (at line 96, column 65) for  -pseudosign
      % expected type  {k: nzint |
                     %          FORALL (ii: nat):
                     %            ii <
                     %             length[int]
                     %                 (nonzero_version
                     %                  (primitize_list(thisrem)))
                     %             IMPLIES
                     %             divides(k,
                     %                     nth[int]
                     %                     (nonzero_version
                     %                      (primitize_list(thisrem)),
                     %                      ii))}
  adjusted_remainder_TCC1: OBLIGATION
    FORALL (g: [nat -> int], n: nat, h: [nat -> int], (m: nat | h(m) /= 0),
            ppd:
              {DT: DivListType |
                       (m > n OR
                         0 > n - m AND
                          length[int](DT`reml) = 1 + n AND DT`rdegl = n)
                        OR
                        (m = 0 AND length[int](DT`reml) = 0 AND DT`rdegl = 0)
                         OR
                         (m > 0 AND
                           length[int](DT`reml) = m AND
                            length[int](DT`reml) = 1 + DT`rdegl)}):
      ppd = pseudo_div(g, n)(h, m)(0) IMPLIES
       (FORALL (thisrem: list[int]):
          thisrem = ppd`reml IMPLIES
           (FORALL (pseudosign: nzint):
              pseudosign =
               IF h(m) > 0 OR mod(n - m + 1, 2) = 0 OR m > n THEN 1
               ELSE -1
               ENDIF
               IMPLIES
               (FORALL (ii: nat):
                  ii < length[int](nonzero_version(primitize_list(thisrem)))
                   IMPLIES
                   divides(-pseudosign,
                           nth[int]
                               (nonzero_version(primitize_list(thisrem)),
                                ii)))));

  % Subtype TCC generated (at line 106, column 62) for  i
      % expected type  below[length(thisrem)]
  adjusted_remainder_def_TCC1: OBLIGATION
    FORALL (g, h: [nat -> int], m, n: nat):
      (FORALL (ii: nat): ii > m IMPLIES h(ii) = 0) AND
       (FORALL (ii: nat): ii > n IMPLIES g(ii) = 0) AND h(m) /= 0
       IMPLIES
       (FORALL (thisrem: list[int]):
          thisrem = adjusted_remainder(g, n)(h, m) IMPLIES
           (FORALL (pd: DivType):
              pd = poly_divide(g, n)(h, m)(0) IMPLIES
               (FORALL (thisdeg: int):
                  thisdeg = length[int](thisrem) - 1 IMPLIES
                   (FORALL (i: nat):
                      i <= thisdeg IMPLIES i < length[int](thisrem)))));

  % Subtype TCC generated (at line 137, column 33) for  4
      % expected type  {m | h(m) /= 0}
  adjusted_remainder_test_TCC1: OBLIGATION
    FORALL (g: [nat -> int]):
      g =
       (LAMBDA (i: nat):
          IF i = 0 THEN 1
          ELSIF i = 1 THEN 2
          ELSIF i = 2 THEN 2
          ELSIF i = 3 THEN 5
          ELSIF i = 5 THEN 2
          ELSIF i = 6 THEN -7
          ELSE 0
          ENDIF)
       IMPLIES
       (FORALL (h: [nat -> int]):
          h =
           (LAMBDA (i: nat):
              IF i = 0 THEN -4
              ELSIF i = 1 THEN -4
              ELSIF i = 2 THEN 2
              ELSIF i = 3 THEN 5
              ELSIF i = 4 THEN -2
              ELSE 0
              ENDIF)
           IMPLIES h(4) /= 0);


body:
  remainder_sequence: THEORY
  BEGIN

  IMPORTING polynomial_pseudo_divide

    a,r,g,h : VAR [nat->int]
    p : VAR [nat->[nat->int]]
    d,n,m,i,j,k : VAR nat
    pn : VAR posnat
    x,y,c,b : VAR real
    curr: VAR list[list[int]]

    is_neg_remainder_list?(g,(n|g(n)/=0),h,(m|h(m)/=0))(curr): bool =
      (FORALL (icurr,jcurr:nat):icurr<jcurr AND jcurr<length(curr)-1 
                     IMPLIES
  			length(nth(curr,icurr)) < length(nth(curr,jcurr))) AND
      (FORALL (icurr:nat): icurr<length(curr) IMPLIES LET thiscurr = nth(curr,icurr) IN
  			length(thiscurr)>0 IMPLIES nth(thiscurr,length(thiscurr)-1)/=0) AND
      (length(curr)>0 IMPLIES nth(curr,length(curr)-1) = array2list[int](n+1)(g)) AND
      (length(curr)>1 IMPLIES nth(curr,length(curr)-2) = array2list[int](m+1)(h)) AND
      (FORALL (j:nat): j<length(curr)-2 IMPLIES 
        LET pbig = list2array[int](0)(nth(curr,j+2)),
        	  nbig = length(nth(curr,j+2))-1,
  	  plittle = list2array[int](0)(nth(curr,j+1)),
  	  nlittle:nat = length(nth(curr,j+1))-1
        IN  nth(curr,j) = adjusted_remainder(pbig,nbig)(plittle,nlittle))


    compute_remainder_seq(g,(n|g(n)/=0),h,(m|h(m)/=0))
      (curr:(is_neg_remainder_list?(g,n,h,m))):
      RECURSIVE {crem:(is_neg_remainder_list?(g,n,h,m))|length(crem)>1 AND length(nth(crem,0))=0} =
      LET currlength = length(curr) IN
        IF currlength = 0 THEN 
            compute_remainder_seq(g,n,h,m)(cons[list[int]](array2list[int](m+1)(h),
  	              cons[list[int]](array2list[int](n+1)(g),curr)))
        ELSIF currlength = 1 THEN 
            compute_remainder_seq(g,n,h,m)(cons[list[int]](array2list[int](m+1)(h),
  	              curr))
        ELSIF length(nth(curr,0))=0 THEN curr
        ELSE
          LET csplittle  = nth(curr,0),
  	    cspbig     = nth(curr,1),
  	    newg       = list2array[int](0)(cspbig),
  	    newn       = length(cspbig)-1,
  	    newh       = list2array[int](0)(csplittle),
  	    newm       = length(csplittle)-1,
  	    newlist    = adjusted_remainder(newg,newn)(newh,newm)
          IN  compute_remainder_seq(g,n,h,m)(cons(newlist,curr))
        ENDIF MEASURE IF null?(curr) THEN m+n+4 ELSIF length(curr)=1 THEN m+n+3
        	    ELSIF length(curr)=2 THEN m+n+2 ELSE length(nth(curr,0)) ENDIF

    remainder_seq(g,(n|g(n)/=0),h,(m|h(m)/=0)):
      {crem:(is_neg_remainder_list?(g,n,h,m))|length(crem)>1 AND length(nth(crem,0))=0} =
      compute_remainder_seq(g,n,h,m)(null[list[int]])

    sturm_chain(g,(pn|g(pn)/=0)) : MACRO list[list[int]] = 
      remainder_seq(g,pn,poly_deriv(g),pn-1)

    remainder_seq_test: LEMMA
      LET g=(LAMBDA (i:nat): IF i<=3 THEN 2 ELSIF i<=6 
      		  	   THEN -3 ELSE 0 ENDIF)
      IN sturm_chain(g,6) =
        (:(::),(:-1:),(:-579,-608:),(:2,4,55:),
          (:126,140,105,120:),(:-70,-56,-42,-48,21:),
           (:2,4,6,-12,-15,-18:),(:2,2,2,2,-3,-3,-3:):)

  END remainder_sequence

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

  % Subtype TCC generated (at line 16, column 19) for  icurr
      % expected type  below[length[list[int]](curr)]
  is_neg_remainder_list?_TCC1: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]], icurr, jcurr: nat):
      icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
       icurr < length[list[int]](curr);

  % Subtype TCC generated (at line 16, column 45) for  jcurr
      % expected type  below[length[list[int]](curr)]
  is_neg_remainder_list?_TCC2: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]], icurr, jcurr: nat):
      icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
       jcurr < length[list[int]](curr);

  % Subtype TCC generated (at line 18, column 43) for  length(thiscurr) - 1
      % expected type  below[length(thiscurr)]
  is_neg_remainder_list?_TCC3: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      (FORALL (icurr, jcurr: nat):
         icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
          length(nth(curr, icurr)) < length(nth(curr, jcurr)))
       IMPLIES
       (FORALL (icurr1: nat):
          icurr1 < length(curr) IMPLIES
           (FORALL (thiscurr: list[int]):
              length(thiscurr) > 0 AND thiscurr = nth(curr, icurr1) IMPLIES
               length[int](thiscurr) - 1 >= 0 AND
                length[int](thiscurr) - 1 < length[int](thiscurr)));

  % Subtype TCC generated (at line 19, column 37) for  length(curr) - 1
      % expected type  below[length[list[int]](curr)]
  is_neg_remainder_list?_TCC4: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      (length(curr) > 0 AND
        (FORALL (icurr: nat):
           icurr < length(curr) IMPLIES
            LET thiscurr = nth(curr, icurr) IN
              length(thiscurr) > 0 IMPLIES
               nth(thiscurr, length(thiscurr) - 1) /= 0)
         AND
         (FORALL (icurr, jcurr: nat):
            icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
             length(nth(curr, icurr)) < length(nth(curr, jcurr))))
       IMPLIES
       length[list[int]](curr) - 1 >= 0 AND
        length[list[int]](curr) - 1 < length[list[int]](curr);

  % Subtype TCC generated (at line 20, column 37) for  length(curr) - 2
      % expected type  below[length[list[int]](curr)]
  is_neg_remainder_list?_TCC5: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      (length(curr) > 1 AND
        (length(curr) > 0 IMPLIES
          nth(curr, length(curr) - 1) = array2list[int](n + 1)(g))
         AND
         (FORALL (icurr: nat):
            icurr < length(curr) IMPLIES
             LET thiscurr = nth(curr, icurr) IN
               length(thiscurr) > 0 IMPLIES
                nth(thiscurr, length(thiscurr) - 1) /= 0)
          AND
          (FORALL (icurr, jcurr: nat):
             icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
              length(nth(curr, icurr)) < length(nth(curr, jcurr))))
       IMPLIES
       length[list[int]](curr) - 2 >= 0 AND
        length[list[int]](curr) - 2 < length[list[int]](curr);

  % Subtype TCC generated (at line 22, column 45) for  j + 2
      % expected type  below[length[list[int]](curr)]
  is_neg_remainder_list?_TCC6: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      ((length(curr) > 1 IMPLIES
         nth(curr, length(curr) - 2) = array2list[int](m + 1)(h))
        AND
        (length(curr) > 0 IMPLIES
          nth(curr, length(curr) - 1) = array2list[int](n + 1)(g))
         AND
         (FORALL (icurr: nat):
            icurr < length(curr) IMPLIES
             LET thiscurr = nth(curr, icurr) IN
               length(thiscurr) > 0 IMPLIES
                nth(thiscurr, length(thiscurr) - 1) /= 0)
          AND
          (FORALL (icurr, jcurr: nat):
             icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
              length(nth(curr, icurr)) < length(nth(curr, jcurr))))
       IMPLIES
       (FORALL (j: nat):
          j < length(curr) - 2 IMPLIES j + 2 < length[list[int]](curr));

  % Subtype TCC generated (at line 24, column 41) for  j + 1
      % expected type  below[length[list[int]](curr)]
  is_neg_remainder_list?_TCC7: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      ((length(curr) > 1 IMPLIES
         nth(curr, length(curr) - 2) = array2list[int](m + 1)(h))
        AND
        (length(curr) > 0 IMPLIES
          nth(curr, length(curr) - 1) = array2list[int](n + 1)(g))
         AND
         (FORALL (icurr: nat):
            icurr < length(curr) IMPLIES
             LET thiscurr = nth(curr, icurr) IN
               length(thiscurr) > 0 IMPLIES
                nth(thiscurr, length(thiscurr) - 1) /= 0)
          AND
          (FORALL (icurr, jcurr: nat):
             icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
              length(nth(curr, icurr)) < length(nth(curr, jcurr))))
       IMPLIES
       (FORALL (j: nat):
          j < length(curr) - 2 IMPLIES
           (FORALL (pbig: [nat -> int]):
              pbig = list2array[int](0)(nth(curr, j + 2)) IMPLIES
               (FORALL (nbig: int):
                  nbig = length(nth(curr, j + 2)) - 1 IMPLIES
                   j + 1 < length[list[int]](curr))));

  % Subtype TCC generated (at line 25, column 17) for
      % length(nth(curr, j + 1)) - 1
      % expected type  nat
  is_neg_remainder_list?_TCC8: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      ((length(curr) > 1 IMPLIES
         nth(curr, length(curr) - 2) = array2list[int](m + 1)(h))
        AND
        (length(curr) > 0 IMPLIES
          nth(curr, length(curr) - 1) = array2list[int](n + 1)(g))
         AND
         (FORALL (icurr: nat):
            icurr < length(curr) IMPLIES
             LET thiscurr = nth(curr, icurr) IN
               length(thiscurr) > 0 IMPLIES
                nth(thiscurr, length(thiscurr) - 1) /= 0)
          AND
          (FORALL (icurr, jcurr: nat):
             icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
              length(nth(curr, icurr)) < length(nth(curr, jcurr))))
       IMPLIES
       (FORALL (j: nat):
          j < length(curr) - 2 IMPLIES
           (FORALL (pbig: [nat -> int]):
              pbig = list2array[int](0)(nth(curr, j + 2)) IMPLIES
               (FORALL (nbig: int):
                  nbig = length(nth(curr, j + 2)) - 1 IMPLIES
                   (FORALL (plittle: [nat -> int]):
                      plittle = list2array[int](0)(nth(curr, j + 1)) IMPLIES
                       length[int](nth[list[int]](curr, j + 1)) - 1 >= 0))));

  % Subtype TCC generated (at line 26, column 19) for  j
      % expected type  below[length[list[int]](curr)]
  is_neg_remainder_list?_TCC9: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      ((length(curr) > 1 IMPLIES
         nth(curr, length(curr) - 2) = array2list[int](m + 1)(h))
        AND
        (length(curr) > 0 IMPLIES
          nth(curr, length(curr) - 1) = array2list[int](n + 1)(g))
         AND
         (FORALL (icurr: nat):
            icurr < length(curr) IMPLIES
             LET thiscurr = nth(curr, icurr) IN
               length(thiscurr) > 0 IMPLIES
                nth(thiscurr, length(thiscurr) - 1) /= 0)
          AND
          (FORALL (icurr, jcurr: nat):
             icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
              length(nth(curr, icurr)) < length(nth(curr, jcurr))))
       IMPLIES
       (FORALL (j: nat):
          j < length(curr) - 2 IMPLIES
           (FORALL (pbig: [nat -> int]):
              pbig = list2array[int](0)(nth(curr, j + 2)) IMPLIES
               (FORALL (nbig: int):
                  nbig = length(nth(curr, j + 2)) - 1 IMPLIES
                   (FORALL (plittle: [nat -> int]):
                      plittle = list2array[int](0)(nth(curr, j + 1)) IMPLIES
                       (FORALL (nlittle: nat):
                          nlittle = length(nth(curr, j + 1)) - 1 IMPLIES
                           j < length[list[int]](curr))))));

  % Subtype TCC generated (at line 26, column 62) for  nlittle
      % expected type  {m | plittle(m) /= 0}
  is_neg_remainder_list?_TCC10: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      ((length(curr) > 1 IMPLIES
         nth(curr, length(curr) - 2) = array2list[int](m + 1)(h))
        AND
        (length(curr) > 0 IMPLIES
          nth(curr, length(curr) - 1) = array2list[int](n + 1)(g))
         AND
         (FORALL (icurr: nat):
            icurr < length(curr) IMPLIES
             LET thiscurr = nth(curr, icurr) IN
               length(thiscurr) > 0 IMPLIES
                nth(thiscurr, length(thiscurr) - 1) /= 0)
          AND
          (FORALL (icurr, jcurr: nat):
             icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
              length(nth(curr, icurr)) < length(nth(curr, jcurr))))
       IMPLIES
       (FORALL (j: nat):
          j < length(curr) - 2 IMPLIES
           (FORALL (pbig: [nat -> int]):
              pbig = list2array[int](0)(nth(curr, j + 2)) IMPLIES
               (FORALL (nbig: int):
                  nbig = length(nth(curr, j + 2)) - 1 IMPLIES
                   (FORALL (plittle: [nat -> int]):
                      plittle = list2array[int](0)(nth(curr, j + 1)) IMPLIES
                       (FORALL (nlittle: nat):
                          nlittle = length(nth(curr, j + 1)) - 1 IMPLIES
                           plittle(nlittle) /= 0)))));

  % Subtype TCC generated (at line 26, column 48) for  nbig
      % expected type  nat
  is_neg_remainder_list?_TCC11: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: list[list[int]]):
      ((length(curr) > 1 IMPLIES
         nth(curr, length(curr) - 2) = array2list[int](m + 1)(h))
        AND
        (length(curr) > 0 IMPLIES
          nth(curr, length(curr) - 1) = array2list[int](n + 1)(g))
         AND
         (FORALL (icurr: nat):
            icurr < length(curr) IMPLIES
             LET thiscurr = nth(curr, icurr) IN
               length(thiscurr) > 0 IMPLIES
                nth(thiscurr, length(thiscurr) - 1) /= 0)
          AND
          (FORALL (icurr, jcurr: nat):
             icurr < jcurr AND jcurr < length(curr) - 1 IMPLIES
              length(nth(curr, icurr)) < length(nth(curr, jcurr))))
       IMPLIES
       (FORALL (j: nat):
          j < length(curr) - 2 IMPLIES
           (FORALL (pbig: [nat -> int]):
              pbig = list2array[int](0)(nth(curr, j + 2)) IMPLIES
               (FORALL (nbig: int):
                  nbig = length(nth(curr, j + 2)) - 1 IMPLIES
                   (FORALL (plittle: [nat -> int]):
                      plittle = list2array[int](0)(nth(curr, j + 1)) IMPLIES
                       (FORALL (nlittle: nat):
                          nlittle = length(nth(curr, j + 1)) - 1 IMPLIES
                           nbig >= 0)))));

  % Subtype TCC generated (at line 31, column 89) for  0
      % expected type  below[length[list[int]](crem)]
  compute_remainder_seq_TCC1: OBLIGATION
    FORALL (g, h, (m: nat | h(m) /= 0), (n: nat | g(n) /= 0),
            crem: (is_neg_remainder_list?(g, n, h, m))):
      length(crem) > 1 IMPLIES 0 < length[list[int]](crem);

  % Subtype TCC generated (at line 50, column 64) for  0
      % expected type  below[length[list[int]](curr)]
  compute_remainder_seq_TCC2: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0),
            curr: (is_neg_remainder_list?(g, n, h, m))):
      NOT length(curr) = 2 AND NOT length(curr) = 1 AND NOT null?(curr)
       IMPLIES 0 < length[list[int]](curr);

  % Subtype TCC generated (at line 50, column 64) for  0
      % expected type  below[length[list[int]](z)]
  compute_remainder_seq_TCC3: OBLIGATION
    FORALL (d1:
              [g: [nat -> int], {n | g(n) /= 0}, h: [nat -> int],
               {m | h(m) /= 0}],
            z: (is_neg_remainder_list?(d1`1, d1`2, d1`3, d1`4))):
      NOT null?(z) AND NOT length(z) = 1 AND NOT length(z) = 2 IMPLIES
       0 < length[list[int]](z);

  % Subtype TCC generated (at line 34, column 41) for
      % cons[list[int]]
      %     (array2list[int](m + 1)(h),
      %      cons[list[int]](array2list[int](n + 1)(g), curr))
      % expected type  (is_neg_remainder_list?(g, n, h, m))
  compute_remainder_seq_TCC4: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      currlength = 0 AND currlength = length(curr) IMPLIES
       is_neg_remainder_list?(g, n, h, m)
                             (cons[list[int]]
                                  (array2list[int](m + 1)(h),
                                   cons[list[int]]
                                       (array2list[int](n + 1)(g), curr)));

  % Termination TCC generated (at line 34, column 10) for
      % compute_remainder_seq(g, n, h, m)
      %                      (cons[list[int]]
      %                           (array2list[int](m + 1)(h),
      %                            cons[list[int]]
      %                                (array2list[int](n + 1)(g), curr)))
  compute_remainder_seq_TCC5: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      currlength = 0 AND currlength = length(curr) IMPLIES
       IF length[list[int]]
              (cons[list[int]]
                   (array2list[int](m + 1)(h),
                    cons[list[int]](array2list[int](n + 1)(g), curr)))
           = 1
         THEN m + n + 3
       ELSIF length[list[int]]
                 (cons[list[int]]
                      (array2list[int](m + 1)(h),
                       cons[list[int]](array2list[int](n + 1)(g), curr)))
              = 2
         THEN m + n + 2
       ELSE length[int]
                (nth[list[int]]
                     (cons[list[int]]
                          (array2list[int](m + 1)(h),
                           cons[list[int]](array2list[int](n + 1)(g), curr)),
                      0)) ENDIF
        <
        IF null?[list[int]](curr) THEN m + n + 4
        ELSIF length[list[int]](curr) = 1 THEN m + n + 3
        ELSIF length[list[int]](curr) = 2 THEN m + n + 2
        ELSE length[int](nth[list[int]](curr, 0))
        ENDIF;

  % Subtype TCC generated (at line 37, column 41) for
      % cons[list[int]](array2list[int](m + 1)(h), curr)
      % expected type  (is_neg_remainder_list?(g, n, h, m))
  compute_remainder_seq_TCC6: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      currlength = 1 AND NOT currlength = 0 AND currlength = length(curr)
       IMPLIES
       is_neg_remainder_list?(g, n, h, m)
                             (cons[list[int]]
                                  (array2list[int](m + 1)(h), curr));

  % Termination TCC generated (at line 37, column 10) for
      % compute_remainder_seq(g, n, h, m)
      %                      (cons[list[int]]
      %                           (array2list[int](m + 1)(h), curr))
  compute_remainder_seq_TCC7: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      currlength = 1 AND NOT currlength = 0 AND currlength = length(curr)
       IMPLIES
       IF length[list[int]](cons[list[int]](array2list[int](m + 1)(h), curr))
           = 1
         THEN m + n + 3
       ELSIF length[list[int]]
                 (cons[list[int]](array2list[int](m + 1)(h), curr))
              = 2
         THEN m + n + 2
       ELSE length[int]
                (nth[list[int]]
                     (cons[list[int]](array2list[int](m + 1)(h), curr),
                      0)) ENDIF
        <
        IF null?[list[int]](curr) THEN m + n + 4
        ELSIF length[list[int]](curr) = 1 THEN m + n + 3
        ELSIF length[list[int]](curr) = 2 THEN m + n + 2
        ELSE length[int](nth[list[int]](curr, 0))
        ENDIF;

  % Subtype TCC generated (at line 39, column 28) for  0
      % expected type  below[length[list[int]](curr)]
  compute_remainder_seq_TCC8: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      NOT currlength = 1 AND NOT currlength = 0 AND currlength = length(curr)
       IMPLIES 0 < length[list[int]](curr);

  % Subtype TCC generated (at line 39, column 39) for  curr
      % expected type  {crem: (is_neg_remainder_list?(g, n, h, m)) |
                     %          length(crem) > 1 AND length(nth(crem, 0)) = 0}
  compute_remainder_seq_TCC9: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      length(nth(curr, 0)) = 0 AND
       NOT currlength = 1 AND
        NOT currlength = 0 AND currlength = length(curr)
       IMPLIES
       length[list[int]](curr) > 1 AND
        length[int](nth[list[int]](curr, 0)) = 0;

  % Subtype TCC generated (at line 42, column 27) for  1
      % expected type  below[length[list[int]](curr)]
  compute_remainder_seq_TCC10: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      NOT length(nth(curr, 0)) = 0 AND
       NOT currlength = 1 AND
        NOT currlength = 0 AND currlength = length(curr)
       IMPLIES
       (FORALL (csplittle: list[int]):
          csplittle = nth(curr, 0) IMPLIES 1 < length[list[int]](curr));

  % Subtype TCC generated (at line 47, column 53) for  newm
      % expected type  {m | newh(m) /= 0}
  compute_remainder_seq_TCC11: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      NOT length(nth(curr, 0)) = 0 AND
       NOT currlength = 1 AND
        NOT currlength = 0 AND currlength = length(curr)
       IMPLIES
       (FORALL (csplittle: list[int]):
          csplittle = nth(curr, 0) IMPLIES
           (FORALL (cspbig: list[int]):
              cspbig = nth(curr, 1) IMPLIES
               (FORALL (newg: [nat -> int]):
                  newg = list2array[int](0)(cspbig) IMPLIES
                   (FORALL (newn: int):
                      newn = length(cspbig) - 1 IMPLIES
                       (FORALL (newh: [nat -> int]):
                          newh = list2array[int](0)(csplittle) IMPLIES
                           (FORALL (newm: int):
                              newm = length(csplittle) - 1 IMPLIES
                               newm >= 0 AND newh(newm) /= 0))))));

  % Subtype TCC generated (at line 47, column 42) for  newn
      % expected type  nat
  compute_remainder_seq_TCC12: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      NOT length(nth(curr, 0)) = 0 AND
       NOT currlength = 1 AND
        NOT currlength = 0 AND currlength = length(curr)
       IMPLIES
       (FORALL (csplittle: list[int]):
          csplittle = nth(curr, 0) IMPLIES
           (FORALL (cspbig: list[int]):
              cspbig = nth(curr, 1) IMPLIES
               (FORALL (newg: [nat -> int]):
                  newg = list2array[int](0)(cspbig) IMPLIES
                   (FORALL (newn: int):
                      newn = length(cspbig) - 1 IMPLIES
                       (FORALL (newh: [nat -> int]):
                          newh = list2array[int](0)(csplittle) IMPLIES
                           (FORALL (newm: int):
                              newm = length(csplittle) - 1 IMPLIES
                               newn >= 0))))));

  % Subtype TCC generated (at line 48, column 43) for  cons(newlist, curr)
      % expected type  (is_neg_remainder_list?(g, n, h, m))
  compute_remainder_seq_TCC13: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      NOT length(nth(curr, 0)) = 0 AND
       NOT currlength = 1 AND
        NOT currlength = 0 AND currlength = length(curr)
       IMPLIES
       (FORALL (csplittle: list[int]):
          csplittle = nth(curr, 0) IMPLIES
           (FORALL (cspbig: list[int]):
              cspbig = nth(curr, 1) IMPLIES
               (FORALL (newg: [nat -> int]):
                  newg = list2array[int](0)(cspbig) IMPLIES
                   (FORALL (newn: int):
                      newn = length(cspbig) - 1 IMPLIES
                       (FORALL (newh: [nat -> int]):
                          newh = list2array[int](0)(csplittle) IMPLIES
                           (FORALL (newm: int):
                              newm = length(csplittle) - 1 IMPLIES
                               (FORALL (newlist: list[int]):
                                  newlist =
                                   adjusted_remainder(newg, newn)(newh, newm)
                                   IMPLIES
                                   is_neg_remainder_list?(g, n, h, m)
                                                         (cons[list[int]]
                                                          (newlist,
                                                           curr)))))))));

  % Termination TCC generated (at line 48, column 12) for
      % compute_remainder_seq(g, n, h, m)(cons(newlist, curr))
  compute_remainder_seq_TCC14: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0), curr: (is_neg_remainder_list?(g, n, h, m)),
            currlength: nat):
      NOT length(nth(curr, 0)) = 0 AND
       NOT currlength = 1 AND
        NOT currlength = 0 AND currlength = length(curr)
       IMPLIES
       (FORALL (csplittle: list[int]):
          csplittle = nth(curr, 0) IMPLIES
           (FORALL (cspbig: list[int]):
              cspbig = nth(curr, 1) IMPLIES
               (FORALL (newg: [nat -> int]):
                  newg = list2array[int](0)(cspbig) IMPLIES
                   (FORALL (newn: int):
                      newn = length(cspbig) - 1 IMPLIES
                       (FORALL (newh: [nat -> int]):
                          newh = list2array[int](0)(csplittle) IMPLIES
                           (FORALL (newm: int):
                              newm = length(csplittle) - 1 IMPLIES
                               (FORALL (newlist: list[int]):
                                  newlist =
                                   adjusted_remainder(newg, newn)(newh, newm)
                                   IMPLIES
                                   IF length[list[int]]
                                      (cons[list[int]](newlist, curr))
                                      =
                                      1
                                     THEN m + n + 3
                                   ELSIF length[list[int]]
                                         (cons[list[int]](newlist, curr))
                                         =
                                         2
                                     THEN m + n + 2
                                   ELSE length[int]
                                        (nth[list[int]]
                                         (cons[list[int]](newlist, curr),
                                          0)) ENDIF
                                    <
                                    IF null?[list[int]](curr) THEN m + n + 4
                                    ELSIF length[list[int]](curr) = 1
                                      THEN m + n + 3
                                    ELSIF length[list[int]](curr) = 2
                                      THEN m + n + 2
                                    ELSE length[int](nth[list[int]](curr, 0))
                                    ENDIF)))))));

  % Subtype TCC generated (at line 54, column 35) for  null[list[int]]
      % expected type  (is_neg_remainder_list?(g, n, h, m))
  remainder_seq_TCC1: OBLIGATION
    FORALL (g: [nat -> int], (n: nat | g(n) /= 0), h: [nat -> int],
            (m: nat | h(m) /= 0)):
      is_neg_remainder_list?(g, n, h, m)(null[list[int]]);

  % Subtype TCC generated (at line 57, column 23) for  poly_deriv(g)
      % expected type  [nat -> int]
  sturm_chain_TCC1: OBLIGATION
    FORALL (g: [nat -> int], (pn: posnat | g(pn) /= 0)):
      FORALL (x1: nat):
        rational_pred(poly_deriv(g)(x1)) AND integer_pred(poly_deriv(g)(x1));

  % Subtype TCC generated (at line 57, column 37) for  pn - 1
      % expected type  {m | poly_deriv(g)(m) /= 0}
  sturm_chain_TCC2: OBLIGATION
    FORALL (g: [nat -> int], (pn: posnat | g(pn) /= 0)):
      pn - 1 >= 0 AND poly_deriv(g)(pn - 1) /= 0;

  % Subtype TCC generated (at line 62, column 21) for  6
      % expected type  {n | g(n) /= 0}
  remainder_seq_test_TCC1: OBLIGATION
    FORALL (g: [nat -> int]):
      g =
       (LAMBDA (i: nat): IF i <= 3 THEN 2 ELSIF i <= 6 THEN -3 ELSE 0 ENDIF)
       IMPLIES g(6) /= 0;

  % Subtype TCC generated (at line 57, column 23) for  poly_deriv(g)
      % expected type  [nat -> int]
  remainder_seq_test_TCC2: OBLIGATION
    FORALL (g: [nat -> int]):
      g =
       (LAMBDA (i: nat): IF i <= 3 THEN 2 ELSIF i <= 6 THEN -3 ELSE 0 ENDIF)
       IMPLIES
       (FORALL (x1: nat):
          rational_pred(poly_deriv(g)(x1)) AND
           integer_pred(poly_deriv(g)(x1)));

  % Subtype TCC generated (at line 57, column 37) for  6 - 1
      % expected type  {m | poly_deriv(g)(m) /= 0}
  remainder_seq_test_TCC3: OBLIGATION
    FORALL (g: [nat -> int]):
      g =
       (LAMBDA (i: nat): IF i <= 3 THEN 2 ELSIF i <= 6 THEN -3 ELSE 0 ENDIF)
       IMPLIES 6 - 1 >= 0 AND poly_deriv(g)(6 - 1) /= 0;


body:
  number_sign_changes: THEORY
  BEGIN

    IMPORTING reals@sign

    a,b,r : VAR [nat->real]
    i,j,k,d,n : VAR nat
    sig: VAR real

    NSC : TYPE = [# num: nat, lastnz: real #] 

    number_sign_changes(a,i): RECURSIVE NSC =
      IF i = 0 THEN (# num:= 0, lastnz:= a(0) #)
      ELSE LET prev = number_sign_changes(a,i-1)
      	 IN  IF a(i)/=0 AND prev`lastnz/=0 AND sign_ext(a(i))/=sign_ext(prev`lastnz)
  	       THEN (# num:=prev`num+1,lastnz:=a(i) #)
  	     ELSIF a(i)/=0
  	       THEN prev WITH [lastnz:=a(i)]
  	     ELSE prev
  	     ENDIF
      ENDIF MEASURE i

    num    : VAR nat
    lastnz : VAR real

    sign_changes(a,n,(i:subrange(1,n+1)),num,lastnz) : RECURSIVE 
      {m: nat | LET nsci = number_sign_changes(a,i-1),
                    nscn = number_sign_changes(a,n) IN
                    num = nsci`num AND lastnz = nsci`lastnz IMPLIES
                    m = nscn`num} =
      IF i = n+1 THEN num
      ELSIF a(i)/=0 AND lastnz/=0 AND sign_ext(a(i))/=sign_ext(lastnz) THEN
        sign_changes(a,n,i+1,num+1,a(i))
      ELSIF a(i)/=0 THEN
        sign_changes(a,n,i+1,num,a(i))
      ELSE
        sign_changes(a,n,i+1,num,lastnz)
      ENDIF
    MEASURE n-i+1

    num_sign_changes_def : LEMMA
      number_sign_changes(a,i)`num = sign_changes(a,i,1,0,a(0))

    number_sign_changes_lastnz_nonzero: LEMMA
      number_sign_changes(a,i)`lastnz = 0 IFF
      (FORALL (j:nat): j<=i IMPLIES a(j)=0)

    number_sign_changes_lastnz: LEMMA
      a(i)/=0 IMPLIES number_sign_changes(a,i)`lastnz=a(i)

    number_sign_changes_eq: LEMMA
      (FORALL (j:upto(i)): sign_ext(a(j))=sign_ext(b(j))) IMPLIES
      LET nsca = number_sign_changes(a,i),
          nscb = number_sign_changes(b,i)
      IN (nsca`num = nscb`num AND sign_ext(nsca`lastnz)=sign_ext(nscb`lastnz))

    testseqaa1(i):real = (-1)^i % (1,-1,1,-1,1,-1,1,-1,1,-1,...)
    testseqaa2:sequence[real] = testseqaa1 WITH [6:=-1] % (1,-1,1,-1,1,-1,-1,-1,1,-1,1,...)
    testseqaa3:sequence[real] = testseqaa2 WITH [7:=0] % (1,-1,1,-1,1,-1,-1,0,1,-1,1,...)
    testseqaa4:sequence[real] = testseqaa1 WITH [4:=0] % (1,-1,1,-1,0,-1,1,-1,1,-1,...)
    testseqaa5(i): real = IF i = 5 THEN 3 ELSIF i=6 
    		 THEN 4 ELSIF i=7 THEN 0 ELSIF i=8 THEN -4 ELSE (-1)^i ENDIF
  		 % (1,-1,1,-1,1,3,4,0,-4,-1,1,-1,1,...)
    testseqaa6(i):real = IF i = 0 OR i = 1 THEN 0 ELSE testseqaa1(i) ENDIF

    number_sign_changes_easy: LEMMA number_sign_changes(testseqaa2,7 ) = (# num:=5,lastnz:=-1 #)

    number_sign_changes_test1: LEMMA number_sign_changes(testseqaa1,i ) = (# num:=i,lastnz:=(-1)^i #)
    number_sign_changes_test2: LEMMA number_sign_changes(testseqaa2,7 ) = (# num:=5,lastnz:=-1 #)
    number_sign_changes_test3: LEMMA number_sign_changes(testseqaa2,8 ) = (# num:=6,lastnz:= 1 #)
    number_sign_changes_test4: LEMMA number_sign_changes(testseqaa3,7 ) = (# num:=5,lastnz:=-1 #)
    number_sign_changes_test5: LEMMA number_sign_changes(testseqaa3,9 ) = (# num:=7,lastnz:=-1 #)
    number_sign_changes_test6: LEMMA number_sign_changes(testseqaa4,8 ) = (# num:=6,lastnz:= 1 #)
    number_sign_changes_test7: LEMMA number_sign_changes(testseqaa5,10) = (# num:=6,lastnz:= 1 #)

    nsc_regular_swap: LEMMA
      k<=d AND
      (FORALL (j): j<=k IMPLIES (sign_ext(a(j))=sign_ext(b(j)) OR
        (sign_ext(a(j))/=sign_ext(b(j)) AND
          a(j+1)/=0 AND
          (j>0 IMPLIES sign_ext(a(j-1))=-sign_ext(a(j+1))) AND
  	(j>0 IMPLIES sign_ext(b(j-1))=-sign_ext(b(j+1))) AND
  	(j=0 IMPLIES sign_ext(a(0))  =-sign_ext(a(1))))))
      AND sign_ext(a(k)) = sign_ext(b(k))
      AND (FORALL (j:nat): j<k IMPLIES 
      		a(j)/=0 AND b(j)/=0)
      IMPLIES
        LET nsca = number_sign_changes(a,k),
        	  nscb = number_sign_changes(b,k)
        IN  ((k>=1 IMPLIES sign_ext(nsca`lastnz)=sign_ext(nscb`lastnz)) AND
        	  nsca`num = nscb`num + 
  	    (IF k>=1 AND sign_ext(a(0))=-sign_ext(b(0)) THEN 1 ELSE 0 ENDIF))

    nsc_edge_diff: LEMMA (sig=-1 OR sig=1) AND
      k<=d AND
      (FORALL (j): j<=k IMPLIES (sign_ext(a(j))=sign_ext(b(j)) OR b(j)=0))
      AND (FORALL (j): 0<j AND j<=k AND b(j)=0 IMPLIES b(j-1)/=0)
      AND sign_ext(a(k)) = sign_ext(b(k))
      AND (FORALL (j:nat): j<k IMPLIES a(j)/=0)
      AND (b(0)=0 IMPLIES sign_ext(a(0))=sig*sign_ext(a(1)))
      AND (FORALL (j:nat): 0<j AND j<k AND b(j)=0 IMPLIES sign_ext(b(j-1))=-sign_ext(b(j+1)))
      IMPLIES
        LET nsca = number_sign_changes(a,k),
        	  nscb = number_sign_changes(b,k)
        IN  ((k>=1 IMPLIES sign_ext(nsca`lastnz)=sign_ext(nscb`lastnz)) AND
        	  nsca`num = nscb`num + 
  	    (IF k>=1 AND b(0)=0 AND sig=-1 THEN 1 ELSE 0 ENDIF))

    nsc_multiroot: LEMMA (sig=-1 OR sig=1) AND
      k<=d AND
      (FORALL (j): 0<j AND j<=k IMPLIES sign_ext(a(j))=sig*sign_ext(b(j))) AND
      sign_ext(a(0))=-sig*sign_ext(b(0)) AND
      sign_ext(a(0))=-sign_ext(a(1)) AND
      sign_ext(b(0))= sign_ext(b(1)) AND
      (FORALL (j): j<k IMPLIES (a(j)/=0 AND b(j)/=0))
      IMPLIES
        LET nsca = number_sign_changes(a,k)`num,
        	  nscb = number_sign_changes(b,k)`num
        IN  nsca = nscb + (IF k>=1 THEN 1 ELSE 0 ENDIF)

    nsc_multiroot_full: LEMMA FORALL (sigfun:[nat->real]):
      (sig=-1 OR sig=1) AND % The nominal sign
      (FORALL (j): sigfun(j)=-1 OR sigfun(j)=1) AND
      k<=d AND
      (FORALL (j): 0<j AND j<=k IMPLIES sign_ext(a(j))=sigfun(j)*sign_ext(b(j))) AND
      (FORALL (j): 0<j AND j<=k AND sigfun(j)/=sig 
        IMPLIES (1<j AND j<k AND sigfun(j-1)=sig AND sigfun(j+1)=sig
        	      AND sign_ext(a(j-1))=-sign_ext(a(j+1)) AND sign_ext(b(j-1))=-sign_ext(b(j+1)))) AND 
      sign_ext(a(0))=-sig*sign_ext(b(0)) AND
      sign_ext(a(0))=-sign_ext(a(1)) AND
      sign_ext(b(0))= sign_ext(b(1)) AND
      (FORALL (j): j<=k IMPLIES (a(j)/=0 AND b(j)/=0))
      IMPLIES
        LET nsca = number_sign_changes(a,k)`num,
        	  nscb = number_sign_changes(b,k)`num
        IN  nsca = nscb + (IF k>=1 THEN 1 ELSE 0 ENDIF)
    
  END number_sign_changes

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

  % Subtype TCC generated (at line 14, column 42) for  i - 1
      % expected type  nat
  number_sign_changes_TCC1: OBLIGATION
    FORALL (i: nat): NOT i = 0 IMPLIES i - 1 >= 0;

  % Termination TCC generated (at line 14, column 20) for
      % number_sign_changes(a, i - 1)
  number_sign_changes_TCC2: OBLIGATION
    FORALL (i: nat): NOT i = 0 IMPLIES i - 1 < i;

  % Subtype TCC generated (at line 27, column 47) for  i - 1
      % expected type  nat
  sign_changes_TCC1: OBLIGATION
    FORALL (n, (i: subrange(1, n + 1))): i - 1 >= 0;

  % Subtype TCC generated (at line 39, column 10) for  n - i + 1
      % expected type  naturalnumber
  sign_changes_TCC2: OBLIGATION
    FORALL (n: nat, (i: subrange(1, n + 1))): n - i + 1 >= 0;

  % Subtype TCC generated (at line 31, column 20) for  num
      % expected type  {m: nat |
                     %          num = number_sign_changes(a, i - 1)`num AND
                     %           lastnz =
                     %            number_sign_changes(a, i - 1)`lastnz
                     %           IMPLIES m = number_sign_changes(a, n)`num}
  sign_changes_TCC3: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)), num: nat,
            lastnz: real):
      i = n + 1 IMPLIES
       num = number_sign_changes(a, i - 1)`num AND
        lastnz = number_sign_changes(a, i - 1)`lastnz
        IMPLIES num = number_sign_changes(a, n)`num;

  % Subtype TCC generated (at line 33, column 23) for  i + 1
      % expected type  subrange(1, 1 + n)
  sign_changes_TCC4: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)), lastnz: real):
      a(i) /= 0 AND
       lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz) AND NOT i = n + 1
       IMPLIES 1 <= i + 1 AND i + 1 <= 1 + n;

  % Termination TCC generated (at line 33, column 6) for
      % sign_changes(a, n, i + 1, num + 1, a(i))
  sign_changes_TCC5: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)), lastnz: real):
      a(i) /= 0 AND
       lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz) AND NOT i = n + 1
       IMPLIES n - (i + 1) + 1 < n - i + 1;

  % Subtype TCC generated (at line 33, column 6) for
      % sign_changes(a, n, i + 1, num + 1, a(i))
      % expected type  {m: nat |
                     %          num = number_sign_changes(a, i - 1)`num AND
                     %           lastnz =
                     %            number_sign_changes(a, i - 1)`lastnz
                     %           IMPLIES m = number_sign_changes(a, n)`num}
  sign_changes_TCC6: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)),
            v:
              [d1:
                 {z: [[nat -> real], n: nat, subrange(1, 1 + n), nat, real] |
                          1 - z`3 + z`2 < 1 + n - i} ->
                 {m: nat |
                          d1`4 = number_sign_changes(d1`1, d1`3 - 1)`num AND
                           d1`5 = number_sign_changes(d1`1, d1`3 - 1)`lastnz
                           IMPLIES m = number_sign_changes(d1`1, d1`2)`num}],
            num: nat, lastnz: real):
      a(i) /= 0 AND
       lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz) AND NOT i = n + 1
       IMPLIES
       num = number_sign_changes(a, i - 1)`num AND
        lastnz = number_sign_changes(a, i - 1)`lastnz
        IMPLIES v(a, n, i + 1, num + 1, a(i)) = number_sign_changes(a, n)`num;

  % Subtype TCC generated (at line 35, column 23) for  i + 1
      % expected type  subrange(1, 1 + n)
  sign_changes_TCC7: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)), lastnz: real):
      a(i) /= 0 AND
       NOT (a(i) /= 0 AND lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz))
        AND NOT i = n + 1
       IMPLIES 1 <= i + 1 AND i + 1 <= 1 + n;

  % Termination TCC generated (at line 35, column 6) for
      % sign_changes(a, n, i + 1, num, a(i))
  sign_changes_TCC8: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)), lastnz: real):
      a(i) /= 0 AND
       NOT (a(i) /= 0 AND lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz))
        AND NOT i = n + 1
       IMPLIES n - (i + 1) + 1 < n - i + 1;

  % Subtype TCC generated (at line 35, column 6) for
      % sign_changes(a, n, i + 1, num, a(i))
      % expected type  {m: nat |
                     %          num = number_sign_changes(a, i - 1)`num AND
                     %           lastnz =
                     %            number_sign_changes(a, i - 1)`lastnz
                     %           IMPLIES m = number_sign_changes(a, n)`num}
  sign_changes_TCC9: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)),
            v:
              [d1:
                 {z: [[nat -> real], n: nat, subrange(1, 1 + n), nat, real] |
                          1 - z`3 + z`2 < 1 + n - i} ->
                 {m: nat |
                          d1`4 = number_sign_changes(d1`1, d1`3 - 1)`num AND
                           d1`5 = number_sign_changes(d1`1, d1`3 - 1)`lastnz
                           IMPLIES m = number_sign_changes(d1`1, d1`2)`num}],
            num: nat, lastnz: real):
      a(i) /= 0 AND
       NOT (a(i) /= 0 AND lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz))
        AND NOT i = n + 1
       IMPLIES
       num = number_sign_changes(a, i - 1)`num AND
        lastnz = number_sign_changes(a, i - 1)`lastnz
        IMPLIES v(a, n, i + 1, num, a(i)) = number_sign_changes(a, n)`num;

  % Subtype TCC generated (at line 37, column 23) for  i + 1
      % expected type  subrange(1, 1 + n)
  sign_changes_TCC10: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)), lastnz: real):
      NOT a(i) /= 0 AND
       NOT (a(i) /= 0 AND lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz))
        AND NOT i = n + 1
       IMPLIES 1 <= i + 1 AND i + 1 <= 1 + n;

  % Termination TCC generated (at line 37, column 6) for
      % sign_changes(a, n, i + 1, num, lastnz)
  sign_changes_TCC11: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)), lastnz: real):
      NOT a(i) /= 0 AND
       NOT (a(i) /= 0 AND lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz))
        AND NOT i = n + 1
       IMPLIES n - (i + 1) + 1 < n - i + 1;

  % Subtype TCC generated (at line 37, column 6) for
      % sign_changes(a, n, i + 1, num, lastnz)
      % expected type  {m: nat |
                     %          num = number_sign_changes(a, i - 1)`num AND
                     %           lastnz =
                     %            number_sign_changes(a, i - 1)`lastnz
                     %           IMPLIES m = number_sign_changes(a, n)`num}
  sign_changes_TCC12: OBLIGATION
    FORALL (a: [nat -> real], n: nat, (i: subrange(1, n + 1)),
            v:
              [d1:
                 {z: [[nat -> real], n: nat, subrange(1, 1 + n), nat, real] |
                          1 - z`3 + z`2 < 1 + n - i} ->
                 {m: nat |
                          d1`4 = number_sign_changes(d1`1, d1`3 - 1)`num AND
                           d1`5 = number_sign_changes(d1`1, d1`3 - 1)`lastnz
                           IMPLIES m = number_sign_changes(d1`1, d1`2)`num}],
            num: nat, lastnz: real):
      NOT a(i) /= 0 AND
       NOT (a(i) /= 0 AND lastnz /= 0 AND sign_ext(a(i)) /= sign_ext(lastnz))
        AND NOT i = n + 1
       IMPLIES
       num = number_sign_changes(a, i - 1)`num AND
        lastnz = number_sign_changes(a, i - 1)`lastnz
        IMPLIES v(a, n, i + 1, num, lastnz) = number_sign_changes(a, n)`num;

  % Subtype TCC generated (at line 42, column 52) for  1
      % expected type  subrange(1, 1 + i)
  num_sign_changes_def_TCC1: OBLIGATION
    FORALL (i: nat): 1 <= 1 AND 1 <= 1 + i;

  % Subtype TCC generated (at line 81, column 32) for  j - 1
      % expected type  nat
  nsc_regular_swap_TCC1: OBLIGATION
    FORALL (a, b: [nat -> real], d, k: nat):
      k <= d IMPLIES
       (FORALL (j: nat):
               j > 0 AND a(j + 1) /= 0 AND sign_ext(a(j)) /= sign_ext(b(j))
           AND NOT sign_ext(a(j)) = sign_ext(b(j)) AND j <= k
           IMPLIES j - 1 >= 0);

  % Subtype TCC generated (at line 97, column 55) for  j - 1
      % expected type  nat
  nsc_edge_diff_TCC1: OBLIGATION
    FORALL (a, b: [nat -> real], d, k: nat, sig: real):
      ((sig = -1 OR sig = 1) AND
        k <= d AND
         (FORALL (j):
            j <= k IMPLIES (sign_ext(a(j)) = sign_ext(b(j)) OR b(j) = 0)))
       IMPLIES
       (FORALL (j1: nat):
          0 < j1 AND j1 <= k AND b(j1) = 0 IMPLIES j1 - 1 >= 0);

  % Subtype TCC generated (at line 101, column 67) for  j - 1
      % expected type  nat
  nsc_edge_diff_TCC2: OBLIGATION
    FORALL (a, b: [nat -> real], d, k: nat, sig: real):
           (sig = -1 OR sig = 1) AND k <= d
       AND FORALL (j):
             j <= k IMPLIES (sign_ext(a(j)) = sign_ext(b(j)) OR b(j) = 0)
       AND FORALL (j): 0 < j AND j <= k AND b(j) = 0 IMPLIES b(j - 1) /= 0
       AND sign_ext(a(k)) = sign_ext(b(k))
       AND FORALL (j: nat): j < k IMPLIES a(j) /= 0
       AND (b(0) = 0 IMPLIES sign_ext(a(0)) = sig * sign_ext(a(1)))
       IMPLIES
       (FORALL (j1: nat):
          0 < j1 AND j1 < k AND b(j1) = 0 IMPLIES j1 - 1 >= 0);

  % Subtype TCC generated (at line 127, column 38) for  j - 1
      % expected type  nat
  nsc_multiroot_full_TCC1: OBLIGATION
    FORALL (a, b: [nat -> real], d, k: nat, sig: real,
            sigfun: [nat -> real]):
      (FORALL (j):
         0 < j AND j <= k IMPLIES
          sign_ext(a(j)) = sigfun(j) * sign_ext(b(j)))
       AND
       k <= d AND
        (FORALL (j): sigfun(j) = -1 OR sigfun(j) = 1) AND
         (sig = -1 OR sig = 1)
       IMPLIES
       (FORALL (j1: nat):
               j1 < k AND 1 < j1 AND 0 < j1 AND j1 <= k AND sigfun(j1) /= sig
           IMPLIES j1 - 1 >= 0);


body:
  sturm: THEORY
  BEGIN

  IMPORTING reals@polynomials,reals@more_polynomial_props,reals@sign,
  	  polynomial_division, 
            structures@more_list_props,ints@gcd,
  	  number_sign_changes,
    	  structures@sort_array,gcd_coeff

    a,r : VAR [nat->real]
    p : VAR [nat->[nat->real]]
    n : VAR [nat->nat]
    d,m,i,j,k : VAR nat
    x,y,c,b : VAR real

    constructed_sturm_sequence?(p,n,m): bool =
      (FORALL (i:below(m)): p(i)(n(i))/=0) AND
      (FORALL (i,j:below(m)): i<j IMPLIES n(i)>n(j)) AND
      p(1) = poly_deriv(p(0)) AND n(1) = n(0)-1 AND
      n(m) = 0 AND p(m)(0) = 0 AND
      (FORALL (j:nat): j>1 AND j<=m IMPLIES LET pd = poly_divide(p(j-2),n(j-2))(p(j-1),n(j-1))(0) IN
      	   	    	    	 	   EXISTS (c:posreal): 
      	   	    	    	 	   polynomial(p(j),n(j)) = 
  					   polynomial(-c*pd`rem,pd`rdeg))
      AND m>=2

    constructed_sturm_seq_repeated_root: LEMMA 
      constructed_sturm_sequence?(p,n,m) IMPLIES
      FORALL (i:nat): i+1<=m AND
      polynomial(p(i),n(i))(x)=0 AND polynomial(p(i+1),n(i+1))(x)=0
      IMPLIES
      (FORALL (j:upto(m)): polynomial(p(j),n(j))(x) = 0)

    constructed_sturm_seq_repeated_root_mth: LEMMA FORALL (mm:posnat):
      constructed_sturm_sequence?(p,n,m) AND
      max_linear_div_power?(p(0),n(0),y)(mm) AND
      i<m AND mm>1 IMPLIES
      FORALL (u:upto(i)): 
      EXISTS (kp:posnat): kp>=mm-1 AND
      max_linear_div_power?(p(u),n(u),y)(kp)

    constructed_sturm_seq_repeated_root_struct: LEMMA
      constructed_sturm_sequence?(p,n,m) IMPLIES
      FORALL (i:nat): i+1<=m AND
      polynomial(p(i),n(i))(y)=0 AND polynomial(p(i+1),n(i+1))(y)=0
      IMPLIES
      EXISTS (mm:posnat): mm>1 AND max_linear_div_power?(p(0),n(0),y)(mm) AND
        (FORALL (j:nat): (1<=j AND j<m-1 AND
          (NOT max_linear_div_power?(p(j),n(j),y)(mm-1))) IMPLIES
  	(1<j AND max_linear_div_power?(p(j-1),n(j-1),y)(mm-1) AND
  	     	     	max_linear_div_power?(p(j+1),n(j+1),y)(mm-1))) AND
        max_linear_div_power?(p(m-1),n(m-1),y)(mm-1)

    sturm_sig(p,n,m)(x): nat = number_sign_changes(LAMBDA (i): polynomial(p(i),n(i))(x),m)`num

    % Part 1: Proving Sturm's Theorem when f has no multiple roots

    constructed_sturm_seq_first_signs_eq: LEMMA
      x<b AND b<y AND 
      polynomial(p(0),n(0))(b)=0 AND
      (FORALL (c:real): x<=c AND c<=y AND polynomial(p(0),n(0))(c)=0 IMPLIES
        (polynomial(p(1),n(1))(c)/=0 AND c = b)) AND
      constructed_sturm_sequence?(p,n,m)
      IMPLIES
      ((x/=b IMPLIES polynomial(p(0),n(0))(x)/=0) AND
       (y/=b IMPLIES polynomial(p(0),n(0))(y)/=0) AND
       (x/=b IMPLIES sign_ext(polynomial(p(0),n(0))(x)) = -sign_ext(polynomial(p(1),n(1))(b))) AND
       (y/=b IMPLIES sign_ext(polynomial(p(0),n(0))(y)) = sign_ext(polynomial(p(1),n(1))(b))))

    sturm_lem_no_roots: LEMMA
      x<y AND
      (FORALL (c:real,i:nat): i<=m AND x<=c AND c<=y IMPLIES polynomial(p(i),n(i))(c)/=0)
      IMPLIES
      sturm_sig(p,n,m)(x) = sturm_sig(p,n,m)(y)

    constructed_sturm_lem_one_simple_root: LEMMA
      x<y AND x<b AND b<y AND
      (FORALL (c:real,i:nat): i<=m-1 AND x<=c AND c<=y AND polynomial(p(i),n(i))(c)=0
       IMPLIES c = b) AND
      (polynomial(p(0),n(0))(b)=0 IMPLIES polynomial(p(1),n(1))(b)/=0) AND
      constructed_sturm_sequence?(p,n,m)
      IMPLIES
      LET nsc = LAMBDA (xyz:real,pj:nat): number_sign_changes(LAMBDA (i): polynomial(p(i),n(i))(xyz),pj) IN
        sign_ext(nsc(x,m-1)`lastnz) = sign_ext(nsc(y,m-1)`lastnz) AND
        nsc(x,m-1)`num = nsc(y,m-1)`num+(IF polynomial(p(0),n(0))(b)=0 THEN 1 ELSE 0 ENDIF)

    constructed_sturm_lem_one_multi_root: LEMMA
      x<y AND x<b AND b<y AND
      (FORALL (c:real,i:nat): i<=m-1 AND x<=c AND c<=y AND polynomial(p(i),n(i))(c)=0
       IMPLIES c = b) AND
      polynomial(p(0),n(0))(b)=0 AND polynomial(p(1),n(1))(b)=0 AND
      constructed_sturm_sequence?(p,n,m)
      IMPLIES
      LET nsc = LAMBDA (xyz:real,pj:nat): number_sign_changes(LAMBDA (i): polynomial(p(i),n(i))(xyz),pj) IN
        nsc(x,m-1)`num = nsc(y,m-1)`num+1

    constructed_sturm_lem_edge_root: LEMMA
      x<y AND (x=b OR y=b) AND
      (FORALL (c:real,i:nat): i<=m-1 AND x<=c AND c<=y AND polynomial(p(i),n(i))(c)=0
       IMPLIES c = b) AND
      (polynomial(p(0),n(0))(b)=0 IMPLIES polynomial(p(1),n(1))(b)/=0) AND 
      constructed_sturm_sequence?(p,n,m)
      IMPLIES
      LET nsc = LAMBDA (xyz:real,pj:nat): number_sign_changes(LAMBDA (i): polynomial(p(i),n(i))(xyz),pj) IN
        sign_ext(nsc(x,m-1)`lastnz) = sign_ext(nsc(y,m-1)`lastnz) AND
        nsc(x,m-1)`num = nsc(y,m-1)`num+(IF b=y AND polynomial(p(0),n(0))(b)=0 THEN 1 ELSE 0 ENDIF)

    constructed_sturm_roots_between_enum: LEMMA % THIS NEEDS TO BE FOR ALL P(i) NOT JUST P(0)
      x<y AND constructed_sturm_sequence?(p,n,m) IMPLIES
        EXISTS ((K:nat|K>=2),enum:[below(K)->real]):
          (FORALL (i,j:below(K)): i<j IMPLIES enum(i)<enum(j)) AND
    	enum(0)=x AND enum(K-1)=y AND
    	(FORALL (b:real,j:nat): j<=m-1 AND x<b AND b<=y AND polynomial(p(j),n(j))(b)=0 IMPLIES
    	  EXISTS (i:below(K)): b = enum(i))

    constructed_sturm_lem_no_roots_full: LEMMA
      x<y AND
      (FORALL (c:real,i:nat): i<=m-1 AND x<c AND c<=y IMPLIES polynomial(p(i),n(i))(c)/=0) AND
      constructed_sturm_sequence?(p,n,m) AND
      (polynomial(p(0),n(0))(x)=0 IMPLIES
        polynomial(p(1),n(1))(x)/=0)
      IMPLIES
      sturm_sig(p,n,m-1)(x) = sturm_sig(p,n,m-1)(y)

    sturm: LEMMA
      x<y AND
      constructed_sturm_sequence?(p,n,m) AND
      (polynomial(p(1),n(1))(x)/=0 OR polynomial(p(0),n(0))(x)/=0) AND
      (polynomial(p(1),n(1))(y)/=0 OR polynomial(p(0),n(0))(y)/=0)
      IMPLIES
        LET nsc = LAMBDA (xyz:real): number_sign_changes(LAMBDA (i): polynomial(p(i),n(i))(xyz),m-1),
        	  Nroots = nsc(x)`num-nsc(y)`num
        IN Nroots>=0 AND EXISTS (bij: [below(Nroots)->{xr:real|x<xr AND xr<=y AND polynomial(p(0),n(0))(xr)=0}]):
             bijective?(bij)

    sturm_unbounded_left: LEMMA
      constructed_sturm_sequence?(p,n,m) AND
      (polynomial(p(1),n(1))(y)/=0 OR polynomial(p(0),n(0))(y)/=0)
      IMPLIES
        LET nscy    = number_sign_changes(LAMBDA (i): polynomial(p(i),n(i))(y),m-1),
        	  nscninf = number_sign_changes(LAMBDA (i): (-1)^(n(i))*p(i)(n(i)),m-1),
        	  Nroots  = nscninf`num-nscy`num
        IN Nroots>=0 AND EXISTS (bij: [below(Nroots)->{xr:real|xr<=y AND polynomial(p(0),n(0))(xr)=0}]):
             bijective?(bij)

    sturm_unbounded_right: LEMMA
      constructed_sturm_sequence?(p,n,m) AND
      (polynomial(p(1),n(1))(x)/=0 OR polynomial(p(0),n(0))(x)/=0)
      IMPLIES
        LET nscx   = number_sign_changes(LAMBDA (i): polynomial(p(i),n(i))(x),m-1),
        	  nscinf = number_sign_changes(LAMBDA (i): p(i)(n(i)),m-1),
        	  Nroots = nscx`num-nscinf`num
        IN Nroots>=0 AND EXISTS (bij: [below(Nroots)->{xr:real|xr>x AND polynomial(p(0),n(0))(xr)=0}]):
             bijective?(bij)

    sturm_unbounded: LEMMA
      constructed_sturm_sequence?(p,n,m) IMPLIES
        LET nschigh = number_sign_changes(LAMBDA (i): p(i)(n(i)),m-1),
        	  nsclow  = number_sign_changes(LAMBDA (i): (-1)^(n(i))*p(i)(n(i)),m-1),
        	  Nroots  = nsclow`num-nschigh`num
        IN Nroots>=0 AND EXISTS (bij: [below(Nroots)->{xr:real|polynomial(p(0),n(0))(xr)=0}]):
             bijective?(bij)

  END sturm

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

  % Subtype TCC generated (at line 21, column 80) for  j - 1
      % expected type  nat
  constructed_sturm_sequence?_TCC1: OBLIGATION
    FORALL (p: [nat -> [nat -> real]], n: [nat -> nat], m: nat):
      (     p(m)(0) = 0 AND n(m) = 0 AND n(1) = n(0) - 1
        AND p(1) = poly_deriv(p(0))
        AND FORALL (i, j: below(m)): i < j IMPLIES n(i) > n(j)
        AND FORALL (i: below(m)): p(i)(n(i)) /= 0)
       IMPLIES (FORALL (j1: nat): j1 > 1 AND j1 <= m IMPLIES j1 - 1 >= 0);

  % Subtype TCC generated (at line 21, column 85) for  n(j - 1)
      % expected type  {m | p(j - 1)(m) /= 0}
  constructed_sturm_sequence?_TCC2: OBLIGATION
    FORALL (p: [nat -> [nat -> real]], n: [nat -> nat], m: nat):
      (     p(m)(0) = 0 AND n(m) = 0 AND n(1) = n(0) - 1
        AND p(1) = poly_deriv(p(0))
        AND FORALL (i, j: below(m)): i < j IMPLIES n(i) > n(j)
        AND FORALL (i: below(m)): p(i)(n(i)) /= 0)
       IMPLIES
       (FORALL (j1: nat):
          j1 > 1 AND j1 <= m IMPLIES p(j1 - 1)(n(j1 - 1)) /= 0);

  % Subtype TCC generated (at line 21, column 65) for  j - 2
      % expected type  nat
  constructed_sturm_sequence?_TCC3: OBLIGATION
    FORALL (p: [nat -> [nat -> real]], n: [nat -> nat], m: nat):
      (     p(m)(0) = 0 AND n(m) = 0 AND n(1) = n(0) - 1
        AND p(1) = poly_deriv(p(0))
        AND FORALL (i, j: below(m)): i < j IMPLIES n(i) > n(j)
        AND FORALL (i: below(m)): p(i)(n(i)) /= 0)
       IMPLIES (FORALL (j1: nat): j1 > 1 AND j1 <= m IMPLIES j1 - 2 >= 0);

  % Subtype TCC generated (at line 49, column 48) for  mm - 1
      % expected type  posnat
  constructed_sturm_seq_repeated_root_struct_TCC1: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], y: real):
      constructed_sturm_sequence?(p, n, m) IMPLIES
       (FORALL (i: nat):
          i + 1 <= m AND
           polynomial(p(i), n(i))(y) = 0 AND
            polynomial(p(i + 1), n(i + 1))(y) = 0
           IMPLIES
           (FORALL (mm: posnat):
              max_linear_div_power?(p(0), n(0), y)(mm) AND mm > 1 IMPLIES
               (FORALL (j: nat):
                  j < m - 1 AND 1 <= j IMPLIES mm - 1 >= 0 AND mm - 1 > 0)));

  % Subtype TCC generated (at line 50, column 34) for  j - 1
      % expected type  nat
  constructed_sturm_seq_repeated_root_struct_TCC2: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], y: real):
      constructed_sturm_sequence?(p, n, m) IMPLIES
       (FORALL (i: nat):
          i + 1 <= m AND
           polynomial(p(i), n(i))(y) = 0 AND
            polynomial(p(i + 1), n(i + 1))(y) = 0
           IMPLIES
           (FORALL (mm: posnat):
              max_linear_div_power?(p(0), n(0), y)(mm) AND mm > 1 IMPLIES
               (FORALL (j: nat):
                  1 < j AND
                   1 <= j AND
                    j < m - 1 AND
                     (NOT max_linear_div_power?(p(j), n(j), y)(mm - 1))
                   IMPLIES j - 1 >= 0)));

  % Subtype TCC generated (at line 52, column 45) for  mm - 1
      % expected type  posnat
  constructed_sturm_seq_repeated_root_struct_TCC3: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], y: real):
      constructed_sturm_sequence?(p, n, m) IMPLIES
       (FORALL (i: nat):
          i + 1 <= m AND
           polynomial(p(i), n(i))(y) = 0 AND
            polynomial(p(i + 1), n(i + 1))(y) = 0
           IMPLIES
           (FORALL (mm: posnat):
              (FORALL (j: nat):
                 (1 <= j AND
                   j < m - 1 AND
                    (NOT max_linear_div_power?(p(j), n(j), y)(mm - 1)))
                  IMPLIES
                  (1 < j AND
                    max_linear_div_power?(p(j - 1), n(j - 1), y)(mm - 1) AND
                     max_linear_div_power?(p(j + 1), n(j + 1), y)(mm - 1)))
               AND max_linear_div_power?(p(0), n(0), y)(mm) AND mm > 1
               IMPLIES mm - 1 >= 0 AND mm - 1 > 0));

  % Subtype TCC generated (at line 52, column 30) for  m - 1
      % expected type  nat
  constructed_sturm_seq_repeated_root_struct_TCC4: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], y: real):
      constructed_sturm_sequence?(p, n, m) IMPLIES
       (FORALL (i: nat):
          i + 1 <= m AND
           polynomial(p(i), n(i))(y) = 0 AND
            polynomial(p(i + 1), n(i + 1))(y) = 0
           IMPLIES
           (FORALL (mm: posnat):
              (FORALL (j: nat):
                 (1 <= j AND
                   j < m - 1 AND
                    (NOT max_linear_div_power?(p(j), n(j), y)(mm - 1)))
                  IMPLIES
                  (1 < j AND
                    max_linear_div_power?(p(j - 1), n(j - 1), y)(mm - 1) AND
                     max_linear_div_power?(p(j + 1), n(j + 1), y)(mm - 1)))
               AND max_linear_div_power?(p(0), n(0), y)(mm) AND mm > 1
               IMPLIES m - 1 >= 0));

  % Subtype TCC generated (at line 84, column 21) for  m - 1
      % expected type  nat
  constructed_sturm_lem_one_simple_root_TCC1: OBLIGATION
    FORALL (b: real, m: nat, n: [nat -> nat], p: [nat -> [nat -> real]],
            x, y: real):
           constructed_sturm_sequence?(p, n, m)
       AND (polynomial(p(0), n(0))(b) = 0 IMPLIES
             polynomial(p(1), n(1))(b) /= 0)
       AND FORALL (c: real, i: nat):
             i <= m - 1 AND
              x <= c AND c <= y AND polynomial(p(i), n(i))(c) = 0
              IMPLIES c = b
       AND b < y AND x < b AND x < y
       IMPLIES
       (FORALL (nsc: [[real, nat] -> NSC]):
          (nsc =
            (LAMBDA (xyz: real, pj: nat):
               number_sign_changes(LAMBDA (i): polynomial(p(i), n(i))(xyz),
                                   pj)))
           IMPLIES m - 1 >= 0);

  % Subtype TCC generated (at line 95, column 12) for  m - 1
      % expected type  nat
  constructed_sturm_lem_one_multi_root_TCC1: OBLIGATION
    FORALL (b: real, m: nat, n: [nat -> nat], p: [nat -> [nat -> real]],
            x, y: real):
           constructed_sturm_sequence?(p, n, m)
       AND polynomial(p(1), n(1))(b) = 0 AND polynomial(p(0), n(0))(b) = 0
       AND FORALL (c: real, i: nat):
             i <= m - 1 AND
              x <= c AND c <= y AND polynomial(p(i), n(i))(c) = 0
              IMPLIES c = b
       AND b < y AND x < b AND x < y
       IMPLIES
       (FORALL (nsc: [[real, nat] -> NSC]):
          (nsc =
            (LAMBDA (xyz: real, pj: nat):
               number_sign_changes(LAMBDA (i): polynomial(p(i), n(i))(xyz),
                                   pj)))
           IMPLIES m - 1 >= 0);

  % Subtype TCC generated (at line 105, column 21) for  m - 1
      % expected type  nat
  constructed_sturm_lem_edge_root_TCC1: OBLIGATION
    FORALL (b: real, m: nat, n: [nat -> nat], p: [nat -> [nat -> real]],
            x, y: real):
           constructed_sturm_sequence?(p, n, m)
       AND (polynomial(p(0), n(0))(b) = 0 IMPLIES
             polynomial(p(1), n(1))(b) /= 0)
       AND FORALL (c: real, i: nat):
             i <= m - 1 AND
              x <= c AND c <= y AND polynomial(p(i), n(i))(c) = 0
              IMPLIES c = b
       AND (x = b OR y = b) AND x < y
       IMPLIES
       (FORALL (nsc: [[real, nat] -> NSC]):
          (nsc =
            (LAMBDA (xyz: real, pj: nat):
               number_sign_changes(LAMBDA (i): polynomial(p(i), n(i))(xyz),
                                   pj)))
           IMPLIES m - 1 >= 0);

  % Subtype TCC generated (at line 112, column 8) for  0
      % expected type  below(K)
  constructed_sturm_roots_between_enum_TCC1: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], x, y: real):
      constructed_sturm_sequence?(p, n, m) AND x < y IMPLIES
       (FORALL ((K: nat | K >= 2), enum: [below(K) -> real]):
          (FORALL (i, j: below(K)): i < j IMPLIES enum(i) < enum(j)) IMPLIES
           0 < K);

  % Subtype TCC generated (at line 112, column 22) for  K - 1
      % expected type  below(K)
  constructed_sturm_roots_between_enum_TCC2: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], x, y: real):
      constructed_sturm_sequence?(p, n, m) AND x < y IMPLIES
       (FORALL ((K: nat | K >= 2), enum: [below(K) -> real]):
          enum(0) = x AND
           (FORALL (i, j: below(K)): i < j IMPLIES enum(i) < enum(j))
           IMPLIES K - 1 >= 0 AND K - 1 < K);

  % Subtype TCC generated (at line 123, column 18) for  m - 1
      % expected type  nat
  constructed_sturm_lem_no_roots_full_TCC1: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], x, y: real):
      (polynomial(p(0), n(0))(x) = 0 IMPLIES polynomial(p(1), n(1))(x) /= 0)
       AND
       constructed_sturm_sequence?(p, n, m) AND
        (FORALL (c: real, i: nat):
           i <= m - 1 AND x < c AND c <= y IMPLIES
            polynomial(p(i), n(i))(c) /= 0)
         AND x < y
       IMPLIES m - 1 >= 0;

  % Subtype TCC generated (at line 131, column 94) for  m - 1
      % expected type  nat
  sturm_TCC1: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], x, y: real):
      (polynomial(p(1), n(1))(y) /= 0 OR polynomial(p(0), n(0))(y) /= 0) AND
       (polynomial(p(1), n(1))(x) /= 0 OR polynomial(p(0), n(0))(x) /= 0) AND
        constructed_sturm_sequence?(p, n, m) AND x < y
       IMPLIES m - 1 >= 0;

  % Subtype TCC generated (at line 140, column 77) for  m - 1
      % expected type  nat
  sturm_unbounded_left_TCC1: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]], y: real):
      (polynomial(p(1), n(1))(y) /= 0 OR polynomial(p(0), n(0))(y) /= 0) AND
       constructed_sturm_sequence?(p, n, m)
       IMPLIES m - 1 >= 0;

  % Subtype TCC generated (at line 158, column 63) for  m - 1
      % expected type  nat
  sturm_unbounded_TCC1: OBLIGATION
    FORALL (m: nat, n: [nat -> nat], p: [nat -> [nat -> real]]):
      constructed_sturm_sequence?(p, n, m) IMPLIES m - 1 >= 0;


body:
  compute_sturm: THEORY
  BEGIN

    IMPORTING sturm,
  	    remainder_sequence,
  	    clear_denominators,
              reals@RealInt,
  	    reals@more_polynomial_props,
  	    reals@real_orders,
  	    reals@real_order_ep

    a : VAR [nat->int]
    n : VAR posnat
    I : VAR RealInt	
    x,y,z: VAR real

    %%% Support Lemmas %%%

    finite_bij_real_remove_one: LEMMA
      FORALL (m:nat,A:set[real],bij:[below(m)->(A)]):
        bijective?(bij) AND A(x) IMPLIES
         m-1>=0 AND EXISTS (bijec:[below(m-1)->{r:(A)|r/=x}]):
           bijective?(bijec)

    finite_bij_real_remove_two: LEMMA
      FORALL (m:nat,A:set[real],bij:[below(m)->(A)]):
        bijective?(bij) AND A(x) AND A(y) AND x/=y IMPLIES
         m-2>=0 AND EXISTS (bijec:[below(m-2)->{r:(A)|r/=x AND r/=y}]):
           bijective?(bijec)

    computed_sturm_spec: LEMMA a(n)/=0 AND (FORALL (i:nat): i>n IMPLIES a(i)=0) IMPLIES
      LET sl = sturm_chain(a,n),
      	P: [nat->[nat->int]] = (LAMBDA (j:nat): IF j<length(sl) 
  	   		          THEN list2array[int](0)(nth(sl,length(sl)-1-j))
  	   		         ELSE (LAMBDA (i:nat): 0) ENDIF),
          N: [nat->nat] = (LAMBDA (j:nat): IF j<length(sl) 
  	                   THEN max(length(nth(sl,length(sl)-1-j))-1,0) ELSE 0 ENDIF),
  	M: nat = length(sl)-1
      IN  constructed_sturm_sequence?(P,N,M) AND P(0)=a AND N(0)=n


    Eq_computed_remainder?(a,(n|a(n)/=0))(sl:list[list[int]]): bool =
      sl = sturm_chain(LAMBDA (i:nat): IF i<=n THEN a(i) ELSE 0 ENDIF,n)

    % Standard but possibly unbounded interval %

    lower_bound,upper_bound: VAR bool

    % Formalizatin brings in complications with evaluating at infinity

    roots_closed_int(a,(n|a(n)/=0),low:real,(high:real|low<high),lower_bound,upper_bound:bool,
  		   sl:(Eq_computed_remainder?(a,n))): 
      int =
      LET newa       = (LAMBDA (i:nat): IF i<=n THEN a(i) ELSE 0 ENDIF),
      	P: [nat->[nat->int]] = (LAMBDA (j:nat): IF j<length(sl) 
  	                          THEN list2array[int](0)(nth(sl,length(sl)-1-j))
  	   		         ELSE (LAMBDA (i:nat): 0) ENDIF),
          N: [nat->nat] = (LAMBDA (j:nat): IF j<length(sl) 
  	                   THEN max(length(nth(sl,length(sl)-1-j))-1,0) ELSE 0 ENDIF),
  	M: nat     = length(sl)-1,
  	nscnorm    = LAMBDA (xyz:real): number_sign_changes(
  	                  LAMBDA (i:nat): polynomial(P(i),N(i))(xyz),M-1),
          nschighlow = LAMBDA (b:bool): IF b THEN number_sign_changes(LAMBDA (i:nat): P(i)(N(i)),M-1)
  		     	    	      ELSE number_sign_changes(LAMBDA (i:nat): (-1)^N(i)*P(i)(N(i)),M-1) ENDIF,
  	newlow     = IF ((NOT lower_bound) OR polynomial(P(0),N(0))(low)/=0 
  	                                   OR polynomial(P(1),N(1))(low)/=0) THEN low
  		     ELSE low-poly_rootless_width(a,n,low,TRUE)/2 ENDIF,
  	newhigh    = IF ((NOT upper_bound) OR polynomial(P(0),N(0))(high)/=0 
  		     	      		   OR polynomial(P(1),N(1))(high)/=0) THEN high
  		     ELSE high+poly_rootless_width(a,n,high,TRUE)/2 ENDIF,
        	Nroots     = IF lower_bound and upper_bound THEN nscnorm(newlow)`num-nscnorm(newhigh)`num
  		     ELSIF upper_bound THEN nschighlow(FALSE)`num-nscnorm(newhigh)`num
  		     ELSIF lower_bound THEN nscnorm(newlow)`num-nschighlow(TRUE)`num
  		     ELSE nschighlow(FALSE)`num-nschighlow(TRUE)`num ENDIF,
          adjlow     = IF lower_bound AND polynomial(P(0),N(0))(low)=0 AND polynomial(P(1),N(1))(low)/=0
  		     THEN 1 ELSE 0 ENDIF
      IN Nroots + adjlow


    roots_closed_int_def_truetrue: LEMMA FORALL (sl:(Eq_computed_remainder?(a,n))): a(n)/=0 AND x<y IMPLIES
  	LET rootnum = roots_closed_int(a,n,x,y,true,true,sl),
  	    Aset = {z:real|x<=z AND z<=y AND polynomial(a,n)(z)=0}
          IN rootnum>=0 AND EXISTS (bij: [below(rootnum)->(Aset)]): bijective?(bij)

    roots_closed_int_def_falsetrue: LEMMA FORALL (sl:(Eq_computed_remainder?(a,n))): a(n)/=0 AND x<y IMPLIES
  	LET rootnum = roots_closed_int(a,n,x,y,false,true,sl),
  	    Aset = {z:real|z<=y AND polynomial(a,n)(z)=0}
          IN rootnum>=0 AND EXISTS (bij: [below(rootnum)->(Aset)]): bijective?(bij)

    roots_closed_int_def_truefalse: LEMMA FORALL (sl:(Eq_computed_remainder?(a,n))): a(n)/=0 AND x<y IMPLIES
  	LET rootnum = roots_closed_int(a,n,x,y,true,false,sl),
  	    Aset = {z:real|x<=z AND polynomial(a,n)(z)=0}
          IN rootnum>=0 AND EXISTS (bij: [below(rootnum)->(Aset)]): bijective?(bij)

    roots_closed_int_def_falsefalse: LEMMA FORALL (sl:(Eq_computed_remainder?(a,n))): a(n)/=0 AND x<y IMPLIES
  	LET rootnum = roots_closed_int(a,n,x,y,false,false,sl),
  	    Aset = {z:real| polynomial(a,n)(z)=0}
          IN rootnum>=0 AND EXISTS (bij: [below(rootnum)->(Aset)]): bijective?(bij)


    roots_closed_int_def: LEMMA FORALL (sl:(Eq_computed_remainder?(a,n))): a(n)/=0 AND x<y IMPLIES
  	LET rootnum = roots_closed_int(a,n,x,y,lower_bound,upper_bound,sl),
  	    Aset = {z:real|(lower_bound IMPLIES x<=z) 
  		       	    AND (upper_bound IMPLIES z<=y)
                        	    AND polynomial(a,n)(z)=0}
          IN rootnum>=0 AND EXISTS (bij: [below(rootnum)->(Aset)]): bijective?(bij)

    number_roots_interval(a,(n|a(n)/=0),I,(sl:(Eq_computed_remainder?(a,n)))): nat =
      IF I`lb >= I`ub THEN 0
      ELSE
        LET rootstotal = roots_closed_int(a,n,I`lb,I`ub,I`bounded_below,I`bounded_above,sl),
            adjlow     = IF I`bounded_below AND (NOT I`closed_below) AND polynomial(a,n)(I`lb)=0
  	    	       THEN -1 ELSE 0 ENDIF,
            adjhigh    = IF I`bounded_above AND (NOT I`closed_above) AND polynomial(a,n)(I`ub)=0
  	  	       THEN -1 ELSE 0 ENDIF
        IN rootstotal + adjlow + adjhigh
      ENDIF

    number_roots_interval_def: LEMMA FORALL (sl:(Eq_computed_remainder?(a,n))): a(n)/=0 AND I`lb<I`ub
  	   IMPLIES
    	LET rootnum = number_roots_interval(a,n,I,sl),
  	    Aset = {z:real|contains?(I)(z) AND polynomial(a,n)(z)=0}
          IN rootnum>=0 AND EXISTS (bij: [below(rootnum)->(Aset)]): bijective?(bij)

    meas_fun_alw_nonneg(a,(n|a(n)/=0),x,y:real,sl:(Eq_computed_remainder?(a,n))):real = y-x

    always_nonnegative_int(a,(n|a(n)/=0),x,y:real,(sl:(Eq_computed_remainder?(a,n)))): RECURSIVE {bb:bool|
      bb IFF FORALL (z:real): x<=z AND z<=y IMPLIES polynomial(a,n)(z)>=0} =
      IF x>y THEN TRUE
      ELSIF x=y THEN polynomial(a,n)(x)>=0
      ELSIF roots_closed_int(a,n,x,y,TRUE,TRUE,sl) <= 1 THEN
        polynomial(a,n)(x)>=0 AND polynomial(a,n)(y)>=0
      ELSE
        always_nonnegative_int(a,n,x,(x+y)/2,sl) AND
        always_nonnegative_int(a,n,(x+y)/2,y,sl)
      ENDIF
    MEASURE meas_fun_alw_nonneg BY real_ord_ep(min_poly_root_dist(a,n))

    always_nonnegative(a,(n|a(n)/=0),(I|I`lb<I`ub)): bool =
      LET newa = (LAMBDA (i:nat): IF i<=n THEN a(i) ELSE 0 ENDIF),
          sl = sturm_chain(newa,n)
      IN
        IF I`bounded_below AND I`bounded_above 
          THEN always_nonnegative_int(a,n,I`lb,I`ub,sl)
        ELSE
          LET M = Knuth_poly_root_strict_bound(a,n) IN
            IF I`bounded_above THEN
  	    always_nonnegative_int(a,n,min(-M,I`ub-1),I`ub,sl)
  	  ELSIF I`bounded_below THEN
  	    always_nonnegative_int(a,n,I`lb,max(M,I`lb+1),sl)
  	  ELSE always_nonnegative_int(a,n,-M,M,sl)
  	  ENDIF
        ENDIF

    always_nonnegative_def: LEMMA a(n)/=0 AND I`lb<I`ub IMPLIES
      (always_nonnegative(a,n,I) IFF
      (FORALL (x:real): contains?(I)(x) IMPLIES polynomial(a,n)(x)>=0))

    R:VAR [[real,real]->bool]
    
    SturmRel?(R): bool = (R = (<)) OR (R = (<=)) OR (R = (>)) OR (R = (>=))
    	       	       OR (R = (/=[real]))

    realord,ro: VAR (SturmRel?)

    strict?(realord): bool = (realord = (<)) OR (realord = (>)) OR (realord = (/=[real]))

    swap(realord): (SturmRel?) =
  	  IF realord = (<) THEN >
  	  ELSIF realord = (<=) THEN >=
  	  ELSIF realord = (>) THEN <
  	  ELSIF realord = (>=) THEN <=
  	  ELSE (/=[real])
  	  ENDIF

    swap_lt : LEMMA
      swap(<) = (>)

    swap_gt : LEMMA
      swap(>) = (<)

    swap_le : LEMMA
      swap(<=) = (>=)

    swap_ge : LEMMA
      swap(>=) = (<=)

    swap_ne : LEMMA
      swap(/=[real]) = (/=[real])

    real_order_scal_pos: LEMMA
      FORALL (p:posreal,x,y:real): realord(p*x,p*y)=realord(x,y)

    compute_poly_sat(a,(n|a(n)/=0),(I|I`lb<I`ub),realord): bool =
      IF realord = (>=) THEN always_nonnegative(a,n,I)
      ELSIF realord = (<=) THEN always_nonnegative(-a,n,I)
      ELSE
        LET newa = (LAMBDA (i:nat): IF i<=n THEN a(i) ELSE 0 ENDIF),
            sl = sturm_chain(newa,n)
        IN number_roots_interval(a,n,I,sl)=0 AND realord(polynomial(a,n)((I`lb+I`ub)/2),0)
      ENDIF

    compute_poly_sat_def: LEMMA a(n)/=0 AND I`lb<I`ub IMPLIES
      (compute_poly_sat(a,n,I,realord) IFF
       (FORALL (x:real): contains?(I)(x) IMPLIES realord(polynomial(a,n)(x),0)))

    aq: VAR [nat->rat]

    compute_poly_sat_rational(aq,(n|aq(n)/=0),(I|I`lb<I`ub),realord): bool =
      compute_poly_sat(rat_poly_to_int(aq,n),n,I,realord)

    compute_poly_sat_rational_def: LEMMA aq(n)/=0 AND I`lb<I`ub IMPLIES
      (compute_poly_sat_rational(aq,n,I,realord) IFF
      (FORALL (x:real): contains?(I)(x) IMPLIES realord(polynomial(aq,n)(x),0)))

    % Next function assumes x<y

    compute_poly_mono_basic(aq,(n|aq(n)/=0),(I|I`lb<I`ub),realord): bool =
      IF n = 1 THEN realord(sign(aq(1))*I`lb,sign(aq(1))*I`ub)
      ELSIF (realord = (/=[real])) THEN
        compute_poly_sat_rational(poly_deriv(aq),n-1,I,>=) OR
        compute_poly_sat_rational(poly_deriv(aq),n-1,I,<=)
      ELSIF realord(I`lb,I`ub) THEN
        compute_poly_sat_rational(poly_deriv(aq),n-1,I,>=)
      ELSE
        compute_poly_sat_rational(poly_deriv(aq),n-1,I,<=)
      ENDIF

    compute_poly_mono_basic_def: LEMMA aq(n)/=0 AND I`lb<I`ub IMPLIES
      ((FORALL (x,y:real): x<y AND contains?(I)(x) AND contains?(I)(y) IMPLIES
        realord(polynomial(aq,n)(x),polynomial(aq,n)(y))) IFF
      compute_poly_mono_basic(aq,n,I,realord))

    mono(aq,(n|aq(n)/=0),(I|I`lb<I`ub),ro,realord): bool =
      IF ro(1,1) AND NOT realord(1,1) THEN FALSE
      ELSIF (ro=(<)) OR (ro=(<=)) THEN compute_poly_mono_basic(aq,n,I,realord)
      ELSIF (ro=(>)) OR (ro=(>=)) THEN compute_poly_mono_basic(aq,n,I,swap(realord))
      ELSIF NOT (realord=(/=[real])) THEN FALSE
      ELSE compute_poly_mono_basic(aq,n,I,realord)
           OR compute_poly_mono_basic(aq,n,I,swap(realord))
      ENDIF 

    poly_non_constant_real_int: LEMMA aq(n)/=0 AND I`lb<I`ub IMPLIES
      EXISTS (x,y:real): x<y AND contains?(I)(x) AND contains?(I)(y) AND
        polynomial(aq,n)(x)/=polynomial(aq,n)(y)

    mono_def: LEMMA aq(n)/=0 AND I`lb<I`ub IMPLIES
      ((FORALL (x,y:real): ro(x,y) AND contains?(I)(x) AND contains?(I)(y) IMPLIES
        realord(polynomial(aq,n)(x),polynomial(aq,n)(y))) IFF
      mono(aq,n,I,ro,realord))

  END compute_sturm

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

  % Subtype TCC generated (at line 57, column 23) for  poly_deriv(a)
      % expected type  [nat -> int]
  computed_sturm_spec_TCC1: OBLIGATION
    FORALL (a: [nat -> int], n: posnat):
      (FORALL (i: nat): i > n IMPLIES a(i) = 0) AND a(n) /= 0 IMPLIES
       (FORALL (x1: nat):
          rational_pred(poly_deriv(a)(x1)) AND
           integer_pred(poly_deriv(a)(x1)));

  % Subtype TCC generated (at line 57, column 37) for  n - 1
      % expected type  {m | poly_deriv(a)(m) /= 0}
  computed_sturm_spec_TCC2: OBLIGATION
    FORALL (a: [nat -> int], n: posnat):
      (FORALL (i: nat): i > n IMPLIES a(i) = 0) AND a(n) /= 0 IMPLIES
       n - 1 >= 0 AND poly_deriv(a)(n - 1) /= 0;

  % Subtype TCC generated (at line 34, column 47) for  length(sl) - 1 - j
      % expected type  below[length[list[int]](sl)]
  computed_sturm_spec_TCC3: OBLIGATION
    FORALL (a: [nat -> int], n: posnat):
      (FORALL (i: nat): i > n IMPLIES a(i) = 0) AND a(n) /= 0 IMPLIES
       (FORALL (sl: list[list[int]]):
          sl = remainder_seq(a, n, poly_deriv(a), n - 1) IMPLIES
           (FORALL (j: nat):
              j < length(sl) IMPLIES
               length[list[int]](sl) - 1 - j >= 0 AND
                length[list[int]](sl) - 1 - j < length[list[int]](sl)));

  % Subtype TCC generated (at line 37, column 25) for
      % max(length(nth(sl, length(sl) - 1 - j)) - 1, 0)
      % expected type  nat
  computed_sturm_spec_TCC4: OBLIGATION
    FORALL (a: [nat -> int], n: posnat):
      (FORALL (i: nat): i > n IMPLIES a(i) = 0) AND a(n) /= 0 IMPLIES
       (FORALL (sl: list[list[int]]):
          sl = remainder_seq(a, n, poly_deriv(a), n - 1) IMPLIES
           (FORALL (P: [nat -> [nat -> int]]):
              (P =
                (LAMBDA (j: nat):
                   IF j < length(sl)
                     THEN list2array[int](0)(nth(sl, length(sl) - 1 - j))
                   ELSE (LAMBDA (i: nat): 0)
                   ENDIF))
               IMPLIES
               (FORALL (j1: nat):
                  j1 < length(sl) IMPLIES
                   max(length[int]
                           (nth[list[int]]
                                (sl, length[list[int]](sl) - 1 - j1))
                        - 1,
                       0)
                    >= 0)));

  % Subtype TCC generated (at line 38, column 10) for  length(sl) - 1
      % expected type  nat
  computed_sturm_spec_TCC5: OBLIGATION
    FORALL (a: [nat -> int], n: posnat):
      (FORALL (i: nat): i > n IMPLIES a(i) = 0) AND a(n) /= 0 IMPLIES
       (FORALL (sl: list[list[int]]):
          sl = remainder_seq(a, n, poly_deriv(a), n - 1) IMPLIES
           (FORALL (P: [nat -> [nat -> int]]):
              (P =
                (LAMBDA (j: nat):
                   IF j < length(sl)
                     THEN list2array[int](0)(nth(sl, length(sl) - 1 - j))
                   ELSE (LAMBDA (i: nat): 0)
                   ENDIF))
               IMPLIES
               (FORALL (N: [nat -> nat]):
                  (N =
                    (LAMBDA (j: nat):
                       IF j < length(sl)
                         THEN max(length(nth(sl, length(sl) - 1 - j)) - 1, 0)
                       ELSE 0
                       ENDIF))
                   IMPLIES length[list[int]](sl) - 1 >= 0)));

  % Subtype TCC generated (at line 43, column 68) for  n
      % expected type  {n_1 | IF n_1 <= n THEN a(n_1) ELSE 0 ENDIF /= 0}
  Eq_computed_remainder?_TCC1: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0)):
      IF n <= n THEN a(n) ELSE 0 ENDIF /= 0;

  % Subtype TCC generated (at line 57, column 23) for
      % poly_deriv(LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)
      % expected type  [nat -> int]
  Eq_computed_remainder?_TCC2: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0)):
      FORALL (x1: nat):
        rational_pred(poly_deriv(LAMBDA (i: nat):
                                   IF i <= n THEN a(i) ELSE 0 ENDIF)
                                (x1))
         AND
         integer_pred(poly_deriv(LAMBDA (i: nat):
                                   IF i <= n THEN a(i) ELSE 0 ENDIF)
                                (x1));

  % Subtype TCC generated (at line 57, column 37) for  n - 1
      % expected type  {m |
                     %          poly_deriv(LAMBDA
                     %                     (i: nat):
                     %                     IF i <= n THEN a(i) ELSE 0 ENDIF)
                     %                    (m)
                     %           /= 0}
  Eq_computed_remainder?_TCC3: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0)):
      n - 1 >= 0 AND
       poly_deriv(LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)(n - 1)
        /= 0;

  % Subtype TCC generated (at line 56, column 58) for  length(sl) - 1 - j
      % expected type  below[length[list[int]](sl)]
  roots_closed_int_TCC1: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), low: real,
            (high: real | low < high), sl: (Eq_computed_remainder?(a, n)),
            newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (j: nat):
          j < length(sl) IMPLIES
           length[list[int]](sl) - 1 - j >= 0 AND
            length[list[int]](sl) - 1 - j < length[list[int]](sl));

  % Subtype TCC generated (at line 59, column 25) for
      % max(length(nth(sl, length(sl) - 1 - j)) - 1, 0)
      % expected type  nat
  roots_closed_int_TCC2: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), low: real,
            (high: real | low < high), sl: (Eq_computed_remainder?(a, n)),
            newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (P: [nat -> [nat -> int]]):
          (P =
            (LAMBDA (j: nat):
               IF j < length(sl)
                 THEN list2array[int](0)(nth(sl, length(sl) - 1 - j))
               ELSE (LAMBDA (i: nat): 0)
               ENDIF))
           IMPLIES
           (FORALL (j1: nat):
              j1 < length(sl) IMPLIES
               max(length[int]
                       (nth[list[int]](sl, length[list[int]](sl) - 1 - j1))
                    - 1,
                   0)
                >= 0));

  % Subtype TCC generated (at line 60, column 14) for  length(sl) - 1
      % expected type  nat
  roots_closed_int_TCC3: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), low: real,
            (high: real | low < high), sl: (Eq_computed_remainder?(a, n)),
            newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (P: [nat -> [nat -> int]]):
          (P =
            (LAMBDA (j: nat):
               IF j < length(sl)
                 THEN list2array[int](0)(nth(sl, length(sl) - 1 - j))
               ELSE (LAMBDA (i: nat): 0)
               ENDIF))
           IMPLIES
           (FORALL (N: [nat -> nat]):
              (N =
                (LAMBDA (j: nat):
                   IF j < length(sl)
                     THEN max(length(nth(sl, length(sl) - 1 - j)) - 1, 0)
                   ELSE 0
                   ENDIF))
               IMPLIES length[list[int]](sl) - 1 >= 0));

  % Subtype TCC generated (at line 62, column 62) for  M - 1
      % expected type  nat
  roots_closed_int_TCC4: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), low: real,
            (high: real | low < high), sl: (Eq_computed_remainder?(a, n)),
            newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (P: [nat -> [nat -> int]]):
          (P =
            (LAMBDA (j: nat):
               IF j < length(sl)
                 THEN list2array[int](0)(nth(sl, length(sl) - 1 - j))
               ELSE (LAMBDA (i: nat): 0)
               ENDIF))
           IMPLIES
           (FORALL (N: [nat -> nat]):
              (N =
                (LAMBDA (j: nat):
                   IF j < length(sl)
                     THEN max(length(nth(sl, length(sl) - 1 - j)) - 1, 0)
                   ELSE 0
                   ENDIF))
               IMPLIES
               (FORALL (M: nat): M = length(sl) - 1 IMPLIES M - 1 >= 0)));

  % Subtype TCC generated (at line 67, column 44) for  TRUE
      % expected type  {nzb: bool | nzb IFF (EXISTS (i: upto(n)): a(i) /= 0)}
  roots_closed_int_TCC5: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), low: real,
            (high: real | low < high), lower_bound: bool,
            sl: (Eq_computed_remainder?(a, n)), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (P: [nat -> [nat -> int]]):
          (P =
            (LAMBDA (j: nat):
               IF j < length(sl)
                 THEN list2array[int](0)(nth(sl, length(sl) - 1 - j))
               ELSE (LAMBDA (i: nat): 0)
               ENDIF))
           IMPLIES
           (FORALL (N: [nat -> nat]):
              (N =
                (LAMBDA (j: nat):
                   IF j < length(sl)
                     THEN max(length(nth(sl, length(sl) - 1 - j)) - 1, 0)
                   ELSE 0
                   ENDIF))
               IMPLIES
               (FORALL (M: nat):
                  M = length(sl) - 1 IMPLIES
                   (FORALL (nscnorm: [real -> NSC]):
                      (nscnorm =
                        (LAMBDA (xyz: real):
                           number_sign_changes(LAMBDA
                                               (i: nat):
                                               polynomial(P(i), N(i))(xyz),
                                               M - 1)))
                       IMPLIES
                       (FORALL (nschighlow: [bool -> NSC]):
                          (lower_bound AND
                            NOT polynomial(P(0), N(0))(low) /= 0 AND
                             NOT polynomial(P(1), N(1))(low) /= 0 AND
                              nschighlow =
                               (LAMBDA (b: bool):
                                  IF b
                                    THEN number_sign_changes
                                         (LAMBDA (i: nat): P(i)(N(i)), M - 1)
                                  ELSE number_sign_changes
                                       (LAMBDA
                                        (i: nat):
                                        (-1) ^ N(i) * P(i)(N(i)),
                                        M - 1)
                                  ENDIF))
                           IMPLIES
                           (TRUE IFF (EXISTS (i: upto(n)): a(i) /= 0)))))));

  % Subtype TCC generated (at line 70, column 46) for  TRUE
      % expected type  {nzb: bool | nzb IFF (EXISTS (i: upto(n)): a(i) /= 0)}
  roots_closed_int_TCC6: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), low: real,
            (high: real | low < high), lower_bound, upper_bound: bool,
            sl: (Eq_computed_remainder?(a, n)), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (P: [nat -> [nat -> int]]):
          (P =
            (LAMBDA (j: nat):
               IF j < length(sl)
                 THEN list2array[int](0)(nth(sl, length(sl) - 1 - j))
               ELSE (LAMBDA (i: nat): 0)
               ENDIF))
           IMPLIES
           (FORALL (N: [nat -> nat]):
              (N =
                (LAMBDA (j: nat):
                   IF j < length(sl)
                     THEN max(length(nth(sl, length(sl) - 1 - j)) - 1, 0)
                   ELSE 0
                   ENDIF))
               IMPLIES
               (FORALL (M: nat):
                  M = length(sl) - 1 IMPLIES
                   (FORALL (nscnorm: [real -> NSC]):
                      (nscnorm =
                        (LAMBDA (xyz: real):
                           number_sign_changes(LAMBDA
                                               (i: nat):
                                               polynomial(P(i), N(i))(xyz),
                                               M - 1)))
                       IMPLIES
                       (FORALL (nschighlow: [bool -> NSC]):
                          (nschighlow =
                            (LAMBDA (b: bool):
                               IF b
                                 THEN number_sign_changes
                                      (LAMBDA (i: nat): P(i)(N(i)), M - 1)
                               ELSE number_sign_changes(LAMBDA
                                                        (i: nat):
                                                        (-1) ^ N(i)
                                                        *
                                                        P(i)(N(i)),
                                                        M - 1)
                               ENDIF))
                           IMPLIES
                           (FORALL (newlow: real):
                              upper_bound AND
                               NOT polynomial(P(0), N(0))(high) /= 0 AND
                                NOT polynomial(P(1), N(1))(high) /= 0 AND
                                 newlow =
                                  IF ((NOT lower_bound)
                                      OR
                                      polynomial(P(0), N(0))(low) /= 0
                                      OR
                                      polynomial(P(1), N(1))(low) /= 0)
                                    THEN low
                                  ELSE low
                                       -
                                       poly_rootless_width(a, n, low, TRUE)
                                       /
                                       2
                                  ENDIF
                               IMPLIES
                               (TRUE IFF
                                 (EXISTS (i: upto(n)): a(i) /= 0))))))));

  % Subtype TCC generated (at line 111, column 49) for  I`ub
      % expected type  {high: real | I`lb < high}
  number_roots_interval_TCC1: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), I: RealInt,
            (sl: (Eq_computed_remainder?(a, n)))):
      NOT I`lb >= I`ub IMPLIES I`lb < I`ub;

  % Subtype TCC generated (at line 116, column 9) for
      % rootstotal + adjlow + adjhigh
      % expected type  nat
  number_roots_interval_TCC2: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), I: RealInt,
            (sl: (Eq_computed_remainder?(a, n)))):
      NOT I`lb >= I`ub IMPLIES
       (FORALL (rootstotal: int):
          rootstotal =
           roots_closed_int(a, n, I`lb, I`ub, I`bounded_below,
                            I`bounded_above, sl)
           IMPLIES
           (FORALL (adjlow: int):
              adjlow =
               IF I`bounded_below AND
                   (NOT I`closed_below) AND polynomial(a, n)(I`lb) = 0
                 THEN -1
               ELSE 0
               ENDIF
               IMPLIES
               (FORALL (adjhigh: int):
                  adjhigh =
                   IF I`bounded_above AND
                       (NOT I`closed_above) AND polynomial(a, n)(I`ub) = 0
                     THEN -1
                   ELSE 0
                   ENDIF
                   IMPLIES rootstotal + adjlow + adjhigh >= 0)));

  % Well-founded TCC generated (at line 137, column 33) for
      % real_ord_ep(min_poly_root_dist(a, n))
      % for always_nonnegative_int
  always_nonnegative_int_TCC1: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0)):
      well_founded?(LAMBDA (x1: real, y1: real):
                      real_ord_ep(min_poly_root_dist(a, n))(x1, y1));

  % Subtype TCC generated (at line 129, column 16) for  TRUE
      % expected type  {bb: bool |
                     %          bb IFF
                     %           (FORALL (z: real):
                     %              x <= z AND z <= y IMPLIES
                     %               polynomial(a, n)(z) >= 0)}
  always_nonnegative_int_TCC2: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), x, y: real,
            (sl: (Eq_computed_remainder?(a, n)))):
      x > y IMPLIES
       (TRUE IFF
         (FORALL (z: real):
            x <= z AND z <= y IMPLIES polynomial(a, n)(z) >= 0));

  % Subtype TCC generated (at line 130, column 19) for
      % polynomial(a, n)(x) >= 0
      % expected type  {bb: bool |
                     %          bb IFF
                     %           (FORALL (z: real):
                     %              x <= z AND z <= y IMPLIES
                     %               polynomial(a, n)(z) >= 0)}
  always_nonnegative_int_TCC3: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), x, y: real,
            (sl: (Eq_computed_remainder?(a, n)))):
      x = y AND NOT x > y IMPLIES
       (polynomial(a, n)(x) >= 0 IFF
         (FORALL (z: real):
            x <= z AND z <= y IMPLIES polynomial(a, n)(z) >= 0));

  % Subtype TCC generated (at line 131, column 33) for  y
      % expected type  {high: real | x < high}
  always_nonnegative_int_TCC4: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), x, y: real,
            (sl: (Eq_computed_remainder?(a, n)))):
      NOT x = y AND NOT x > y IMPLIES x < y;

  % Subtype TCC generated (at line 132, column 6) for
      % polynomial(a, n)(x) >= 0 AND polynomial(a, n)(y) >= 0
      % expected type  {bb: bool |
                     %          bb IFF
                     %           (FORALL (z: real):
                     %              x <= z AND z <= y IMPLIES
                     %               polynomial(a, n)(z) >= 0)}
  always_nonnegative_int_TCC5: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), x, y: real,
            (sl: (Eq_computed_remainder?(a, n)))):
      roots_closed_int(a, n, x, y, TRUE, TRUE, sl) <= 1 AND
       NOT x = y AND NOT x > y
       IMPLIES
       (polynomial(a, n)(x) >= 0 AND polynomial(a, n)(y) >= 0 IFF
         (FORALL (z: real):
            x <= z AND z <= y IMPLIES polynomial(a, n)(z) >= 0));

  % Termination TCC generated (at line 134, column 6) for
      % always_nonnegative_int(a, n, x, (x + y) / 2, sl)
  always_nonnegative_int_TCC6: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), x, y: real,
            (sl: (Eq_computed_remainder?(a, n)))):
      NOT roots_closed_int(a, n, x, y, TRUE, TRUE, sl) <= 1 AND
       NOT x = y AND NOT x > y
       IMPLIES
       real_ord_ep(min_poly_root_dist(a, n))
                  (meas_fun_alw_nonneg(a, n, x, (x + y) / 2, sl),
                   meas_fun_alw_nonneg(a, n, x, y, sl));

  % Termination TCC generated (at line 135, column 6) for
      % always_nonnegative_int(a, n, (x + y) / 2, y, sl)
  always_nonnegative_int_TCC7: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), x, y: real,
            (sl: (Eq_computed_remainder?(a, n))),
            v:
              [d1:
                 {z1:
                    [a: [nat -> int], n: {n | a(n) /= 0}, real, real,
                     (Eq_computed_remainder?(a, n))] |
                          real_ord_ep(min_poly_root_dist(a, n))
                                     (meas_fun_alw_nonneg(z1),
                                      meas_fun_alw_nonneg
                                      (a, n, x, y, sl))} ->
                 {bb: bool |
                          bb IFF
                           (FORALL (z: real):
                              d1`3 <= z AND z <= d1`4 IMPLIES
                               polynomial(d1`1, d1`2)(z) >= 0)}]):
      v(a, n, x, (x + y) / 2, sl) AND
       NOT roots_closed_int(a, n, x, y, TRUE, TRUE, sl) <= 1 AND
        NOT x = y AND NOT x > y
       IMPLIES
       real_ord_ep(min_poly_root_dist(a, n))
                  (meas_fun_alw_nonneg(a, n, (x + y) / 2, y, sl),
                   meas_fun_alw_nonneg(a, n, x, y, sl));

  % Subtype TCC generated (at line 134, column 6) for
      % always_nonnegative_int(a, n, x, (x + y) / 2, sl) AND
      %  always_nonnegative_int(a, n, (x + y) / 2, y, sl)
      % expected type  {bb: bool |
                     %          bb IFF
                     %           (FORALL (z: real):
                     %              x <= z AND z <= y IMPLIES
                     %               polynomial(a, n)(z) >= 0)}
  always_nonnegative_int_TCC8: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0), x, y: real,
            (sl: (Eq_computed_remainder?(a, n))),
            v:
              [d1:
                 {z1:
                    [a: [nat -> int], n: {n | a(n) /= 0}, real, real,
                     (Eq_computed_remainder?(a, n))] |
                          real_ord_ep(min_poly_root_dist(a, n))
                                     (meas_fun_alw_nonneg(z1),
                                      meas_fun_alw_nonneg
                                      (a, n, x, y, sl))} ->
                 {bb: bool |
                          bb IFF
                           (FORALL (z: real):
                              d1`3 <= z AND z <= d1`4 IMPLIES
                               polynomial(d1`1, d1`2)(z) >= 0)}]):
      NOT roots_closed_int(a, n, x, y, TRUE, TRUE, sl) <= 1 AND
       NOT x = y AND NOT x > y
       IMPLIES
       (v(a, n, x, (x + y) / 2, sl) AND v(a, n, (x + y) / 2, y, sl) IFF
         (FORALL (z: real):
            x <= z AND z <= y IMPLIES polynomial(a, n)(z) >= 0));

  % Subtype TCC generated (at line 141, column 30) for  n
      % expected type  {n | newa(n) /= 0}
  always_nonnegative_TCC1: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       newa(n) /= 0;

  % Subtype TCC generated (at line 57, column 23) for  poly_deriv(newa)
      % expected type  [nat -> int]
  always_nonnegative_TCC2: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (x1: nat):
          rational_pred(poly_deriv(newa)(x1)) AND
           integer_pred(poly_deriv(newa)(x1)));

  % Subtype TCC generated (at line 57, column 37) for  n - 1
      % expected type  {m | poly_deriv(newa)(m) /= 0}
  always_nonnegative_TCC3: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       n - 1 >= 0 AND poly_deriv(newa)(n - 1) /= 0;

  % Subtype TCC generated (at line 144, column 50) for  sl
      % expected type  (Eq_computed_remainder?(a, n))
  always_nonnegative_TCC4: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (sl: list[list[int]]):
          I`bounded_below AND
           I`bounded_above AND
            sl = remainder_seq(newa, n, poly_deriv(newa), n - 1)
           IMPLIES Eq_computed_remainder?(a, n)(sl));

  % Subtype TCC generated (at line 148, column 52) for  sl
      % expected type  (Eq_computed_remainder?(a, n))
  always_nonnegative_TCC5: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (sl: list[list[int]]):
          NOT (I`bounded_below AND I`bounded_above) AND
           sl = remainder_seq(newa, n, poly_deriv(newa), n - 1)
           IMPLIES
           (FORALL (M:
                      {K: posreal |
                               FORALL (x: real):
                                 polynomial(a, n)(x) = 0 IMPLIES
                                  abs(x) < K}):
              I`bounded_above AND M = Knuth_poly_root_strict_bound(a, n)
               IMPLIES Eq_computed_remainder?(a, n)(sl)));

  % Subtype TCC generated (at line 150, column 51) for  sl
      % expected type  (Eq_computed_remainder?(a, n))
  always_nonnegative_TCC6: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (sl: list[list[int]]):
          NOT (I`bounded_below AND I`bounded_above) AND
           sl = remainder_seq(newa, n, poly_deriv(newa), n - 1)
           IMPLIES
           (FORALL (M:
                      {K: posreal |
                               FORALL (x: real):
                                 polynomial(a, n)(x) = 0 IMPLIES
                                  abs(x) < K}):
              I`bounded_below AND
               NOT I`bounded_above AND M = Knuth_poly_root_strict_bound(a, n)
               IMPLIES Eq_computed_remainder?(a, n)(sl)));

  % Subtype TCC generated (at line 151, column 40) for  sl
      % expected type  (Eq_computed_remainder?(a, n))
  always_nonnegative_TCC7: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), newa: [nat -> int]):
      (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF)) IMPLIES
       (FORALL (sl: list[list[int]]):
          NOT (I`bounded_below AND I`bounded_above) AND
           sl = remainder_seq(newa, n, poly_deriv(newa), n - 1)
           IMPLIES
           (FORALL (M:
                      {K: posreal |
                               FORALL (x: real):
                                 polynomial(a, n)(x) = 0 IMPLIES
                                  abs(x) < K}):
              NOT I`bounded_below AND
               NOT I`bounded_above AND M = Knuth_poly_root_strict_bound(a, n)
               IMPLIES Eq_computed_remainder?(a, n)(sl)));

  % Subtype TCC generated (at line 169, column 25) for  >
      % expected type  (SturmRel?)
  swap_TCC1: OBLIGATION
    FORALL (realord: (SturmRel?)): realord = (<) IMPLIES SturmRel?(>);

  % Subtype TCC generated (at line 170, column 29) for  >=
      % expected type  (SturmRel?)
  swap_TCC2: OBLIGATION
    FORALL (realord: (SturmRel?)):
      realord = (<=) AND NOT realord = (<) IMPLIES SturmRel?(>=);

  % Subtype TCC generated (at line 171, column 28) for  <
      % expected type  (SturmRel?)
  swap_TCC3: OBLIGATION
    FORALL (realord: (SturmRel?)):
      realord = (>) AND NOT realord = (<=) AND NOT realord = (<) IMPLIES
       SturmRel?(<);

  % Subtype TCC generated (at line 172, column 29) for  <=
      % expected type  (SturmRel?)
  swap_TCC4: OBLIGATION
    FORALL (realord: (SturmRel?)):
      realord = (>=) AND
       NOT realord = (>) AND NOT realord = (<=) AND NOT realord = (<)
       IMPLIES SturmRel?(<=);

  % Subtype TCC generated (at line 173, column 9) for  (/=[real])
      % expected type  (SturmRel?)
  swap_TCC5: OBLIGATION
    FORALL (realord: (SturmRel?)):
      NOT realord = (>=) AND
       NOT realord = (>) AND NOT realord = (<=) AND NOT realord = (<)
       IMPLIES SturmRel?((/=[real]));

  % Subtype TCC generated (at line 177, column 9) for  <
      % expected type  (SturmRel?)
  swap_lt_TCC1: OBLIGATION SturmRel?(<);

  % Subtype TCC generated (at line 180, column 9) for  >
      % expected type  (SturmRel?)
  swap_gt_TCC1: OBLIGATION SturmRel?(>);

  % Subtype TCC generated (at line 183, column 9) for  <=
      % expected type  (SturmRel?)
  swap_le_TCC1: OBLIGATION SturmRel?(<=);

  % Subtype TCC generated (at line 186, column 9) for  >=
      % expected type  (SturmRel?)
  swap_ge_TCC1: OBLIGATION SturmRel?(>=);

  % Subtype TCC generated (at line 189, column 9) for  /=[real]
      % expected type  (SturmRel?)
  swap_ne_TCC1: OBLIGATION SturmRel?(/=[real]);

  % Subtype TCC generated (at line 196, column 49) for  -a
      % expected type  [nat -> int]
  compute_poly_sat_TCC1: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      realord = (<=) AND NOT realord = (>=) IMPLIES
       (FORALL (x1: nat): rational_pred((-a)(x1)) AND integer_pred((-a)(x1)));

  % Subtype TCC generated (at line 196, column 52) for  n
      % expected type  {n | (-a)(n) /= 0}
  compute_poly_sat_TCC2: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      realord = (<=) AND NOT realord = (>=) IMPLIES (-a)(n) /= 0;

  % Subtype TCC generated (at line 200, column 37) for  sl
      % expected type  (Eq_computed_remainder?(a, n))
  compute_poly_sat_TCC3: OBLIGATION
    FORALL (a: [nat -> int], (n: posnat | a(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      NOT realord = (<=) AND NOT realord = (>=) IMPLIES
       (FORALL (newa: [nat -> int]):
          (newa = (LAMBDA (i: nat): IF i <= n THEN a(i) ELSE 0 ENDIF))
           IMPLIES
           (FORALL (sl: list[list[int]]):
              sl = remainder_seq(newa, n, poly_deriv(newa), n - 1) IMPLIES
               Eq_computed_remainder?(a, n)(sl)));

  % Subtype TCC generated (at line 210, column 43) for  n
      % expected type  {n_1 | rat_poly_to_int(aq, n)(n_1) /= 0}
  compute_poly_sat_rational_TCC1: OBLIGATION
    FORALL (aq: [nat -> rat], (n: posnat | aq(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      rat_poly_to_int(aq, n)(n) /= 0;

  % Subtype TCC generated (at line 221, column 32) for  poly_deriv(aq)
      % expected type  [nat -> rat]
  compute_poly_mono_basic_TCC1: OBLIGATION
    FORALL (aq: [nat -> rat], (n: posnat | aq(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      (realord = (/=[real])) AND NOT n = 1 IMPLIES
       (FORALL (x1: nat): rational_pred(poly_deriv(aq)(x1)));

  % Subtype TCC generated (at line 221, column 47) for  n - 1
      % expected type  {n | poly_deriv(aq)(n) /= 0}
  compute_poly_mono_basic_TCC2: OBLIGATION
    FORALL (aq: [nat -> rat], (n: posnat | aq(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      (realord = (/=[real])) AND NOT n = 1 IMPLIES
       n - 1 >= 0 AND n - 1 > 0 AND poly_deriv(aq)(n - 1) /= 0;

  % Subtype TCC generated (at line 224, column 32) for  poly_deriv(aq)
      % expected type  [nat -> rat]
  compute_poly_mono_basic_TCC3: OBLIGATION
    FORALL (aq: [nat -> rat], (n: posnat | aq(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      realord(I`lb, I`ub) AND NOT (realord = (/=[real])) AND NOT n = 1
       IMPLIES (FORALL (x1: nat): rational_pred(poly_deriv(aq)(x1)));

  % Subtype TCC generated (at line 224, column 47) for  n - 1
      % expected type  {n | poly_deriv(aq)(n) /= 0}
  compute_poly_mono_basic_TCC4: OBLIGATION
    FORALL (aq: [nat -> rat], (n: posnat | aq(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      realord(I`lb, I`ub) AND NOT (realord = (/=[real])) AND NOT n = 1
       IMPLIES n - 1 >= 0 AND n - 1 > 0 AND poly_deriv(aq)(n - 1) /= 0;

  % Subtype TCC generated (at line 226, column 32) for  poly_deriv(aq)
      % expected type  [nat -> rat]
  compute_poly_mono_basic_TCC5: OBLIGATION
    FORALL (aq: [nat -> rat], (n: posnat | aq(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      NOT realord(I`lb, I`ub) AND NOT (realord = (/=[real])) AND NOT n = 1
       IMPLIES (FORALL (x1: nat): rational_pred(poly_deriv(aq)(x1)));

  % Subtype TCC generated (at line 226, column 47) for  n - 1
      % expected type  {n | poly_deriv(aq)(n) /= 0}
  compute_poly_mono_basic_TCC6: OBLIGATION
    FORALL (aq: [nat -> rat], (n: posnat | aq(n) /= 0),
            (I: RealInt | I`lb < I`ub), realord: (SturmRel?)):
      NOT realord(I`lb, I`ub) AND NOT (realord = (/=[real])) AND NOT n = 1
       IMPLIES n - 1 >= 0 AND n - 1 > 0 AND poly_deriv(aq)(n - 1) /= 0;


body:
  polylist : THEORY 
  BEGIN

    IMPORTING structures@array2list[rat],reals@polynomials,reals@sq

    Polylist : TYPE = (cons?[rat])

    pl,ql : VAR Polylist
    x,acc : VAR real
    c	: VAR rat
    n     : VAR nat  
    rnz	: VAR nzrat

    zero_pol(x:nat) : rat = 0

    eval_polylist(pl:Polylist,deg:upfrom(length(pl)-1),acc:real)(x:real) : RECURSIVE real =
      LET newl = cdr(pl),
          thisco = car(pl),
  	thisdeg = deg-length(pl)+1
      IN IF null?(newl) THEN acc+thisco*x^thisdeg
         ELSE eval_polylist(newl,deg,acc+thisco*x^thisdeg)(x)
         ENDIF
      MEASURE length(pl)

    eval_polylist_times_x: LEMMA
      FORALL (deg:upfrom(length(pl))):
      eval_polylist(pl,deg-1,acc)(x)*x =
      eval_polylist(pl,deg,acc*x)(x)

    eval_polylist_remove_acc: LEMMA
      FORALL (deg:upfrom(length(pl)-1)):
      eval_polylist(pl,deg,acc)(x) =
      eval_polylist(pl,deg,0)(x) + acc

    eval_polylist_test: LEMMA
      eval_polylist((: 1,2,3,4 :),3,0)(x) = 1+2*x+3*x^2+4*x^3

    polylist(pl)(x) : real =
      eval_polylist(pl,length(pl)-1,0)(x)

    pconst(c): Polylist = (: c :)

    pmonom(c:rat,deg:nat): RECURSIVE {pl:Polylist|
    			 length(pl)=deg+1 AND
    			 FORALL (x:real): polylist(pl)(x) = c*x^deg} =
      IF deg=0 THEN pconst(c)
      ELSE cons(0,pmonom(c,deg-1)) ENDIF
      MEASURE deg

    psum(pl,ql) : RECURSIVE {pql:Polylist|
      FORALL (x): polylist(pql)(x) = polylist(pl)(x)+polylist(ql)(x)} =
      LET plcoeff = car(pl),
      	qlcoeff = car(ql),
  	newpl   = cdr(pl),
  	newql   = cdr(ql)
      IN IF null?(newpl) THEN cons(plcoeff+qlcoeff,newql)
         ELSIF null?(newql) THEN cons(plcoeff+qlcoeff,newpl)
         ELSE cons(car(pl)+car(ql),psum(cdr(pl),cdr(ql)))
      ENDIF
    MEASURE length(pl)+length(ql)

    ;+(pl,ql) : MACRO Polylist = psum(pl,ql)

    pscal(c,pl): RECURSIVE {pql:Polylist|
      length[rat](pql)=length[rat](pl) AND 
      FORALL (x): polylist(pql)(x) = c*polylist(pl)(x)} =
      IF null?(cdr(pl)) THEN (: c*car(pl) :)
      ELSE cons(c*car(pl),pscal(c,cdr(pl))) ENDIF
      MEASURE length(pl)

    ;*(c,pl) : MACRO Polylist = pscal(c,pl)

    pminus(pl,ql) : Polylist =
      psum(pl,(-1)*ql)

    ;-(pl,ql) : MACRO Polylist = pminus(pl,ql)

    pneg(pl) : Polylist =
      (-1)*pl

    ;-(pl): MACRO Polylist = pneg(pl)

    pprod(pl,ql) : Polylist =
      array2list[rat](length(pl)+length(ql)-1)(polynomial_prod(list2array[rat](0)(pl),length(pl)-1,
                                                        list2array[rat](0)(ql),length(ql)-1))
    ;*(pl,ql) : MACRO Polylist = pprod(pl,ql)

    ppow(pl,n): RECURSIVE Polylist =
      IF n = 0 THEN pconst(1)
      ELSIF n = 1 THEN pl
      ELSE pprod(pl,ppow(pl,n-1))
      ENDIF
    MEASURE n

    ;^(pl,n) : MACRO Polylist = ppow(pl,n)

    pdiv(pl,rnz): Polylist = (1/rnz)*pl

    ;/(pl,rnz): MACRO Polylist = pdiv(pl,rnz)

    psq(pl): Polylist = pprod(pl,pl)

    deg_rec(pl): RECURSIVE 
      {degans:[# allzero: bool,maxnon:below(length(pl)) #] |
        LET (dz,dmax)=(degans`allzero,degans`maxnon),
        	  len	   =length(pl) 
        IN
          (dz IFF (FORALL (j:below(len)): nth(pl,j)=0)) AND
  	(dz OR FORALL (j:below(len)): j>dmax IMPLIES nth(pl,j)=0) AND
  	(dz OR nth(pl,dmax)/=0)} =
      IF null?(cdr(pl)) AND car(pl)=0 THEN (# allzero:=TRUE,maxnon:=0 #)
      ELSIF null?(cdr(pl)) THEN (# allzero:=FALSE,maxnon:=0 #)
      ELSE
        LET upans = deg_rec(cdr(pl)),
        	  upvalid=(NOT upans`allzero)
        IN  IF upvalid THEN (# allzero:=FALSE,maxnon:=1+upans`maxnon #)
        	  ELSIF car(pl)=0 THEN (# allzero:=TRUE,maxnon:=0 #)
  	  ELSE (# allzero:=FALSE,maxnon:=0 #) ENDIF
      ENDIF MEASURE length(pl)
    

    deg(pl): {d:below(length(pl)) |
      (d>0 IFF EXISTS (j:below(length(pl))): j>0 AND nth(pl,j)/=0) AND
      (d>0 IMPLIES (FORALL (j:below(length(pl))): j>d IMPLIES nth(pl,j)=0)) AND
      (d>0 IMPLIES nth(pl,d)/=0)} =
      LET drec = deg_rec(pl) IN
        IF drec`allzero THEN 0 ELSE drec`maxnon ENDIF

    %%% Lemmas for Strategy %%%

    polylist_eval : LEMMA
      polylist(pl)(x) = polynomial(list2array[rat](0)(pl),length(pl)-1)(x)

    polylist_eval_deg: LEMMA deg(pl)>0 IMPLIES
      polynomial(list2array[rat](0)(pl),length(pl)-1)(x) =
      polynomial(list2array[rat](0)(pl),deg(pl))(x)

    polylist_const: LEMMA
      polylist(pconst(c))(x) = c

    polylist_monom: LEMMA
      polylist(pmonom(c,n))(x) = c*x^n

    polylist_prod: LEMMA
     polylist(pl*ql)(x) = polylist(pl)(x)*polylist(ql)(x)

    polylist_scal: LEMMA
      polylist(c*pl)(x) = c*polylist(pl)(x)

    polylist_sum: LEMMA
     polylist(pl+ql)(x) =  polylist(pl)(x)+polylist(ql)(x)

    polylist_minus: LEMMA
     polylist(pl-ql)(x) = polylist(pl)(x)-polylist(ql)(x)

    polylist_pow: LEMMA
      polylist(pl^n)(x) = polylist(pl)(x)^n

    polylist_neg: LEMMA
      polylist(-pl)(x) = -polylist(pl)(x)

    polylist_div: LEMMA
      polylist(pl/rnz)(x) = polylist(pl)(x)/rnz

    polylist_sq: LEMMA
      polylist(psq(pl))(x) = sq(polylist(pl)(x))

  END polylist

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

  % Subtype TCC generated (at line 20, column 40) for  thisdeg
      % expected type  {i: int | x /= 0 OR i >= 0}
  eval_polylist_TCC1: OBLIGATION
    FORALL (pl: Polylist, deg: upfrom(length[rat](pl) - 1), x: real,
            newl: list[rat]):
      newl = cdr(pl) IMPLIES
       (FORALL (thisco: rat):
          thisco = car(pl) IMPLIES
           (FORALL (thisdeg: int):
              null?(newl) AND thisdeg = deg - length(pl) + 1 IMPLIES
               x /= 0 OR thisdeg >= 0));

  % Subtype TCC generated (at line 21, column 26) for  newl
      % expected type  Polylist
  eval_polylist_TCC2: OBLIGATION
    FORALL (pl: Polylist, deg: upfrom(length[rat](pl) - 1), newl: list[rat]):
      newl = cdr(pl) IMPLIES
       (FORALL (thisco: rat):
          thisco = car(pl) IMPLIES
           (FORALL (thisdeg: int):
              NOT null?(newl) AND thisdeg = deg - length(pl) + 1 IMPLIES
               cons?[rat](newl)));

  % Subtype TCC generated (at line 21, column 31) for  deg
      % expected type  upfrom(length(newl) - 1)
  eval_polylist_TCC3: OBLIGATION
    FORALL (pl: Polylist, deg: upfrom(length[rat](pl) - 1), newl: list[rat]):
      newl = cdr(pl) IMPLIES
       (FORALL (thisco: rat):
          thisco = car(pl) IMPLIES
           (FORALL (thisdeg: int):
              NOT null?(newl) AND thisdeg = deg - length(pl) + 1 IMPLIES
               deg >= length[rat](newl) - 1));

  % Subtype TCC generated (at line 21, column 48) for  thisdeg
      % expected type  {i: int | x /= 0 OR i >= 0}
  eval_polylist_TCC4: OBLIGATION
    FORALL (pl: Polylist, deg: upfrom(length[rat](pl) - 1), x: real,
            newl: list[rat]):
      newl = cdr(pl) IMPLIES
       (FORALL (thisco: rat):
          thisco = car(pl) IMPLIES
           (FORALL (thisdeg: int):
              NOT null?(newl) AND thisdeg = deg - length(pl) + 1 IMPLIES
               x /= 0 OR thisdeg >= 0));

  % Termination TCC generated (at line 21, column 12) for
      % eval_polylist(newl, deg, acc + thisco * x ^ thisdeg)
  eval_polylist_TCC5: OBLIGATION
    FORALL (pl: Polylist, deg: upfrom(length[rat](pl) - 1), newl: list[rat]):
      newl = cdr(pl) IMPLIES
       (FORALL (thisco: rat):
          thisco = car(pl) IMPLIES
           (FORALL (thisdeg: int):
              NOT null?(newl) AND thisdeg = deg - length(pl) + 1 IMPLIES
               length[rat](newl) < length[rat](pl)));

  % Subtype TCC generated (at line 27, column 21) for  deg - 1
      % expected type  upfrom(length(pl) - 1)
  eval_polylist_times_x_TCC1: OBLIGATION
    FORALL (pl: Polylist, deg: upfrom(length[rat](pl))):
      deg - 1 >= length[rat](pl) - 1;

  % Subtype TCC generated (at line 28, column 21) for  deg
      % expected type  upfrom(length(pl) - 1)
  eval_polylist_times_x_TCC2: OBLIGATION
    FORALL (pl: Polylist, deg: upfrom(length[rat](pl))):
      deg >= length[rat](pl) - 1;

  % Subtype TCC generated (at line 36, column 23) for  (: 2, 3, 4 :)
      % expected type  list[rat]
  eval_polylist_test_TCC1: OBLIGATION
    every[number]
        (LAMBDA (x: number):
           number_field_pred(x) AND real_pred(x) AND rational_pred(x))
        ((: 2, 3, 4 :));

  % Subtype TCC generated (at line 36, column 32) for  3
      % expected type  upfrom(length((: 1, 2, 3, 4 :)) - 1)
  eval_polylist_test_TCC2: OBLIGATION 3 >= length[rat]((: 1, 2, 3, 4 :)) - 1;

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

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

  % Subtype TCC generated (at line 39, column 21) for  length(pl) - 1
      % expected type  upfrom(length(pl) - 1)
  polylist_TCC1: OBLIGATION
    FORALL (pl: Polylist): length[rat](pl) - 1 >= length[rat](pl) - 1;

  % Subtype TCC generated (at line 45, column 45) for  deg
      % expected type  {i: int | x /= 0 OR i >= 0}
  pmonom_TCC1: OBLIGATION
    FORALL (deg: nat, pl: Polylist):
      length(pl) = deg + 1 IMPLIES (FORALL (x: real): x /= 0 OR deg >= 0);

  % Subtype TCC generated (at line 46, column 18) for  pconst(c)
      % expected type  {pl: Polylist |
                     %          length(pl) = 1 + deg AND
                     %           (FORALL (x: real):
                     %              polylist(pl)(x) = c * x ^ deg)}
  pmonom_TCC2: OBLIGATION
    FORALL (c: rat, deg: nat):
      deg = 0 IMPLIES
       length[rat](pconst(c)) = 1 + deg AND
        (FORALL (x: real): polylist(pconst(c))(x) = c * x ^ deg);

  % Subtype TCC generated (at line 47, column 25) for  deg - 1
      % expected type  nat
  pmonom_TCC3: OBLIGATION FORALL (deg: nat): NOT deg = 0 IMPLIES deg - 1 >= 0;

  % Termination TCC generated (at line 47, column 16) for  pmonom(c, deg - 1)
  pmonom_TCC4: OBLIGATION
    FORALL (deg: nat): NOT deg = 0 IMPLIES deg - 1 < deg;

  % Subtype TCC generated (at line 47, column 9) for
      % cons(0, pmonom(c, deg - 1))
      % expected type  {pl: Polylist |
                     %          length(pl) = 1 + deg AND
                     %           (FORALL (x: real):
                     %              polylist(pl)(x) = c * x ^ deg)}
  pmonom_TCC5: OBLIGATION
    FORALL (c: rat, deg: nat,
            v:
              [d1: {z: [rat, nat] | z`2 < deg} ->
                 {pl: Polylist |
                          length(pl) = 1 + d1`2 AND
                           (FORALL (x: real):
                              polylist(pl)(x) = d1`1 * x ^ d1`2)}]):
      NOT deg = 0 IMPLIES
       length[rat](cons[rat](0, v(c, deg - 1))) = 1 + deg AND
        (FORALL (x: real):
           polylist(cons[rat](0, v(c, deg - 1)))(x) = c * x ^ deg);

  % Subtype TCC generated (at line 56, column 28) for
      % cons(plcoeff + qlcoeff, newql)
      % expected type  {pql: Polylist |
                     %          FORALL (x):
                     %            polylist(pql)(x) =
                     %             polylist(pl)(x) + polylist(ql)(x)}
  psum_TCC1: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist, plcoeff: rat):
      plcoeff = car(pl) IMPLIES
       (FORALL (qlcoeff: rat):
          qlcoeff = car(ql) IMPLIES
           (FORALL (newpl: list[rat]):
              newpl = cdr(pl) IMPLIES
               (FORALL (newql: list[rat]):
                  null?(newpl) AND newql = cdr(ql) IMPLIES
                   (FORALL (x):
                      polylist(cons[rat](plcoeff + qlcoeff, newql))(x) =
                       polylist(pl)(x) + polylist(ql)(x)))));

  % Subtype TCC generated (at line 57, column 31) for
      % cons(plcoeff + qlcoeff, newpl)
      % expected type  {pql: Polylist |
                     %          FORALL (x):
                     %            polylist(pql)(x) =
                     %             polylist(pl)(x) + polylist(ql)(x)}
  psum_TCC2: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist, plcoeff: rat):
      plcoeff = car(pl) IMPLIES
       (FORALL (qlcoeff: rat):
          qlcoeff = car(ql) IMPLIES
           (FORALL (newpl: list[rat]):
              newpl = cdr(pl) IMPLIES
               (FORALL (newql: list[rat]):
                  null?(newql) AND NOT null?(newpl) AND newql = cdr(ql)
                   IMPLIES
                   (FORALL (x):
                      polylist(cons[rat](plcoeff + qlcoeff, newpl))(x) =
                       polylist(pl)(x) + polylist(ql)(x)))));

  % Subtype TCC generated (at line 58, column 38) for  cdr(pl)
      % expected type  Polylist
  psum_TCC3: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist, plcoeff: rat):
      plcoeff = car(pl) IMPLIES
       (FORALL (qlcoeff: rat):
          qlcoeff = car(ql) IMPLIES
           (FORALL (newpl: list[rat]):
              newpl = cdr(pl) IMPLIES
               (FORALL (newql: list[rat]):
                  NOT null?(newql) AND NOT null?(newpl) AND newql = cdr(ql)
                   IMPLIES cons?[rat](cdr[rat](pl)))));

  % Subtype TCC generated (at line 58, column 46) for  cdr(ql)
      % expected type  Polylist
  psum_TCC4: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist, plcoeff: rat):
      plcoeff = car(pl) IMPLIES
       (FORALL (qlcoeff: rat):
          qlcoeff = car(ql) IMPLIES
           (FORALL (newpl: list[rat]):
              newpl = cdr(pl) IMPLIES
               (FORALL (newql: list[rat]):
                  NOT null?(newql) AND NOT null?(newpl) AND newql = cdr(ql)
                   IMPLIES cons?[rat](cdr[rat](ql)))));

  % Termination TCC generated (at line 58, column 33) for
      % psum(cdr(pl), cdr(ql))
  psum_TCC5: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist, plcoeff: rat):
      plcoeff = car(pl) IMPLIES
       (FORALL (qlcoeff: rat):
          qlcoeff = car(ql) IMPLIES
           (FORALL (newpl: list[rat]):
              newpl = cdr(pl) IMPLIES
               (FORALL (newql: list[rat]):
                  NOT null?(newql) AND NOT null?(newpl) AND newql = cdr(ql)
                   IMPLIES
                   length[rat](cdr[rat](pl)) + length[rat](cdr[rat](ql)) <
                    length[rat](pl) + length[rat](ql))));

  % Subtype TCC generated (at line 58, column 12) for
      % cons(car(pl) + car(ql), psum(cdr(pl), cdr(ql)))
      % expected type  {pql: Polylist |
                     %          FORALL (x):
                     %            polylist(pql)(x) =
                     %             polylist(pl)(x) + polylist(ql)(x)}
  psum_TCC6: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist, plcoeff: rat):
      plcoeff = car(pl) IMPLIES
       (FORALL (qlcoeff: rat):
          qlcoeff = car(ql) IMPLIES
           (FORALL (newpl: list[rat]):
              newpl = cdr(pl) IMPLIES
               (FORALL (newql: list[rat]):
                  NOT null?(newql) AND NOT null?(newpl) AND newql = cdr(ql)
                   IMPLIES
                   (FORALL (x,
                            v:
                              [d1:
                                 {z: [Polylist, Polylist] |
                                          length[rat](z`1) + length[rat](z`2)
                                          <
                                          length[rat](pl)
                                          +
                                          length[rat](ql)} ->
                                 {pql: Polylist |
                                          FORALL
                                          (x_1: real):
                                          polylist(pql)(x_1)
                                          =
                                          polylist(d1`1)(x_1)
                                          +
                                          polylist(d1`2)(x_1)}]):
                      polylist(cons[rat]
                                   (car[rat](pl) + car[rat](ql),
                                    v(cdr[rat](pl), cdr[rat](ql))))
                              (x)
                       = polylist(pl)(x) + polylist(ql)(x)))));

  % Subtype TCC generated (at line 67, column 27) for  (: c * car(pl) :)
      % expected type  {pql: Polylist |
                     %          length[rat](pql) = length[rat](pl) AND
                     %           (FORALL (x):
                     %              polylist(pql)(x) = c * polylist(pl)(x))}
  pscal_TCC1: OBLIGATION
    FORALL (c: rat, pl: Polylist):
      null?(cdr(pl)) IMPLIES
       length[rat]((: c * car[rat](pl) :)) = length[rat](pl) AND
        (FORALL (x):
           polylist((: c * car[rat](pl) :))(x) = c * polylist(pl)(x));

  % Subtype TCC generated (at line 68, column 32) for  cdr(pl)
      % expected type  Polylist
  pscal_TCC2: OBLIGATION
    FORALL (pl: Polylist):
      NOT null?(cdr(pl)) IMPLIES cons?[rat](cdr[rat](pl));

  % Termination TCC generated (at line 68, column 24) for  pscal(c, cdr(pl))
  pscal_TCC3: OBLIGATION
    FORALL (pl: Polylist):
      NOT null?(cdr(pl)) IMPLIES length[rat](cdr[rat](pl)) < length[rat](pl);

  % Subtype TCC generated (at line 68, column 9) for
      % cons(c * car(pl), pscal(c, cdr(pl)))
      % expected type  {pql: Polylist |
                     %          length[rat](pql) = length[rat](pl) AND
                     %           (FORALL (x):
                     %              polylist(pql)(x) = c * polylist(pl)(x))}
  pscal_TCC4: OBLIGATION
    FORALL (c: rat, pl: Polylist,
            v:
              [d1: {z: [rat, Polylist] | length(z`2) < length(pl)} ->
                 {pql: Polylist |
                          length[rat](pql) = length[rat](d1`2) AND
                           (FORALL (x):
                              polylist(pql)(x) =
                               d1`1 * polylist(d1`2)(x))}]):
      NOT null?(cdr(pl)) IMPLIES
       length[rat](cons[rat](c * car[rat](pl), v(c, cdr[rat](pl)))) =
        length[rat](pl)
        AND
        (FORALL (x):
           polylist(cons[rat](c * car[rat](pl), v(c, cdr[rat](pl))))(x) =
            c * polylist(pl)(x));

  % Subtype TCC generated (at line 84, column 84) for  length(pl) - 1
      % expected type  nat
  pprod_TCC1: OBLIGATION FORALL (pl: Polylist): length[rat](pl) - 1 >= 0;

  % Subtype TCC generated (at line 84, column 45) for
      % polynomial_prod(list2array[rat](0)(pl), length(pl) - 1,
      %                 list2array[rat](0)(ql), length(ql) - 1)
      % expected type  a: [nat -> rat]
  pprod_TCC2: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist):
      FORALL (x1: nat):
        rational_pred(polynomial_prod(list2array[rat](0)(pl),
                                      length[rat](pl) - 1,
                                      list2array[rat](0)(ql),
                                      length[rat](ql) - 1)
                                     (x1));

  % Subtype TCC generated (at line 84, column 20) for
      % length(pl) + length(ql) - 1
      % expected type  n: nat
  pprod_TCC3: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist):
      length[rat](pl) + length[rat](ql) - 1 >= 0;

  % Subtype TCC generated (at line 84, column 4) for
      % array2list[rat]
      %     (length(pl) + length(ql) - 1)
      %     (polynomial_prod(list2array[rat](0)(pl), length(pl) - 1,
      %                      list2array[rat](0)(ql), length(ql) - 1))
      % expected type  Polylist
  pprod_TCC4: OBLIGATION
    FORALL (pl: Polylist, ql: Polylist):
      cons?[rat]
          (array2list[rat]
               (length[rat](pl) + length[rat](ql) - 1)
               (polynomial_prod(list2array[rat](0)(pl), length[rat](pl) - 1,
                                list2array[rat](0)(ql),
                                length[rat](ql) - 1)));

  % Subtype TCC generated (at line 108, column 47) for  j
      % expected type  below[length[rat](pl)]
  deg_rec_TCC1: OBLIGATION
    FORALL (pl, degans: [# allzero: bool, maxnon: below(length[rat](pl)) #],
            dz: bool, dmax: below(length[rat](pl))):
      dmax = degans`maxnon AND dz = degans`allzero IMPLIES
       (FORALL (len: nat):
          len = length(pl) IMPLIES
           (FORALL (j: below(len)): j < length[rat](pl)));

  % Subtype TCC generated (at line 111, column 66) for  0
      % expected type  below(length(pl))
  deg_rec_TCC2: OBLIGATION
    FORALL (pl: Polylist):
      null?(cdr(pl)) AND car(pl) = 0 IMPLIES 0 < length[rat](pl);

  % Subtype TCC generated (at line 111, column 41) for
      % (# allzero := TRUE, maxnon := 0 #)
      % expected type  {degans:
                     %    [# allzero: bool, maxnon: below(length(pl)) #] |
                     %          (degans`allzero IFF
                     %            (FORALL (j: below(length(pl))):
                     %               nth(pl, j) = 0))
                     %           AND
                     %           (degans`allzero OR
                     %             (FORALL (j: below(length(pl))):
                     %                j > degans`maxnon
                     %                IMPLIES
                     %                nth(pl, j) = 0))
                     %            AND
                     %            (degans`allzero OR
                     %              nth(pl, degans`maxnon) /= 0)}
  deg_rec_TCC3: OBLIGATION
    FORALL (pl: Polylist):
      null?(cdr(pl)) AND car(pl) = 0 IMPLIES
       (TRUE IFF (FORALL (j: below(length[rat](pl))): nth[rat](pl, j) = 0));

  % Subtype TCC generated (at line 112, column 56) for  0
      % expected type  below(length(pl))
  deg_rec_TCC4: OBLIGATION
    FORALL (pl: Polylist):
      null?(cdr(pl)) AND NOT (null?(cdr(pl)) AND car(pl) = 0) IMPLIES
       0 < length[rat](pl);

  % Subtype TCC generated (at line 112, column 30) for
      % (# allzero := FALSE, maxnon := 0 #)
      % expected type  {degans:
                     %    [# allzero: bool, maxnon: below(length(pl)) #] |
                     %          (degans`allzero IFF
                     %            (FORALL (j: below(length(pl))):
                     %               nth(pl, j) = 0))
                     %           AND
                     %           (degans`allzero OR
                     %             (FORALL (j: below(length(pl))):
                     %                j > degans`maxnon
                     %                IMPLIES
                     %                nth(pl, j) = 0))
                     %            AND
                     %            (degans`allzero OR
                     %              nth(pl, degans`maxnon) /= 0)}
  deg_rec_TCC5: OBLIGATION
    FORALL (pl: Polylist):
      null?(cdr(pl)) AND NOT (null?(cdr(pl)) AND car(pl) = 0) IMPLIES
       (FALSE IFF (FORALL (j: below(length[rat](pl))): nth[rat](pl, j) = 0))
        AND
        (FORALL (j: below(length[rat](pl))):
           j > 0 IMPLIES nth[rat](pl, j) = 0)
         AND nth[rat](pl, 0) /= 0;

  % Subtype TCC generated (at line 116, column 52) for  1 + upans`maxnon
      % expected type  below(length(pl))
  deg_rec_TCC6: OBLIGATION
    FORALL (pl: Polylist,
            v:
              [pl1: {z: Polylist | length(z) < length(pl)} ->
                 {degans: [# allzero: bool, maxnon: below(length(pl1)) #] |
                          (degans`allzero IFF
                            (FORALL (j: below(length(pl1))):
                               nth(pl1, j) = 0))
                           AND
                           (degans`allzero OR
                             (FORALL (j: below(length(pl1))):
                                j > degans`maxnon IMPLIES nth(pl1, j) = 0))
                            AND
                            (degans`allzero OR
                              nth(pl1, degans`maxnon) /= 0)}]):
      NOT null?(cdr(pl)) AND NOT (null?(cdr(pl)) AND car(pl) = 0) IMPLIES
       (FORALL (upans:
                  {degans:
                     [# allzero: bool, maxnon: below(length(cdr(pl))) #] |
                           (degans`allzero IFF
                             (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                nth[rat](cdr[rat](pl), j) = 0))
                            AND
                            (degans`allzero OR
                              (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                 j > degans`maxnon IMPLIES
                                  nth[rat](cdr[rat](pl), j) = 0))
                             AND
                             (degans`allzero OR
                               nth[rat](cdr[rat](pl), degans`maxnon) /= 0)}):
          upans = v(cdr(pl)) IMPLIES
           (FORALL (upvalid: bool):
              upvalid AND upvalid = (NOT upans`allzero) IMPLIES
               1 + upans`maxnon < length[rat](pl)));

  % Subtype TCC generated (at line 116, column 26) for
      % (# allzero := FALSE, maxnon := 1 + upans`maxnon #)
      % expected type  {degans:
                     %    [# allzero: bool, maxnon: below(length(pl)) #] |
                     %          (degans`allzero IFF
                     %            (FORALL (j: below(length(pl))):
                     %               nth(pl, j) = 0))
                     %           AND
                     %           (degans`allzero OR
                     %             (FORALL (j: below(length(pl))):
                     %                j > degans`maxnon
                     %                IMPLIES
                     %                nth(pl, j) = 0))
                     %            AND
                     %            (degans`allzero OR
                     %              nth(pl, degans`maxnon) /= 0)}
  deg_rec_TCC7: OBLIGATION
    FORALL (pl: Polylist,
            v:
              [pl1: {z: Polylist | length(z) < length(pl)} ->
                 {degans: [# allzero: bool, maxnon: below(length(pl1)) #] |
                          (degans`allzero IFF
                            (FORALL (j: below(length(pl1))):
                               nth(pl1, j) = 0))
                           AND
                           (degans`allzero OR
                             (FORALL (j: below(length(pl1))):
                                j > degans`maxnon IMPLIES nth(pl1, j) = 0))
                            AND
                            (degans`allzero OR
                              nth(pl1, degans`maxnon) /= 0)}]):
      NOT null?(cdr(pl)) AND NOT (null?(cdr(pl)) AND car(pl) = 0) IMPLIES
       (FORALL (upans:
                  {degans:
                     [# allzero: bool, maxnon: below(length(cdr(pl))) #] |
                           (degans`allzero IFF
                             (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                nth[rat](cdr[rat](pl), j) = 0))
                            AND
                            (degans`allzero OR
                              (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                 j > degans`maxnon IMPLIES
                                  nth[rat](cdr[rat](pl), j) = 0))
                             AND
                             (degans`allzero OR
                               nth[rat](cdr[rat](pl), degans`maxnon) /= 0)}):
          upans = v(cdr(pl)) IMPLIES
           (FORALL (upvalid: bool):
              upvalid AND upvalid = (NOT upans`allzero) IMPLIES
               (FALSE IFF
                 (FORALL (j: below(length[rat](pl))): nth[rat](pl, j) = 0))
                AND
                (FORALL (j: below(length[rat](pl))):
                   j > 1 + upans`maxnon IMPLIES nth[rat](pl, j) = 0)
                 AND nth[rat](pl, 1 + upans`maxnon) /= 0));

  % Subtype TCC generated (at line 117, column 55) for  0
      % expected type  below(length(pl))
  deg_rec_TCC8: OBLIGATION
    FORALL (pl: Polylist,
            v:
              [pl1: {z: Polylist | length(z) < length(pl)} ->
                 {degans: [# allzero: bool, maxnon: below(length(pl1)) #] |
                          (degans`allzero IFF
                            (FORALL (j: below(length(pl1))):
                               nth(pl1, j) = 0))
                           AND
                           (degans`allzero OR
                             (FORALL (j: below(length(pl1))):
                                j > degans`maxnon IMPLIES nth(pl1, j) = 0))
                            AND
                            (degans`allzero OR
                              nth(pl1, degans`maxnon) /= 0)}]):
      NOT null?(cdr(pl)) AND NOT (null?(cdr(pl)) AND car(pl) = 0) IMPLIES
       (FORALL (upans:
                  {degans:
                     [# allzero: bool, maxnon: below(length(cdr(pl))) #] |
                           (degans`allzero IFF
                             (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                nth[rat](cdr[rat](pl), j) = 0))
                            AND
                            (degans`allzero OR
                              (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                 j > degans`maxnon IMPLIES
                                  nth[rat](cdr[rat](pl), j) = 0))
                             AND
                             (degans`allzero OR
                               nth[rat](cdr[rat](pl), degans`maxnon) /= 0)}):
          upans = v(cdr(pl)) IMPLIES
           (FORALL (upvalid: bool):
              car(pl) = 0 AND NOT upvalid AND upvalid = (NOT upans`allzero)
               IMPLIES 0 < length[rat](pl)));

  % Subtype TCC generated (at line 117, column 30) for
      % (# allzero := TRUE, maxnon := 0 #)
      % expected type  {degans:
                     %    [# allzero: bool, maxnon: below(length(pl)) #] |
                     %          (degans`allzero IFF
                     %            (FORALL (j: below(length(pl))):
                     %               nth(pl, j) = 0))
                     %           AND
                     %           (degans`allzero OR
                     %             (FORALL (j: below(length(pl))):
                     %                j > degans`maxnon
                     %                IMPLIES
                     %                nth(pl, j) = 0))
                     %            AND
                     %            (degans`allzero OR
                     %              nth(pl, degans`maxnon) /= 0)}
  deg_rec_TCC9: OBLIGATION
    FORALL (pl: Polylist,
            v:
              [pl1: {z: Polylist | length(z) < length(pl)} ->
                 {degans: [# allzero: bool, maxnon: below(length(pl1)) #] |
                          (degans`allzero IFF
                            (FORALL (j: below(length(pl1))):
                               nth(pl1, j) = 0))
                           AND
                           (degans`allzero OR
                             (FORALL (j: below(length(pl1))):
                                j > degans`maxnon IMPLIES nth(pl1, j) = 0))
                            AND
                            (degans`allzero OR
                              nth(pl1, degans`maxnon) /= 0)}]):
      NOT null?(cdr(pl)) AND NOT (null?(cdr(pl)) AND car(pl) = 0) IMPLIES
       (FORALL (upans:
                  {degans:
                     [# allzero: bool, maxnon: below(length(cdr(pl))) #] |
                           (degans`allzero IFF
                             (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                nth[rat](cdr[rat](pl), j) = 0))
                            AND
                            (degans`allzero OR
                              (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                 j > degans`maxnon IMPLIES
                                  nth[rat](cdr[rat](pl), j) = 0))
                             AND
                             (degans`allzero OR
                               nth[rat](cdr[rat](pl), degans`maxnon) /= 0)}):
          upans = v(cdr(pl)) IMPLIES
           (FORALL (upvalid: bool):
              car(pl) = 0 AND NOT upvalid AND upvalid = (NOT upans`allzero)
               IMPLIES
               (TRUE IFF
                 (FORALL (j: below(length[rat](pl))): nth[rat](pl, j) = 0))));

  % Subtype TCC generated (at line 118, column 34) for  0
      % expected type  below(length(pl))
  deg_rec_TCC10: OBLIGATION
    FORALL (pl: Polylist,
            v:
              [pl1: {z: Polylist | length(z) < length(pl)} ->
                 {degans: [# allzero: bool, maxnon: below(length(pl1)) #] |
                          (degans`allzero IFF
                            (FORALL (j: below(length(pl1))):
                               nth(pl1, j) = 0))
                           AND
                           (degans`allzero OR
                             (FORALL (j: below(length(pl1))):
                                j > degans`maxnon IMPLIES nth(pl1, j) = 0))
                            AND
                            (degans`allzero OR
                              nth(pl1, degans`maxnon) /= 0)}]):
      NOT null?(cdr(pl)) AND NOT (null?(cdr(pl)) AND car(pl) = 0) IMPLIES
       (FORALL (upans:
                  {degans:
                     [# allzero: bool, maxnon: below(length(cdr(pl))) #] |
                           (degans`allzero IFF
                             (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                nth[rat](cdr[rat](pl), j) = 0))
                            AND
                            (degans`allzero OR
                              (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                 j > degans`maxnon IMPLIES
                                  nth[rat](cdr[rat](pl), j) = 0))
                             AND
                             (degans`allzero OR
                               nth[rat](cdr[rat](pl), degans`maxnon) /= 0)}):
          upans = v(cdr(pl)) IMPLIES
           (FORALL (upvalid: bool):
              NOT car(pl) = 0 AND
               NOT upvalid AND upvalid = (NOT upans`allzero)
               IMPLIES 0 < length[rat](pl)));

  % Subtype TCC generated (at line 118, column 8) for
      % (# allzero := FALSE, maxnon := 0 #)
      % expected type  {degans:
                     %    [# allzero: bool, maxnon: below(length(pl)) #] |
                     %          (degans`allzero IFF
                     %            (FORALL (j: below(length(pl))):
                     %               nth(pl, j) = 0))
                     %           AND
                     %           (degans`allzero OR
                     %             (FORALL (j: below(length(pl))):
                     %                j > degans`maxnon
                     %                IMPLIES
                     %                nth(pl, j) = 0))
                     %            AND
                     %            (degans`allzero OR
                     %              nth(pl, degans`maxnon) /= 0)}
  deg_rec_TCC11: OBLIGATION
    FORALL (pl: Polylist,
            v:
              [pl1: {z: Polylist | length(z) < length(pl)} ->
                 {degans: [# allzero: bool, maxnon: below(length(pl1)) #] |
                          (degans`allzero IFF
                            (FORALL (j: below(length(pl1))):
                               nth(pl1, j) = 0))
                           AND
                           (degans`allzero OR
                             (FORALL (j: below(length(pl1))):
                                j > degans`maxnon IMPLIES nth(pl1, j) = 0))
                            AND
                            (degans`allzero OR
                              nth(pl1, degans`maxnon) /= 0)}]):
      NOT null?(cdr(pl)) AND NOT (null?(cdr(pl)) AND car(pl) = 0) IMPLIES
       (FORALL (upans:
                  {degans:
                     [# allzero: bool, maxnon: below(length(cdr(pl))) #] |
                           (degans`allzero IFF
                             (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                nth[rat](cdr[rat](pl), j) = 0))
                            AND
                            (degans`allzero OR
                              (FORALL (j: below(length[rat](cdr[rat](pl)))):
                                 j > degans`maxnon IMPLIES
                                  nth[rat](cdr[rat](pl), j) = 0))
                             AND
                             (degans`allzero OR
                               nth[rat](cdr[rat](pl), degans`maxnon) /= 0)}):
          upans = v(cdr(pl)) IMPLIES
           (FORALL (upvalid: bool):
              NOT car(pl) = 0 AND
               NOT upvalid AND upvalid = (NOT upans`allzero)
               IMPLIES
               (FALSE IFF
                 (FORALL (j: below(length[rat](pl))): nth[rat](pl, j) = 0))
                AND
                (FORALL (j: below(length[rat](pl))):
                   j > 0 IMPLIES nth[rat](pl, j) = 0)
                 AND nth[rat](pl, 0) /= 0));

  % Subtype TCC generated (at line 127, column 27) for  0
      % expected type  {d: below(length(pl)) |
                     %          (d > 0 IFF
                     %            (EXISTS (j: below(length(pl))):
                     %               j > 0 AND nth(pl, j) /= 0))
                     %           AND
                     %           (d > 0 IMPLIES
                     %             (FORALL (j: below(length(pl))):
                     %                j > d IMPLIES nth(pl, j) = 0))
                     %            AND (d > 0 IMPLIES nth(pl, d) /= 0)}
  deg_TCC1: OBLIGATION
    FORALL (pl: Polylist,
            drec:
              {degans: [# allzero: bool, maxnon: below(length(pl)) #] |
                       (degans`allzero IFF
                         (FORALL (j: below(length[rat](pl))):
                            nth[rat](pl, j) = 0))
                        AND
                        (degans`allzero OR
                          (FORALL (j: below(length[rat](pl))):
                             j > degans`maxnon IMPLIES nth[rat](pl, j) = 0))
                         AND
                         (degans`allzero OR
                           nth[rat](pl, degans`maxnon) /= 0)}):
      drec`allzero AND drec = deg_rec(pl) IMPLIES
       ((0 > 0 IFF
          (EXISTS (j: below(length[rat](pl))):
             j > 0 AND nth[rat](pl, j) /= 0))
         AND
         (0 > 0 IMPLIES
           (FORALL (j: below(length[rat](pl))):
              j > 0 IMPLIES nth[rat](pl, j) = 0))
          AND (0 > 0 IMPLIES nth[rat](pl, 0) /= 0))
        AND 0 < length[rat](pl);

  % Subtype TCC generated (at line 127, column 34) for  drec`maxnon
      % expected type  {d: below(length(pl)) |
                     %          (d > 0 IFF
                     %            (EXISTS (j: below(length(pl))):
                     %               j > 0 AND nth(pl, j) /= 0))
                     %           AND
                     %           (d > 0 IMPLIES
                     %             (FORALL (j: below(length(pl))):
                     %                j > d IMPLIES nth(pl, j) = 0))
                     %            AND (d > 0 IMPLIES nth(pl, d) /= 0)}
  deg_TCC2: OBLIGATION
    FORALL (pl: Polylist,
            drec:
              {degans: [# allzero: bool, maxnon: below(length(pl)) #] |
                       (degans`allzero IFF
                         (FORALL (j: below(length[rat](pl))):
                            nth[rat](pl, j) = 0))
                        AND
                        (degans`allzero OR
                          (FORALL (j: below(length[rat](pl))):
                             j > degans`maxnon IMPLIES nth[rat](pl, j) = 0))
                         AND
                         (degans`allzero OR
                           nth[rat](pl, degans`maxnon) /= 0)}):
      NOT drec`allzero AND drec = deg_rec(pl) IMPLIES
       (drec`maxnon > 0 IFF
         (EXISTS (j: below(length[rat](pl))):
            j > 0 AND nth[rat](pl, j) /= 0))
        AND
        (drec`maxnon > 0 IMPLIES
          (FORALL (j: below(length[rat](pl))):
             j > drec`maxnon IMPLIES nth[rat](pl, j) = 0))
         AND (drec`maxnon > 0 IMPLIES nth[rat](pl, drec`maxnon) /= 0);

  % Subtype TCC generated (at line 142, column 35) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  polylist_monom_TCC1: OBLIGATION FORALL (n: nat, x: real): x /= 0 OR n >= 0;

  % Subtype TCC generated (at line 157, column 40) for  n
      % expected type  {i: int | polylist(pl)(x) /= 0 OR i >= 0}
  polylist_pow_TCC1: OBLIGATION
    FORALL (n: nat, pl: Polylist, x: real): polylist(pl)(x) /= 0 OR n >= 0;


body:
  poly_strategy : THEORY 
  BEGIN

    IMPORTING polylist,compute_sturm

    pl : VAR Polylist
    I  : VAR RealInt

    realord: VAR (SturmRel?)

    sturm((pl|deg(pl)>0),(I|I`lb<I`ub),realord): bool =
      compute_poly_sat_rational(list2array[rat](0)(pl),deg(pl),I,realord)

    sturm_def: LEMMA 
      I`lb<I`ub AND 
      (deg(pl)>0 OR (EXISTS (j:below(length(pl))):j>0 AND nth(pl,j)/=0))
      IMPLIES
      (sturm(pl,I,realord) IFF
       (FORALL (x:real): contains?(I)(x) IMPLIES realord(polylist(pl)(x),0)))

  END poly_strategy

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

  % Subtype TCC generated (at line 12, column 53) for  deg(pl)
      % expected type  {n | list2array[rat](0)(pl)(n) /= 0}
  sturm_TCC1: OBLIGATION
    FORALL ((pl: Polylist | deg(pl) > 0), (I: RealInt | I`lb < I`ub),
            realord: (SturmRel?)):
      deg(pl) > 0 AND list2array[rat](0)(pl)(deg(pl)) /= 0;

  % Subtype TCC generated (at line 18, column 11) for  pl
      % expected type  {pl | deg(pl) > 0}
  sturm_def_TCC1: OBLIGATION
    FORALL (I: RealInt, pl: Polylist):
      (deg(pl) > 0 OR
        (EXISTS (j: below(length(pl))): j > 0 AND nth(pl, j) /= 0))
       AND I`lb < I`ub
       IMPLIES deg(pl) > 0;


body:
  strategies : THEORY
  BEGIN

    IMPORTING poly_strategy, 
              structures@Unit,
              reals@abs_lems,
              interval_arith@interval
    
    %% This constant is used by the strategies to check if all the required theories 
    %% have been imported in the current context

    SturmStrategy__ : Unit 

  END strategies


body:
  examples: THEORY
  BEGIN

    IMPORTING 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 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;


