# TheoryBodies

body:
  OutBoxes_adt_reduce[n: posnat, range: TYPE]: THEORY
   BEGIN

    IMPORTING OutBoxes_adt[n]

    IMPORTING boxes_def

    reduce(unknown_box?_fun: range, full_box?_fun: range,
           empty_box?_fun: range, boxes?_fun: [Boxes(n) -> range]):
          [OutBoxes[n] -> range] =
        LAMBDA (OutBoxes_adtvar: OutBoxes[n]):
          LET red: [OutBoxes[n] -> range] =
                reduce(unknown_box?_fun, full_box?_fun, empty_box?_fun,
                       boxes?_fun)
            IN
            CASES OutBoxes_adtvar
              OF UnknownBox: unknown_box?_fun,
                 FullBox: full_box?_fun,
                 EmptyBox: empty_box?_fun,
                 Output(Output1_var): boxes?_fun(Output1_var)
              ENDCASES;

    REDUCE(unknown_box?_fun: [OutBoxes[n] -> range],
           full_box?_fun: [OutBoxes[n] -> range],
           empty_box?_fun: [OutBoxes[n] -> range],
           boxes?_fun: [[Boxes(n), OutBoxes[n]] -> range]):
          [OutBoxes[n] -> range] =
        LAMBDA (OutBoxes_adtvar: OutBoxes[n]):
          LET red: [OutBoxes[n] -> range] =
                REDUCE(unknown_box?_fun, full_box?_fun, empty_box?_fun,
                       boxes?_fun)
            IN
            CASES OutBoxes_adtvar
              OF UnknownBox: unknown_box?_fun(OutBoxes_adtvar),
                 FullBox: full_box?_fun(OutBoxes_adtvar),
                 EmptyBox: empty_box?_fun(OutBoxes_adtvar),
                 Output(Output1_var):
                   boxes?_fun(Output1_var, OutBoxes_adtvar)
              ENDCASES;
   END OutBoxes_adt_reduce


body:
  %%% ADT file generated from Outcome

  Outcome_adt: THEORY
   BEGIN

    Outcome: TYPE

    IMPORTING list[real]

    istrue?, isfalse?, unknown?: [Outcome -> boolean]

    counterexample: [(isfalse?) -> (cons?)]

    IsTrue: (istrue?)

    Counterexample: [(cons?) -> (isfalse?)]

    Unknown: (unknown?)

    Outcome_ord: [Outcome -> upto(2)]

    Outcome_ord_defaxiom: AXIOM
      Outcome_ord(IsTrue) = 0 AND
       (FORALL (counterexample: (cons?)):
          Outcome_ord(Counterexample(counterexample)) = 1)
        AND Outcome_ord(Unknown) = 2;

    ord(x: Outcome): [Outcome -> upto(2)] =
        CASES x
          OF IsTrue: 0, Counterexample(Counterexample1_var): 1, Unknown: 2
          ENDCASES

    Outcome_IsTrue_extensionality: AXIOM
      FORALL (istrue?_var: (istrue?), istrue?_var2: (istrue?)):
        istrue?_var = istrue?_var2;

    Outcome_Counterexample_extensionality: AXIOM
      FORALL (isfalse?_var: (isfalse?), isfalse?_var2: (isfalse?)):
        counterexample(isfalse?_var) = counterexample(isfalse?_var2) IMPLIES
         isfalse?_var = isfalse?_var2;

    Outcome_Counterexample_eta: AXIOM
      FORALL (isfalse?_var: (isfalse?)):
        Counterexample(counterexample(isfalse?_var)) = isfalse?_var;

    Outcome_Unknown_extensionality: AXIOM
      FORALL (unknown?_var: (unknown?), unknown?_var2: (unknown?)):
        unknown?_var = unknown?_var2;

    Outcome_counterexample_Counterexample: AXIOM
      FORALL (Counterexample1_var: (cons?)):
        counterexample(Counterexample(Counterexample1_var)) =
         Counterexample1_var;

    Outcome_inclusive: AXIOM
      FORALL (Outcome_var: Outcome):
        istrue?(Outcome_var) OR
         isfalse?(Outcome_var) OR unknown?(Outcome_var);

    Outcome_induction: AXIOM
      FORALL (p: [Outcome -> boolean]):
        p(IsTrue) AND
         (FORALL (Counterexample1_var: (cons?)):
            p(Counterexample(Counterexample1_var)))
          AND p(Unknown)
         IMPLIES (FORALL (Outcome_var: Outcome): p(Outcome_var));

    subterm(x: Outcome, y: Outcome):  boolean = x = y;

    <<:  (strict_well_founded?[Outcome]) = LAMBDA (x, y: Outcome): FALSE;

    Outcome_well_founded: AXIOM strict_well_founded?[Outcome](<<);

    reduce_nat(istrue?_fun: nat, isfalse?_fun: [(cons?) -> nat],
               unknown?_fun: nat):
          [Outcome -> nat] =
        LAMBDA (Outcome_adtvar: Outcome):
          LET red: [Outcome -> nat] =
                reduce_nat(istrue?_fun, isfalse?_fun, unknown?_fun)
            IN
            CASES Outcome_adtvar
              OF IsTrue: istrue?_fun,
                 Counterexample(Counterexample1_var):
                   isfalse?_fun(Counterexample1_var),
                 Unknown: unknown?_fun
              ENDCASES;

    REDUCE_nat(istrue?_fun: [Outcome -> nat],
               isfalse?_fun: [[(cons?), Outcome] -> nat],
               unknown?_fun: [Outcome -> nat]):
          [Outcome -> nat] =
        LAMBDA (Outcome_adtvar: Outcome):
          LET red: [Outcome -> nat] =
                REDUCE_nat(istrue?_fun, isfalse?_fun, unknown?_fun)
            IN
            CASES Outcome_adtvar
              OF IsTrue: istrue?_fun(Outcome_adtvar),
                 Counterexample(Counterexample1_var):
                   isfalse?_fun(Counterexample1_var, Outcome_adtvar),
                 Unknown: unknown?_fun(Outcome_adtvar)
              ENDCASES;

    reduce_ordinal(istrue?_fun: ordinal, isfalse?_fun: [(cons?) -> ordinal],
                   unknown?_fun: ordinal):
          [Outcome -> ordinal] =
        LAMBDA (Outcome_adtvar: Outcome):
          LET red: [Outcome -> ordinal] =
                reduce_ordinal(istrue?_fun, isfalse?_fun, unknown?_fun)
            IN
            CASES Outcome_adtvar
              OF IsTrue: istrue?_fun,
                 Counterexample(Counterexample1_var):
                   isfalse?_fun(Counterexample1_var),
                 Unknown: unknown?_fun
              ENDCASES;

    REDUCE_ordinal(istrue?_fun: [Outcome -> ordinal],
                   isfalse?_fun: [[(cons?), Outcome] -> ordinal],
                   unknown?_fun: [Outcome -> ordinal]):
          [Outcome -> ordinal] =
        LAMBDA (Outcome_adtvar: Outcome):
          LET red: [Outcome -> ordinal] =
                REDUCE_ordinal(istrue?_fun, isfalse?_fun, unknown?_fun)
            IN
            CASES Outcome_adtvar
              OF IsTrue: istrue?_fun(Outcome_adtvar),
                 Counterexample(Counterexample1_var):
                   isfalse?_fun(Counterexample1_var, Outcome_adtvar),
                 Unknown: unknown?_fun(Outcome_adtvar)
              ENDCASES;
   END Outcome_adt


body:
  Outcome_adt_reduce[range: TYPE]: THEORY
   BEGIN

    IMPORTING Outcome_adt

    IMPORTING list[real]

    reduce(istrue?_fun: range, isfalse?_fun: [(cons?) -> range],
           unknown?_fun: range):
          [Outcome -> range] =
        LAMBDA (Outcome_adtvar: Outcome):
          LET red: [Outcome -> range] =
                reduce(istrue?_fun, isfalse?_fun, unknown?_fun)
            IN
            CASES Outcome_adtvar
              OF IsTrue: istrue?_fun,
                 Counterexample(Counterexample1_var):
                   isfalse?_fun(Counterexample1_var),
                 Unknown: unknown?_fun
              ENDCASES;

    REDUCE(istrue?_fun: [Outcome -> range],
           isfalse?_fun: [[(cons?), Outcome] -> range],
           unknown?_fun: [Outcome -> range]):
          [Outcome -> range] =
        LAMBDA (Outcome_adtvar: Outcome):
          LET red: [Outcome -> range] =
                REDUCE(istrue?_fun, isfalse?_fun, unknown?_fun)
            IN
            CASES Outcome_adtvar
              OF IsTrue: istrue?_fun(Outcome_adtvar),
                 Counterexample(Counterexample1_var):
                   isfalse?_fun(Counterexample1_var, Outcome_adtvar),
                 Unknown: unknown?_fun(Outcome_adtvar)
              ENDCASES;
   END Outcome_adt_reduce


body:
  %------------------------------------------------------------------------------
  % top.pvs
  % ACCoRD v1.0
  %------------------------------------------------------------------------------

  top : THEORY
  BEGIN

    IMPORTING 

      %%%% Utilities and Constants
      util,
      horizontal_dist_convexity,
      vertical_dist_convexity,

      %%%% Basic Definitions 
      definitions,
      gs_only,
      trk_only,
      opt_trk_gs,

      %%%% Horizontal Criteria 
      horizontal,
      horizontal_criteria,
      horizontal_criterion_line,
      line_solutions,
      tangent_line,
      predicate_coordination_2D,

      %%%% Horizontal Resolutions
      trk_line,
      gs_line,
      opt_line,
      horizontal_cr,

      %%%% Loss of Separation
      repulsive,
      horizontal_los_criterion,
      horizontal_los,
      vertical_los_criterion,
      vertical_los_crit_CA,
  %    vertical_los,

      %%%% Vertical Conflict Detection
      cd_vertical,

      %%%% 2-D Conflict Detection 
      omega_v2,
      horizontal_sq_dtca,
      cd2d,
      cd2d_inf,
      cd3d_inf,

      %%%% 2-D Bands
      bands_util,
      gs_bands_2D,
      track,
      trk_bands_2D,
      bands_2D,

      %%%% 1-D Vertical Criteria
      vertical,
      vz_criteria,

      %%%% 3-D Criteria
      space_3D,
      circle_criterion,
      vertical_criterion,
      circle_solutions,
      predicate_coordination,
      criteria_3D,

      %%%% 3-D Horizonal Resolution Algorithms
      gs_circle,
      trk_circle,
      opt_vertical,

      %%%% Vertical Resolution Algorithms
      vs_only,
      vs_circle,
      vertical_cr,

      %%%% 3-D Conflict Detection 
      cd3d,
      cd_sphere,
      delay_3D,
      tca_3D,
      tca_3D_interval,

      %%%% Conflict Resolution
      cr3d,

      %%%% 3-D Bands
      vs_bands,
      bands_3D,

      %%%% Other Algorithms
  %    repulsive_turn,
      repulsive_iterative,
      losr_iterative,
      kb,  % Karl Bilimoria's Geometric Optimization
  %    mvp, % Modified Voltage Potential

      %%%% Flight plans
      flightplan,

      %%%% Conflict detection for state-based ownship and intent-based intruder
      cd3d_si,

      %%%% Conflict detection for intent-based ownship and intruder
      cd3d_ii,

      %%%% Prevention bands for state-based ownship and intent-based intruder
      bands_si,

      %%%% Auxilliary files for fseqs

      fseqs_aux_2D,
      fseqs_aux_vertical%,

      %%%% Higher level functions used in Java and C++
  %    java_connection

  END top


body:
  fseqs_aux_vertical[vsmin,vsmax:real] : THEORY
  BEGIN

    IMPORTING structures@sort_fseq[real,<=],
  	    structures@fseqs_ops[real],
              trig_fnd@to2pi

    vs,fs   : VAR fseq


    %%%%% Vertical Speed %%%%%

    vs_fseq?(vs): bool =
      FORALL (i:below(vs`length)): vsmin<=vs`seq(i) AND vs`seq(i)<=vsmax

    vsb,vsb1,vsb2 : VAR (vs_fseq?)

    empty_vs_fseq : JUDGEMENT
      emptyseq HAS_TYPE (vs_fseq?)

    comp_vs_fseq : JUDGEMENT
      o(vsb1,vsb2) HAS_TYPE (vs_fseq?)

    sort_vs_fseq : JUDGEMENT
      sort(vsb) HAS_TYPE (vs_fseq?)

  END fseqs_aux_vertical

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

  % Judgement subtype TCC generated (at line 19, column 4) for  emptyseq
      % expected type  (vs_fseq?)
  empty_vs_fseq: OBLIGATION
    (FORALL (i: nat):
       i >= emptyseq[real]`length IMPLIES
        emptyseq[real]`seq(i) = default[real])
     AND vs_fseq?(emptyseq[real]);

  % Judgement subtype TCC generated (at line 22, column 4) for  vsb1 o vsb2
      % expected type  (vs_fseq?)
  comp_vs_fseq: OBLIGATION FORALL (vsb1, vsb2): vs_fseq?(o[real](vsb1, vsb2));

  % Judgement subtype TCC generated (at line 25, column 4) for  sort(vsb)
      % expected type  (vs_fseq?)
  sort_vs_fseq: OBLIGATION FORALL (vsb): vs_fseq?(sort[real, <=](vsb));


body:
  fseqs_aux_2D[gsmin,gsmax:posreal] : THEORY
  BEGIN

    IMPORTING structures@sort_fseq[real,<=],
  	    structures@fseqs_ops[real],
              trig_fnd@to2pi

    vs,fs   : VAR fseq

    %%%%% Track Angle %%%%%

    trk_fseq?(fs): bool = 
      FORALL (i:below(fs`length)): 0 <= fs`seq(i) AND fs`seq(i) <= 2*pi 

    empty_trk_fseq : JUDGEMENT
      emptyseq HAS_TYPE (trk_fseq?)

    trkb,trkb1,trkb2 : VAR (trk_fseq?)

    comp_trk_fseq : JUDGEMENT
      o(trkb1,trkb2) HAS_TYPE (trk_fseq?)

    sort_trk_fseq : JUDGEMENT
      sort(trkb) HAS_TYPE (trk_fseq?)

    %%%%% Ground Speed %%%%%

    gs_fseq?(fs) : bool = 
      FORALL (i:below(fs`length)): gsmin<=fs`seq(i) AND fs`seq(i)<=gsmax

   gsb,gsb1,gsb2 : VAR (gs_fseq?)

    empty_gs_fseq : JUDGEMENT
      emptyseq HAS_TYPE (gs_fseq?)

    comp_gs_fseq : JUDGEMENT
      o(gsb1,gsb2) HAS_TYPE (gs_fseq?)

    sort_gs_fseq : JUDGEMENT
      sort(gsb) HAS_TYPE (gs_fseq?)


  END fseqs_aux_2D

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

  % Judgement subtype TCC generated (at line 16, column 4) for  emptyseq
      % expected type  (trk_fseq?)
  empty_trk_fseq: OBLIGATION
    (FORALL (i: nat):
       i >= emptyseq[real]`length IMPLIES
        emptyseq[real]`seq(i) = default[real])
     AND trk_fseq?(emptyseq[real]);

  % Judgement subtype TCC generated (at line 21, column 4) for  trkb1 o trkb2
      % expected type  (trk_fseq?)
  comp_trk_fseq: OBLIGATION
    FORALL (trkb1, trkb2): trk_fseq?(o[real](trkb1, trkb2));

  % Judgement subtype TCC generated (at line 24, column 4) for  sort(trkb)
      % expected type  (trk_fseq?)
  sort_trk_fseq: OBLIGATION FORALL (trkb): trk_fseq?(sort[real, <=](trkb));

  % Judgement subtype TCC generated (at line 34, column 4) for  emptyseq
      % expected type  (gs_fseq?)
  empty_gs_fseq: OBLIGATION
    (FORALL (i: nat):
       i >= emptyseq[real]`length IMPLIES
        emptyseq[real]`seq(i) = default[real])
     AND gs_fseq?(emptyseq[real]);

  % Judgement subtype TCC generated (at line 37, column 4) for  gsb1 o gsb2
      % expected type  (gs_fseq?)
  comp_gs_fseq: OBLIGATION FORALL (gsb1, gsb2): gs_fseq?(o[real](gsb1, gsb2));

  % Judgement subtype TCC generated (at line 40, column 4) for  sort(gsb)
      % expected type  (gs_fseq?)
  sort_gs_fseq: OBLIGATION FORALL (gsb): gs_fseq?(sort[real, <=](gsb));


body:
  %------------------------------------------------------------------------------
  % definitions.pvs
  % ACCoRD v1.0
  %------------------------------------------------------------------------------

  definitions : THEORY
  BEGIN

    IMPORTING vectors@vectors_2D, 
  	    vectors@det_2D, 
              vectors@closest_approach_2D,
              reals@quad_minmax

    s,v,w,
    vo,vi,
    vo1,vo2 : VAR Vect2
    dir     : VAR Sign
    nzs,nzv : VAR Nz_vect2
    t,k,j   : VAR real
    nzj     : VAR nzreal
    t1,t2   : VAR nnreal
    sz,vz   : VAR real
    nzvz    : VAR nzreal

    Entry  : MACRO Sign = -1
    Exit   : MACRO Sign =  1

    %------------------------------------------------------------------------------
    % Horizontal Definitions
    %------------------------------------------------------------------------------

    %% horizontal_dir?(s,v,Entry) if s,v points towards (0,0)
    %% horizontal_dir?(s,v,Exit) if s,v, points away from (0,0)

    horizontal_dir?(s,v,dir) : MACRO bool =
      dir*(s*v) >= 0

    horizontal_dir_at?(s,v,t,dir) : MACRO bool =
      horizontal_dir?(s+t*v,v,dir)

    horizontal_entry?(s,v) : MACRO bool = 
      horizontal_dir?(s,v,Entry)

    horizontal_entry_at?(s,v,t) : MACRO bool =
      horizontal_entry?(s+t*v,v)

    horizontal_exit?(s,v)  : MACRO bool = 
      horizontal_dir?(s,v,Exit)

    horizontal_exit_at?(s,v,t) : MACRO bool =
      horizontal_exit?(s+t*v,v)

    horizontal_tangent?(s,v) : MACRO bool = 
      s*v = 0

    horizontal_diverging?(s,v) : MACRO bool =
      s*v > 0 

    horizontal_converging?(s,v) : MACRO bool =
      s*v < 0

    % Returns the eps that determines the closest horizontal tangent to relative 
    % velocity vector v
    horizontalCoordination(s,v) : Sign =
      sign(det(v,s))

    % HorizontalCoordinationConflict is an horizontal strategy
    horizontalCoordination_symm : LEMMA
      horizontalCoordination(-s,-v) = horizontalCoordination(s,v)

    Horizontal_Strategy : TYPE+ = {f:[[Vect2,Vect2]->Sign]| FORALL (s,v):f(-s,-v)=f(s,v)} 

    horizontalCoordination_strategy : JUDGEMENT
      horizontalCoordination HAS_TYPE Horizontal_Strategy

    % Time of closest approach
    horizontal_tca(s,nzv) : real =
      -(s*nzv)/sqv(nzv) 

    horizontal_tca_gt_0 : LEMMA
       horizontal_converging?(s,v) IMPLIES horizontal_tca(s,v) > 0

    horizontal_tca_nzv_gt_0 : LEMMA
       horizontal_converging?(s,nzv) IFF horizontal_tca(s,nzv) > 0

    horizontal_tca_lt_0 : LEMMA
       horizontal_diverging?(s,v) IMPLIES horizontal_tca(s,v) < 0

    horizontal_tca_nzv_lt_0 : LEMMA
       horizontal_diverging?(s,nzv) IFF horizontal_tca(s,nzv) < 0

    horizontal_tca_dot_zero: LEMMA
      (s+horizontal_tca(s,nzv)*nzv)*nzv = 0

    % Square of distance at time of closest approach
    horizontal_sq_dtca(s,nzv) : real = 
      sq(det(s,nzv))/sqv(nzv)

    horizontal_sq_dtca_eq : LEMMA
      horizontal_sq_dtca(s,nzv) = sqv(s+horizontal_tca(s,nzv)*nzv)

    horizontal_tca_min : LEMMA
      horizontal_sq_dtca(s,nzv) <= sqv(s+t*nzv)

    sqv_decreasing_before_horizontal_tca: LEMMA
      LET htca = horizontal_tca(s,nzv) IN
        FORALL (tr1,tr2:real): (tr1<=htca AND tr2<=htca) IMPLIES
          (tr1<tr2 IFF sqv(s+tr1*nzv)>sqv(s+tr2*nzv))

    sqv_increasing_after_horizontal_tca: LEMMA
      LET htca = horizontal_tca(s,nzv) IN
        FORALL (tr1,tr2:real): (tr1>=htca AND tr2>=htca) IMPLIES
          (tr1>tr2 IFF sqv(s+tr1*nzv)>sqv(s+tr2*nzv))

    % Velocity vector comparison with respect to a vector
    le?(v)(vo1,vo2): bool =
      norm(vo1-v) <= norm(vo2-v)

    le_rel : LEMMA
      le?(vo-vi)(vo1-vi,vo2-vi) IFF le?(vo)(vo1,vo2)

    % Vdir is a vector perpendicular to nzs that points in the same 
    % direction as v
    Vdir(nzs,v) : Nz_vect2 =  
      LET ps = perpR(nzs) IN
      sign(ps*v)*ps

    % Vdir(s,v) is perpendicular to s
    Vdir_perp : LEMMA
     nzs*Vdir(nzs,v) = 0

    % W0(s,j) is a vector such that s*W0(s,j) = j
    W0(nzs,j) : Vect2 =
      (j/sqv(nzs))*nzs
   
    W0_dot : LEMMA
      nzs*W0(nzs,j) = j

    nz_W0 : JUDGEMENT
      W0(nzs,nzj) HAS_TYPE Nz_vect2

    % W is a parametric vector that represents the equation: nzs*W=j
    % if k is positive W points in the same direction as v
    W(nzs,v,k)(j) : MACRO Vect2 = 
      W0(nzs,j)+k*Vdir(nzs,v)

    nz_W : JUDGEMENT
      W(nzs,v,k)(nzj) HAS_TYPE Nz_vect2

    W_dot : LEMMA
      nzs*W(nzs,v,k)(j) = j

    dot_W : LEMMA
      nzs*w = j IFF
      EXISTS (k) : w = W(nzs,v,k)(j) 

    s_dot_Vdir_eq_0: LEMMA
      nzs*Vdir(nzs,v) = 0

    W0_dot_Vdir_eq_0: LEMMA
      W0(nzs,j)*Vdir(nzs,v) = 0

    norm_W0_ge: LEMMA
      t1 >= t2 AND
      j >= 0 IMPLIES
      norm(nzs+t1*W0(nzs,j)) >= norm(nzs+t2*W0(nzs,j))

    divergent?(s,v): MACRO bool =
      divergent?(s,zero,v,zero)

    dot_pos_divergent : LEMMA 
      s * v > 0 IMPLIES divergent?(s,v)

    dot_nneg_divergent: LEMMA
      s*nzv >= 0 IFF divergent?(s,nzv)

    gs(v) : nnreal = norm(v)

    gs_nz : JUDGEMENT
      gs(nzv) HAS_TYPE posreal

    %%
    %% Ground Speed Only Solutions 
    %%

    gs_only?(vo1)(vo2) : bool =
      EXISTS (l:posreal): vo2 = l*vo1

    gs_only_id : LEMMA
      gs_only?(v)(v)

    gs_only_scal : LEMMA
      FORALL (l:posreal):
        gs_only?(v)(l*v)

    gs_only_symm : LEMMA
      gs_only?(vo1)(vo2) IFF gs_only?(vo2)(vo1)

    gs_only_trans : LEMMA
      gs_only?(vo)(vo1) AND gs_only?(vo1)(vo2) IMPLIES
      gs_only?(vo)(vo2)

    gs_only_normalize : LEMMA
      gs_only?(nzv)(v) IFF
      EXISTS (k:posreal): v = k*^(nzv)

    gs_only_zero_left : LEMMA
      gs_only?(zero)(v) IFF v = zero

    gs_only_zero_right : LEMMA
      gs_only?(v)(zero) IFF v = zero

    %%
    %% Track Only Solutions 
    %%

    trk_only?(vo1)(vo2) : bool =
      norm(vo2) = norm(vo1)

    trk_only_id : LEMMA
      trk_only?(v)(v)

    trk_only_symm : LEMMA
      trk_only?(vo1)(vo2) IFF trk_only?(vo2)(vo1)

    trk_only_zero_left : LEMMA
      trk_only?(zero)(v) IFF v = zero

    trk_only_zero_right : LEMMA
      trk_only?(v)(zero) IFF v = zero

    %%
    %% Optimal Solutions 
    %%

    optimal?(vo,nzv)(vo1) : bool =
      FORALL (vo2) : parallel?(vo2-vo1,nzv) IMPLIES le?(vo)(vo1,vo2)

    optimal_id : LEMMA
       optimal?(vo,nzv)(vo)

    %------------------------------------------------------------------------------
    % Vertical Definitions
    %------------------------------------------------------------------------------

    %% vertical_dir?(sz,vz,Entry) if sz,vz points towards   0
    %% vertical_dir?(sz,vz,Exit) if sz,vz points away from 0

    vertical_dir?(sz,vz,dir) : MACRO bool =
      dir*(sz*vz) >= 0

    vertical_dir_at?(sz,vz,t,dir) : MACRO bool =
      vertical_dir?(sz+t*vz,vz,dir)   

    vertical_entry?(sz,vz) : MACRO bool = vertical_dir?(sz,vz,Entry)

    vertical_exit?(sz,vz) : MACRO bool = vertical_dir?(sz,vz,Exit)

    vertical_tau(sz,nzvz) : real = 
      -sz/nzvz 

    z_at_vertical_tau_eq_0 : LEMMA
      sz + vertical_tau(sz,nzvz)*nzvz = 0

  END definitions

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

  % Existence TCC generated (at line 71, column 2) for
      % Horizontal_Strategy: TYPE+ =
      %       {f: [[Vect2, Vect2] -> Sign] |
      %                FORALL (s, v): f(-s, -v) = f(s, v)}
  Horizontal_Strategy_TCC1: OBLIGATION
    EXISTS (x:
              {f: [[Vect2, Vect2] -> Sign] |
                       FORALL (s, v): f(-s, -v) = f(s, v)}):
      TRUE;

  % Judgement subtype TCC generated (at line 74, column 4) for
      % horizontalCoordination
      % expected type  Horizontal_Strategy
  horizontalCoordination_strategy: OBLIGATION
    FORALL (s, v):
      horizontalCoordination(-s, -v) = horizontalCoordination(s, v);

  % Subtype TCC generated (at line 81, column 58) for  v
      % expected type  Nz_vect2
  horizontal_tca_gt_0_TCC1: OBLIGATION
    FORALL (s, v: Vect2): s * v < 0 IMPLIES v /= zero;

  % Subtype TCC generated (at line 87, column 57) for  v
      % expected type  Nz_vect2
  horizontal_tca_lt_0_TCC1: OBLIGATION
    FORALL (s, v: Vect2): s * v > 0 IMPLIES v /= zero;

  % Judgement subtype TCC generated (at line 140, column 4) for  W0(nzs, nzj)
      % expected type  Nz_vect2
  nz_W0: OBLIGATION FORALL (nzj, nzs): W0(nzs, nzj) /= zero;

  % Judgement subtype TCC generated (at line 145, column 4) for
      % W0(nzs, nzj) + k * Vdir(nzs, v)
      % expected type  Nz_vect2
  nz_W: OBLIGATION
    FORALL (k, nzj, nzs, v): W0(nzs, nzj) + k * Vdir(nzs, v) /= zero;

  % Judgement subtype TCC generated (at line 180, column 4) for  gs(nzv)
      % expected type  posreal
  gs_nz: OBLIGATION FORALL (nzv): gs(nzv) > 0;


body:
  track : THEORY
  BEGIN 

    IMPORTING trig_fnd@to2pi,
              definitions

     trk        : VAR real
     s,v,vi,nvo : VAR Nz_vect2
     gsp        : VAR posreal

    trkgs2vect(trk,gsp) : Nz_vect2 =
      gsp*(sin(trk),cos(trk))

    track(v) : nnreal_lt_2pi =
      atan2(v`y,v`x)

    sin_track : LEMMA
      sin(track(v)) = v`x/norm(v)

    cos_track : LEMMA
      cos(track(v)) = v`y/norm(v)

    norm_id : LEMMA
      norm(trkgs2vect(trk,gsp)) = gsp

    track_id : LEMMA
      track(trkgs2vect(trk,gsp)) = to2pi(trk)

    trkgs2vect_id : LEMMA
      trkgs2vect(track(v),norm(v)) = v

    %% ordered eps=1 
    ordered_eps_1 : LEMMA
      abs(det(vi,s)/(norm(nvo)*norm(s))) <= 1 IMPLIES
      LET phi   = track(s),
          psi   = asin(det(vi,s)/(norm(nvo)*norm(s))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (det(nvo,s) > det(vi,s) IFF
       0 < to2pi(track(nvo)-alpha) AND to2pi(track(nvo)-alpha) < beta)

    ordered_det_ge : LEMMA
      abs(det(vi,s)/(norm(nvo)*norm(s))) <= 1 IMPLIES
      LET phi   = track(s),
          psi   = asin(det(vi,s)/(norm(nvo)*norm(s))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (det(nvo,s) >= det(vi,s) IFF
       0 <= to2pi(track(nvo)-alpha) AND to2pi(track(nvo)-alpha) <= beta)

    ordered_eps_neg_1 : LEMMA
      abs(det(vi,s)/(norm(nvo)*norm(s))) <= 1 IMPLIES
      LET phi   = track(s),
          psi   = asin(det(vi,s)/(norm(nvo)*norm(s))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (det(nvo,s) < det(vi,s) IFF
       beta < to2pi(track(nvo)-alpha) AND to2pi(track(nvo)-alpha) < 2*pi)

    %% ordered within eps = 1
    ordered_eps_1_dot_gt_0 : LEMMA
      abs(det(vi,s)/(norm(nvo)*norm(s))) <= 1 IMPLIES
      LET phi   = track(s),
          psi   = asin(det(vi,s)/(norm(nvo)*norm(s))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (det(nvo,s) > det(vi,s) AND nvo*s > 0 IFF
       0 < to2pi(track(nvo)-alpha) AND to2pi(track(nvo)-alpha) < beta/2)

    ordered_eps_1_dot_ge_0 : LEMMA
      abs(det(vi,s)/(norm(nvo)*norm(s))) <= 1 IMPLIES
      LET phi   = track(s),
          psi   = asin(det(vi,s)/(norm(nvo)*norm(s))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (det(nvo,s) > det(vi,s) AND nvo*s >= 0 IFF
       0 < to2pi(track(nvo)-alpha) AND to2pi(track(nvo)-alpha) <= beta/2)

    ordered_eps_1_dot_lt_0 : LEMMA
      abs(det(vi,s)/(norm(nvo)*norm(s))) <= 1 IMPLIES
      LET phi   = track(s),
          psi   = asin(det(vi,s)/(norm(nvo)*norm(s))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (det(nvo,s) > det(vi,s) AND nvo*s < 0 IFF
       beta/2 < to2pi(track(nvo)-alpha) AND to2pi(track(nvo)-alpha) < beta)

    ordered_eps_1_dot_le_0 : LEMMA
      abs(det(vi,s)/(norm(nvo)*norm(s))) <= 1 IMPLIES
      LET phi   = track(s),
          psi   = asin(det(vi,s)/(norm(nvo)*norm(s))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (det(nvo,s) > det(vi,s) AND nvo*s <= 0 IFF
       beta/2 <= to2pi(track(nvo)-alpha) AND to2pi(track(nvo)-alpha) < beta)

  END track

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

  % Subtype TCC generated (at line 12, column 4) for
      % gsp * (# x := sin(trk), y := cos(trk) #)
      % expected type  Nz_vect2
  trkgs2vect_TCC1: OBLIGATION
    FORALL (trk: real, gsp: posreal):
      gsp * (# x := sin(trk), y := cos(trk) #) /= zero;

  % Subtype TCC generated (at line 15, column 14) for  v`x
      % expected type  {z: real | v`y = 0 => z /= 0}
  track_TCC1: OBLIGATION FORALL (v: Nz_vect2): v`y = 0 => v`x /= 0;

  % Subtype TCC generated (at line 36, column 21) for
      % det(vi, s) / (norm(nvo) * norm(s))
      % expected type  real_abs_le1
  ordered_eps_1_TCC1: OBLIGATION
    FORALL (nvo, s, vi: Nz_vect2):
      abs(det(vi, s) / (norm(nvo) * norm(s))) <= 1 IMPLIES
       (FORALL (phi: nnreal_lt_2pi):
          phi = track(s) IMPLIES
           -1 <= det(vi, s) / (norm(nvo) * norm(s)) AND
            det(vi, s) / (norm(nvo) * norm(s)) <= 1);


body:
  %------------------------------------------------------------------------------
  % definitions_3D.pvs
  % ACCoRD v1.0
  %------------------------------------------------------------------------------

  definitions_3D : THEORY
  BEGIN

    IMPORTING definitions,
              vectors@vect_3D_2D
   
    s,v,
    vo1,vo2 : VAR Vect3
    nzs     : VAR Nz_vect3

    Zv2_vect3  : TYPE = {v | zero_vect2?(v)}
    Nzv2_vect3 : TYPE = {v | nz_vect2?(v)}

    nzv : VAR Nzv2_vect3

    nzv2 : JUDGEMENT
      vect2(nzv) HAS_TYPE Nz_vect2

  %%
  %% Symmetry breaking
  %%

    break_symmetry(s) : Sign = 
      IF s`z > 0 OR 
         s`z = 0 AND s`x > 0 OR
         s`z = 0 AND s`x = 0 AND s`y > 0 THEN 
         1
      ELSE
        -1
      ENDIF

    break_symmetry_neg : LEMMA
      break_symmetry(-nzs) = -break_symmetry(nzs)

  %%
  %% Kind of Resolutions 
  %%

    horizontal_only?(vo1)(vo2) : MACRO bool =
      vo1`z = vo2`z

    gs_only_3D?(vo1)(vo2) : MACRO bool =
      gs_only?(vo1)(vo2) AND
      vo1`z = vo2`z
    
    gsho : JUDGEMENT
      (gs_only_3D?(v)) SUBTYPE_OF (horizontal_only?(v))

    trk_only_3D?(vo1)(vo2) : MACRO bool =
      trk_only?(vo1)(vo2) AND
      vo1`z = vo2`z

    trkho : JUDGEMENT
      (trk_only_3D?(v)) SUBTYPE_OF (horizontal_only?(v))

    vs(v) : real = v`z

    vs_only?(vo1)(vo2) : bool =
      vect2(vo1) = vect2(vo2)

    vs_only_symm : LEMMA
      vs_only?(vo1)(vo2) IFF vs_only?(vo2)(vo1)

  END definitions_3D

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

  % Judgement subtype TCC generated (at line 22, column 4) for  vect2(nzv)
      % expected type  Nz_vect2
  nzv2: OBLIGATION FORALL (nzv): vect2(nzv) /= zero;


body:
  bands_util : THEORY
  BEGIN
    
    % various non-parameterized definitions and lemmas used in bands

    IMPORTING definitions_3D,
              track

    vo3,vi3	  : VAR Nzv2_vect3
    x,k,y,trk,vsp	  : VAR real
    vo2,vi2,nvo2    : VAR Nz_vect2
    gsp   	  : VAR posreal
    %----------------------%
    % Definitions bands 2d %
    %----------------------%

    trk2v2(vo2)(trk) : (trk_only?(vo2)) =
      trkgs2vect(trk,norm(vo2))

    trk2v2_Nzv : JUDGEMENT
      trk2v2(vo2)(trk) HAS_TYPE Nz_vect2

    Vtrk(vo2,vi2)(trk:real): Vect2 =
      trk2v2(vo2)(trk) - vi2

    gs2v2(vo2)(k) : Vect2 = k*^(vo2)

    gs2v2_gs_only : JUDGEMENT
      gs2v2(vo2)(gsp) HAS_TYPE (gs_only?(vo2))

    gs2v2_id: LEMMA
      gs_only?(vo2)(nvo2)
      IMPLIES
      gs2v2(vo2)(gs(nvo2)) = nvo2

    %----------------------%
    % Definitions bands 3d %
    %----------------------%

    % Track %

    trk2v3(vo3)(trkz:real) : (trk_only_3D?(vo3)) =
      trkgs2vect(trkz,norm(vect2(vo3))) WITH [z |-> vo3`z] 

    vect2_trk2v3 : LEMMA
      vect2(trk2v3(vo3)(trk)) = trk2v2(vo3)(trk)

    trk2v3_Nzv : JUDGEMENT
      trk2v3(vo3)(trk) HAS_TYPE Nzv2_vect3

    Vtrk_3D(vo3,vi3)(trkz:real):(horizontal_only?(vo3-vi3)) =
      trk2v3(vo3)(trkz) - vi3

    trk2v3_trk2v3 : LEMMA
      trk2v3(trk2v3(vo3)(trk))(trk)=trk2v3(vo3)(trk)

    trk2v3_0 : LEMMA
      vect2(vo3) /= zero AND x >= 0 AND x < 2 * pi IMPLIES vect2(trk2v3(vo3)(x)) /= zero


    gs2v3(vo3)(k) : Vect3 = gs2v2(vo3)(k) WITH [z |-> vo3`z]

    gs2v3_gs_only : JUDGEMENT
      gs2v3(vo3)(gsp) HAS_TYPE (gs_only_3D?(vo3))

    vect2_gs2v3 : LEMMA
      vect2(gs2v3(vo3)(gsp)) = gs2v2(vo3)(gsp)

    Vgs_3D(vo3,vi3)(k) : (horizontal_only?(vo3-vi3)) = 
      gs2v3(vo3)(k)-vi3


    vs2v3(vo3)(vsp) : (vs_only?(vo3)) = vo3 WITH [z := vsp]

    vect2_vs2v3 : LEMMA
      vect2(vs2v3(vo3)(vsp)) = vect2(vo3)

    Vs(vo3,vi3)(vsp) : (vs_only?(vo3-vi3)) = 
      vs2v3(vo3)(vsp)-vi3


  END bands_util

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

  % Subtype TCC generated (at line 18, column 4) for
      % trkgs2vect(trk, norm(vo2))
      % expected type  (trk_only?(vo2))
  trk2v2_TCC1: OBLIGATION
    FORALL (vo2: Nz_vect2, trk: real):
      trk_only?(vo2)(trkgs2vect(trk, norm(vo2)));

  % Judgement subtype TCC generated (at line 21, column 4) for
      % trk2v2(vo2)(trk)
      % expected type  Nz_vect2
  trk2v2_Nzv: OBLIGATION FORALL (trk, vo2): trk2v2(vo2)(trk) /= zero;

  % Judgement subtype TCC generated (at line 29, column 4) for  gs2v2(vo2)(gsp)
      % expected type  (gs_only?(vo2))
  gs2v2_gs_only: OBLIGATION FORALL (gsp, vo2): gs_only?(vo2)(gs2v2(vo2)(gsp));

  % Subtype TCC generated (at line 43, column 4) for
      % trkgs2vect(trkz, norm(vect2(vo3))) WITH [z |-> vo3`z]
      % expected type  (LAMBDA (vo2):
                     %    trk_only?(vect2(vo3))(vect2(vo2)) AND vo3`z = vo2`z)
  trk2v3_TCC1: OBLIGATION
    FORALL (vo3: Nzv2_vect3, trkz: real):
      trk_only?(vect2(vo3))
               (vect2((trkgs2vect(trkz, norm(vect2(vo3)))
                         WITH [z |-> vo3`z])));

  % Judgement subtype TCC generated (at line 49, column 4) for
      % trk2v3(vo3)(trk)
      % expected type  Nzv2_vect3
  trk2v3_Nzv: OBLIGATION FORALL (trk, vo3): vect2(trk2v3(vo3)(trk)) /= zero;

  % Subtype TCC generated (at line 52, column 4) for  trk2v3(vo3)(trkz) - vi3
      % expected type  (LAMBDA (vo2): (vo3 - vi3)`z = vo2`z)
  Vtrk_3D_TCC1: OBLIGATION
    FORALL (vo3: Nzv2_vect3, vi3: Nzv2_vect3, trkz: real):
      (vo3 - vi3)`z = (trk2v3(vo3)(trkz) - vi3)`z;

  % Judgement subtype TCC generated (at line 64, column 4) for  gs2v3(vo3)(gsp)
      % expected type  (LAMBDA (vo2):
                     %    gs_only?(vect2(vo3))(vect2(vo2)) AND vo3`z = vo2`z)
  gs2v3_gs_only: OBLIGATION
    FORALL (gsp, vo3):
      gs_only?(vect2(vo3))(vect2(gs2v3(vo3)(gsp))) AND
       vo3`z = gs2v3(vo3)(gsp)`z;

  % Subtype TCC generated (at line 70, column 4) for  gs2v3(vo3)(k) - vi3
      % expected type  (LAMBDA (vo2): (vo3 - vi3)`z = vo2`z)
  Vgs_3D_TCC1: OBLIGATION
    FORALL (vo3: Nzv2_vect3, vi3: Nzv2_vect3, k: real):
      (vo3 - vi3)`z = (gs2v3(vo3)(k) - vi3)`z;

  % Subtype TCC generated (at line 73, column 38) for  vo3 WITH [z := vsp]
      % expected type  (vs_only?(vo3))
  vs2v3_TCC1: OBLIGATION
    FORALL (vo3: Nzv2_vect3, vsp: real): vs_only?(vo3)((vo3 WITH [z := vsp]));

  % Subtype TCC generated (at line 79, column 4) for  vs2v3(vo3)(vsp) - vi3
      % expected type  (vs_only?(vo3 - vi3))
  Vs_TCC1: OBLIGATION
    FORALL (vo3: Nzv2_vect3, vi3: Nzv2_vect3, vsp: real):
      vs_only?(vo3 - vi3)(vs2v3(vo3)(vsp) - vi3);


body:
  util : THEORY
  BEGIN

    IMPORTING reals@sign,
              reals@sqrt
    
    b,d   : VAR nnreal
    a,c,e : VAR real

    % An algebraic way to determine a*sqrt(b) = e
    eq(a,b,e) : bool = 
      a*e >= 0 AND sq(a)*b = sq(e)

    eq_correct_1 : LEMMA
      eq(a,b,e) IFF a*sqrt(b) = e

    eq_neg : LEMMA
      eq(-a,b,-e) = eq(a,b,e)

    % An algebraic way to determine a*sqrt(b) > e
    gt(a,b,e) : bool =
      IF a >= 0 THEN
        e < 0 OR sq(a)*b > sq(e)
      ELSE
        e < 0 AND sq(a)*b < sq(e) 
      ENDIF

    gt_correct_1 : LEMMA
      gt(a,b,e) IFF a*sqrt(b) > e

    % An algebraic way to determine a*sqrt(b) < e
    lt(a,b,e) : bool =
      gt(-a,b,-e)

    lt_correct_1 : LEMMA
      lt(a,b,e) IFF a*sqrt(b) < e

    % An algebraic way to determine a*sqrt(b) >= e
    ge(a,b,e) : bool =
      NOT lt(a,b,e)

    ge_correct_1 : LEMMA
      ge(a,b,e) IFF a*sqrt(b) >= e

    % An algebraic way to determine a*sqrt(b) <= e
    le(a,b,e) : bool =
      NOT gt(a,b,e)

    le_correct_1 : LEMMA
      le(a,b,e) IFF a*sqrt(b) <= e

    % An algebraic way to determine if a*sqrt(b) > c*sqrt(d)+e
    gt(a,b,c,d,e) : bool =
      IF a >= 0 THEN
        lt(c,d,-e) OR lt(2*e*c,d,sq(a)*b-sq(c)*d-sq(e))
      ELSE
        lt(c,d,-e) AND gt(2*e*c,d,sq(a)*b-sq(c)*d-sq(e))
      ENDIF

    gt_correct_2 : LEMMA
      gt(a,b,c,d,e) IFF a*sqrt(b) > c*sqrt(d)+e

    % An algebraic way to determine a*sqrt(b) < c*sqrt(d)+e
    lt(a,b,c,d,e) : bool =
      gt(-a,b,-c,d,-e)

    lt_correct_2 : LEMMA
      lt(a,b,c,d,e) IFF a*sqrt(b) < c*sqrt(d)+e

    % An algebraic way to determine a*sqrt(b) >= c*sqrt(d)+e
    ge(a,b,c,d,e) : bool =
      NOT lt(a,b,c,d,e)

    ge_correct_2 : LEMMA
      ge(a,b,c,d,e) IFF a*sqrt(b) >= c*sqrt(d)+e

    % An algebraic way to determine a*sqrt(b) <= c*sqrt(d)+e
    le(a,b,c,d,e) : bool =
      NOT gt(a,b,c,d,e)

    le_correct_2 : LEMMA
      le(a,b,c,d,e) IFF a*sqrt(b) <= c*sqrt(d)+e

  END util


body:
  horizontal_dist_convexity[D:posreal] : THEORY
  BEGIN

    IMPORTING analysis@convex_function_props,
    	    vectors@vectors_2D
               
    s,v,w		: VAR Vect2
    ttt,tw,tx,ty	: VAR real

           % 1.B Horizontal Distance

               % 1.B.1 Definitions

    horiz_dist_scaf(s)(t: real,v): real = sqv(s+t*v)-sq(D)


  	     % 1.B.2 Convexity

    horiz_dist_convex_scaf: LEMMA convex?((LAMBDA (ttt): horiz_dist_scaf(s)(ttt,v)))


    horiz_dist_strictly_convex_scaf: LEMMA v /= zero IMPLIES strictly_convex?((LAMBDA (ttt): horiz_dist_scaf(s)(ttt,v)))

  END horizontal_dist_convexity


body:
  %------------------------------------------------------------------------------
  % horizontal.pvs
  % ACCoRD v1.0
  %
  % This theory provides definitions for horizontal separation and conflict.
  %
  % It also provides solutions to the times when a velocity vector
  % intersects the circular protected zone. Given a current position s,
  % a vector v intersects the circle of radius D at times Theta_D's that 
  % are roots to the quadratic equation
  %    a = sqv(v)
  %    b = 2*(s*v)
  %    c = sqv(s) - D^2
  % The discriminant of this equation is 4*Delta. 
  %------------------------------------------------------------------------------

  horizontal[D: posreal]: THEORY
  BEGIN
    
    IMPORTING reals@sign,
              reals@quadratic_2b,
  	    reals@quad_minmax,
              vectors@det_2D,
              vectors@closest_approach_2D,
              definitions,
  	    vectors@parallel_2D,
  	    horizontal_dist_convexity[D]

    s,v,w     : VAR Vect2
    nzv     : VAR Nz_vect2
    eps,dir : VAR Sign
    t,
    t1,t2   : VAR real
    nzk     : VAR nzreal
    pt,pr   : VAR posreal
   
    %% Horizontal separation at current time
    horizontal_sep?(s): MACRO bool = 
      sqv(s) >= sq(D)
    
    horizontal_sep_at?(s,v,t): MACRO bool =
      horizontal_sep?(s+t*v)

    %% Strict horizontal separation
    strict_horizontal_sep?(s): MACRO bool = 
      sqv(s) > sq(D)

    on_D?(s): MACRO bool =
      sqv(s) = sq(D)

    Sp_vect2  : TYPE = (horizontal_sep?)
    Ss_vect2  : TYPE = (strict_horizontal_sep?)

    sp : VAR Sp_vect2
    ss : VAR Ss_vect2

    ss_nzv : JUDGEMENT
      Ss_vect2 SUBTYPE_OF Nz_vect2

    ss_sp : JUDGEMENT
      Ss_vect2 SUBTYPE_OF Sp_vect2

    neg_ss : JUDGEMENT
      -(ss) HAS_TYPE Ss_vect2

    neg_sp : JUDGEMENT
      -(sp) HAS_TYPE Sp_vect2

    %% Horizontal separation in the direction given by dir (1=after,-1=before)
    horizontal_sep_dir_at?(s,v,t1,dir): MACRO bool =
      FORALL(t2): dir*t2 >= dir*t1 IMPLIES horizontal_sep_at?(s,v,t2)

    horizontal_sep_after?(s,v,t): MACRO bool = 
      horizontal_sep_dir_at?(s,v,t,1)

    %% Horizontal loss of separation
    horizontal_los?(s): MACRO bool = 
      sqv(s) < sq(D)

    horizontal_los_at?(s,v,t): MACRO bool =
      horizontal_los?(s+t*v)

    LoS_vect2 : TYPE  = {s: Nz_vect2 | horizontal_los?(s)}

    %% Horizontal conflict ever (infinite look-ahead time)
    horizontal_conflict_ever?(s,v): bool =
      EXISTS (t:real) : horizontal_los_at?(s,v,t)

    %% Horizontal conflict in the future (infinite look-ahead time)
    horizontal_conflict?(s,v):bool =
      EXISTS (nnt:nnreal) : horizontal_los_at?(s,v,nnt) 

    horizontal_conflict_sum_closed: LEMMA
      horizontal_conflict?(s,v) AND horizontal_conflict?(s,w)
      IMPLIES
      horizontal_conflict?(s,v+w)

    horizontal_conflict_neg : LEMMA
      horizontal_conflict?(-s,-v) IMPLIES horizontal_conflict?(s,v)

    horizontal_conflict_symm : LEMMA
      horizontal_conflict?(-s,-v) IFF horizontal_conflict?(s,v)

    horizontal_conflict_scal : LEMMA
      horizontal_conflict?(s,v) IFF horizontal_conflict?(s,pt*v)    

    horizontal_conflict_ever : LEMMA
      horizontal_conflict?(s,v) IMPLIES
      horizontal_conflict_ever?(s,v) 

    horizontal_conflict_ever_scal : LEMMA
      horizontal_conflict_ever?(s,v) IFF
      horizontal_conflict_ever?(s,nzk*v)    

    Delta(s,v) : real = 
      sq(D)*sqv(v) - sq(det(s,v))

    Delta_zero_eq_0 : LEMMA
      Delta(s,zero) = 0

    Delta_scal: LEMMA
      Delta(s,t*v) = sq(t)*Delta(s,v)

    Delta_eq : LEMMA
      Delta(s,v) = Delta(s+t*v,v) 

    Delta_symm : LEMMA 
      Delta(-s,-v) = Delta(s,v) 

    Delta_discr2b : LEMMA
      LET a = sqv(nzv),
          b = s*nzv,
          c = sqv(s) - sq(D) IN
      Delta(s,nzv) = discr2b(a,b,c)

    Delta_gt_0_nzv : LEMMA           
      Delta(s,v) > 0
      IMPLIES
        nz_vector?(v)

    ground_speed : LEMMA
      horizontal_conflict_ever?(sp,v)
      IMPLIES
        nz_vector?(v)

    Delta_gt_0 : LEMMA
      (horizontal_sep?(s) OR nz_vector?(v)) AND
      horizontal_conflict_ever?(s,v)
      IMPLIES 
        Delta(s,v) > 0

    Delta_gt_0_on_D: LEMMA on_D?(s) AND 
      s*v /= 0 IMPLIES
      Delta(s,v) > 0

    Delta_eq_0_dot_on_D: LEMMA on_D?(s) 
      AND s*v = 0 IMPLIES
      Delta(s,v) = 0

    Delta_ge_0 : LEMMA
      Delta(s,nzv) >= 0 IFF 
      (EXISTS (t: real): on_D?(s+t*nzv))

    Delta_ge_0_2: LEMMA
      Delta(s,nzv) >= 0 IFF 
      (EXISTS (t: real): sqv(s+t*nzv) <= sq(D))

    Delta_eq_0_eq_tca: LEMMA
      Delta(s,nzv) = 0 AND on_D?(s+t*nzv) IMPLIES
      ((s+t*nzv)*nzv = 0 AND t = horizontal_tca(s,nzv))

    sdotv_lt_0 : LEMMA  
      horizontal_conflict?(sp,v)
      IMPLIES
        sp*v < 0 

    %% eps chooses between the two solutions of the quadratic equation
    %% eps = Entry:  entry time into protected zone
    %% eps = Exit :  exit time from protected zone

    Theta_D(s,(nzv|Delta(s,nzv)>=0),eps):real =
      LET a = sqv(nzv),
          b = s*nzv,
          c = sqv(s) - sq(D) IN
      root2b(a,b,c,eps)

    Theta_D_on_D : LEMMA
      Delta(s,nzv) >= 0 IMPLIES
        LET t = Theta_D(s,nzv,eps) IN
        on_D?(s+t*nzv)

    Theta_D_unique_eps: LEMMA
      Delta(s,nzv) >= 0
      IMPLIES
        (on_D?(s+t*nzv) IFF
         EXISTS (eps): t = Theta_D(s,nzv,eps))

    Theta_D_unique: LEMMA
      Delta(s,nzv) >= 0 IMPLIES
        (on_D?(s+t*nzv) IFF
         t = Theta_D(s,nzv,Entry) OR t = Theta_D(s,nzv,Exit))

    Theta_D_symm : LEMMA
      Delta(s,nzv) >= 0 IMPLIES
        Theta_D(-s,-nzv,eps) = Theta_D(s,nzv,eps) 

    Theta_D_scal: LEMMA
       Delta(s,nzv) >= 0 IMPLIES
        nzk*Theta_D(s,nzk*nzv,eps) = Theta_D(s,nzv,sign(nzk)*eps)

    Theta_D_neg_nzv: LEMMA  
        Delta(s,nzv) >= 0 IMPLIES
        Theta_D(s,-nzv,-eps) = -Theta_D(s,nzv,eps) 

    Theta_D_le : LEMMA
      Delta(s,nzv) >= 0 IMPLIES
        Theta_D(s,nzv,Entry) <= Theta_D(s,nzv,Exit)

    Theta_D_lt : LEMMA
      Delta(s,v) > 0 IMPLIES
        Theta_D(s,v,Entry) < Theta_D(s,v,Exit)

    Theta_D_Delta_eq_0: LEMMA
      Delta(s,nzv) >= 0 IMPLIES
      (Delta(s,nzv) = 0 IFF
       Theta_D(s,nzv,Entry) = Theta_D(s,nzv,Exit))

    Theta_D_eq_0 : LEMMA
      on_D?(s) AND
      Delta(s,nzv) >= 0 AND
      horizontal_entry?(s,nzv)
      IMPLIES
      Theta_D(s,nzv,Entry) = 0

    Theta_D_ge_0 : LEMMA 
      Delta(sp,nzv) >= 0 AND
      horizontal_entry?(sp,nzv)
      IMPLIES 
        Theta_D(sp,nzv,Entry) >= 0

    Theta_D_neq_0 : LEMMA 
      Delta(ss,nzv) >= 0 
      IMPLIES 
        Theta_D(ss,nzv,eps) /= 0

    horizontal_conflict : LEMMA
      horizontal_conflict?(s,nzv) IFF
      Delta(s,nzv) > 0 AND 
      (horizontal_los?(s) OR horizontal_entry?(s,nzv))

    horizontal_conflict_on_D: LEMMA
      on_D?(s) IMPLIES
      (horizontal_conflict?(s,v) IFF s*v < 0)

    horizontal_entry_le : LEMMA
      t1 <= t2 AND
      sqv(s+t2*v) = sq(D) AND
      horizontal_entry_at?(s,v,t2) IMPLIES
      sqv(s+t1*v) >= sq(D) 

    not_horizontal_entry_lt : LEMMA
      LET t1 = max(0,horizontal_tca(s,nzv)) IN
        t2 > 0 AND
        sqv(s+t2*nzv) = sq(D) AND
        NOT horizontal_entry_at?(s,nzv,t2) IMPLIES
        t1 < t2 AND 
        horizontal_los?(s+t1*nzv)

    horizontal_los_inside_Theta : LEMMA
      Delta(s,nzv) >= 0 IMPLIES
        (t > Theta_D(s,nzv,Entry) AND
         t < Theta_D(s,nzv,Exit) IFF
         horizontal_los?(s+t*nzv))  

    horizontal_sep_outside_Theta : LEMMA
      Delta(s,nzv) >= 0 IMPLIES
      (t < Theta_D(s,nzv,Entry) OR
      t > Theta_D(s,nzv,Exit) IFF
      sqv(s + t*nzv) > sq(D))

    not_horiz_sep_inside_closed_Theta: LEMMA
      Delta(s,nzv) >= 0 IMPLIES
        (t >= Theta_D(s,nzv,Entry) AND  
         t <= Theta_D(s,nzv,Exit) IFF
        sqv(s+t*nzv) <= sq(D))

    Theta_D_entry_gt_0 : LEMMA
      horizontal_conflict?(ss,nzv) IMPLIES
        Theta_D(ss,nzv,Entry) > 0

    Theta_D_exit_gt_0 : LEMMA
      Delta(s,v) > 0
      IMPLIES
        (horizontal_los?(s) OR horizontal_entry?(s,v)
         IFF 
         Theta_D(s,v,Exit) > 0)

    Theta_D_entry_lt_t :LEMMA
      LET d = Delta(s,v),
          a = sqv(v),
  	b = s*v IN
      d > 0 IMPLIES
        (d > sq(a*t+b) or a*t+b >= 0 
         IFF 
         Theta_D(s,v,Entry) < t)

    horizontal_conflict_entry : LEMMA
      horizontal_conflict?(sp,nzv) AND
      t <= Theta_D(sp,nzv,Entry)
      IMPLIES
        horizontal_conflict?(sp+t*nzv,nzv)

    not_horizontal_conflict_exit : LEMMA
      horizontal_conflict?(s,nzv) AND
      t >= Theta_D(s,nzv,Exit)
      IMPLIES
        NOT horizontal_conflict?(s+t*nzv,nzv)

    Theta_D_horizontal_dir: LEMMA
      nz_vect2?(v) AND Delta(s,v) >= 0 OR
      Delta(s,v) > 0 
      IMPLIES
      horizontal_dir_at?(s,v,Theta_D(s,v,eps),eps)

    horizontal_tca_midpoint : LEMMA
      Delta(s,nzv) >= 0 IMPLIES
        horizontal_tca(s,nzv) = (Theta_D(s,nzv,Entry)+Theta_D(s,nzv,Exit))/2

    horizontal_tca_entry_exit : LEMMA
      Delta(s,nzv) > 0 IMPLIES
        horizontal_tca(s,nzv) > Theta_D(s,nzv,Entry) AND 
        horizontal_tca(s,nzv) < Theta_D(s,nzv,Exit) 

    horizontal_tca_los : LEMMA
      Delta(s,nzv) > 0 IMPLIES
      horizontal_los?(s+horizontal_tca(s,nzv)*nzv)

    horizontal_tca_le_D : LEMMA
      Delta(s,nzv) >= 0 IMPLIES
      sqv(s+horizontal_tca(s,nzv)*nzv) <= sq(D)

    horizontal_tca_pos : LEMMA
      Delta(sp,nzv) > 0 AND
      horizontal_entry?(sp,nzv)
      IMPLIES 
        horizontal_tca(sp,nzv) > 0

    Theta_D_positive_conflict: LEMMA
      Delta(s,v) > 0 IMPLIES
      (horizontal_conflict?(s,v) IFF
      Theta_D(s,v,Exit) > 0)

    %% Circle solutions are vectors v such that at time t the ownship is on the 
    %% circle of radius D. If dir=-1, v points into the circle; if dir=1, v points
    %% outside the circle.

    circle_solution_2D?(s,v,t,dir): bool =
      on_D?(s+t*v) AND
      horizontal_dir_at?(s,v,t,dir)

    circle_solution_2D_horizontal_sep : LEMMA
      circle_solution_2D?(s,v,t,Entry) IMPLIES
      FORALL (tt:real) : tt <= t IMPLIES horizontal_sep_at?(s,v,tt)

    Theta_D_circle_solution_2D: LEMMA
      nz_vect2?(v) AND Delta(s,v) >= 0 OR
      Delta(s,v) > 0 IMPLIES
      circle_solution_2D?(s,v,Theta_D(s,v,eps),eps)

    circle_solution_2D_Delta_ge_0 : LEMMA
      circle_solution_2D?(s,nzv,t,dir) IMPLIES
      Delta(s,nzv) >= 0 

    circle_solution_2D_Theta_D: LEMMA
      circle_solution_2D?(s,nzv,t,dir) IMPLIES
      t = Theta_D(s,nzv,dir)

    circle_solution_2D_strict_horizontal_sep : LEMMA
      circle_solution_2D?(s,nzv,t,Entry) IMPLIES
      FORALL (tt:real) : tt < t IMPLIES strict_horizontal_sep?(s+tt*nzv)

    Theta_D_line_intersection: LEMMA
      Delta(s,v) > 0 IMPLIES
      LET ppoint = s + Theta_D(s,v,eps)*v IN
      v*ppoint /= 0
      IMPLIES
      (sq(D) - s*ppoint)/(v*ppoint) = Theta_D(s,v,eps)

    tangent_line_intersection_v_independent: LEMMA
      sqv(s+pt*v) = (s+pr*w)*(s+pt*v)
      IMPLIES
      sign(v*(s+pt*v)) = sign(w*(s+pt*v))

    tangent_vector_not_conflict: LEMMA
      Delta(s,v) > 0 AND
      (s+t*w)*(s+Theta_D(s,v,dir)*v) = sq(D) AND
      w*(s+Theta_D(s,v,dir)*v) = 0 AND
      Theta_D(s,v,dir) /= 0
      IMPLIES
      NOT horizontal_conflict?(s,v)

    horizontal_conflict_is_an_open_set: LEMMA
        FORALL (ss, vv: Vect2):
        horizontal_conflict?(ss, vv) IMPLIES
        (EXISTS (epsilon: posreal):
        FORALL (ww: Vect2):
        norm(ww) < epsilon IMPLIES horizontal_conflict?(ss, vv + ww))

  END horizontal

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

  % Judgement subtype TCC generated (at line 58, column 4) for  x
      % expected type  Nz_vect2
  ss_nzv: OBLIGATION FORALL (x: Ss_vect2): x /= zero;

  % Judgement subtype TCC generated (at line 61, column 4) for  x
      % expected type  Sp_vect2
  ss_sp: OBLIGATION FORALL (x: Ss_vect2): sqv(x) >= sq(D);

  % Judgement subtype TCC generated (at line 64, column 4) for  -ss
      % expected type  Ss_vect2
  neg_ss: OBLIGATION FORALL (ss): sqv(-ss) > sq(D);

  % Judgement subtype TCC generated (at line 67, column 4) for  -sp
      % expected type  Sp_vect2
  neg_sp: OBLIGATION FORALL (sp): sqv(-sp) >= sq(D);

  % Subtype TCC generated (at line 185, column 15) for  c
      % expected type  {c: real | discr2b(a, b, c) >= 0}
  Theta_D_TCC1: OBLIGATION
    FORALL (s: Vect2, (nzv: Nz_vect2 | Delta(s, nzv) >= 0), a: posreal):
      a = sqv(nzv) IMPLIES
       (FORALL (b: real):
          b = s * nzv IMPLIES
           (FORALL (c: real):
              c = sqv(s) - sq(D) IMPLIES discr2b(a, b, c) >= 0));

  % Subtype TCC generated (at line 205, column 17) for  -nzv
      % expected type  {nzv | Delta(-s, nzv) >= 0}
  Theta_D_symm_TCC1: OBLIGATION
    FORALL (nzv: Nz_vect2, s: Vect2):
      Delta(s, nzv) >= 0 IMPLIES Delta(-s, -nzv) >= 0;

  % Subtype TCC generated (at line 209, column 20) for  nzk * nzv
      % expected type  {nzv | Delta(s, nzv) >= 0}
  Theta_D_scal_TCC1: OBLIGATION
    FORALL (nzk: nzreal, nzv: Nz_vect2, s: Vect2):
      Delta(s, nzv) >= 0 IMPLIES Delta(s, nzk * nzv) >= 0;

  % Subtype TCC generated (at line 213, column 16) for  -nzv
      % expected type  {nzv | Delta(s, nzv) >= 0}
  Theta_D_neg_nzv_TCC1: OBLIGATION
    FORALL (nzv: Nz_vect2, s: Vect2):
      Delta(s, nzv) >= 0 IMPLIES Delta(s, -nzv) >= 0;

  % Subtype TCC generated (at line 221, column 16) for  v
      % expected type  {nzv | Delta(s, nzv) >= 0}
  Theta_D_lt_TCC1: OBLIGATION
    FORALL (s, v: Vect2):
      Delta(s, v) > 0 IMPLIES v /= zero AND Delta(s, v) >= 0;

  % Subtype TCC generated (at line 289, column 17) for  nzv
      % expected type  {nzv | Delta(ss, nzv) >= 0}
  Theta_D_entry_gt_0_TCC1: OBLIGATION
    FORALL (nzv: Nz_vect2, ss: Ss_vect2):
      horizontal_conflict?(ss, nzv) IMPLIES Delta(ss, nzv) >= 0;

  % Subtype TCC generated (at line 305, column 17) for  v
      % expected type  {nzv | Delta(s, nzv) >= 0}
  Theta_D_entry_lt_t_TCC1: OBLIGATION
    FORALL (s, v: Vect2, d: real):
      d = Delta(s, v) IMPLIES
       (FORALL (a: nnreal):
          a = sqv(v) IMPLIES
           (FORALL (b: real):
              d > 0 AND b = s * v IMPLIES v /= zero AND Delta(s, v) >= 0));

  % Subtype TCC generated (at line 309, column 20) for  nzv
      % expected type  {nzv | Delta(sp, nzv) >= 0}
  horizontal_conflict_entry_TCC1: OBLIGATION
    FORALL (nzv: Nz_vect2, sp: Sp_vect2):
      horizontal_conflict?(sp, nzv) IMPLIES Delta(sp, nzv) >= 0;

  % Subtype TCC generated (at line 315, column 19) for  nzv
      % expected type  {nzv | Delta(s, nzv) >= 0}
  not_horizontal_conflict_exit_TCC1: OBLIGATION
    FORALL (nzv: Nz_vect2, s: Vect2):
      horizontal_conflict?(s, nzv) IMPLIES Delta(s, nzv) >= 0;

  % Subtype TCC generated (at line 323, column 37) for  v
      % expected type  {nzv | Delta(s, nzv) >= 0}
  Theta_D_horizontal_dir_TCC1: OBLIGATION
    FORALL (s, v: Vect2):
      v /= zero AND Delta(s, v) >= 0 OR Delta(s, v) > 0 IMPLIES
       v /= zero AND Delta(s, v) >= 0;

  % Subtype TCC generated (at line 331, column 40) for  nzv
      % expected type  {nzv | Delta(s, nzv) >= 0}
  horizontal_tca_entry_exit_TCC1: OBLIGATION
    FORALL (nzv: Nz_vect2, s: Vect2):
      Delta(s, nzv) > 0 IMPLIES Delta(s, nzv) >= 0;

  % Subtype TCC generated (at line 376, column 18) for  nzv
      % expected type  {nzv | Delta(s, nzv) >= 0}
  circle_solution_2D_Theta_D_TCC1: OBLIGATION
    FORALL (dir: Sign, nzv: Nz_vect2, s: Vect2, t: real):
      circle_solution_2D?(s, nzv, t, dir) IMPLIES Delta(s, nzv) >= 0;


body:
  %------------------------------------------------------------------------------
  % predicate_coordination_2D.pvs - General Theory of Coordination for 3D Maneuvers
  %------------------------------------------------------------------------------

  predicate_coordination_2D: THEORY
  BEGIN

    IMPORTING definitions

    s,v,nv,
    nw,vo,nvo,
    vi,nvi  : VAR Vect2
    eps     : VAR Sign
    pr	  : VAR posreal
    l,l1,l2 : VAR real

    Criter: TYPE = [[Vect2,Vect2]->set[Vect2]]
    SignedCrit2D: TYPE = [Sign -> Criter]

    Vector_Predicate: TYPE+ = [[Vect2,Vect2]->set[Vect2]]

    Crit,Crit1,Crit2,Crit3: VAR Criter
    Scrit,Scrit1,Scrit2,Scrit3: VAR SignedCrit2D


    C : VAR Vector_Predicate



      % BASIC DEFINITIONS

      sum_closed_2D?(C): bool =
          FORALL (s,v,nv,nw:Vect2):
  	C(s,v)(nv) AND C(s,v)(nw) IMPLIES C(s,v)(nv+nw)

      symmetric_2D?(C) : bool = 
         FORALL (s,v,nv:Vect2):
  	C(s,v)(nv) IFF C(-s,-v)(-nv)


      crit_sum_closed_2D?(Crit): bool =
          FORALL (s,v,nv,nw:Vect2):
  	Crit(s,v)(nv) AND Crit(s,v)(nw) IMPLIES Crit(s,v)(nv+nw)


      sum_independent_2D?(Crit,C): bool = 
          FORALL (v,s,nv,nw: Vect2):
          (Crit(s,v)(nv) AND Crit(s,v)(nw) AND C(s,v)(v)
          IMPLIES
          NOT C(s,v)(nv+nw))

      open_2D?(C): bool = 
          FORALL (s,v,nv: Vect2): C(s,v)(nv) IMPLIES
  	(EXISTS (epsilon:posreal):
  	FORALL (nw: Vect2):
  	norm(nw)<epsilon
  	IMPLIES
  	C(s,v)(nv+nw))


      crit_independent_of_length_2D?(Crit): bool =
          FORALL (v,s,nv: Vect2,pr: posreal):
  	(Crit(s,v)(nv) IFF Crit(s,pr*v)(nv))

      independent_of_length_2D?(C): bool = 
          FORALL (s,v,nv:Vect2,pr,pz:posreal):
  	(C(s,v)(nv) IFF C(s,pz*v)(pr*nv))

      coordinated_2D?(Crit1,Crit2,C): bool =
          FORALL (vo,vi,nvo,nvi,s: Vect2):
          (C(s,vo-vi)(vo-vi) AND
          Crit1(s,vo-vi)(nvo-vi) AND
          Crit2(-s,vi-vo)(nvi-vo)
          IMPLIES
          NOT C(s,vo-vi)(nvo-nvi))

      coordinated_symmetric_2D: LEMMA symmetric_2D?(C) IMPLIES
      			   (coordinated_2D?(Crit1,Crit2,C) IFF coordinated_2D?(Crit2,Crit1,C))


      crit_symmetric_2D?(Crit): bool =
          FORALL (v,s,nv: Vect2):
          (Crit(s,v)(nv) IFF Crit(-s,-v)(-nv))

      sum_indep_coordinated_2D: LEMMA
          crit_symmetric_2D?(Crit) AND
          sum_independent_2D?(Crit,C) AND
  	sum_closed_2D?(C)
          IMPLIES
          coordinated_2D?(Crit,Crit,C)

      coordinated_sum_indep_2D: LEMMA
      	crit_symmetric_2D?(Crit) AND
          crit_independent_of_length_2D?(Crit) AND
  	coordinated_2D?(Crit,Crit,C) AND
  	open_2D?(C) AND
  	independent_of_length_2D?(C)
  	IMPLIES
  	sum_independent_2D?(Crit,C)

      crit_antisymmetric_2D?(Scrit): bool =
          FORALL (v,s,nv: Vect2, eps:Sign):
          (Scrit(eps)(s,v)(nv) IFF Scrit(-eps)(-s,-v)(-nv))

      sum_indep_coordinated_antisym_2D: LEMMA
          crit_antisymmetric_2D?(Scrit) AND
          sum_independent_2D?(Scrit(eps),C) AND
  	sum_closed_2D?(C)
          IMPLIES
          coordinated_2D?(Scrit(eps),Scrit(-eps),C)

      coordinated_antisym_sum_indep_2D: LEMMA
      	crit_antisymmetric_2D?(Scrit) AND
          crit_independent_of_length_2D?(Scrit(eps)) AND
  	coordinated_2D?(Scrit(eps),Scrit(-eps),C) AND
  	open_2D?(C) AND
  	independent_of_length_2D?(C)
  	IMPLIES
  	sum_independent_2D?(Scrit(eps),C)


    % The DERIVED Criterion

    deriv(Crit,l): Criter = (LAMBDA (s,v): (LAMBDA (nv): Crit(s,v)(nv-l*v)))

    deriv_0_2D: LEMMA deriv(Crit,0) = Crit

    deriv_subset_2D: LEMMA
      Crit(s,v)(-l*v) AND
      crit_sum_closed_2D?(Crit)
       IMPLIES
      subset?(Crit(s,v),deriv(Crit,l)(s,v))

    deriv_coordinated_2D: LEMMA l1+l2 = 1 IMPLIES
    			      crit_symmetric_2D?(Crit) AND
    			      sum_independent_2D?(Crit,C) IMPLIES
  			      coordinated_2D?(deriv(Crit,l1),deriv(Crit,l2),C)

    deriv_coordinated_1: LEMMA crit_symmetric_2D?(Crit) AND
    			      sum_independent_2D?(Crit,C) IMPLIES
  			      coordinated_2D?(deriv(Crit,1),Crit,C)

    Comb(Crit1,Crit2): Criter = (LAMBDA (s,v): (LAMBDA (nv): Crit1(s,v)(nv) OR (Crit2(s,v)(nv) AND deriv(Crit1,1)(s,v)(nv))))

    Comb_coordinated_2D: LEMMA
      sum_independent_2D?(Crit1,C) AND
      crit_symmetric_2D?(Crit1) AND
      coordinated_2D?(Crit2,Crit3,C) AND
      sum_closed_2D?(C) AND
      symmetric_2D?(C)
      IMPLIES
      coordinated_2D?(Comb(Crit1,Crit2),Comb(Crit1,Crit3),C)

      coordinated_implies_independent_2D: LEMMA
          crit_symmetric_2D?(Crit) AND
          crit_independent_of_length_2D?(Crit) AND
  	coordinated_2D?(Crit,Crit,C) AND
  	open_2D?(C) AND
  	independent_of_length_2D?(C) AND
  	crit_sum_closed_2D?(Crit) AND
  	sum_closed_2D?(C) IMPLIES
  	(FORALL (s,v,nv:Vect2): ((C(s,v)(v) AND Crit(s,v)(nv)) IMPLIES (NOT C(s,v)(nv))))

      

    			      	    



  END predicate_coordination_2D


body:
  %------------------------------------------------------------------------------
  % horizontal_criteria.pvs
  % ACCoRD v1.0
  %
  % This theory proposes criteria for horizontal separation for non-negative 
  % times. These criteria guarantee independence and (implicit) coordination. 
  %------------------------------------------------------------------------------

  horizontal_criteria[D: posreal]: THEORY
  BEGIN

    IMPORTING predicate_coordination_2D,horizontal[D]

    v,w       : VAR Vect2
    nzv       : VAR Nz_vect2
    sp        : VAR Sp_vect2
    ss        : VAR Ss_vect2
    vo,vi,
    nvo,nvi   : VAR Vect2
    eps,
    eps1,eps2 : VAR Sign

    R(sp):nnreal = sqrt(sqv(sp)-sq(D))/D

    R_eq_0 : LEMMA
      on_D?(sp) IFF
      R(sp) = 0

    R_gt_0 : JUDGEMENT
      R(ss) HAS_TYPE posreal
   
    R_symm : LEMMA
      R(-sp) = R(sp)

    sq_R_det : LEMMA 
      sp*v <= 0 IMPLIES
        (sq(sp*v) > sq(R(sp))*sq(det(sp, v)) IFF
         sp*v < R(sp)*det(sp,v) AND R(sp)*det(sp,v) < -(sp*v))

    Delta_sq_det: LEMMA   
      Delta(sp,nzv) > 0 IFF sq(R(sp))*sq(det(sp,nzv)) < sq(sp*nzv)

    Delta_sq_det_equality: LEMMA
      Delta(sp,nzv) = 0 IFF sq(R(sp))*sq(det(sp,nzv)) = sq(sp*nzv)

    Delta_zero_eps_line_equality: LEMMA
      Delta(sp,nzv) = 0 AND sp*nzv <= 0 
      IMPLIES 
      EXISTS (eps: Sign):
        eps*R(sp)*det(sp,nzv) = sp*nzv
        AND
        eps*det(sp,nzv) <= 0

    horizontal_solution: LEMMA
      horizontal_conflict?(sp,v)
      IFF
        (sp*v) < R(sp)*det(sp,v) AND R(sp)*det(sp,v) < -(sp*v)

    horizontal_criterion?(sp,eps)(v):bool =
      sp*v >= R(sp)*eps*det(sp,v) AND
      eps*det(sp,v) <= 0

    % horizontal_criterion_neg: LEMMA
    %   NOT horizontal_criterion?(sp,eps)(v) IMPLIES horizontal_criterion?(sp,eps)(-v)

    horizontal_criterion_scal: LEMMA
      FORALL (cc:nnreal): horizontal_criterion?(sp,eps)(v)
      	   		 IMPLIES
  			 horizontal_criterion?(sp,eps)(cc*v)

    horizontal_criterion?(sp,v) : MACRO bool =
      EXISTS (eps:Sign): horizontal_criterion?(sp,eps)(v)

    horizontal_criterion_eps : LEMMA
      horizontal_criterion?(sp,v) IMPLIES
      horizontal_criterion?(sp,sign(-det(sp,v)))(v)

    horizontal_criterion_symmetric: LEMMA
     horizontal_criterion?(sp,eps)(v) IFF
     horizontal_criterion?(-sp,eps)(-v)

    horizontal_criterion_eps_unique : LEMMA
      horizontal_criterion?(sp,eps1)(v) AND
      horizontal_criterion?(sp,eps2)(v) AND
      NOT (det(sp,v) = 0 AND sp*v >= 0)
      IMPLIES
      eps1=eps2

    horizontal_criterion_independence : THEOREM
      horizontal_criterion?(sp,v) IFF
      NOT horizontal_conflict?(sp,v)

    horizontal_criterion_sum_closed: LEMMA
      horizontal_criterion?(sp,eps)(v) AND
      horizontal_criterion?(sp,eps)(w)
      IMPLIES
      horizontal_criterion?(sp,eps)(v+w)

    horizontal_criterion_coordination : THEOREM
       horizontal_conflict?(sp,vo-vi) AND
       horizontal_criterion?(sp,eps)(nvo-vi) AND
       horizontal_criterion?(-sp,eps)(nvi-vo) 
       IMPLIES
       NOT horizontal_conflict?(sp,nvo-nvi)

    horizontal_sep_dir: LEMMA
      horizontal_dir?(sp,v,eps)
      IMPLIES
        horizontal_sep_dir_at?(sp,v,0,eps)

    horizontal_exit_independence: THEOREM
      horizontal_exit?(sp,v) OR Delta(sp,v) <= 0
      IFF
        NOT horizontal_conflict?(sp,v)

    horizontal_exit_coordination: THEOREM
      horizontal_conflict?(sp,vo-vi) AND
      horizontal_exit?(sp,nvo-vi) AND
      horizontal_exit?(-sp,nvi-vo) 
      IMPLIES
        NOT horizontal_conflict?(sp,nvo-nvi)

  END horizontal_criteria

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

  % Subtype TCC generated (at line 23, column 22) for  sqv(sp) - sq(D)
      % expected type  nnx: nonneg_real
  R_TCC1: OBLIGATION FORALL (sp: Sp_vect2[D]): sqv(sp) - sq(D) >= 0;

  % Judgement subtype TCC generated (at line 30, column 4) for  R(ss)
      % expected type  posreal
  R_gt_0: OBLIGATION FORALL (ss): R(ss) > 0;


body:
  %--------------------------------------
  % Lookahead
  %--------------------------------------

  Lookahead[B:real,T:real]  : THEORY 

  BEGIN

    Lookahead : TYPE = {t:nnreal | B <= t AND t <= T}

  END Lookahead


body:
  %------------------------------------------------------------------------------
  % line_solutions.pvs
  % ACCoRD v1.0
  %
  % Line solutions are a special case of horizontal solutions. They are
  % are tangent to the protected zone. In this case, eps determines the 
  % side of the protected zone that the is touched.
  % It is proven that line solutions satisfy independence and (implicit)
  % coordination.
  %------------------------------------------------------------------------------

  line_solutions[D: posreal]: THEORY
  BEGIN

    IMPORTING horizontal_criteria[D],
        	    vectors@linear_transformations_2D

    sp,s2         : VAR Sp_vect2
    s,v,v1,v2,v3,
    vo,vi,nvo,nvi : VAR Vect2
    eps,eps1,eps2 : VAR Sign
    t,t2,t3    : VAR real
    nzv,nzv1,nzv2 : VAR Nz_vect2
    k             : VAR real
    pk            : VAR posreal
    tt		: VAR nnreal

    line_solution?(sp,v,eps):bool =
        R(sp)*eps*det(sp,v) = sp*v AND eps*det(sp,v) <= 0

    line_solution_dot_neg : LEMMA
      line_solution?(sp,v,eps) IMPLIES
      sp*v <= 0

    line_solution_sep_dot_negative: LEMMA
      sqv(sp) > sq(D) AND v /= zero AND
      line_solution?(sp,v,eps) IMPLIES
      sp*v < 0

    line_solution?(sp,v) : MACRO bool =
       EXISTS (eps: Sign): line_solution?(sp,v,eps)

    line_solution_on_D: LEMMA
      on_D?(s) IMPLIES
      line_solution?(s,eps*perpR(s),eps)

    on_D_line : LEMMA
      on_D?(s) AND s*v = 0 IMPLIES line_solution?(s,v) 

    line_solution_scal : LEMMA
      line_solution?(sp,v,eps) IFF line_solution?(sp,pk*v,eps)

    line_solution_zero_eps : LEMMA
      line_solution?(sp,zero,eps)

    line_solution_zero : LEMMA
      line_solution?(sp,zero)

    line_solution_Delta: LEMMA
      line_solution?(sp,v) IFF Delta(sp,v) = 0 AND horizontal_entry?(sp,v)

    det_neq_0 : LEMMA
      line_solution?(sp,nzv) IMPLIES
      det(sp,nzv) /= 0

    eps_line(s,v): Sign = -sign(det(s,v))

    line_solution_eps : LEMMA
      line_solution?(sp,nzv,eps) IMPLIES
      eps = eps_line(sp,nzv)

    line_solution_eps_line : LEMMA
      line_solution?(sp,v) IMPLIES 
      line_solution?(sp,v,eps_line(sp,v))

    line_solution_meets_horizontal_criterion: LEMMA
      line_solution?(sp,v,eps) IMPLIES
      horizontal_criterion?(sp,eps)(v)

    line_solution_independence : THEOREM
      line_solution?(sp,v) IMPLIES
      NOT horizontal_conflict_ever?(sp,v)

    line_solution_invariant: LEMMA
      sign(-(sp*v)) = sign(-((sp+t*v)*v)) IMPLIES
     (line_solution?(sp,v) IMPLIES line_solution?(sp+t*v,v))

    line_solution_rewrite: LEMMA line_solution?(sp,nzv) IFF
      EXISTS (tt): on_D?(sp+tt*nzv) AND (sp+tt*nzv)*nzv = 0

    line_solution_det: LEMMA line_solution?(sp,v,eps)
      IFF (-eps*det(sp,v) = D*norm(v) AND horizontal_entry?(sp,v))

    line_solution_scal_unique: LEMMA
      line_solution?(sp,nzv1,eps) AND line_solution?(sp,nzv2,eps)
      AND
      sqv(sp) > sq(D)
      IMPLIES
      EXISTS (pk:posreal): nzv1 = pk*nzv2

    line_solution_coordination : THEOREM
       horizontal_conflict?(sp,vo-vi) AND
       line_solution?(sp,nvo-vi,eps) AND
       line_solution?(-sp,nvi-vo,eps)
       IMPLIES
       NOT horizontal_conflict?(sp,nvo-nvi)

    line_solution_along_line: LEMMA 
      det(v1,v2) /= 0 IMPLIES
      LET t1 = ((-eps)*D*norm(v2) - det(sp,v2))/det(v1,v2) IN
      (sp + t1*v1)*v2 <= 0 IMPLIES line_solution?(sp + t1*v1,v2,eps)

  END line_solutions

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

  % Subtype TCC generated (at line 45, column 19) for  s
      % expected type  Sp_vect2[D]
  line_solution_on_D_TCC1: OBLIGATION
    FORALL (s: Vect2): sqv(s) = sq(D) IMPLIES sqv(s) >= sq(D);

  % Subtype TCC generated (at line 86, column 48) for  sp + t * v
      % expected type  Sp_vect2[D]
  line_solution_invariant_TCC1: OBLIGATION
    FORALL (sp: Sp_vect2[D], t: real, v: Vect2):
      (sign(-(sp * v)) = sign(-((sp + t * v) * v)) AND
        (EXISTS (eps: Sign): line_solution?(sp, v, eps)))
       IMPLIES sqv(sp + t * v) >= sq(D);

  % Subtype TCC generated (at line 111, column 48) for  sp + t1 * v1
      % expected type  Sp_vect2[D]
  line_solution_along_line_TCC1: OBLIGATION
    FORALL (eps: Sign, sp: Sp_vect2[D], v1, v2: Vect2):
      det(v1, v2) /= 0 IMPLIES
       (FORALL (t1: real):
          (sp + t1 * v1) * v2 <= 0 AND
           t1 = ((-eps) * D * norm(v2) - det(sp, v2)) / det(v1, v2)
           IMPLIES sqv(sp + t1 * v1) >= sq(D));


body:
  %------------------------------------------------------------------------------
  % tangent_line.pvs
  % ACCoRD v1.0
  %
  % This file provides a simple framework to compute line solutions. 
  % By definition all line solutions lay on the tangent lines to the 
  % protected zone. We consider two cases, if sq(s) = sq(D), tangent
  % solutions lay on a vector perpendicular to s. Otherwise, tangent solutions
  % lay on the line defined by the two points s and Q(s,eps), where
  % eps = +-1.
  %------------------------------------------------------------------------------

  tangent_line[D: posreal] : THEORY
  BEGIN
    
    IMPORTING line_solutions[D], 
              vectors@parallel_2D

    sp       : VAR Sp_vect2
    ss       : VAR Ss_vect2
    eps      : VAR Sign
    vo,vi,v,
    nvo,nvi  : VAR Vect2
    nzv      : VAR Nz_vect2

    alpha(ss) : {x:posreal | x < 1} =  sq(D)/sqv(ss)

    beta(ss)  : nnreal =  D*sqrt(sqv(ss)-sq(D))/sqv(ss)

    alpha_neg : LEMMA
      alpha(-ss) = alpha(ss)

    beta_neg : LEMMA
      beta(-ss) = beta(ss)

    sq_alpha_beta : LEMMA
      sq(alpha(ss)) + sq(beta(ss)) = alpha(ss)

    Q(ss,eps) : Vect2 = alpha(ss)*ss+eps*beta(ss)*perpR(ss)

    Q_on_D : LEMMA
      sqv(Q(ss,eps)) = sq(D)

    Q_asymm : LEMMA
      Q(-ss,eps) = -Q(ss,eps)

    Qs(ss,eps) : Vect2 = 
      Q(ss,eps)-ss

    Qs_asymm : LEMMA
      Qs(-ss,eps) = -Qs(ss,eps)

    sqv_Qs : LEMMA
      sqv(Qs(ss,eps)) =  sqv(ss) - sq(D) 

    Qs_nzv : JUDGEMENT
      Qs(ss,eps) HAS_TYPE Nz_vect2

    s_dot_Qs_lt_0 : LEMMA
     ss*Qs(ss,eps) < 0

    det_s_Qs_lt_0 : LEMMA
     eps*det(ss,Qs(ss,eps)) < 0

    alpha_D : LEMMA
      alpha(ss)*sqv(ss) = sq(D)

    beta_R  : LEMMA
      beta(ss)*sqv(ss)*R(ss) = sqv(ss)-sq(D)

    alpha_beta: LEMMA 
      alpha(ss)*R(ss) = beta(ss)

    beta_alpha : LEMMA
      -beta(ss)*R(ss) = alpha(ss)-1

    det_v_Q : LEMMA
      det(v,Q(ss,eps)) = alpha(ss)*(det(v,ss)) - eps*beta(ss)*(ss*v)

    s_dot_Q : LEMMA
      ss*Q(ss,eps) = alpha(ss)*sqv(ss)

    det_s_Qs : LEMMA 
      det(ss,Qs(ss,eps)) = -eps*(beta(ss)*sqv(ss))

    det_Q_s : LEMMA
      det(Q(ss,eps),ss) = eps*D*sqrt(sqv(ss)-sq(D))

    Q_eq_Qs_perp : LEMMA
      Q(ss,eps) = -eps*(D/sqrt(sqv(ss)-sq(D)))*perpR(Qs(ss,eps))

    line_solution_Qs: LEMMA 
      line_solution?(ss,Qs(ss,eps),eps)

    parallel_nzv_Qs : LEMMA
      line_solution?(ss,nzv,eps) IMPLIES
      dir_parallel?(nzv,Qs(ss,eps))

    parallel_nzv_perp : LEMMA
      on_D?(sp) AND
      line_solution?(sp,nzv,eps) IMPLIES
      dir_parallel?(nzv,eps*perpR(sp))

    tangent_line(sp,eps) : Nz_vect2 =
      IF on_D?(sp) THEN 
        eps*perpR(sp) 
      ELSE 
        Qs(sp,eps) 
      ENDIF 

    tangent_line_asymm : LEMMA 
      tangent_line(-sp,eps) = -tangent_line(sp,eps)

    line_solution_tangent_line: LEMMA
      line_solution?(sp,tangent_line(sp,eps),eps)

    parallel_nzv_tangent_line: LEMMA
      line_solution?(sp,nzv,eps) IMPLIES
      dir_parallel?(nzv,tangent_line(sp,eps))

    tangent_line?(sp,v,eps) : bool =
      EXISTS (nnk:nnreal): v = nnk*tangent_line(sp,eps)

    tangent_line_solution : LEMMA 
      tangent_line?(sp,v,eps) IFF
      line_solution?(sp,v,eps)

    tangent_line_independence : LEMMA
      tangent_line?(sp,v,eps) IMPLIES
         NOT horizontal_conflict_ever?(sp,v)

    tangent_line_coordination: LEMMA
       horizontal_conflict?(sp,vo-vi) AND
       tangent_line?(sp,nvo-vi,eps) AND
       tangent_line?(-sp,nvi-vo,eps) 
       IMPLIES
         NOT horizontal_conflict?(sp,nvo-nvi)

  END tangent_line

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

  % Subtype TCC generated (at line 26, column 37) for  sq(D) / sqv(ss)
      % expected type  {x: posreal | x < 1}
  alpha_TCC1: OBLIGATION FORALL (ss: Ss_vect2[D]): sq(D) / sqv(ss) < 1;

  % Subtype TCC generated (at line 28, column 31) for  sqv(ss) - sq(D)
      % expected type  nnx: nonneg_real
  beta_TCC1: OBLIGATION FORALL (ss: Ss_vect2[D]): sqv(ss) - sq(D) >= 0;

  % Judgement subtype TCC generated (at line 57, column 4) for  Qs(ss, eps)
      % expected type  Nz_vect2
  Qs_nzv: OBLIGATION FORALL (eps, ss): Qs(ss, eps) /= zero;

  % Subtype TCC generated (at line 90, column 24) for  sqrt(sqv(ss) - sq(D))
      % expected type  nznum
  Q_eq_Qs_perp_TCC1: OBLIGATION
    FORALL (ss: Ss_vect2[D]): sqrt(sqv(ss) - sq(D)) /= 0;

  % Subtype TCC generated (at line 106, column 6) for  eps * perpR(sp)
      % expected type  Nz_vect2
  tangent_line_TCC1: OBLIGATION
    FORALL (sp: Sp_vect2[D], eps: Sign):
      sqv(sp) = sq(D) IMPLIES eps * perpR(sp) /= zero;

  % Subtype TCC generated (at line 108, column 9) for  sp
      % expected type  Ss_vect2[D]
  tangent_line_TCC2: OBLIGATION
    FORALL (sp: Sp_vect2[D]): NOT sqv(sp) = sq(D) IMPLIES sqv(sp) > sq(D);


body:
  %------------------------------------------------------------------------------
  % cd2d.pvs
  % ACCoRD v1.0
  %
  % Correctness and completeness of 2-D conflict detection algorithm. 
  %   D : Horizontal separation
  %   T : Lookahead time
  %------------------------------------------------------------------------------

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

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

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


    t	: VAR Lookahead

    % Conflict during interval [B,T]
    conflict_2D?(s,v) : bool =
      EXISTS (t: Lookahead): sqv(s+t*v) < sq(D)

    conflict_2D_horizontal : LEMMA
      conflict_2D?(s,v) IMPLIES
      horizontal_conflict?(s,v)

    on_D_conflict: LEMMA
      on_D?(s+B*v) IMPLIES
        (conflict_2D?(s,v) IFF (s+B*v)*v < 0)


    % tau: Minimum distance during interval [B,T]
    tau_v2(s,nzv) : Lookahead = min(max(B,horizontal_tca(s,nzv)),T)

    % tau_vv = tau*v^2 [defined such that it's continuous everywhere]
    tau_vv(s)(v) : real = min(max(B*sqv(v),-(s*v)),T*sqv(v))

    tau_vv : LEMMA
      tau_vv(s)(nzv) = sqv(nzv)*tau_v2(s,nzv)

    tau_vv_continuous : JUDGEMENT
      tau_vv(s) HAS_TYPE continuous_vr_fun

    % omega: Distance during interval [B,T]
    horizontal_omega(s,nzv) : nnreal = sqv(s + tau_v2(s,nzv)*nzv)

    horizontal_omega_min : LEMMA
      FORALL (t: Lookahead):
      horizontal_omega(s,nzv) <= sqv(s+t*nzv)
           
    horizontal_omega_conflict : LEMMA
      conflict_2D?(s,nzv) IFF horizontal_omega(s,nzv) - sq(D) < 0

    % omega_vv = omega*v^2 - D^2*v^2 [defined such that it's continuous everywhere]
    omega_vv(s)(v) : real = 
      IF on_D?(s) AND B=0 THEN s*v
      ELSE 
        sqv(v)*sqv(s) + (2*tau_vv(s)(v))*(s*v) + sq(tau_vv(s)(v)) - sq(D)*sqv(v)
      ENDIF

    omega_vv_continuous : JUDGEMENT
      omega_vv(s) HAS_TYPE continuous_vr_fun

    omega_vv : LEMMA NOT (on_D?(s) AND B=0) IMPLIES
      omega_vv(s)(nzv) = sqv(nzv)*(horizontal_omega(s,nzv)-sq(D))

    omega_vv_conflict : LEMMA 
      ((NOT horizontal_los?(s)) OR v /= zero) IMPLIES
      (omega_vv(s)(v) < 0 IFF conflict_2D?(s,v))

    omega_vv_zero : THEOREM NOT (on_D?(s) AND B=0) IMPLIES
      (omega_vv(s)(v) = 0 IFF v=zero OR horizontal_omega(s,v) = sq(D))

    % omega_half = Distance during interval [0,...) 
    omega_half(s,nzv) : nnreal = sqv(s + max(0,-(s*nzv)/sqv(nzv))*nzv)

    omega_half_line : LEMMA
      omega_half(ss,nzv) = sq(D) IMPLIES line_solution?(ss,nzv) 

    
    %-----------------------------------------------%
    % 2-D Conflict interval detection [tin,tout]    %
    %     (tin,tout) is the conflict interval       %
    %-----------------------------------------------%  

    detection_2D(s,v) : [Lookahead,Lookahead] =
      IF zero_vect2?(v) AND horizontal_los?(s) THEN 
        (B,T)
      ELSIF Delta(s,v) > 0 THEN
        LET tin  = Theta_D(s,v,Entry),
            tout = Theta_D(s,v,Exit) IN
          (min(max(tin,B),T),max(min(tout,T),B))
      ELSE
        (B,B)
      ENDIF

    detection_2D_correct : THEOREM
      LET (tin,tout) = detection_2D(s,v) IN
       tin < t AND t < tout IMPLIES horizontal_los?(s+t*v)

    detection_2D_complete : THEOREM
      LET (tin,tout) = detection_2D(s,v) IN
        horizontal_los?(s+t*v) IMPLIES tin <= t AND t <= tout AND tin < tout

    conflict_detection_2D : THEOREM
      LET (tin,tout) = detection_2D(s,v) IN
      conflict_2D?(s,v) IFF tin < tout

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

    cd2d?(s,v) : bool =
      horizontal_los?(s+B*v) OR omega_vv(s)(v) < 0

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

    cd2d : THEOREM 
      conflict_2D?(s,v)
      IFF
      cd2d?(s,v)

  END cd2d

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

  % Subtype TCC generated (at line 42, column 30) for
      % min(max(B, horizontal_tca(s, nzv)), T)
      % expected type  Lookahead[B, T]
  tau_v2_TCC1: OBLIGATION
    FORALL (s: Vect2, nzv: Nz_vect2):
      min(max(B, horizontal_tca(s, nzv)), T) >= 0 AND
       B <= min(max(B, horizontal_tca(s, nzv)), T) AND
        min(max(B, horizontal_tca(s, nzv)), T) <= T;

  % Judgement subtype TCC generated (at line 51, column 4) for  tau_vv(s)
      % expected type  continuous_vr_fun
  tau_vv_continuous: OBLIGATION FORALL (s): continuous_vr?(tau_vv(s));

  % Judgement subtype TCC generated (at line 71, column 4) for  omega_vv(s)
      % expected type  continuous_vr_fun
  omega_vv_continuous: OBLIGATION FORALL (s): continuous_vr?(omega_vv(s));

  % Subtype TCC generated (at line 81, column 57) for  v
      % expected type  Nz_vect2
  omega_vv_zero_TCC1: OBLIGATION
    FORALL (s, v: Vect2):
      NOT (sqv(s) = sq(D) AND B = 0) AND NOT v = zero IMPLIES v /= zero;

  % Subtype TCC generated (at line 97, column 7) for  B
      % expected type  Lookahead[B, T]
  detection_2D_TCC1: OBLIGATION
    FORALL (s: Vect2, v: Vect2):
      v = zero AND sqv(s) < sq(D) IMPLIES B <= B AND B <= T;

  % Subtype TCC generated (at line 97, column 9) for  T
      % expected type  Lookahead[B, T]
  detection_2D_TCC2: OBLIGATION
    FORALL (s: Vect2, v: Vect2):
      v = zero AND sqv(s) < sq(D) IMPLIES B <= T AND T <= T;

  % Subtype TCC generated (at line 99, column 27) for  v
      % expected type  {nzv | Delta(s, nzv) >= 0}
  detection_2D_TCC3: OBLIGATION
    FORALL (s: Vect2, v: Vect2):
      Delta(s, v) > 0 AND NOT (v = zero AND sqv(s) < sq(D)) IMPLIES
       v /= zero AND Delta[D](s, v) >= 0;

  % Subtype TCC generated (at line 101, column 9) for  min(max(tin, B), T)
      % expected type  Lookahead[B, T]
  detection_2D_TCC4: OBLIGATION
    FORALL (s: Vect2, v: Vect2):
      Delta(s, v) > 0 AND NOT (v = zero AND sqv(s) < sq(D)) IMPLIES
       (FORALL (tin: real):
          tin = Theta_D(s, v, -1) IMPLIES
           (FORALL (tout: real):
              tout = Theta_D(s, v, 1) IMPLIES
               min(max(tin, B), T) >= 0 AND
                B <= min(max(tin, B), T) AND min(max(tin, B), T) <= T));

  % Subtype TCC generated (at line 101, column 27) for  max(min(tout, T), B)
      % expected type  Lookahead[B, T]
  detection_2D_TCC5: OBLIGATION
    FORALL (s: Vect2, v: Vect2):
      Delta(s, v) > 0 AND NOT (v = zero AND sqv(s) < sq(D)) IMPLIES
       (FORALL (tin: real):
          tin = Theta_D(s, v, -1) IMPLIES
           (FORALL (tout: real):
              tout = Theta_D(s, v, 1) IMPLIES
               max(min(tout, T), B) >= 0 AND
                B <= max(min(tout, T), B) AND max(min(tout, T), B) <= T));

  % Subtype TCC generated (at line 103, column 7) for  B
      % expected type  Lookahead[B, T]
  detection_2D_TCC6: OBLIGATION
    FORALL (s: Vect2, v: Vect2):
      NOT Delta(s, v) > 0 AND NOT (v = zero AND sqv(s) < sq(D)) IMPLIES
       B <= B AND B <= T;


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

    IMPORTING cd2d[D,B,T],
              horizontal_criteria[D],
  	    vect_analysis@vect2_Heine,
  	    analysis@metric_space_real_fun[[real,Vect2],d],
  	    analysis@ms_composition_cont[[real,Vect2],d,Vect2,dist,real,real_dist],
  	    analysis@continuity_of_max_min[[real,Vect2],d],
  	    analysis@convex_function_props

               
    s,v,w		: VAR Vect2
    t,tlh,t1,t2	: VAR Lookahead
    ttt,tw,tx,ty	: VAR real
    dir,eps	: VAR Sign
    M		: VAR real
    sz,vz		: VAR real



      % 1 Distance Functions


           % 1.B Horizontal Distance


  	     % 1.B.2 Continuity

    horiz_dist_cont_scaf: LEMMA continuous?(horiz_dist_scaf(s),fullset[[Lookahead,Vect2]])


    conflict_2D_on_open_interval: LEMMA conflict_2D?(s,v) IFF
      EXISTS (topen: Lookahead): B<topen AND topen <T AND sqv(s+topen*v)<sq(D)


  	     % 1.B.4 Trajectory Information

    circle_hit: LEMMA horiz_dist_scaf(s)(t,v) < M IMPLIES
    		 EXISTS (epsilon: posreal): FORALL (t1: Lookahead): abs(t1 - t) < epsilon 
  		 IMPLIES horiz_dist_scaf(s)(t1,v) < M


           % 1.C Cylindrical Distance

               % 1.C.1 Definitions

  	     % 1.C.2 Continuity/Boundedness of omega/omega_2D

    horiz_dist_scaf_bounded_below : LEMMA
      bounded_below?(LAMBDA(t: Lookahead):horiz_dist_scaf(s)(t,v))

    omega_2D(s)(v) : real = 
      inf(LAMBDA(t: Lookahead):horiz_dist_scaf(s)(t,v))


    tau_2D_nonempty : LEMMA
      nonempty?({t: Lookahead | horiz_dist_scaf(s)(t,v) = omega_2D(s)(v)})




  	     % 1.C.4 tau_2D Definitions and Basic Properties

    tau_2D(s,v) : Lookahead =
      choose({t: Lookahead | horiz_dist_scaf(s)(t,v) = omega_2D(s)(v)})

    tau_2D_def: LEMMA horiz_dist_scaf(s)(tau_2D(s,v),v) = omega_2D(s)(v)


    omega_2D_min_rew: LEMMA omega_2D(s)(v) = min({r: real | EXISTS (t: Lookahead):horiz_dist_scaf(s)(t,v) = r})


    tau_2D_min : LEMMA
      horiz_dist_scaf(s)(tau_2D(s,v),v) <= horiz_dist_scaf(s)(t,v)

    omega_2D_continuous: LEMMA continuous?(omega_2D(s))

    tau_2D_unique: LEMMA
  		 v /= zero AND
    		 horiz_dist_scaf(s)(tau_2D(s,v),v) = horiz_dist_scaf(s)(t,v)
  		 IMPLIES tau_2D(s,v) = t

    tau_2D_connected: LEMMA horiz_dist_scaf(s)(tau_2D(s,v),v) = 0
    		    	  AND horiz_dist_scaf(s)(t,v) = 0
  			  IMPLIES
  			  (FORALL (ttt: real): 0<=ttt AND ttt<= 1 IMPLIES
  			  horiz_dist_scaf(s)(ttt*tau_2D(s,v) + (1-ttt)*t,v)=0)

    tau_2D_v2: LEMMA v/= zero IMPLIES tau_2D(s,v) = tau_v2(s,v)

    omega_2D_horizontal_omega: LEMMA v/= zero IMPLIES omega_2D(s)(v) = horizontal_omega(s,v) - sq(D)


  	     % 1.C.5 Conflicts

    omega_2D_conflict : LEMMA
      omega_2D(s)(v) < 0 IFF conflict_2D?(s,v)


      % 2 Critical Points

           % 2.A Case Subdivision

    omega_2D_eq_0 : LEMMA
      omega_2D(s)(v) = 0  IFF
      on_D?(s+tau_2D(s,v)*v)

    parts_of_v_nonzero_2D: LEMMA omega_2D(s)(v) = 0 AND NOT horiz_dist_scaf(s)(0,v)=0
    		      IMPLIES 
  		      v /= zero


  	 % 2.C Open Tape Solutions


  	     % 2.C.2 Line Solutions or 2-D Circle Solutions

    % tape hit solution

    lower_circle_hit_solution: LEMMA omega_2D(s)(v) = 0 AND
    			     	   on_D?(s+B*v) IMPLIES
  				   circle_solution_2D?(s,v,B,Exit)

    circle_hit_solution: LEMMA NOT v = zero AND
  		 omega_2D(s)(v) = 0 AND
  		 sqv(s+B*v) /= sq(D)
  		 IMPLIES
  		 horizontal_sep?(s) AND line_solution?(s,v) OR circle_solution_2D?(s,v,T,Entry)


  	     % 2.C.4 |s`z|<H and v`z = 0: 2-D circle solutions


           % 2.D Open Disc Solutions


  	     % 2.D.4 omega_2D(s)(v) = 0 and v = 0 implies s is inside circle
    
    % no_horiz_speed_closed_circle
    no_horiz_speed_on_D: LEMMA omega_2D(s)(v) = 0 AND v = zero 
    				IMPLIES sqv(s) = sq(D)


           % 2.E Corner Solutions

  	     % 2.E.1 Delta >= 0

    omega_2D_Delta: LEMMA omega_2D(s)(v) <= 0
    	       IMPLIES Delta(s,v) >= 0



  	     % 2.E.2 Relationship Between Theta_D(Entry) and Theta_D(Exit)

    Theta_Ds_equal_line_sol_2D: LEMMA omega_2D(s)(v) = 0 
    			   AND strict_horizontal_sep?(s) 
  			   AND Theta_D(s,v,Entry) = Theta_D(s,v,Exit) 
  			   IMPLIES 
  			   line_solution?(s,v)



      % 2 The Final Theorem For omega_2D


  	 % 2.B The Critical Points of omega_2D

    critical_points_2D : THEOREM
      omega_2D(s)(v) = 0 IMPLIES horizontal_sep?(s) AND line_solution?(s,v) OR
                                 circle_solution_2D?(s,v,T,Entry) OR
  			       circle_solution_2D?(s,v,B,Exit)





  END omega_2D

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

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

  % Assuming TCC generated (at line 8, column 5) for
      % analysis@ms_composition_cont
      %     [[real, Vect2], d, Vect2, dist, real, real_dist]
      % generated from assumption ms_composition_cont.fullset_metric_space2
  IMP_ms_composition_cont_TCC1: OBLIGATION
    metric_space?[Vect2, dist](fullset[Vect2]);

  % Assuming TCC generated (at line 8, column 5) for
      % analysis@ms_composition_cont
      %     [[real, Vect2], d, Vect2, dist, real, real_dist]
      % generated from assumption ms_composition_cont.fullset_metric_space3
  IMP_ms_composition_cont_TCC2: OBLIGATION
    metric_space?[real, real_dist](fullset[real]);

  % Subtype TCC generated (at line 54, column 8) for
      % LAMBDA (t: Lookahead): horiz_dist_scaf(s)(t, v)
      % expected type  {f | bounded_below?[Lookahead[B, T]](f)}
  omega_2D_TCC1: OBLIGATION
    FORALL (s: Vect2, v: Vect2):
      bounded_below?[Lookahead[B, T]]
          (LAMBDA (t: Lookahead[B, T]): horiz_dist_scaf[D](s)(t, v));

  % Existence TCC generated (at line 54, column 4) for  inf
  omega_2D_TCC2: OBLIGATION EXISTS (x: Lookahead[B, T]): TRUE;

  % Subtype TCC generated (at line 66, column 11) for
      % {t: Lookahead | horiz_dist_scaf(s)(t, v) = omega_2D(s)(v)}
      % expected type  p: (nonempty?[Lookahead[B, T]])
  tau_2D_TCC1: OBLIGATION
    FORALL (s: Vect2, v: Vect2):
      nonempty?[Lookahead[B, T]]
          ({t: Lookahead[B, T] |
              horiz_dist_scaf[D](s)(t, v) = omega_2D(s)(v)});

  % Subtype TCC generated (at line 71, column 47) for
      % {r: real | EXISTS (t: Lookahead): horiz_dist_scaf(s)(t, v) = r}
      % expected type  min_set[real]
  omega_2D_min_rew_TCC1: OBLIGATION
    FORALL (s, v: Vect2):
      nonempty?[real]
          ({r: real |
              EXISTS (t: Lookahead[B, T]): horiz_dist_scaf[D](s)(t, v) = r})
       AND
       below_bounded[real]
           ({r: real |
               EXISTS (t: Lookahead[B, T]): horiz_dist_scaf[D](s)(t, v) = r})
        AND
        ext[real]
            ({r: real |
                EXISTS (t: Lookahead[B, T]): horiz_dist_scaf[D](s)(t, v) = r})
            (inf[real]
                 ({r: real |
                     EXISTS (t: Lookahead[B, T]):
                       horiz_dist_scaf[D](s)(t, v) = r}));

  % Subtype TCC generated (at line 158, column 20) for  v
      % expected type  {nzv | Delta(s, nzv) >= 0}
  Theta_Ds_equal_line_sol_2D_TCC1: OBLIGATION
    FORALL (s, v: Vect2):
      omega_2D(s)(v) = 0 AND sqv(s) > sq(D) IMPLIES
       v /= zero AND Delta[D](s, v) >= 0;

  % Subtype TCC generated (at line 160, column 21) for  s
      % expected type  Sp_vect2[D]
  Theta_Ds_equal_line_sol_2D_TCC2: OBLIGATION
    FORALL (s, v: Vect2):
      Theta_D(s, v, -1) = Theta_D(s, v, 1) AND
       sqv(s) > sq(D) AND omega_2D(s)(v) = 0
       IMPLIES sqv(s) >= sq(D);


body:
  vertical_dist_convexity[H:posreal] : THEORY
  BEGIN

    IMPORTING analysis@convex_function_props,
    	    vectors@vectors_3D
               
    s,v,w		: VAR Vect3
    ttt,tw,tx,ty	: VAR real

           % 1.A Vertical Distance

               % 1.A.1 Definitions

    % Vertical Distance
    vert_dist_scaf(s)(t: real,v): real = abs(s`z+t*v`z)-H

    % The Squared Version...
    vert_dist_sq_scaf(s)(t: real, v): real = sq(s`z + t*v`z) - sq(H)


  	     % 1.A.2 Convexity

    vert_dist_convex_scaf: LEMMA convex?((LAMBDA (ttt): vert_dist_scaf(s)(ttt,v)))

    vert_dist_strictly_convex_scaf: LEMMA v`z /= 0 IMPLIES strictly_convex?((LAMBDA (ttt): vert_dist_sq_scaf(s)(ttt,v)))


  	     % 1.A.4 Relationship to Squared Version

    vert_dist_scaf_quad_eq_0: LEMMA vert_dist_scaf(s)(ttt,v) = 0 IFF sq(s`z + ttt*v`z) = sq(H)

    vert_dist_scaf_quad_ge_0: LEMMA vert_dist_scaf(s)(ttt,v) >= 0 IFF sq(s`z + ttt*v`z) >= sq(H)

    vert_dist_scaf_quad_gt_0: LEMMA vert_dist_scaf(s)(ttt,v) > 0 IFF sq(s`z + ttt*v`z) > sq(H)

    vert_dist_scaf_quad_le_0: LEMMA vert_dist_scaf(s)(ttt,v) <= 0 IFF sq(s`z + ttt*v`z) <= sq(H)

    vert_dist_scaf_quad_lt_0: LEMMA vert_dist_scaf(s)(ttt,v) < 0 IFF sq(s`z + ttt*v`z) < sq(H)

  END vertical_dist_convexity


body:
  %------------------------------------------------------------------------------
  % vertical.pvs
  % ACCoRD v1.0
  %
  % This theory provides definitions for vertical separation and conflict.
  %
  % It also provides solutions to the times when a velocity vector
  % intersects the rectangular protected zone. Given a current position s,
  % a vector v intersects the rectangle of base 2D and height 2H at times
  % Theta_H's that solutions to the equation:
  %  sz + t*vz = +/ H
  %------------------------------------------------------------------------------

  vertical[H: posreal] : THEORY
  BEGIN

    IMPORTING reals@sq,
              reals@sign,
    	    reals@abs_lems,
              definitions,
  	    vertical_dist_convexity[H]

    sz,vz,t,
    voz,viz : VAR real
    nzvz    : VAR nzreal
    eps,dir : VAR Sign
    nzt     : VAR nzreal
    pt      : VAR posreal
    b	  : VAR nnreal

    %% Vertical separation at current time

    vertical_sep?(sz): MACRO bool = 
      abs(sz) >= H

    vertical_sep_at?(sz,vz,t): MACRO bool =
      vertical_sep?(sz+t*vz)

    % Strict vertical separation

    strict_vertical_sep?(sz): MACRO bool = 
      abs(sz) > H

    Spz : TYPE = (vertical_sep?)

    spz : VAR Spz

    nz_spz : JUDGEMENT
      Spz SUBTYPE_OF nzreal

    neg_spz : JUDGEMENT
      -(spz) HAS_TYPE Spz

    on_H?(sz): MACRO bool = 
      abs(sz) = H

    on_signed_H?(sz,eps) : MACRO bool =
      sz = eps*H

    on_signed_H : LEMMA
      on_signed_H?(sz,eps) IMPLIES
      on_H?(sz)

    %% Vertical separation in the direction given by eps (-1=before,1=after)
    vertical_sep_dir?(sz,vz,eps): MACRO bool =
      FORALL(t:real): eps*t >= 0 IMPLIES vertical_sep_at?(sz,vz,t)

    %% Vertical loss of separation
    vertical_los?(sz): MACRO bool = 
      abs(sz) < H

    vertical_los_at?(sz,vz,t): MACRO bool =
      vertical_los?(sz+t*vz)

    %% Vertical conflict for infinite look-ahead time
    vertical_conflict?(sz,vz):bool =
      EXISTS (nnt:nnreal) : vertical_los_at?(sz,vz,nnt)

    vertical_conflict_neg : LEMMA
      vertical_conflict?(-sz,-vz) IMPLIES vertical_conflict?(sz,vz)

    vertical_conflict_symm : LEMMA
      vertical_conflict?(-sz,-vz) IFF vertical_conflict?(sz,vz)

    Theta_H(sz,nzvz,eps) : real =
     (eps*sign(nzvz)*H-sz)/nzvz

    Theta_H_symm : LEMMA
      Theta_H(-sz,-nzvz,eps) = Theta_H(sz,nzvz,eps) 

    Theta_H_lt : LEMMA
      Theta_H(sz,nzvz,Entry) < Theta_H(sz,nzvz,Exit)
    
    Theta_H_on_H : LEMMA
       LET t = Theta_H(sz,nzvz,eps) IN
        on_H?(sz+t*nzvz)

    Theta_H_eq_0 : LEMMA
      on_H?(sz) AND
      vertical_entry?(sz,nzvz)
      IMPLIES
      Theta_H(sz,nzvz,Entry) = 0

    Theta_H_ge_0 : LEMMA 
      vertical_entry?(spz,nzvz)
      IMPLIES 
        Theta_H(spz,nzvz,Entry) >= 0

    Theta_H_exit_gt_0 : LEMMA
      H > sign(nzvz)*sz IFF
      Theta_H(sz,nzvz,Exit) > 0

    Theta_H_unique_eps: LEMMA 
     on_H?(sz+t*nzvz) 
     IFF EXISTS (eps): t = Theta_H(sz,nzvz,eps)

    Theta_H_unique: LEMMA 
     on_H?(sz+t*nzvz) 
     IFF t = Theta_H(sz,nzvz,Entry) OR t = Theta_H(sz,nzvz,Exit) 

    vertical_los_entry : LEMMA
      vertical_los?(sz) OR vertical_entry?(sz,nzvz)
      IFF
      H > sign(nzvz)*sz 

    Theta_H_entry_lt_t : LEMMA
      -H < sign(nzvz)*(sz+t*nzvz) IFF
      Theta_H(sz,nzvz,Entry) < t

    vertical_conflict : LEMMA
      vertical_conflict?(sz,nzvz) IFF
      vertical_los?(sz) OR vertical_entry?(sz,nzvz)

    vertical_los_inside_Theta : LEMMA
      t > Theta_H(sz,nzvz,Entry) AND  
      t < Theta_H(sz,nzvz,Exit) IFF
      vertical_los?(sz+t*nzvz)       

   vertical_sep_outside_Theta: LEMMA
      t < Theta_H(sz,nzvz,Entry) OR
      t > Theta_H(sz,nzvz,Exit) IFF
      abs(sz + t*nzvz) > H

    Theta_H_vertical_dir: LEMMA
      vertical_dir_at?(sz,nzvz,Theta_H(sz,nzvz,eps),eps)

    vertical_tau_entry_exit : LEMMA
      vertical_tau(sz,nzvz) > Theta_H(sz,nzvz,Entry) AND 
      vertical_tau(sz,nzvz) < Theta_H(sz,nzvz,Exit) 

    vertical_tau_midpoint : LEMMA
      vertical_tau(sz,nzvz) = (Theta_H(sz,nzvz,Entry)+Theta_H(sz,nzvz,Exit))/2

    vertical_tau_pos : LEMMA
      vertical_entry?(spz,nzvz)
      IMPLIES 
        vertical_tau(spz,nzvz) > 0

    % eps = +1   -- Top circle of protected zone
    % eps = -1   -- Bottom circle protected zone

    vs_at(sz,nzt,eps) : real =
       (eps*H - sz)/nzt

    vs_at_neg : LEMMA 
      vs_at(-sz,nzt,-eps) = -vs_at(sz,nzt,eps)

    vs_at_H: LEMMA
      sz + nzt*vs_at(sz,nzt,eps) = eps*H

    vs_at_complete : LEMMA
      sz + nzt*vz = eps*H IMPLIES
      vz = vs_at(sz,nzt,eps)

    vertical_sep_dir: LEMMA
      vertical_dir?(spz,vz,dir) IFF vertical_sep_dir?(spz,vz,dir)

    vertical_sep_at_sign: LEMMA
      vertical_dir?(spz,vz,dir) AND
      dir*t >= 0
      IMPLIES
        vertical_sep?(spz+t*vz) AND 
        sign(spz)=sign(spz+t*vz)

    vertical_solution?(sz,vz,t,dir): bool = 
      on_H?(sz+t*vz) AND vertical_dir_at?(sz,vz,t,dir) 

    vertical_solution_vertical_sep : LEMMA
      vertical_solution?(sz,vz,t,Entry) IMPLIES
      FORALL (tt:real) : tt <= t IMPLIES vertical_sep_at?(sz,vz,tt) 

    vertical_solution_strict_vertical_sep : LEMMA
      vertical_solution?(sz,nzvz,t,Entry) IMPLIES
      FORALL (tt:real) : tt < t IMPLIES strict_vertical_sep?(sz+tt*nzvz)

    Theta_H_vertical_solution: LEMMA
      vertical_solution?(sz,nzvz,Theta_H(sz,nzvz,eps),eps)

    vertical_solution_Theta_H : LEMMA
      vertical_solution?(sz,nzvz,t,dir) IMPLIES
      t = Theta_H(sz,nzvz,dir) 
    
    vs_at_complete_vertical_solution : LEMMA
      vertical_solution?(sz,vz,pt,Entry) IMPLIES
      vz = vs_at(sz,pt,sign(sz))

    vs_at_complete_dir: LEMMA
      vertical_solution?(sz,vz,pt,dir) IMPLIES
      EXISTS (eps: Sign): vz = vs_at(sz,pt,eps)

    vertical_solution_exit : LEMMA
      vertical_solution?(sz,nzvz,pt,Exit) IMPLIES
      sign(sz+pt*nzvz)*sz < H

    % vs_circle_at - An algorithm that computes critical points for 1 dimensional
    % vertical speed bands

    vs_circle_at(sz,viz,pt,eps,dir): [bool,real] =
      (pt > 0 AND dir*eps*sz <= dir*H,vs_at(sz,pt,eps) + viz)

    vs_circle_at_direction: LEMMA
      LET cpv = vs_circle_at(sz,viz,pt,eps,dir) IN
      cpv`1 IMPLIES vertical_dir_at?(sz,cpv`2-viz,pt,dir)

    vs_circle_at?(sz,viz,b,t)(voz): bool =
      b < t AND
      ((abs(sz) < H AND b > 0 AND 
      		(vs_circle_at(sz,viz,b,-1,1)`1 AND 
                   voz = vs_circle_at(sz,viz,b,-1,1)`2 OR
  		 vs_circle_at(sz,viz,b,1,1)`1 AND 
                   voz = vs_circle_at(sz,viz,b,1,1)`2)) OR
      (abs(sz) >= H AND b > 0 AND 
        vs_circle_at(sz,viz,b,-sign(sz),1)`1 AND 
        voz = vs_circle_at(sz,viz,b,-sign(sz),1)`2) OR
      (abs(sz) >= H AND t > 0 AND 
        vs_circle_at(sz,viz,t,sign(sz),-1)`1 AND  
        voz = vs_circle_at(sz,viz,t,sign(sz),-1)`2))

    vs_circle_at_complete: LEMMA
      b < t AND
      ((EXISTS (eps: Sign): vz = vs_at(sz,t,eps) + viz AND 
       vertical_dir_at?(sz,vz-viz,t,-1)) OR
       (b > 0 AND 
        EXISTS (eps: Sign): vz = vs_at(sz,b,eps) + viz AND 
        vertical_dir_at?(sz,vz-viz,b,1)))
      IMPLIES
      vs_circle_at?(sz,viz,b,t)(vz)

  END vertical

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

  % Judgement subtype TCC generated (at line 49, column 4) for  x
      % expected type  nzreal
  nz_spz: OBLIGATION FORALL (x: Spz): x /= 0;

  % Judgement subtype TCC generated (at line 52, column 4) for  -spz
      % expected type  Spz
  neg_spz: OBLIGATION FORALL (spz): abs(-spz) >= H;

  % Subtype TCC generated (at line 236, column 26) for  t
      % expected type  posreal
  vs_circle_at?_TCC1: OBLIGATION
    FORALL (sz: real, viz: real, b: nnreal, t: real, voz: real):
           t > 0 AND abs(sz) >= H
       AND NOT (abs(sz) >= H AND
                 b > 0 AND
                  vs_circle_at(sz, viz, b, -sign(sz), 1)`1 AND
                   voz = vs_circle_at(sz, viz, b, -sign(sz), 1)`2)
       AND NOT (abs(sz) < H AND
                 b > 0 AND
                  (vs_circle_at(sz, viz, b, -1, 1)`1 AND
                    voz = vs_circle_at(sz, viz, b, -1, 1)`2
                    OR
                    vs_circle_at(sz, viz, b, 1, 1)`1 AND
                     voz = vs_circle_at(sz, viz, b, 1, 1)`2))
       AND b < t
       IMPLIES t >= 0;

  % Subtype TCC generated (at line 241, column 40) for  t
      % expected type  nzreal
  vs_circle_at_complete_TCC1: OBLIGATION
    FORALL (b: nnreal, t: real): b < t IMPLIES t /= 0;

  % Subtype TCC generated (at line 244, column 40) for  b
      % expected type  nzreal
  vs_circle_at_complete_TCC2: OBLIGATION
    FORALL (b: nnreal, sz, t, viz, vz: real):
      b < t AND
       NOT (EXISTS (eps: Sign):
              vz = vs_at(sz, t, eps) + viz AND
               -1 * ((sz + t * (vz - viz)) * (vz - viz)) >= 0)
        AND b > 0
       IMPLIES b /= 0;


body:
  %------------------------------------------------------------------------------
  % cd_vertical.pvs
  % ACCoRD v1.0
  %
  % Correctness and completeness of vertical conflict detection algorithm. 
  %   H : Vertical separation
  %   B : Lookahead time
  %   T : Lookahead time
  %------------------------------------------------------------------------------

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

    IMPORTING vertical[H],
  	    util,
  	    Lookahead[B,T],
  	    reals@min_max

    sz,vz,t : VAR real
    nzvz    : VAR nzreal
    eps,dir : VAR Sign
    nzt     : VAR nzreal
    pt      : VAR posreal

    % Conflict during interval [0,T]
    conflict_vertical?(sz,vz) : bool =
      EXISTS (t: Lookahead): vertical_los_at?(sz,vz,t)

    cd_vertical?(sz,vz) : bool =
    		    (vz = 0 AND abs(sz)<H) OR
  		    (vz /= 0 AND min(max(-H-sign(vz)*sz,B*abs(vz)),T*abs(vz)) < max(min(H-sign(vz)*sz,T*abs(vz)),B*abs(vz)))

    cd_vertical_rewrite: LEMMA cd_vertical?(sz,vz) IFF 
    		       (vz = 0 AND abs(sz)<H) OR
         		       (vz /= 0 AND min(max(Theta_H(sz,vz,Entry),B),T) < max(min(Theta_H(sz,vz,Exit),T),B))


    cd_vertical_correct : THEOREM
      cd_vertical?(sz,vz) IMPLIES
      conflict_vertical?(sz,vz)

    cd_vertical_complete : THEOREM 
      conflict_vertical?(sz,vz)
      IMPLIES
      cd_vertical?(sz,vz)

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

    cd_vertical : THEOREM
      conflict_vertical?(sz,vz) IFF
      cd_vertical?(sz,vz) 


    conflict_vertical_on_open_interval: LEMMA conflict_vertical?(sz,vz) IFF
      EXISTS (topen: Lookahead): B<topen AND topen <T AND vertical_los_at?(sz,vz,topen)

  END cd_vertical


body:
  %------------------------------------------------------------------------------
  % vz_criteria.pvs
  % ACCoRD v1.0
  %
  % This theory proposes a criterion for vertical separation for non-negative
  % times. 
  %------------------------------------------------------------------------------

  vz_criteria[H: posreal]: THEORY
  BEGIN

    IMPORTING vertical[H]

    spz       : VAR Spz
    sz,vz,nvz,
    voiz,vioz,
    t         : VAR real
    nnt       : VAR nnreal
    dir       : VAR Sign

    %%
    %% Assumption: abs(sz) >= H

    vertical_exit_criterion?(spz,vz) : bool =
      vertical_exit?(spz,vz)

    vertical_exit_independence: THEOREM
      vertical_exit_criterion?(spz,vz) IFF NOT vertical_conflict?(spz,vz)

    vertical_exit_coordination: THEOREM
      vertical_conflict?(spz,vz) AND
      vertical_exit_criterion?(spz,voiz) AND
      vertical_exit_criterion?(-spz,vioz) 
      IMPLIES
        vertical_exit_criterion?(spz,voiz-vioz-vz)

    %% The following lemma assumes vertical separation at a given time in the
    %% future and gives sufficient conditions over a new vertical velocity 
    %% that also yields vertical separation at that time.

    vertical_sep_dir_at : LEMMA
      LET signsz = sign(sz+nnt*vz) IN
      vertical_sep?(sz+nnt*vz) AND
      vertical_dir?(sz+nnt*vz,vz,dir) AND
      (dir = Entry IMPLIES signsz*nvz <= 0) AND
      signsz*nvz >= signsz*vz 
      IMPLIES
        vertical_sep?(sz+nnt*nvz) AND
        vertical_dir?(sz+nnt*nvz,nvz,dir)

  END vz_criteria


body:
  %------------------------------------------------------------------------------
  % trk_only.pvs
  % ACCoRD v1.0
  %
  % Line solutions. Solve the following equation on k:
  %   || k*v + vi || = || vo ||.
  %
  % Circle solutions. Solve the following equations on v:
  %   sq(s+t*v) = sq(D)
  %   || v + vi || = || vo || 
  %
  %------------------------------------------------------------------------------

  trk_only[D:posreal] : THEORY
  BEGIN
    
    IMPORTING vectors@vectors_2D, 
  	    vectors@det_2D,
              reals@quadratic_2b,
  	    horizontal[D],
  	    line_solutions[D]

    u,vnz,
    vnzo,vnzi  : VAR Nz_vect2
    dir,irt    : VAR Sign
    vo,vi,    
    nvo,
    vo1,vo2,
    s          : VAR Vect2
    sp	     : VAR Sp_vect2
    k,k1,k2,j  : VAR real
    t          : VAR posreal

    %---------------%
    % Line Solution %
    %---------------%

    % Vector vnz is a directional vector
    % Zero indicates no track solution
    trk_only_line(vnz,vo,vi,irt): {k:real,nvo:Vect2 | 
                                   nz_vect2?(nvo) => trk_only?(vo)(nvo) AND
                                                     k*vnz = nvo-vi} =
      LET a = sqv(vnz),
          b = vnz*vi,
          c = sqv(vi) - sqv(vo) IN
      IF discr2b(a,b,c) >= 0 THEN
        LET k = root2b(a,b,c,irt) IN
        (k,k*vnz+vi)
      ELSE
        (0,zero)
      ENDIF

    % trk_only_line computes the same roots for vectors of the same length
    same_trk_only_line: LEMMA 
      norm(vo1) = norm(vo2) IMPLIES
      trk_only_line(vnz,vo1,vi,irt) = trk_only_line(vnz,vo2,vi,irt)

    trk_only_line?(vnz,vo,vi,irt)(k,nvo) : bool =
      nz_vect2?(nvo) AND
      (k,nvo) = trk_only_line(vnz,vo,vi,irt)

    trk_only_line_complete : LEMMA
      trk_only?(vnzo)(nvo) AND
      k*vnz = nvo-vi IMPLIES
        EXISTS(irt):trk_only_line?(vnz,vnzo,vi,irt)(k,nvo)

    trk_only_line_lt : LEMMA
      trk_only_line?(vnz,vo,vi,-1)(k1,vo1) AND
      trk_only_line?(vnz,vo,vi,1)(k2,vo2) IMPLIES
        k1 <= k2

    % Solve equation on nvo: u*(nvo-vi) = j, such that ||nvo|| = ||vo||
    trk_only_dot(u,vo,vi,j,irt) : {nvo | nz_vect2?(nvo) => 
                                         trk_only?(vo)(nvo) AND
                                         u*(nvo-vi) = j} =
      trk_only_line(Vdir(u,vo-vi),vo,vi+W0(u,j),irt)`2 


    trk_only_dot_complete : LEMMA
      trk_only?(vnzo)(nvo) AND
      u*(nvo-vi) = j IMPLIES
      EXISTS (irt) : nvo = trk_only_dot(u,vnzo,vi,j,irt)


    %-----------------%
    % CircleSolution %
    %-----------------%

    trk_only_circle_eq_dot : LEMMA
      LET v = nvo-vi,
          w = s-t*vi,
          e = (sq(D) - sqv(s) - sq(t)*(sqv(vo)-sqv(vi)))/(2*t) IN
        trk_only?(vo)(nvo) IMPLIES
          (sqv(s+t*v) = sq(D) IFF
           w*v = e)

    trk_special_case?(s,vo,vi,t) : bool =
      s = t*vi AND sqv(vo) = sq(D/t)

    trk_spc_on_D : LEMMA
      trk_special_case?(s,vo,vi,t) AND
      trk_only?(vo)(nvo) IMPLIES
      sqv(s+t*(nvo-vi)) = sq(D)

    trk_spc_Delta_ge_0 : LEMMA
      trk_special_case?(s,vo,vi,t) IMPLIES
      Delta(s,vo-vi) >= 0

    trk_spc_dot : LEMMA
      trk_special_case?(s,vo,vi,t) AND
      trk_only?(vo)(nvo) IMPLIES
      sq(D/t) - vi*nvo = ((s+t*(nvo-vi)) * (nvo-vi))/t

    trk_spc_line_solution: LEMMA 
      trk_special_case?(sp,vo,vi,t) AND
      (sp+t*(vo-vi)) * (vo-vi) = 0 
      IMPLIES line_solution?(sp,vo-vi)

    trk_spc_horizontal_dir : LEMMA
      trk_special_case?(s,vo,vi,t) AND
      trk_only?(vo)(nvo) IMPLIES
      (dir*(vi*nvo - sq(D/t)) <= 0 IFF horizontal_dir_at?(s,nvo-vi,t,dir))

    trk_only_circle(s,vo,vnzi,t,dir,irt): {nvo | nz_vect2?(nvo) => 
                                                 trk_only?(vo)(nvo)} =
        LET w = s-t*vnzi,
            e = (sq(D) - sqv(s) - sq(t)*(sqv(vo)-sqv(vnzi)))/(2*t) IN
        IF nz_vect2?(w) THEN
          LET nvo = trk_only_dot(w,vo,vnzi,e,irt) IN
          IF horizontal_dir_at?(s,nvo-vnzi,t,dir) THEN
            nvo
          ELSE
  	  zero
          ENDIF
        ELSE
          zero
        ENDIF

    trk_only_circle?(s,vo,vnzi,t,dir)(nvo): bool =
       nz_vect2?(nvo) AND
       EXISTS (irt:Sign): nvo = trk_only_circle(s,vo,vnzi,t,dir,irt)

    trk_only_circle_solution : LEMMA
      trk_only_circle?(s,vo,vnzi,t,dir)(nvo) IMPLIES
      circle_solution_2D?(s,nvo-vnzi,t,dir)

    trk_only_circle_complete : LEMMA     
      trk_only?(vnzo)(nvo) AND
      NOT trk_special_case?(s,vnzo,vnzi,t) AND                                              
      circle_solution_2D?(s,nvo-vnzi,t,dir) IMPLIES                                          
        trk_only_circle?(s,vnzo,vnzi,t,dir)(nvo)     

    trk_only_vertical(s,vo,vi,t,dir,irt): {nvo | nz_vect2?(nvo) => 
                                                 trk_only?(vo)(nvo)} =
      LET v = vo-vi IN
      IF Delta(s,v) > 0 AND Theta_D(s,v,dir) > 0 THEN
        LET p = s + Theta_D(s,v,dir)*v IN
          trk_only_dot(t*p,vo,vi,sq(D)-s*p,irt) 
      ELSE
        zero
      ENDIF

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

    trk_only_vertical_on_D: LEMMA
      LET v = vo-vi IN
      trk_only_vertical?(s,vo,vi,t,dir)(nvo) IMPLIES
        Delta(s,v) > 0 AND
        Theta_D(s,v,dir) > 0 AND
        (s+t*(nvo-vi))*(s+Theta_D(s,v,dir)*v) = sq(D) 

  END trk_only

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

  % Subtype TCC generated (at line 48, column 6) for  (k, k * vnz + vi)
      % expected type  {k: real, nvo: Vect2 |
                     %          nvo /= zero =>
                     %           trk_only?(vo)(nvo) AND k * vnz = nvo - vi}
  trk_only_line_TCC1: OBLIGATION
    FORALL (vnz: Nz_vect2, vo: Vect2, vi: Vect2, irt: Sign, a: posreal):
      a = sqv(vnz) IMPLIES
       (FORALL (b: real):
          b = vnz * vi IMPLIES
           (FORALL (c: real):
              discr2b(a, b, c) >= 0 AND c = sqv(vi) - sqv(vo) IMPLIES
               (FORALL (k: real):
                  k = root2b(a, b, c, irt) IMPLIES
                   k * vnz + vi /= zero =>
                    trk_only?(vo)(k * vnz + vi) AND
                     k * vnz = k * vnz + vi - vi)));

  % Subtype TCC generated (at line 50, column 6) for  (0, zero)
      % expected type  {k: real, nvo: Vect2 |
                     %          nvo /= zero =>
                     %           trk_only?(vo)(nvo) AND k * vnz = nvo - vi}
  trk_only_line_TCC2: OBLIGATION
    FORALL (vnz: Nz_vect2, vo: Vect2, vi: Vect2, a: posreal):
      a = sqv(vnz) IMPLIES
       (FORALL (b: real):
          b = vnz * vi IMPLIES
           (FORALL (c: real):
              NOT discr2b(a, b, c) >= 0 AND c = sqv(vi) - sqv(vo) IMPLIES
               zero /= zero => trk_only?(vo)(zero) AND 0 * vnz = zero - vi));

  % Subtype TCC generated (at line 76, column 4) for
      % trk_only_line(Vdir(u, vo - vi), vo, vi + W0(u, j), irt)`2
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           trk_only?(vo)(nvo) AND u * (nvo - vi) = j}
  trk_only_dot_TCC1: OBLIGATION
    FORALL (u: Nz_vect2, vo: Vect2, vi: Vect2, j: real, irt: Sign):
      trk_only_line(Vdir(u, vo - vi), vo, vi + W0(u, j), irt)`2 /= zero =>
       trk_only?(vo)
                (trk_only_line(Vdir(u, vo - vi), vo, vi + W0(u, j), irt)`2)
        AND
        u * (trk_only_line(Vdir(u, vo - vi), vo, vi + W0(u, j), irt)`2 - vi)
         = j;

  % Subtype TCC generated (at line 131, column 10) for  nvo
      % expected type  {nvo | nvo /= zero => trk_only?(vo)(nvo)}
  trk_only_circle_TCC1: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vnzi: Nz_vect2, t: posreal, dir: Sign,
            irt: Sign, w: Vector):
      w = s - t * vnzi IMPLIES
       (FORALL (e: real):
          w /= zero AND
           e = (sq(D) - sqv(s) - sq(t) * (sqv(vo) - sqv(vnzi))) / (2 * t)
           IMPLIES
           (FORALL (nvo:
                      {nvo |
                               nvo /= zero =>
                                trk_only?(vo)(nvo) AND
                                 w * (nvo - vnzi) = e}):
              dir * ((s + t * (nvo - vnzi)) * (nvo - vnzi)) >= 0 AND
               nvo = trk_only_dot(w, vo, vnzi, e, irt)
               IMPLIES nvo /= zero => trk_only?(vo)(nvo)));

  % Subtype TCC generated (at line 133, column 3) for  zero
      % expected type  {nvo | nvo /= zero => trk_only?(vo)(nvo)}
  trk_only_circle_TCC2: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vnzi: Nz_vect2, t: posreal, dir: Sign,
            irt: Sign, w: Vector):
      w = s - t * vnzi IMPLIES
       (FORALL (e: real):
          w /= zero AND
           e = (sq(D) - sqv(s) - sq(t) * (sqv(vo) - sqv(vnzi))) / (2 * t)
           IMPLIES
           (FORALL (nvo:
                      {nvo |
                               nvo /= zero =>
                                trk_only?(vo)(nvo) AND
                                 w * (nvo - vnzi) = e}):
              NOT dir * ((s + t * (nvo - vnzi)) * (nvo - vnzi)) >= 0 AND
               nvo = trk_only_dot(w, vo, vnzi, e, irt)
               IMPLIES zero /= zero => trk_only?(vo)(zero)));

  % Subtype TCC generated (at line 136, column 8) for  zero
      % expected type  {nvo | nvo /= zero => trk_only?(vo)(nvo)}
  trk_only_circle_TCC3: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vnzi: Nz_vect2, t: posreal, w: Vector):
      w = s - t * vnzi IMPLIES
       (FORALL (e: real):
          NOT w /= zero AND
           e = (sq(D) - sqv(s) - sq(t) * (sqv(vo) - sqv(vnzi))) / (2 * t)
           IMPLIES zero /= zero => trk_only?(vo)(zero));

  % Subtype TCC generated (at line 156, column 36) for  v
      % expected type  {nzv | Delta(s, nzv) >= 0}
  trk_only_vertical_TCC1: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, v: Vector):
      Delta(s, v) > 0 AND v = vo - vi IMPLIES
       v /= zero AND Delta[D](s, v) >= 0;

  % Subtype TCC generated (at line 158, column 21) for  t * p
      % expected type  Nz_vect2
  trk_only_vertical_TCC2: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, t: posreal, dir: Sign,
            v: Vector):
      Delta(s, v) > 0 AND Theta_D(s, v, dir) > 0 AND v = vo - vi IMPLIES
       (FORALL (p: Vector):
          p = s + Theta_D(s, v, dir) * v IMPLIES t * p /= zero);

  % Subtype TCC generated (at line 158, column 8) for
      % trk_only_dot(t * p, vo, vi, sq(D) - s * p, irt)
      % expected type  {nvo | nvo /= zero => trk_only?(vo)(nvo)}
  trk_only_vertical_TCC3: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, t: posreal, dir: Sign, irt: Sign,
            v: Vector):
      Delta(s, v) > 0 AND Theta_D(s, v, dir) > 0 AND v = vo - vi IMPLIES
       (FORALL (p: Vector):
          p = s + Theta_D(s, v, dir) * v IMPLIES
           trk_only_dot(t * p, vo, vi, sq(D) - s * p, irt) /= zero =>
            trk_only?(vo)(trk_only_dot(t * p, vo, vi, sq(D) - s * p, irt)));

  % Subtype TCC generated (at line 160, column 6) for  zero
      % expected type  {nvo | nvo /= zero => trk_only?(vo)(nvo)}
  trk_only_vertical_TCC4: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, dir: Sign, v: Vector):
      NOT (Delta(s, v) > 0 AND Theta_D(s, v, dir) > 0) AND v = vo - vi
       IMPLIES zero /= zero => trk_only?(vo)(zero);


body:
  %------------------------------------------------------------------------------
  % space_3D.pvs
  % ACCoRD v1.0
  %
  % This theory provides definitons that are common to horizontal and vertical
  % resolutions.
  %------------------------------------------------------------------------------

  space_3D[D,H: posreal] : THEORY
  BEGIN

    IMPORTING util,
              definitions_3D,
              trk_only[D],
              horizontal[D],
              vertical[H]
   
    s,v,w,
    vo,vi,nvo : VAR Vect3
    t,vz      : VAR real
    s2,v2     : VAR Vect2
    nzs       : VAR Nz_vect3

    separation?(s) : MACRO bool = 
      vertical_sep?(s`z) OR
      horizontal_sep?(s)

    separation_at?(s,v,t) : MACRO bool =
      vertical_sep_at?(s`z,v`z,t) OR
      horizontal_sep_at?(s,v,t)

    conflict_at?(s,v,t) : MACRO bool =
      vertical_los_at?(s`z,v`z,t) AND 
      horizontal_los_at?(s,v,t)

    los?(s) :  MACRO bool =
      vertical_los?(s`z) AND
      horizontal_los?(s) 

    %% Conflict ever (infinite lookahead time)
    conflict_ever?(s,v): bool =
      EXISTS (t:real) : vertical_los_at?(s`z,v`z,t) AND 
                        horizontal_los_at?(s,v,t)

    %% Conflict in the future (infinite look-ahead time)
    conflict?(s,v):bool =
      EXISTS (nnt:nnreal) : vertical_los_at?(s`z,v`z,nnt) AND 
                            horizontal_los_at?(s,v,nnt) 

    conflict_symm : LEMMA
      conflict?(-s,-v) IFF conflict?(s,v)

    conflict_ever : LEMMA
      conflict?(s,v) IMPLIES conflict_ever?(s,v)

    conflict_ever_shift : LEMMA
      conflict_ever?(s,v) IFF conflict_ever?(s+t*v,v)

    conflict_sum_closed: LEMMA
      conflict?(s,v) AND conflict?(s,w)
      IMPLIES
      conflict?(s,v+w)

    conflict_is_an_open_set: LEMMA
        FORALL (ss, vv: Vect3):
        conflict?(ss, vv) IMPLIES
        (EXISTS (epsilon: posreal):
        FORALL (ww: Vect3):
        norm(ww) < epsilon IMPLIES conflict?(ss, vv + ww))

    vertical_horizontal_conflict : LEMMA
      conflict?(s,v) IMPLIES
      vertical_conflict?(s`z,v`z) AND
      horizontal_conflict?(s,v)
   
    Spz_vect3  : TYPE = {s : Vect3 | vertical_sep?(s`z)}
    Sp2_vect3  : TYPE = {s : Vect3 | horizontal_sep?(s)}
    Ss2_vect3  : TYPE = {s : Vect3 | strict_horizontal_sep?(s)}
    Sp_vect3   : TYPE = (separation?)

    spz : VAR Spz_vect3
    sp2 : VAR Sp2_vect3
    sp  : VAR Sp_vect3
    ss2 : VAR Ss2_vect3

    neg_spz : JUDGEMENT
     -(spz) HAS_TYPE Spz_vect3

    neg_sp2 : JUDGEMENT
     -(sp2) HAS_TYPE Sp2_vect3

    neg_sp : JUDGEMENT
      -(sp) HAS_TYPE Sp_vect3

    spv2 : JUDGEMENT
      vect2(sp2) HAS_TYPE Sp_vect2  

    ssv2 : JUDGEMENT
      vect2(ss2) HAS_TYPE Ss_vect2  

    sp_nzv : JUDGEMENT
      Sp_vect3 SUBTYPE_OF Nz_vect3

    verticalCoordinationConflict(s,v) : Sign =
      LET a = sqv(vect2(v)),
          b = vect2(s)*vect2(v),
          c = sqv(vect2(s)) - sq(D),
          d = sq(b)-a*c IN
      IF s = zero THEN
        break_symmetry(v)
      ELSIF v`z = 0 OR zero_vect2?(v) OR d < 0 OR eq(v`z,sq(b)-a*c,s`z*a-v`z*b) THEN
        break_symmetry(s)
      ELSIF gt(v`z,sq(b)-a*c,s`z*a-v`z*b) THEN 
         -1
      ELSE
          1
      ENDIF

    % VerticalCoordinationConflict is a vertical strategy
    verticalCoordinationConflict_asymm : LEMMA
      (s /= zero OR v /= zero) IMPLIES verticalCoordinationConflict(-s,-v) = -verticalCoordinationConflict(s,v)

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

    verticalCoordinationConflict_strategy : JUDGEMENT
      verticalCoordinationConflict HAS_TYPE Vertical_Strategy

    verticalCoordinationConflict_correct : LEMMA
      Delta(nzs,v) > 0 IMPLIES
      LET sz=nzs`z+Theta_D(nzs,v,Entry)*v`z IN
      sz /= 0 IMPLIES
        verticalCoordinationConflict(nzs,v) = sign(sz)

    % vs_los_strategy for recovery from vertical loss of separation

    vs_los_strategy(s,v): Sign =
      IF (horizontal_exit?(s,v) OR vect2(v) = zero) THEN
        (IF s`z /= 0 THEN
          sign(s`z)
        ELSIF v`z/=0 THEN
          sign(v`z)
        ELSIF s /= zero THEN
          break_symmetry(s)
        ELSIF v /= zero THEN
          break_symmetry(v)
        ELSE
          1
        ENDIF)
      ELSIF (s + horizontal_tca(s,v)*v)`z /= 0 THEN
        sign((s + horizontal_tca(s,v)*v)`z)
      ELSIF v`z/=0 THEN
        sign(v`z)
      ELSIF s /= zero THEN
        break_symmetry(s)
      ELSIF v /= zero THEN
        break_symmetry(v)
      ELSE
        1
      ENDIF

    vs_los_vertical_strategy: JUDGEMENT
      vs_los_strategy HAS_TYPE Vertical_Strategy

  END space_3D

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

  % Judgement subtype TCC generated (at line 87, column 3) for  -spz
      % expected type  Spz_vect3
  neg_spz: OBLIGATION FORALL (spz): abs((-spz)`z) >= H;

  % Judgement subtype TCC generated (at line 90, column 3) for  -sp2
      % expected type  Sp2_vect3
  neg_sp2: OBLIGATION FORALL (sp2): sqv(vect2(-sp2)) >= sq(D);

  % Judgement subtype TCC generated (at line 93, column 4) for  -sp
      % expected type  Sp_vect3
  neg_sp: OBLIGATION
    FORALL (sp): abs((-sp)`z) >= H OR sqv(vect2(-sp)) >= sq(D);

  % Judgement subtype TCC generated (at line 96, column 4) for  vect2(sp2)
      % expected type  Sp_vect2[D]
  spv2: OBLIGATION FORALL (sp2): sqv(vect2(sp2)) >= sq(D);

  % Judgement subtype TCC generated (at line 99, column 4) for  vect2(ss2)
      % expected type  Ss_vect2[D]
  ssv2: OBLIGATION FORALL (ss2): sqv(vect2(ss2)) > sq(D);

  % Judgement subtype TCC generated (at line 102, column 4) for  x
      % expected type  Nz_vect3
  sp_nzv: OBLIGATION FORALL (x: Sp_vect3): x /= zero;

  % Subtype TCC generated (at line 111, column 55) for  sq(b) - a * c
      % expected type  nnreal
  verticalCoordinationConflict_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3, a: nnreal):
      a = sqv(vect2(v)) IMPLIES
       (FORALL (b: real):
          b = vect2(s) * vect2(v) IMPLIES
           (FORALL (c: real):
              c = sqv(vect2(s)) - sq(D) IMPLIES
               (FORALL (d: real):
                       NOT d < 0 AND NOT vect2(v) = zero AND NOT v`z = 0
                   AND NOT s = zero AND d = sq(b) - a * c
                   IMPLIES sq(b) - a * c >= 0)));

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

  % Judgement subtype TCC generated (at line 127, column 4) for
      % verticalCoordinationConflict
      % expected type  Vertical_Strategy
  verticalCoordinationConflict_strategy: OBLIGATION
    FORALL (s, v):
      (s /= zero OR v /= zero) =>
       verticalCoordinationConflict(-s, -v) =
        -verticalCoordinationConflict(s, v);

  % Subtype TCC generated (at line 131, column 29) for  vect2(v)
      % expected type  {nzv | Delta(vect2(nzs), nzv) >= 0}
  verticalCoordinationConflict_correct_TCC1: OBLIGATION
    FORALL (nzs: Nz_vect3, v: Vect3):
      Delta(vect2(nzs), vect2(v)) > 0 IMPLIES
       vect2(v) /= zero AND Delta[D](vect2(nzs), vect2(v)) >= 0;

  % Subtype TCC generated (at line 150, column 32) for  vect2(v)
      % expected type  Nz_vect2
  vs_los_strategy_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT 1 * (vect2(s) * vect2(v)) >= 0 AND NOT vect2(v) = zero IMPLIES
       vect2(v) /= zero;

  % Judgement subtype TCC generated (at line 163, column 4) for
      % vs_los_strategy
      % expected type  Vertical_Strategy
  vs_los_vertical_strategy: OBLIGATION
    FORALL (s, v):
      (s /= zero OR v /= zero) =>
       vs_los_strategy(-s, -v) = -vs_los_strategy(s, v);


body:
  %------------------------------------------------------------------------------
  % circle_criterion.pvs
  % ACCoRD v1.0
  %
  %------------------------------------------------------------------------------

  circle_criterion[D,H: posreal]: THEORY
  BEGIN

    IMPORTING space_3D[D,H],
              horizontal_criteria[D],
              vz_criteria[H]

    spz     : VAR Spz_vect3   % Vertically separated
    vzgs    : VAR Zv2_vect3   % Ground speed is zero 
    s,v     : VAR Vect3
    eps,dir : VAR Sign
    t       : VAR real

    %% Vertical separation 
    vertical_sep_independence : THEOREM
      vertical_exit?(spz`z,v`z)
      IMPLIES
        NOT conflict?(spz,v)

    %% Ground speed is 0

    nogs_criterion?(s,vzgs): bool =
      vertical_sep?(s`z) AND vertical_exit?(s`z,vzgs`z) OR 
      horizontal_sep?(s) 

    nogs_criterion_independence : THEOREM
      nogs_criterion?(s,vzgs) IFF NOT conflict?(s,vzgs)

    %% Aircarft are separated
    circle_criterion?(s,v,dir): bool = 
      horizontal_sep?(s) AND 
      vertical_sep?(s`z) AND
      horizontal_dir?(s,v,dir) AND 
      vertical_dir?(s`z,v`z,-dir)

    circle_criterion_at?(s,v,t,dir): MACRO bool = 
      circle_criterion?(s+t*v,v,dir)

    circle_criterion_independence : THEOREM
      circle_criterion?(s,v,dir) IMPLIES
        NOT conflict_ever?(s,v) 

    circle_criterion_at_independence: THEOREM
      circle_criterion_at?(s,v,t,dir)
      IMPLIES
        NOT conflict_ever?(s,v)

  END circle_criterion


body:
  %------------------------------------------------------------------------------
  % cd3d.pvs
  % ACCoRD v1.0
  %
  % Correctness and completeness of 3-D conflict detection algorithm. 
  %   D : Horizontal separation
  %   H : Vertical separation
  %   T : Lookahead time
  %------------------------------------------------------------------------------

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

    IMPORTING circle_criterion[D,H],
    	    cd_vertical,
              omega_2D,
  	    util

    s,v : VAR Vect3       
    t   : VAR Lookahead[B,T]

    % Conflict during interval [0,T]
    conflict_3D?(s,v) : bool =
      EXISTS (t: Lookahead[B,T]): conflict_at?(s,v,t)

    conflict_3D_2D_stable: LEMMA v`z/=0 AND max(-H-sign(v`z)*s`z,B*abs(v`z)) < min(H-sign(v`z)*s`z,T*abs(v`z))
      IMPLIES
      (conflict_3D?(s,v) IFF 
      conflict_2D?[D*abs(v`z),max(-H-sign(v`z)*s`z,B*abs(v`z)),min(H-sign(v`z)*s`z,T*abs(v`z))](abs(v`z)*s,v))

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

    conflict_3D_on_open_interval: LEMMA conflict_3D?(s,v) IFF
      EXISTS (topen: Lookahead[B,T]): B<topen AND topen <T AND sqv(vect2(s)+topen*vect2(v))<sq(D) AND abs(s`z + topen*v`z) < H

    conflict_3D_vertical: LEMMA vect2(v) /= zero AND Delta(s,v) >= 0 AND max(Theta_D(s,v,Entry),B) < min(Theta_D(s,v,Exit),T)
      IMPLIES
      (conflict_3D?(s,v) IFF
      conflict_vertical?[H,max(Theta_D(s,v,Entry),B),min(Theta_D(s,v,Exit),T)](s`z,v`z))

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

    detection_complete : THEOREM
      LET (tin,tout) = detection(s,v) IN
        conflict_at?(s,v,t) IMPLIES tin <= t AND t <= tout AND tin < tout

    conflict_detection : THEOREM
      LET (tin,tout) = detection(s,v) IN
      conflict_3D?(s,v) IFF tin < tout

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

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

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

    cd3d_test: LEMMA
    	     FORALL (nvo,vi:Vect3):
    	     D = 10000.8 AND
  	     H = 283.464 AND
  	     B = 0 AND
  	     T = 300 AND
  	     s = (0,110733.65,0) AND
  	     nvo = (0,-236.48,0) AND
  	     vi = (0,236.48,0)
  	     IMPLIES cd3d?(s,nvo-vi)

    cd3d_correct : THEOREM
      cd3d?(s,v) IMPLIES
      conflict_3D?(s,v)

    cd3d_complete : THEOREM 
      conflict_3D?(s,v)
      IMPLIES
      cd3d?(s,v)

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

    cd3d : THEOREM
      conflict_3D?(s,v) IFF
      cd3d?(s,v) 

    %-----------------------------------------------%
    % Additional Lemmas on conflict_3D              %
    %-----------------------------------------------%


    % Rewriting cd3d in terms of cd_vertical - the vertical conflict probe

    cd3d_rewrite_vertical: LEMMA cd3d?(s,v) IFF
      (vect2(v) = zero AND sqv(vect2(s)) < sq(D) AND cd_vertical?[H,B,T](s`z,v`z))
      OR
      (Delta(s,v)>0 AND max(Theta_D(s,v,Entry),B) < min(Theta_D(s,v,Exit),T) AND
      cd_vertical?[H,max(Theta_D(s,v,Entry),B),min(Theta_D(s,v,Exit),T)](s`z,v`z))

    % ----------------------------------------------%

    vertical_solution_not_conflict_3D : LEMMA
      vertical_solution?(s`z,v`z,T,Entry) IMPLIES
      NOT conflict_3D?(s,v)           

    conflict_3D_horizontal_conflict : LEMMA
      conflict_3D?(s,v) IMPLIES
        horizontal_conflict?(s,v) 

    conflict_3D_vertical_conflict : LEMMA
      conflict_3D?(s,v) IMPLIES
        vertical_conflict?(s`z,v`z) 

    circle_solution_2D_not_conflict_3D: LEMMA
      circle_solution_2D?(s,v,T,Entry) IMPLIES
      NOT conflict_3D?(s,v)

  END cd3d

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

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

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

  % Subtype TCC generated (at line 29, column 61) for
      % min(H - sign(v`z) * s`z, T * abs(v`z))
      % expected type  {AB: posreal |
                     %          AB > max(-H - sign(v`z) * s`z, B * abs(v`z))}
  conflict_3D_2D_stable_TCC3: OBLIGATION
    FORALL (s, v: Vect3):
      max(-H - sign(v`z) * s`z, B * abs(v`z)) <
       min(H - sign(v`z) * s`z, T * abs(v`z))
       AND v`z /= 0
       IMPLIES
       min(H - sign(v`z) * s`z, T * abs(v`z)) >= 0 AND
        min(H - sign(v`z) * s`z, T * abs(v`z)) > 0 AND
         min(H - sign(v`z) * s`z, T * abs(v`z)) >
          max(-H - sign(v`z) * s`z, B * abs(v`z));

  % Subtype TCC generated (at line 39, column 25) for
      % max(Theta_D(vect2(s), vect2(v), -1), B)
      % expected type  nnreal
  conflict_3D_vertical_TCC1: OBLIGATION
    FORALL (s, v: Vect3):
      max(Theta_D(vect2(s), vect2(v), -1), B) <
       min(Theta_D(vect2(s), vect2(v), 1), T)
       AND Delta(vect2(s), vect2(v)) >= 0 AND vect2(v) /= zero
       IMPLIES max(Theta_D[D](vect2(s), vect2(v), -1), B) >= 0;

  % Subtype TCC generated (at line 39, column 51) for
      % min(Theta_D(vect2(s), vect2(v), 1), T)
      % expected type  {AB: posreal |
                     %          AB > max(Theta_D(vect2(s), vect2(v), -1), B)}
  conflict_3D_vertical_TCC2: OBLIGATION
    FORALL (s, v: Vect3):
      max(Theta_D(vect2(s), vect2(v), -1), B) <
       min(Theta_D(vect2(s), vect2(v), 1), T)
       AND Delta(vect2(s), vect2(v)) >= 0 AND vect2(v) /= zero
       IMPLIES
       min(Theta_D[D](vect2(s), vect2(v), 1), T) >= 0 AND
        min(Theta_D[D](vect2(s), vect2(v), 1), T) > 0 AND
         min(Theta_D[D](vect2(s), vect2(v), 1), T) >
          max(Theta_D[D](vect2(s), vect2(v), -1), B);

  % Subtype TCC generated (at line 49, column 9) for
      % min(max(Theta_H(s`z, v`z, -1), B), T)
      % expected type  Lookahead[B, T]
  detection_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      v`z /= 0 AND vect2(v) = zero AND sqv(vect2(s)) < sq(D) IMPLIES
       min(max(Theta_H[H](s`z, v`z, -1), B), T) >= 0 AND
        B <= min(max(Theta_H[H](s`z, v`z, -1), B), T) AND
         min(max(Theta_H[H](s`z, v`z, -1), B), T) <= T;

  % Subtype TCC generated (at line 49, column 46) for
      % max(min(Theta_H(s`z, v`z, 1), T), B)
      % expected type  Lookahead[B, T]
  detection_TCC2: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      v`z /= 0 AND vect2(v) = zero AND sqv(vect2(s)) < sq(D) IMPLIES
       max(min(Theta_H[H](s`z, v`z, 1), T), B) >= 0 AND
        B <= max(min(Theta_H[H](s`z, v`z, 1), T), B) AND
         max(min(Theta_H[H](s`z, v`z, 1), T), B) <= T;

  % Subtype TCC generated (at line 51, column 9) for  B
      % expected type  Lookahead[B, T]
  detection_TCC3: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      abs(s`z) < H AND
       NOT v`z /= 0 AND vect2(v) = zero AND sqv(vect2(s)) < sq(D)
       IMPLIES B <= B AND B <= T;

  % Subtype TCC generated (at line 51, column 11) for  T
      % expected type  Lookahead[B, T]
  detection_TCC4: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      abs(s`z) < H AND
       NOT v`z /= 0 AND vect2(v) = zero AND sqv(vect2(s)) < sq(D)
       IMPLIES B <= T AND T <= T;

  % Subtype TCC generated (at line 53, column 9) for  B
      % expected type  Lookahead[B, T]
  detection_TCC5: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT abs(s`z) < H AND
       NOT v`z /= 0 AND vect2(v) = zero AND sqv(vect2(s)) < sq(D)
       IMPLIES B <= B AND B <= T;

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

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

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

  % Subtype TCC generated (at line 63, column 9) for  min(max(td1, B), T)
      % expected type  Lookahead[B, T]
  detection_TCC9: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (td1: real):
          td1 = Theta_D(vect2(s), vect2(v), -1) IMPLIES
           (FORALL (td2: real):
              abs(s`z) < H AND
               NOT v`z /= 0 AND td2 = Theta_D(vect2(s), vect2(v), 1)
               IMPLIES
               min(max(td1, B), T) >= 0 AND
                B <= min(max(td1, B), T) AND min(max(td1, B), T) <= T));

  % Subtype TCC generated (at line 63, column 27) for  max(min(td2, T), B)
      % expected type  Lookahead[B, T]
  detection_TCC10: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (td1: real):
          td1 = Theta_D(vect2(s), vect2(v), -1) IMPLIES
           (FORALL (td2: real):
              abs(s`z) < H AND
               NOT v`z /= 0 AND td2 = Theta_D(vect2(s), vect2(v), 1)
               IMPLIES
               max(min(td2, T), B) >= 0 AND
                B <= max(min(td2, T), B) AND max(min(td2, T), B) <= T));

  % Subtype TCC generated (at line 65, column 9) for  B
      % expected type  Lookahead[B, T]
  detection_TCC11: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (td1: real):
          td1 = Theta_D(vect2(s), vect2(v), -1) IMPLIES
           (FORALL (td2: real):
              NOT abs(s`z) < H AND
               NOT v`z /= 0 AND td2 = Theta_D(vect2(s), vect2(v), 1)
               IMPLIES B <= B AND B <= T));

  % Subtype TCC generated (at line 68, column 7) for  B
      % expected type  Lookahead[B, T]
  detection_TCC12: OBLIGATION
    FORALL (s: Vect3, v: Vect3):
      NOT Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES B <= B AND B <= T;

  % Subtype TCC generated (at line 100, column 20) for
      % max(Theta_H(s`z, v`z, -1), B)
      % expected type  nnreal
  cd3d_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), B) < min(Theta_H(s`z, v`z, 1), T) AND
        v`z /= 0
       IMPLIES max(Theta_H[H](s`z, v`z, -1), B) >= 0;

  % Subtype TCC generated (at line 100, column 50) for
      % min(Theta_H(s`z, v`z, 1), T)
      % expected type  {AB: posreal | AB > max(Theta_H(s`z, v`z, -1), B)}
  cd3d_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), B) < min(Theta_H(s`z, v`z, 1), T) AND
        v`z /= 0
       IMPLIES
       min(Theta_H[H](s`z, v`z, 1), T) >= 0 AND
        min(Theta_H[H](s`z, v`z, 1), T) > 0 AND
         min(Theta_H[H](s`z, v`z, 1), T) > max(Theta_H[H](s`z, v`z, -1), B);

  % Subtype TCC generated (at line 143, column 36) for  vect2(v)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  cd3d_rewrite_vertical_TCC1: OBLIGATION
    FORALL (s, v: Vect3):
      NOT (vect2(v) = zero AND
            sqv(vect2(s)) < sq(D) AND cd_vertical?[H, B, T](s`z, v`z))
       AND Delta(vect2(s), vect2(v)) > 0
       IMPLIES vect2(v) /= zero AND Delta[D](vect2(s), vect2(v)) >= 0;

  % Subtype TCC generated (at line 144, column 19) for
      % max(Theta_D(vect2(s), vect2(v), -1), B)
      % expected type  nnreal
  cd3d_rewrite_vertical_TCC2: OBLIGATION
    FORALL (s, v: Vect3):
      NOT (vect2(v) = zero AND
            sqv(vect2(s)) < sq(D) AND cd_vertical?[H, B, T](s`z, v`z))
       AND
       Delta(vect2(s), vect2(v)) > 0 AND
        max(Theta_D(vect2(s), vect2(v), -1), B) <
         min(Theta_D(vect2(s), vect2(v), 1), T)
       IMPLIES max(Theta_D[D](vect2(s), vect2(v), -1), B) >= 0;

  % Subtype TCC generated (at line 144, column 45) for
      % min(Theta_D(vect2(s), vect2(v), 1), T)
      % expected type  {AB: posreal |
                     %          AB > max(Theta_D(vect2(s), vect2(v), -1), B)}
  cd3d_rewrite_vertical_TCC3: OBLIGATION
    FORALL (s, v: Vect3):
      NOT (vect2(v) = zero AND
            sqv(vect2(s)) < sq(D) AND cd_vertical?[H, B, T](s`z, v`z))
       AND
       Delta(vect2(s), vect2(v)) > 0 AND
        max(Theta_D(vect2(s), vect2(v), -1), B) <
         min(Theta_D(vect2(s), vect2(v), 1), T)
       IMPLIES
       min(Theta_D[D](vect2(s), vect2(v), 1), T) >= 0 AND
        min(Theta_D[D](vect2(s), vect2(v), 1), T) > 0 AND
         min(Theta_D[D](vect2(s), vect2(v), 1), T) >
          max(Theta_D[D](vect2(s), vect2(v), -1), B);


body:
  %------------------------------------------------------------------------------
  % vs_bands.pvs
  % ACCoRD v.1.0
  %------------------------------------------------------------------------------

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

    IMPORTING  cd_vertical[H,B,T],
    	     util,
  	     reals@connected_set

    sz,vz,t,
    voz,viz,
    vsp     : VAR real
    nzvz    : VAR nzreal
    eps,dir : VAR Sign
    nzt     : VAR nzreal
    pt      : VAR posreal
    band	  : VAR Connected
    BT	  : VAR nnreal
    drc	  : VAR Sign

    %-----------------------------------------------%
    % Vertical Speed Critical Points                %
    %-----------------------------------------------%

    vs_critical?(sz,viz)(vsp) : bool =
      vs_circle_at?(sz,viz,B,T)(vsp)

    vs_bands_vertical_dir_exclusive: LEMMA
      ((BT = T AND drc = 1) OR (BT = B AND drc = -1))
      AND on_H?(sz + BT*(vsp-viz))
      IMPLIES
      (vertical_dir_at?(sz,vsp-viz,BT,drc)
      IFF
      (vsp-viz = 0 OR conflict_vertical?(sz,vsp-viz)))

    band_critical_on_H: LEMMA FORALL (vsp1,vsp2: (band),tlh: Lookahead):
      abs(sz + B*(vsp1-viz)) >= H AND abs(sz + T*(vsp1-viz)) >= H AND
      sign(sz + B*(vsp1-viz)) = sign(sz + T*(vsp1-viz)) AND
      abs(sz + tlh*(vsp2-viz)) < H
      IMPLIES
      (EXISTS (vsp: (band)): (B>0 AND abs(sz + B*(vsp-viz)) = H AND vertical_dir_at?(sz,vsp-viz,B,1)) OR 
                             (abs(sz + T*(vsp-viz)) = H AND vertical_dir_at?(sz,vsp-viz,T,-1)))

    vs_band_critical_B_sz_sign: LEMMA 
      on_H?(sz + B*(vsp-viz)) AND
      B > 0 IMPLIES
      (vertical_dir_at?(sz,vsp-viz,B,1)
      IFF
      sign(sz + B*(vsp-viz))*sz <= H)

    vs_band_critical_T_sz_sign: LEMMA 
      on_H?(sz + T*(vsp-viz)) IMPLIES
      (vertical_dir_at?(sz,vsp-viz,T,-1)
      IFF
      sign(sz + T*(vsp-viz))*sz >= H)
    
    % Bands do not contain critical points
    vs_band?(sz,viz)(band) : bool =
      FORALL (vsp:(band)) :
        NOT vs_critical?(sz,viz)(vsp)

    vs_green?(sz,viz)(band) : bool =
      FORALL (vsp:(band)) :
        NOT conflict_vertical?(sz,vsp-viz)

    vs_red?(sz,viz)(band) : bool =
      FORALL (vsp:(band)) :
        conflict_vertical?(sz,vsp-viz)

    %--------------------------------------------------%
    % THEOREM: Vertical Speed Green Bands Correctness  %
    %--------------------------------------------------%

    vs_green_band : THEOREM
      FORALL (vsp:(band)) :
         vs_band?(sz,viz)(band) IMPLIES
         (NOT cd_vertical?(sz,vsp-viz) IFF
          vs_green?(sz,viz)(band))

    %-------------------------------------------------%
    % THEOREM: Vertical Speed Red Bands Correctness   %
    %-------------------------------------------------%

    vs_red_band : THEOREM
      FORALL (vsp:(band)) :
         vs_band?(sz,viz)(band) IMPLIES
         (cd_vertical?(sz,vsp-viz) IFF
          vs_red?(sz,viz)(band))

  END vs_bands


body:
  bands_1D[H:posreal,B:nnreal,T: {AB: posreal|AB>B},vsmin:real,vsmax:{x: real | x > vsmin}] : THEORY
  BEGIN

    ASSUMING
      vs_min_lt_max: ASSUMPTION vsmin < vsmax
    ENDASSUMING	
    
    IMPORTING vs_bands[H,B,T],
              fseqs_aux_vertical[vsmin,vsmax]


    sz,vz,t,
    voz,viz : VAR real
    nzvz    : VAR nzreal
    eps,dir : VAR Sign
    nzt     : VAR nzreal
    pt      : VAR posreal
    band	  : VAR Connected
    BT	  : VAR nnreal
    drc	  : VAR Sign
    x	  : VAR real
    TF	  : VAR bool
    vsb     : VAR (vs_fseq?)
    vsp	  : VAR {r: real | vsmin<=r AND r<=vsmax}

    AUTO_REWRITE- member
      
    vs_critical(TF,voz) : (vs_fseq?) =
      IF TF AND vsmin<=voz AND voz<=vsmax THEN addend(voz,emptyseq)
      ELSE emptyseq
      ENDIF

    vs_critical_rew: LEMMA
      vs_critical(TF,voz) = IF TF AND vsmin<=voz AND voz<=vsmax THEN singleton(voz)
      		      	ELSE emptyseq
  			ENDIF

    member_vs_critical: LEMMA
    		       member(x,vs_critical(TF,voz))
  		       IFF
  		       (TF AND x = voz AND vsmin<=voz AND voz<=vsmax)

    vs_critical_composition: LEMMA
      FORALL (vsfs: (vs_fseq?), TF: bool, voz: real, x:real):
      	   member(x,vsfs o vs_critical(TF,voz))
  	   IFF
  	   ((TF AND x = voz AND vsmin<=voz AND voz<=vsmax)
  	   OR
  	   member(x,vsfs))

    vs_bands(sz,viz) : {fs: (vs_fseq?) | increasing?(fs)} =
      sort(
      LET 
        fsB : (vs_fseq?) = 
        	IF abs(sz) < H AND B > 0 THEN
             vs_critical(vs_circle_at(sz,viz,B,-1,1)) o 
             vs_critical(vs_circle_at(sz,viz,B,1,1))
        	ELSIF abs(sz) >= H AND B > 0 THEN
  	   vs_critical(vs_circle_at(sz,viz,B,-sign(sz),1))
          ELSE
             emptyseq
          ENDIF,
        fsT : (vs_fseq?) =
          IF abs(sz) >= H THEN
  	   vs_critical(vs_circle_at(sz,viz,T,sign(sz),-1))
  	ELSE
  	   emptyseq
  	ENDIF
      IN
  	(fsB o fsT) o
      	(addend(vsmin,emptyseq) o addend(vsmax,emptyseq)))

    vs_bands_not_empty : LEMMA
      vs_bands(sz,viz)`length > 1

    vs_bands_critical: LEMMA
       (vs_critical?(sz,viz)(vsp) OR vsp = vsmin OR vsp = vsmax) IFF
       member(vsp,vs_bands(sz,viz))

    %------------%
    % THEOREMS   %
    %------------%

    red_vs_band?(sz,viz,vsb)(i:subrange(0,vsb`length-2)) : bool =
      LET mp = (vsb`seq(i)+vsb`seq(i+1))/2 in
      cd_vertical?(sz,mp-viz)  

    vs_red_bands : THEOREM
      LET vsb = vs_bands(sz,viz) IN
       FORALL (i:{ii: subrange(0,vsb`length-2)| vsb`seq(ii) /= vsb`seq(ii+1)}) :  
         red_vs_band?(sz,viz,vsb)(i) IFF
         (FORALL (x | vsb`seq(i) < x AND x < vsb`seq(i+1)):
           conflict_vertical?(sz,x-viz))

    vs_green_bands : THEOREM
      LET vsb = vs_bands(sz,viz) IN
       FORALL (i:{ii: subrange(0,vsb`length-2)| vsb`seq(ii) /= vsb`seq(ii+1)}) :  
         NOT red_vs_band?(sz,viz,vsb)(i) IFF
         (FORALL (x | vsb`seq(i) < x AND x < vsb`seq(i+1)):
           NOT conflict_vertical?(sz,x-viz))

  END bands_1D

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

  % Subtype TCC generated (at line 29, column 45) for  addend(voz, empty_seq)
      % expected type  (vs_fseq?)
  vs_critical_TCC1: OBLIGATION
    FORALL (TF: bool, voz: real):
      TF AND vsmin <= voz AND voz <= vsmax IMPLIES
       vs_fseq?[vsmin, vsmax](addend[real](voz, empty_seq[real]));

  % Subtype TCC generated (at line 30, column 9) for  emptyseq
      % expected type  (vs_fseq?)
  vs_critical_TCC2: OBLIGATION
    FORALL (TF: bool, voz: real):
      NOT (TF AND vsmin <= voz AND voz <= vsmax) IMPLIES
       (FORALL (i: nat):
          i >= emptyseq[real]`length IMPLIES
           emptyseq[real]`seq(i) = default[real])
        AND vs_fseq?[vsmin, vsmax](emptyseq[real]);

  % Subtype TCC generated (at line 52, column 4) for
      % sort(LET fsB: (vs_fseq?) =
      %            IF abs(sz) < H AND B > 0
      %              THEN vs_critical(vs_circle_at(sz, viz, B, -1, 1)) o
      %                    vs_critical(vs_circle_at(sz, viz, B, 1, 1))
      %            ELSIF abs(sz) >= H AND B > 0
      %              THEN vs_critical(vs_circle_at(sz, viz, B, -sign(sz), 1))
      %            ELSE empty_seq
      %            ENDIF,
      %          fsT: (vs_fseq?) =
      %            IF abs(sz) >= H
      %              THEN vs_critical(vs_circle_at(sz, viz, T, sign(sz), -1))
      %            ELSE empty_seq
      %            ENDIF
      %        IN
      %        (fsB o fsT) o
      %         (addend(vsmin, empty_seq) o addend(vsmax, empty_seq)))
      % expected type  {fs: (vs_fseq?) | increasing?(fs)}
  vs_bands_TCC1: OBLIGATION
    FORALL (sz: real, viz: real):
      vs_fseq?[vsmin, vsmax]
          (sort[real, <=]
               (LET fsB: (vs_fseq?[vsmin, vsmax]) =
                      IF abs(sz) < H AND B > 0
                        THEN o[real]
                                 (vs_critical(vs_circle_at[H]
                                              (sz, viz, B, -1, 1)),
                                  vs_critical(vs_circle_at[H]
                                              (sz, viz, B, 1, 1)))
                      ELSIF abs(sz) >= H AND B > 0
                        THEN vs_critical(vs_circle_at[H]
                                         (sz, viz, B, -sign(sz), 1))
                      ELSE empty_seq[real]
                      ENDIF,
                    fsT: (vs_fseq?[vsmin, vsmax]) =
                      IF abs(sz) >= H
                        THEN vs_critical(vs_circle_at[H]
                                         (sz, viz, T, sign(sz), -1))
                      ELSE empty_seq[real]
                      ENDIF
                  IN
                  o[real]
                      ((o[real](fsB, fsT)),
                       (o[real]
                            (addend[real](vsmin, empty_seq[real]),
                             addend[real](vsmax, empty_seq[real]))))))
       AND
       increasing?[real, <=]
           (sort[real, <=]
                (LET fsB: (vs_fseq?[vsmin, vsmax]) =
                       IF abs(sz) < H AND B > 0
                         THEN o[real]
                                  (vs_critical(vs_circle_at[H]
                                               (sz, viz, B, -1, 1)),
                                   vs_critical(vs_circle_at[H]
                                               (sz, viz, B, 1, 1)))
                       ELSIF abs(sz) >= H AND B > 0
                         THEN vs_critical(vs_circle_at[H]
                                          (sz, viz, B, -sign(sz), 1))
                       ELSE empty_seq[real]
                       ENDIF,
                     fsT: (vs_fseq?[vsmin, vsmax]) =
                       IF abs(sz) >= H
                         THEN vs_critical(vs_circle_at[H]
                                          (sz, viz, T, sign(sz), -1))
                       ELSE empty_seq[real]
                       ENDIF
                   IN
                   o[real]
                       ((o[real](fsB, fsT)),
                        (o[real]
                             (addend[real](vsmin, empty_seq[real]),
                              addend[real](vsmax, empty_seq[real]))))));

  % Subtype TCC generated (at line 85, column 22) for  i
      % expected type  nat
  red_vs_band?_TCC1: OBLIGATION
    FORALL (vsb: (vs_fseq?[vsmin, vsmax]), i: subrange(0, vsb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 85, column 33) for  i + 1
      % expected type  nat
  red_vs_band?_TCC2: OBLIGATION
    FORALL (vsb: (vs_fseq?[vsmin, vsmax]), i: subrange(0, vsb`length - 2)):
      i + 1 >= 0;


body:
  %------------------------------------------------------------------------------
  % trk_line.pvs
  % ACCoRD v1.0
  %
  % Track line solutions are track only solutions that are tangent to the 
  % protected zone.
  %------------------------------------------------------------------------------

  trk_line[D: posreal] : THEORY
  BEGIN
    
    IMPORTING trk_only[D],
              tangent_line[D]

    ss         : VAR Ss_vect2
    sp         : VAR Sp_vect2
    eps,irt,
    irt1,irt2  : VAR Sign
    vo,vi,    
    vo2,
    nvo,
    nvo1,nvo2  : VAR Vect2
    vnzo       : VAR Nz_vect2

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

    % zero indicates no track solution

    trk_line_eps_irt(sp,vo,vi,eps,irt): {nvo:Vect2 | nz_vect2?(nvo) => 
                                                     trk_only?(vo)(nvo)} =
      LET (k,nvo)  = trk_only_line(tangent_line(sp,eps),vo,vi,irt) IN
      IF k >= 0 THEN
        nvo
      ELSE
        zero 
      ENDIF

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

    trk_line_eps(sp,vo,vi,eps): {nvo | nz_vect2?(nvo) => 
                                       trk_only?(vo)(nvo)} =
      LET vo1 = trk_line_eps_irt(sp,vo,vi,eps,1),
          vo2 = trk_line_eps_irt(sp,vo,vi,eps,-1) IN
      IF vo2 = zero THEN vo1
      ELSIF vo1 = zero OR
            le?(vo)(vo2,vo1) THEN vo2
      ELSE vo1
      ENDIF

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

    trk_line?(sp,vo,vi)(nvo:Vect2):bool =
      nz_vect2?(nvo) AND 
      EXISTS (eps,irt): nvo = trk_line_eps_irt(sp,vo,vi,eps,irt)

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

    trk_line_eps_irt_tangent_line: LEMMA 
      trk_line_eps_irt?(sp,vo,vi,eps,irt)(nvo) 
      IMPLIES
        tangent_line?(sp,nvo-vi,eps)              
         
    trk_line_eps_irt_dot : LEMMA
      trk_line_eps_irt?(ss,vo,vi,eps,-1)(nvo1) AND
      trk_line_eps_irt?(ss,vo,vi,eps,1)(nvo2) IMPLIES
      nvo2*ss <= nvo1*ss

    irt_trk_line_eps: LEMMA 
      trk_line_eps?(sp,vo,vi,eps)(nvo) 
      IMPLIES
        EXISTS (irt): trk_line_eps_irt?(sp,vo,vi,eps,irt)(nvo)

    trk_line_eps_tangent_line: LEMMA 
      trk_line_eps?(sp,vo,vi,eps)(nvo) 
      IMPLIES
        tangent_line?(sp,nvo-vi,eps)              

    trk_line_is_line_solution: LEMMA 
      trk_line_eps?(sp,vo,vi,eps)(nvo) 
      IMPLIES
        line_solution?(sp,nvo-vi,eps)              

    trk_line_complete : THEOREM
      trk_only?(vnzo)(nvo) AND
      line_solution?(sp,nvo-vi) IMPLIES
        trk_line?(sp,vnzo,vi)(nvo)

  END trk_line

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

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

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


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

    IMPORTING omega_2D[D,B,T], 
              analysis@continuity_of_max_min, 
              analysis@metric_space_real_fun
               
    s,v		: VAR Vect2


    % The Definition Of omega_v2

    omega_v2(s)(v): real =
      IF	on_D?(s) AND B = 0 THEN s*v
      ELSE omega_2D(s)(v) ENDIF

    omega_v2_generic: LEMMA 
      NOT (on_D?(s) AND B = 0) IMPLIES 
      omega_v2(s)(v) = omega_2D(s)(v)

    % Characterizes Conflict

    omega_v2_conflict: LEMMA 
      omega_v2(s)(v) < 0 IFF conflict_2D?(s,v)

    omega_v2_2D_eq_0: LEMMA omega_v2(s)(v) = 0
      IMPLIES omega_2D(s)(v) = 0

    omega_v2_critical_points: LEMMA 
      omega_v2(s)(v) = 0 IMPLIES horizontal_sep?(s) AND line_solution?(s,v) OR
                                 circle_solution_2D?(s,v,T,Entry) OR
  			       (B>0 AND circle_solution_2D?(s,v,B,Exit))

    % Continuity

    omega_v2_continuous: LEMMA 
      continuous?(omega_v2(s))

  END omega_v2


body:
  %-----------------------------------------------------------------------------
  % trk_bands_2D.pvs
  % ACCoRD v.1.0
  %-----------------------------------------------------------------------------

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

    IMPORTING analysis@interm_value_thm,
    	    vect_analysis@vect2_cont_dot[real],
              trig_fnd@sincos,
              omega_v2[D,B,T],
              trk_line[D],
  	    line_solutions[D],
              bands_util
   	    
    nvo,
    vo,vi : VAR Nz_vect2
    sp    : VAR Sp_vect2
    ss    : VAR Ss_vect2
    t     : VAR posreal
    band  : VAR ConnectedGeLt(0,2*pi)
    trk   : VAR real % Track with respect to true north. 
    k     : VAR real

    pm,eps,
    irt,
    irt1,
    irt2   : VAR Sign
    s,
    nvo1,
    nvo2   : VAR Vect2

    trk_band : LEMMA
       nvo = trk_line_eps_irt(ss, vo, vi, eps, irt) IMPLIES
       eps*det(nvo,ss) >= eps*det(vi,ss)

    trk2v2_continuous : JUDGEMENT
      trk2v2(vo) HAS_TYPE continuous_rv_fun

    Vtrk_continuous : JUDGEMENT
      Vtrk(vo,vi) HAS_TYPE continuous_rv_fun

    %-----------------------------------------------%
    % 2-D Track Critical Points                     %
    %-----------------------------------------------%

    trk_critical?(s,vo,vi)(trk) : bool =
      LET trko = trk2v2(vo)(trk) IN
      (sqv(s)>=sq(D) AND trk_line?(s,vo,vi)(trko)) OR
      trk_only_circle?(s,vo,vi,T,Entry)(trko) OR
      (B>0 AND trk_only_circle?(s,vo,vi,B,Exit)(trko))

    Omega_trk_spc(vo,vi,t)(trk) : real =
      vi * trk2v2(vo)(trk) - sq(D/t)

    Omega_trk_spc : JUDGEMENT
      Omega_trk_spc(vo,vi,t) HAS_TYPE (continuous_rr?)

    trk_special_case_invariant: LEMMA
      trk_special_case?(s,vo,vi,t) IFF
      trk_special_case?(s,trk2v2(vo)(trk),vi,t)

    Omega_trk_spc_separated : LEMMA
      Omega_trk_spc(vo,vi,t)(trk) = 0 AND
      trk_special_case?(s,vo,vi,t) IMPLIES
      sqv(s)>=sq(D)

    Omega_trk_spc_critical : LEMMA
      Omega_trk_spc(vo,vi,t)(trk) = 0 AND
      trk_special_case?(s,vo,vi,t) IMPLIES
      line_solution?(s,Vtrk(vo,vi)(trk))

    trk_special_case_conflict_T : LEMMA
      trk_special_case?(s,vo,vi,T) IMPLIES
      (horizontal_entry_at?(s,Vtrk(vo,vi)(trk),T) 
       IFF NOT conflict_2D?(s,Vtrk(vo,vi)(trk)))

    trk_special_case_conflict_B : LEMMA
      B>0 AND trk_special_case?(s,vo,vi,B) IMPLIES
      (horizontal_exit_at?(s,Vtrk(vo,vi)(trk),B)
       IFF NOT conflict_2D?(s,Vtrk(vo,vi)(trk)))

    Omega_trk_spc_conflict_T: LEMMA
      trk_special_case?(s,vo,vi,T) IMPLIES
      (Omega_trk_spc(vo,vi,T)(trk) < 0 IFF
      conflict_2D?(s,Vtrk(vo,vi)(trk)))

    Omega_trk_spc_conflict_B: LEMMA
      B>0 AND trk_special_case?(s,vo,vi,B) IMPLIES
      (-Omega_trk_spc(vo,vi,B)(trk) < 0 IFF
      conflict_2D?(s,Vtrk(vo,vi)(trk)))

    Omega_trk(s,vo,vi) : (continuous_rr?) = 
      omega_v2(s) o Vtrk(vo,vi)

    Omega_trk_critical : LEMMA
      Omega_trk(s,vo,vi)(trk) = 0 AND
      NOT trk_special_case?(s,vo,vi,T) AND
      NOT (B>0 AND trk_special_case?(s,vo,vi,B)) IMPLIES
        trk_critical?(s,vo,vi)(trk) 

    % Bands do not contain critical points
    trk_band?(s,vo,vi)(band) : bool =
      FORALL (trko:(band)) :
        NOT trk_critical?(s,vo,vi)(trko)

    trk_green?(s,vo,vi)(band) : bool =
      FORALL (trko:(band)) :
        NOT conflict_2D?(s,Vtrk(vo,vi)(trko))

    trk_red?(s,vo,vi)(band) : bool =
      FORALL (trko:(band)) :
        conflict_2D?(s,Vtrk(vo,vi)(trko))
   
    trk_line_sort_eps : LEMMA
      nvo /= vi AND 
      trk_line_eps_irt?(ss,vo,vi,eps,irt)(nvo) IMPLIES
      eps*det(nvo,ss) > eps*det(vi,ss)

    trk_line_sort_eps_angle : LEMMA
      abs(det(vi,ss)/(norm(vo)*norm(ss))) <= 1 IMPLIES
      LET phi   = track(ss),
          psi   = asin(det(vi,ss)/(norm(vo)*norm(ss))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      nvo1 /= vi AND
      nvo2 /= vi AND
      trk_line_eps_irt?(ss,vo,vi,1,irt1)(nvo1) AND
      trk_line_eps_irt?(ss,vo,vi,-1,irt2)(nvo2) 
      IMPLIES
        to2pi(track(nvo1)-alpha) < to2pi(track(nvo2)-alpha)

    trk_line_sort_eps_1_angle_case1 : LEMMA
      abs(det(vi,ss)/(norm(vo)*norm(ss))) <= 1 IMPLIES
      LET phi   = track(ss),
          psi   = asin(det(vi,ss)/(norm(vo)*norm(ss))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (nvo1*ss) * (nvo2*ss) < 0 AND 
      nvo1 /= vi AND
      nvo2 /= vi AND
      trk_line_eps_irt?(ss,vo,vi,1,-1)(nvo1) AND
      trk_line_eps_irt?(ss,vo,vi,1,1)(nvo2) 
      IMPLIES
        to2pi(track(nvo1)-alpha) < to2pi(track(nvo2)-alpha)

    trk_line_sort_eps_1_angle_case2 : LEMMA
      abs(det(vi,ss)/(norm(vo)*norm(ss))) <= 1 IMPLIES
      LET phi   = track(ss),
          psi   = asin(det(vi,ss)/(norm(vo)*norm(ss))),
          alpha = phi+psi,
          beta  = pi-2*psi IN
      (nvo1*ss) * (nvo2*ss) >= 0 AND 
      nvo1 /= vi AND
      nvo2 /= vi AND
      trk_line_eps_irt?(ss,vo,vi,1,-1)(nvo1) AND
      trk_line_eps_irt?(ss,vo,vi,1,1)(nvo2) 
      IMPLIES
        (det(nvo1,nvo2) < 0 IFF to2pi(track(nvo1)-alpha) < to2pi(track(nvo2)-alpha))

    trk_line_color : LEMMA
      trk_line_eps_irt?(ss,vo,vi,eps,irt)(nvo) AND
      sq(Qs(ss,eps)*vi) > (sqv(ss)-sq(D))*(sqv(vi)-sqv(vo))
      IMPLIES
      (pm*(Q(ss,eps) * perpR(nvo)) > 0 IFF pm*(eps*irt) < 0)

    %-------------------------------------------%
    % THEOREM: Track Green Bands Correctness    %
    %-------------------------------------------%

    trk_green_band : THEOREM
      FORALL (trko:(band)) :
         trk_band?(s,vo,vi)(band) IMPLIES
          (NOT cd2d?(s,Vtrk(vo,vi)(trko)) IFF
           trk_green?(s,vo,vi)(band))

    %-------------------------------------------%
    % THEOREM: Track Red Bands Correctness      %
    %-------------------------------------------%

    trk_red_band : THEOREM
      FORALL (trko:(band)) :
        trk_band?(s,vo,vi)(band) IMPLIES
        (cd2d?(s,Vtrk(vo,vi)(trko)) IFF
          trk_red?(s,vo,vi)(band))
   
  END trk_bands_2D

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

  % Judgement subtype TCC generated (at line 39, column 4) for  trk2v2(vo)
      % expected type  continuous_rv_fun[real]
  trk2v2_continuous: OBLIGATION FORALL (vo): continuous_rv?[real](trk2v2(vo));

  % Judgement subtype TCC generated (at line 42, column 4) for  Vtrk(vo, vi)
      % expected type  continuous_rv_fun[real]
  Vtrk_continuous: OBLIGATION
    FORALL (vi, vo): continuous_rv?[real](Vtrk(vo, vi));

  % Judgement subtype TCC generated (at line 58, column 4) for
      % Omega_trk_spc(vo, vi, t)
      % expected type  ({f | continuous?(f)})
  Omega_trk_spc: OBLIGATION
    FORALL (t, vi, vo): continuous?[real](Omega_trk_spc(vo, vi, t));

  % Subtype TCC generated (at line 72, column 19) for  s
      % expected type  Sp_vect2[D]
  Omega_trk_spc_critical_TCC1: OBLIGATION
    FORALL (s: Vect2, t: posreal, trk: real, vi, vo: Nz_vect2):
      trk_special_case?(s, vo, vi, t) AND Omega_trk_spc(vo, vi, t)(trk) = 0
       IMPLIES sqv(s) >= sq(D);

  % Subtype TCC generated (at line 95, column 4) for
      % omega_v2(s) o Vtrk(vo, vi)
      % expected type  ({f | continuous?(f)})
  Omega_trk_TCC1: OBLIGATION
    FORALL (s: Vect2, vo: Nz_vect2, vi: Nz_vect2):
      continuous?[real](o[real](omega_v2[D, B, T](s), Vtrk(vo, vi)));

  % Subtype TCC generated (at line 124, column 21) for
      % det(vi, ss) / (norm(vo) * norm(ss))
      % expected type  real_abs_le1
  trk_line_sort_eps_angle_TCC1: OBLIGATION
    FORALL (ss: Ss_vect2[D], vi, vo: Nz_vect2):
      abs(det(vi, ss) / (norm(vo) * norm(ss))) <= 1 IMPLIES
       (FORALL (phi: nnreal_lt_2pi):
          phi = track(ss) IMPLIES
           -1 <= det(vi, ss) / (norm(vo) * norm(ss)) AND
            det(vi, ss) / (norm(vo) * norm(ss)) <= 1);

  % Subtype TCC generated (at line 132, column 18) for  nvo1
      % expected type  Nz_vect2
  trk_line_sort_eps_angle_TCC2: OBLIGATION
    FORALL (irt1, irt2: Sign, nvo1, nvo2: Vect2, ss: Ss_vect2[D],
            vi, vo: Nz_vect2):
      abs(det(vi, ss) / (norm(vo) * norm(ss))) <= 1 IMPLIES
       (FORALL (phi: nnreal_lt_2pi):
          phi = track(ss) IMPLIES
           (FORALL (psi: real_abs_le_pi2):
              psi = asin(det(vi, ss) / (norm(vo) * norm(ss))) IMPLIES
               (FORALL (alpha: real):
                  alpha = phi + psi IMPLIES
                   (FORALL (beta: real):
                           nvo1 /= vi AND nvo2 /= vi
                       AND trk_line_eps_irt?(ss, vo, vi, 1, irt1)(nvo1)
                       AND trk_line_eps_irt?(ss, vo, vi, -1, irt2)(nvo2)
                       AND beta = pi - 2 * psi
                       IMPLIES nvo1 /= zero))));

  % Subtype TCC generated (at line 132, column 45) for  nvo2
      % expected type  Nz_vect2
  trk_line_sort_eps_angle_TCC3: OBLIGATION
    FORALL (irt1, irt2: Sign, nvo1, nvo2: Vect2, ss: Ss_vect2[D],
            vi, vo: Nz_vect2):
      abs(det(vi, ss) / (norm(vo) * norm(ss))) <= 1 IMPLIES
       (FORALL (phi: nnreal_lt_2pi):
          phi = track(ss) IMPLIES
           (FORALL (psi: real_abs_le_pi2):
              psi = asin(det(vi, ss) / (norm(vo) * norm(ss))) IMPLIES
               (FORALL (alpha: real):
                  alpha = phi + psi IMPLIES
                   (FORALL (beta: real):
                           nvo1 /= vi AND nvo2 /= vi
                       AND trk_line_eps_irt?(ss, vo, vi, 1, irt1)(nvo1)
                       AND trk_line_eps_irt?(ss, vo, vi, -1, irt2)(nvo2)
                       AND beta = pi - 2 * psi
                       IMPLIES nvo2 /= zero))));

  % Subtype TCC generated (at line 146, column 18) for  nvo1
      % expected type  Nz_vect2
  trk_line_sort_eps_1_angle_case1_TCC1: OBLIGATION
    FORALL (nvo1, nvo2: Vect2, ss: Ss_vect2[D], vi, vo: Nz_vect2):
      abs(det(vi, ss) / (norm(vo) * norm(ss))) <= 1 IMPLIES
       (FORALL (phi: nnreal_lt_2pi):
          phi = track(ss) IMPLIES
           (FORALL (psi: real_abs_le_pi2):
              psi = asin(det(vi, ss) / (norm(vo) * norm(ss))) IMPLIES
               (FORALL (alpha: real):
                  alpha = phi + psi IMPLIES
                   (FORALL (beta: real):
                           (nvo1 * ss) * (nvo2 * ss) < 0 AND nvo1 /= vi
                       AND nvo2 /= vi
                       AND trk_line_eps_irt?(ss, vo, vi, 1, -1)(nvo1)
                       AND trk_line_eps_irt?(ss, vo, vi, 1, 1)(nvo2)
                       AND beta = pi - 2 * psi
                       IMPLIES nvo1 /= zero))));

  % Subtype TCC generated (at line 146, column 45) for  nvo2
      % expected type  Nz_vect2
  trk_line_sort_eps_1_angle_case1_TCC2: OBLIGATION
    FORALL (nvo1, nvo2: Vect2, ss: Ss_vect2[D], vi, vo: Nz_vect2):
      abs(det(vi, ss) / (norm(vo) * norm(ss))) <= 1 IMPLIES
       (FORALL (phi: nnreal_lt_2pi):
          phi = track(ss) IMPLIES
           (FORALL (psi: real_abs_le_pi2):
              psi = asin(det(vi, ss) / (norm(vo) * norm(ss))) IMPLIES
               (FORALL (alpha: real):
                  alpha = phi + psi IMPLIES
                   (FORALL (beta: real):
                           (nvo1 * ss) * (nvo2 * ss) < 0 AND nvo1 /= vi
                       AND nvo2 /= vi
                       AND trk_line_eps_irt?(ss, vo, vi, 1, -1)(nvo1)
                       AND trk_line_eps_irt?(ss, vo, vi, 1, 1)(nvo2)
                       AND beta = pi - 2 * psi
                       IMPLIES nvo2 /= zero))));

  % Subtype TCC generated (at line 160, column 42) for  nvo1
      % expected type  Nz_vect2
  trk_line_sort_eps_1_angle_case2_TCC1: OBLIGATION
    FORALL (nvo1, nvo2: Vect2, ss: Ss_vect2[D], vi, vo: Nz_vect2):
      abs(det(vi, ss) / (norm(vo) * norm(ss))) <= 1 IMPLIES
       (FORALL (phi: nnreal_lt_2pi):
          phi = track(ss) IMPLIES
           (FORALL (psi: real_abs_le_pi2):
              psi = asin(det(vi, ss) / (norm(vo) * norm(ss))) IMPLIES
               (FORALL (alpha: real):
                  alpha = phi + psi IMPLIES
                   (FORALL (beta: real):
                           (nvo1 * ss) * (nvo2 * ss) >= 0 AND nvo1 /= vi
                       AND nvo2 /= vi
                       AND trk_line_eps_irt?(ss, vo, vi, 1, -1)(nvo1)
                       AND trk_line_eps_irt?(ss, vo, vi, 1, 1)(nvo2)
                       AND beta = pi - 2 * psi
                       IMPLIES nvo1 /= zero))));

  % Subtype TCC generated (at line 160, column 69) for  nvo2
      % expected type  Nz_vect2
  trk_line_sort_eps_1_angle_case2_TCC2: OBLIGATION
    FORALL (nvo1, nvo2: Vect2, ss: Ss_vect2[D], vi, vo: Nz_vect2):
      abs(det(vi, ss) / (norm(vo) * norm(ss))) <= 1 IMPLIES
       (FORALL (phi: nnreal_lt_2pi):
          phi = track(ss) IMPLIES
           (FORALL (psi: real_abs_le_pi2):
              psi = asin(det(vi, ss) / (norm(vo) * norm(ss))) IMPLIES
               (FORALL (alpha: real):
                  alpha = phi + psi IMPLIES
                   (FORALL (beta: real):
                           (nvo1 * ss) * (nvo2 * ss) >= 0 AND nvo1 /= vi
                       AND nvo2 /= vi
                       AND trk_line_eps_irt?(ss, vo, vi, 1, -1)(nvo1)
                       AND trk_line_eps_irt?(ss, vo, vi, 1, 1)(nvo2)
                       AND beta = pi - 2 * psi
                       IMPLIES nvo2 /= zero))));


body:
  %------------------------------------------------------------------------------
  % gs_only.pvs
  % ACCoRD v.1.0
  %
  % Line solutions. Solve the following equation on k and l:
  %   k*v = l*vo-vi.
  %
  % Circle solutions. Solve the following equation on l:
  %   sq(s+t*(l*vo-vi)) = sq(D).
  %
  %------------------------------------------------------------------------------

  gs_only[D:posreal] : THEORY
  BEGIN
    
    IMPORTING reals@min_max,
              vectors@vectors_2D, 
  	    vectors@det_2D,
              reals@quadratic_2b,
              horizontal[D]

    j,k      : VAR real
    vo,vi,    
    s,v,nvo,
    v1,v2    : VAR Vect2
    t        : VAR posreal
    dir,irt  : VAR Sign
    u,
    vnzo     : VAR Nz_vect2

    %---------------%
    % Line Solution %
    %---------------%

    k_l_det: LEMMA
      FORALL (l:real):  
        k*v+vi = l*vo 
        IMPLIES
          k*det(vo,v) = det(vi,vo) AND
          l*det(vo,v) = det(vi,v)

    k_l_det_nz: LEMMA 
      FORALL (l:real):
        det(vo,v) /= 0 AND
        k = det(vi,vo)/det(vo,v) AND
        l = det(vi,v)/det(vo,v) 
        IMPLIES
          k*v = l*vo-vi 


    % Vector v is a directional vector
    % l=0 indicates no solution
    gs_only_line_k_l(v,vo,vi): {k:real,l:nnreal | l > 0 => 
    			                        k*v = l*vo-vi} =
      IF det(vo,v) /= 0 THEN  
        LET k = det(vi,vo)/det(vo,v),
            l = det(vi,v)/det(vo,v) IN
          (k,max(l,0))
      ELSE
        (0,0) 
      ENDIF

    gs_only_line_k_l_complete : LEMMA
      FORALL (l:posreal):
        (det(vi,vo) /= 0 OR det(vo,v) /= 0) AND
        k*v = l*vo-vi IMPLIES
        (k,l) = gs_only_line_k_l(v,vo,vi)

    % Vector v is a directional vector
    % Zero indicates no ground speed solution. 
    gs_only_line(v,vo,vi): {k:real,nvo:Vect2 | nz_vect2?(nvo) => 
                                               gs_only?(vo)(nvo) AND
                                               k*v = nvo-vi} =
      LET (k,l) = gs_only_line_k_l(v,vo,vi) IN
        (k,l*vo)

    % gs_only_line computes the same resolutions for same dir vectors
    same_gs_only_line: LEMMA 
      FORALL (l:posreal) :
        v2 = l*v1
        IMPLIES 
          gs_only_line(v,v1,vi)`2 = gs_only_line(v,v2,vi)`2

    gs_only_line?(v,vo,vi)(k,nvo) : bool =
      nz_vect2?(nvo) AND
      (k,nvo) = gs_only_line(v,vo,vi)

    gs_only_line_complete : LEMMA
      gs_only?(vo)(nvo) AND
      (det(vi,vo) /= 0 OR det(vo,v) /= 0) AND
      k*v = nvo-vi IMPLIES
        gs_only_line?(v,vo,vi)(k,nvo)

    % Solves equation on nvo: u*(nvo-vi) = j, such that exists l > 0: nvo = l*vo
    gs_only_dot(u,vo,vi,j) : {nvo | nz_vect2?(nvo) => 
                                    gs_only?(vo)(nvo) AND
                                    u*(nvo-vi) = j} =
      gs_only_line(Vdir(u,vo-vi),vo,vi+W0(u,j))`2 

    gs_only_dot_complete : LEMMA
      gs_only?(vnzo)(nvo) AND
      (det(vi+W0(u,j),vnzo) /= 0 OR det(vnzo,Vdir(u,vnzo-vi)) /= 0) AND
      u*(nvo-vi) = j IMPLIES
      nvo = gs_only_dot(u,vnzo,vi,j)

    %-----------------%
    % Circle Solution %
    %-----------------%

    %% zero indicates no solution

    gs_only_circle(s,vnzo,vi,t,dir,irt): {nvo | nz_vect2?(nvo) => 
                                                gs_only?(vnzo)(nvo) } =
      LET w = s-t*vi, 
          a = sq(t)*sqv(vnzo),                
          b = t*(w*vnzo),
          c = sqv(w)-sq(D) IN
      IF discr2b(a,b,c) >= 0 THEN
        LET l   = root2b(a,b,c,irt),
            nvo = max(l,0)*vnzo IN
        IF horizontal_dir_at?(s,nvo-vi,t,dir) THEN
          nvo
        ELSE
          zero
        ENDIF
      ELSE
        zero
      ENDIF

    gs_only_circle?(s,vnzo,vi,t,dir)(nvo): bool =
       nz_vect2?(nvo) AND
       EXISTS (irt:Sign): nvo = gs_only_circle(s,vnzo,vi,t,dir,irt)

    gs_only_circle_solution : LEMMA
      gs_only_circle?(s,vnzo,vi,t,dir)(nvo) IMPLIES
      circle_solution_2D?(s,nvo-vi,t,dir)

    gs_only_circle_complete : LEMMA
      gs_only?(vnzo)(nvo) AND
      circle_solution_2D?(s,nvo-vi,t,dir) IMPLIES
        gs_only_circle?(s,vnzo,vi,t,dir)(nvo)

    gs_only_vertical(s,vo,vi,t,dir): {nvo | nz_vect2?(nvo) => 
                                            gs_only?(vo)(nvo)} =
      LET v = vo-vi IN
      IF Delta(s,v) > 0 AND Theta_D(s,v,dir) > 0 THEN
        LET p = s + Theta_D(s,v,dir)*v IN
          gs_only_dot(t*p,vo,vi,sq(D)-s*p) 
      ELSE
        zero
      ENDIF

    gs_only_vertical?(s,vo,vi,t,dir)(nvo) : bool = 
      nz_vect2?(nvo) AND
      nvo =  gs_only_vertical(s,vo,vi,t,dir)

    gs_only_vertical_on_D: LEMMA
      LET v = vo-vi IN
      gs_only_vertical?(s,vo,vi,t,dir)(nvo) IMPLIES
        Delta(s,v) > 0 AND
        Theta_D(s,v,dir) > 0 AND
        (s+t*(nvo-vi))*(s+Theta_D(s,v,dir)*v) = sq(D) 

  END gs_only

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

  % Subtype TCC generated (at line 58, column 8) for  (k, max(l, 0))
      % expected type  {k: real, l: nnreal | l > 0 => k * v = l * vo - vi}
  gs_only_line_k_l_TCC1: OBLIGATION
    FORALL (v: Vect2, vo: Vect2, vi: Vect2):
      det(vo, v) /= 0 IMPLIES
       (FORALL (k: real):
          k = det(vi, vo) / det(vo, v) IMPLIES
           (FORALL (l: real):
              l = det(vi, v) / det(vo, v) IMPLIES
               max(l, 0) > 0 => k * v = max(l, 0) * vo - vi));

  % Subtype TCC generated (at line 60, column 6) for  (0, 0)
      % expected type  {k: real, l: nnreal | l > 0 => k * v = l * vo - vi}
  gs_only_line_k_l_TCC2: OBLIGATION
    FORALL (v: Vect2, vo: Vect2, vi: Vect2):
      NOT det(vo, v) /= 0 IMPLIES 0 > 0 => 0 * v = 0 * vo - vi;

  % Subtype TCC generated (at line 75, column 6) for  (k, l * vo)
      % expected type  {k: real, nvo: Vect2 |
                     %          nvo /= zero =>
                     %           gs_only?(vo)(nvo) AND k * v = nvo - vi}
  gs_only_line_TCC1: OBLIGATION
    FORALL (v: Vect2, vo: Vect2, vi: Vect2, k: real, l: nnreal):
      l = gs_only_line_k_l(v, vo, vi)`2 AND k = gs_only_line_k_l(v, vo, vi)`1
       IMPLIES l * vo /= zero => gs_only?(vo)(l * vo) AND k * v = l * vo - vi;

  % Subtype TCC generated (at line 98, column 4) for
      % gs_only_line(Vdir(u, vo - vi), vo, vi + W0(u, j))`2
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           gs_only?(vo)(nvo) AND u * (nvo - vi) = j}
  gs_only_dot_TCC1: OBLIGATION
    FORALL (u: Nz_vect2, vo: Vect2, vi: Vect2, j: real):
      gs_only_line(Vdir(u, vo - vi), vo, vi + W0(u, j))`2 /= zero =>
       gs_only?(vo)(gs_only_line(Vdir(u, vo - vi), vo, vi + W0(u, j))`2) AND
        u * (gs_only_line(Vdir(u, vo - vi), vo, vi + W0(u, j))`2 - vi) = j;

  % Subtype TCC generated (at line 122, column 8) for  nvo
      % expected type  {nvo | nvo /= zero => gs_only?(vnzo)(nvo)}
  gs_only_circle_TCC1: OBLIGATION
    FORALL (s: Vect2, vnzo: Nz_vect2, vi: Vect2, t: posreal, dir: Sign,
            irt: Sign, w: Vector):
      w = s - t * vi IMPLIES
       (FORALL (a: posreal):
          a = sq(t) * sqv(vnzo) IMPLIES
           (FORALL (b: real):
              b = t * (w * vnzo) IMPLIES
               (FORALL (c: real):
                  discr2b(a, b, c) >= 0 AND c = sqv(w) - sq(D) IMPLIES
                   (FORALL (l: real):
                      l = root2b(a, b, c, irt) IMPLIES
                       (FORALL (nvo: Vect2):
                          dir * ((s + t * (nvo - vi)) * (nvo - vi)) >= 0 AND
                           nvo = max(l, 0) * vnzo
                           IMPLIES nvo /= zero => gs_only?(vnzo)(nvo))))));

  % Subtype TCC generated (at line 124, column 8) for  zero
      % expected type  {nvo | nvo /= zero => gs_only?(vnzo)(nvo)}
  gs_only_circle_TCC2: OBLIGATION
    FORALL (s: Vect2, vnzo: Nz_vect2, vi: Vect2, t: posreal, dir: Sign,
            irt: Sign, w: Vector):
      w = s - t * vi IMPLIES
       (FORALL (a: posreal):
          a = sq(t) * sqv(vnzo) IMPLIES
           (FORALL (b: real):
              b = t * (w * vnzo) IMPLIES
               (FORALL (c: real):
                  discr2b(a, b, c) >= 0 AND c = sqv(w) - sq(D) IMPLIES
                   (FORALL (l: real):
                      l = root2b(a, b, c, irt) IMPLIES
                       (FORALL (nvo: Vect2):
                          NOT dir * ((s + t * (nvo - vi)) * (nvo - vi)) >= 0
                           AND nvo = max(l, 0) * vnzo
                           IMPLIES zero /= zero => gs_only?(vnzo)(zero))))));

  % Subtype TCC generated (at line 127, column 6) for  zero
      % expected type  {nvo | nvo /= zero => gs_only?(vnzo)(nvo)}
  gs_only_circle_TCC3: OBLIGATION
    FORALL (s: Vect2, vnzo: Nz_vect2, vi: Vect2, t: posreal, w: Vector):
      w = s - t * vi IMPLIES
       (FORALL (a: posreal):
          a = sq(t) * sqv(vnzo) IMPLIES
           (FORALL (b: real):
              b = t * (w * vnzo) IMPLIES
               (FORALL (c: real):
                  NOT discr2b(a, b, c) >= 0 AND c = sqv(w) - sq(D) IMPLIES
                   zero /= zero => gs_only?(vnzo)(zero))));

  % Subtype TCC generated (at line 146, column 36) for  v
      % expected type  {nzv | Delta(s, nzv) >= 0}
  gs_only_vertical_TCC1: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, v: Vect2):
      Delta(s, v) > 0 AND v = vo - vi IMPLIES
       v /= zero AND Delta[D](s, v) >= 0;

  % Subtype TCC generated (at line 148, column 20) for  t * p
      % expected type  Nz_vect2
  gs_only_vertical_TCC2: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, t: posreal, dir: Sign, v: Vect2):
      Delta(s, v) > 0 AND Theta_D(s, v, dir) > 0 AND v = vo - vi IMPLIES
       (FORALL (p: Vector):
          p = s + Theta_D(s, v, dir) * v IMPLIES t * p /= zero);

  % Subtype TCC generated (at line 148, column 8) for
      % gs_only_dot(t * p, vo, vi, sq(D) - s * p)
      % expected type  {nvo | nvo /= zero => gs_only?(vo)(nvo)}
  gs_only_vertical_TCC3: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, t: posreal, dir: Sign, v: Vect2):
      Delta(s, v) > 0 AND Theta_D(s, v, dir) > 0 AND v = vo - vi IMPLIES
       (FORALL (p: Vector):
          p = s + Theta_D(s, v, dir) * v IMPLIES
           gs_only_dot(t * p, vo, vi, sq(D) - s * p) /= zero =>
            gs_only?(vo)(gs_only_dot(t * p, vo, vi, sq(D) - s * p)));

  % Subtype TCC generated (at line 150, column 6) for  zero
      % expected type  {nvo | nvo /= zero => gs_only?(vo)(nvo)}
  gs_only_vertical_TCC4: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, dir: Sign, v: Vect2):
      NOT (Delta(s, v) > 0 AND Theta_D(s, v, dir) > 0) AND v = vo - vi
       IMPLIES zero /= zero => gs_only?(vo)(zero);


body:
  %------------------------------------------------------------------------------
  % gs_line.pvs
  % ACCoRD v.1.0
  %
  % Ground speed line solutions are ground speed only solutions that are tangent 
  % to the protected zone.
  %------------------------------------------------------------------------------

  gs_line[D: posreal] : THEORY
  BEGIN
    
    IMPORTING gs_only[D],
              tangent_line[D]

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

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

    % zero indicates no ground speed solution

    gs_line_eps(sp,vo,vi,eps): {nvo | nz_vect2?(nvo) => 
                                      gs_only?(vo)(nvo)} =
      LET (k,nvo) = gs_only_line(tangent_line(sp,eps),vo,vi) IN
      IF k >= 0 THEN
        nvo
      ELSE
        zero
      ENDIF

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

    gs_line?(sp,vo,vi)(nvo):bool =
      nz_vect2?(nvo) AND 
      EXISTS (eps): nvo = gs_line_eps(sp,vo,vi,eps)

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

    gs_line_eps_tangent_line: LEMMA 
      gs_line_eps?(sp,vo,vi,eps)(nvo)
      IMPLIES
        tangent_line?(sp,nvo-vi,eps)              

    gs_line_is_line_solution: LEMMA 
      gs_line_eps?(sp,vo,vi,eps)(nvo)
      IMPLIES
        line_solution?(sp,nvo-vi,eps)              
       
    two_parallel?(sp,vo,vi) : bool =
      det(vi,vo) = 0 AND
      EXISTS (eps:Sign): det(vo,tangent_line(sp,eps)) = 0

    gs_line_complete : LEMMA
      gs_only?(vo)(nvo) AND
      NOT two_parallel?(sp,vo,vi) AND
      line_solution?(sp,nvo-vi) IMPLIES
        gs_line?(sp,vo,vi)(nvo)
       
  END gs_line

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

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

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


body:
  %------------------------------------------------------------------------------
  % gs_bands_2D.pvs
  % ACCoRD v.1.0
  %------------------------------------------------------------------------------

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

    IMPORTING analysis@interm_value_thm,
    	    vect_analysis@vect2_cont_dot[real],
              omega_v2[D,B,T],
              gs_line[D],
  	    line_solutions[D],
              bands_util
   
    s     : VAR Vect2
    vo,vi,
    nvo	: VAR Nz_vect2
    sp    : VAR Sp_vect2
    ss    : VAR Ss_vect2
    band  : VAR ConnectedGt(0)
    gsp   : VAR posreal
    k     : VAR real
    pm,
    eps   : VAR Sign

    gs_band_pos : JUDGEMENT
      (band) SUBTYPE_OF posreal

    gs2v2_continuous : JUDGEMENT
      gs2v2(vo) HAS_TYPE continuous_rv_fun

    %-----------------------------------------------%
    % 2-D Ground Speed Critical Points              %
    %-----------------------------------------------%

    gs_critical?(s,vo,vi)(gsp) : bool =
      LET gso = gs2v2(vo)(gsp) IN
      (sqv(s)>=sq(D) AND gs_line?(s,vo,vi)(gso)) OR
      gs_only_circle?(s,vo,vi,T,Entry)(gso) OR
      (B>0 AND gs_only_circle?(s,vo,vi,B,Exit)(gso))

    Vgs(vo,vi)(gsp:real) : Vect2 = 
      gs2v2(vo)(gsp)-vi

    Vgs_continuous : JUDGEMENT
      Vgs(vo,vi) HAS_TYPE continuous_rv_fun

    Omega_gs(s,vo,vi) : (continuous_rr?) = 
      omega_v2(s) o Vgs(vo,vi)

    Omega_gs_critical : LEMMA
      Omega_gs(s,vo,vi)(gsp) = 0 AND
      NOT (sqv(s)>=sq(D) AND two_parallel?(s,vo,vi)) IMPLIES
        gs_critical?(s,vo,vi)(gsp) 

    % Bands do not contain critical points
    gs_band?(s,vo,vi)(band) : bool =
      FORALL (gso:(band)) :
        NOT gs_critical?(s,vo,vi)(gso)

    gs_green?(s,vo,vi)(band) : bool =
      FORALL (gso:(band)) :
        NOT conflict_2D?(s,Vgs(vo,vi)(gso))

    gs_green_two_parallel : LEMMA
      two_parallel?(sp,vo,vi) IMPLIES
      gs_green?(sp,vo,vi)(band)

    gs_red?(s,vo,vi)(band) : bool =
      FORALL (gso:(band)) :
        conflict_2D?(s,Vgs(vo,vi)(gso))

    gs_line_color : LEMMA
      pm*(Q(ss,eps)*vo) > 0 IFF
      IF pm*(eps*det(ss,vo)) > 0 THEN pm*(ss*vo) > 0 AND sq(D)*sqv(vo) > sq(det(ss,vo)) 
      ELSE pm*(ss*vo) > 0 OR pm*(ss*vo) <= 0 AND sq(D)*sqv(vo) < sq(det(ss,vo))
      ENDIF

    %------------------------------------------------%
    % THEOREM: Ground Speed Green Bands Correctness  %
    %------------------------------------------------%

    gs_green_band : THEOREM
      FORALL (gso:(band)) :
         gs_band?(s,vo,vi)(band) IMPLIES
         (NOT cd2d?(s,Vgs(vo,vi)(gso)) IFF
          gs_green?(s,vo,vi)(band))

    %-----------------------------------------------%
    % THEOREM: Ground Speed Red Bands Correctness   %
    %-----------------------------------------------%

    gs_red_band : THEOREM
      FORALL (gso:(band)) :
        gs_band?(s,vo,vi)(band) IMPLIES
        (cd2d?(s,Vgs(vo,vi)(gso)) IFF
          gs_red?(s,vo,vi)(band))
   
  END gs_bands_2D

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

  % Judgement subtype TCC generated (at line 28, column 4) for  x
      % expected type  posreal
  gs_band_pos: OBLIGATION
    FORALL (band: ConnectedGt(0), x: (band)): x >= 0 AND x > 0;

  % Judgement subtype TCC generated (at line 31, column 4) for  gs2v2(vo)
      % expected type  continuous_rv_fun[real]
  gs2v2_continuous: OBLIGATION FORALL (vo): continuous_rv?[real](gs2v2(vo));

  % Judgement subtype TCC generated (at line 47, column 4) for  Vgs(vo, vi)
      % expected type  continuous_rv_fun[real]
  Vgs_continuous: OBLIGATION
    FORALL (vi, vo): continuous_rv?[real](Vgs(vo, vi));

  % Subtype TCC generated (at line 50, column 4) for
      % omega_v2(s) o Vgs(vo, vi)
      % expected type  ({f | continuous?(f)})
  Omega_gs_TCC1: OBLIGATION
    FORALL (s: Vect2, vo: Nz_vect2, vi: Nz_vect2):
      continuous?[real](o[real](omega_v2[D, B, T](s), Vgs(vo, vi)));


body:
  bands_2D[D:posreal,B:nnreal,T: {AB: posreal|AB>B},gsmin,gsmax:posreal] : THEORY
  BEGIN

    ASSUMING
      gs_min_lt_max: ASSUMPTION gsmin < gsmax
    ENDASSUMING	
    
    IMPORTING gs_bands_2D[D,B,T],
    	    trk_bands_2D[D,B,T],
              fseqs_aux_2D[gsmin,gsmax]


    nvo	  : VAR Vect2
    vo,vi	  : VAR Nz_vect2
    sp   	  : VAR Sp_vect2
    s	  : VAR Vect2
    trkb    : VAR (trk_fseq?)
    gsb     : VAR (gs_fseq?)
    x       : VAR real
    trk	  : VAR nnreal_lt_2pi
    trk2	  : VAR {r: real | 0<=r AND r<=2*pi}
    gsp	  : VAR {r: real | gsmin<=r AND r<=gsmax}


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

    trk_critical(nvo:Vect2) : (trk_fseq?) =
      IF nvo /= zero THEN addend(track(nvo),emptyseq)
      ELSE emptyseq
      ENDIF

    trk_critical_rew: LEMMA
      trk_critical(nvo) = IF nvo /= zero THEN singleton(track(nvo))
      		      	ELSE emptyseq
  			ENDIF

    member_trk_critical: LEMMA
    		       member(x,trk_critical(nvo))
  		       IMPLIES
  		       x = track(nvo)

    trk_critical_composition: LEMMA
      FORALL (trkfs: fseq, nvo:Vect2, x:real):
      	   member(x,trkfs o trk_critical(nvo))
  	   IFF
  	   ((nvo /= zero AND x = track(nvo))
  	   OR
  	   member(x,trkfs))

    trk_bands(s,vo,vi) : {fs : (trk_fseq?) | increasing?(fs)} =
      sort(
      LET fs2 : (trk_fseq?) = 
        IF horizontal_sep?(s) THEN
          trk_critical(trk_line_eps_irt(s,vo,vi,-1,-1)) o 
          trk_critical(trk_line_eps_irt(s,vo,vi,-1, 1)) o 
          trk_critical(trk_line_eps_irt(s,vo,vi, 1,-1)) o 
          trk_critical(trk_line_eps_irt(s,vo,vi, 1, 1)) o 
  	trk_critical(trk_only_circle(s,vo,vi,T,Entry,-1)) o
  	trk_critical(trk_only_circle(s,vo,vi,T,Entry, 1)) 
        ELSE
  	emptyseq
        ENDIF,
          fs3 : (trk_fseq?) =
        IF B > 0 THEN
          trk_critical(trk_only_circle(s,vo,vi,B,Exit,-1)) o
      	trk_critical(trk_only_circle(s,vo,vi,B,Exit, 1))
        ELSE
          emptyseq 
        ENDIF 
      IN
  	(fs2 o fs3) o 
  	(addend(0,emptyseq) o addend(2*pi,emptyseq)))


    trk_bands_not_empty : LEMMA
      trk_bands(s,vo,vi)`length > 1


    AUTO_REWRITE- member

    trk_bands_critical: LEMMA
       (trk_critical?(s,vo,vi)(trk2) OR to2pi(trk2) = 0) IFF
       member(trk2,trk_bands(s,vo,vi))
      
    gs_critical(nvo:Vect2) : (gs_fseq?) =
      IF nvo/=zero AND gsmin<=gs(nvo) AND gs(nvo)<=gsmax THEN addend(gs(nvo),emptyseq)
      ELSE emptyseq
      ENDIF

    gs_critical_rew: LEMMA
      FORALL (nvo:Vect2):
      gs_critical(nvo) = IF nvo/=zero AND gsmin<=gs(nvo) AND gs(nvo)<=gsmax THEN singleton(gs(nvo))
      		      	ELSE emptyseq
  			ENDIF

    member_gs_critical: LEMMA
      FORALL (nvo:Vect2,x:real):
    		       member(x,gs_critical(nvo))
  		       IMPLIES
  		       x = gs(nvo)

    gs_critical_composition: LEMMA
      FORALL (gsfs: (gs_fseq?), nvo:Vect2, x:real):
      	   member(x,gsfs o gs_critical(nvo))
  	   IFF
  	   ((nz_vect2?(nvo) AND x = gs(nvo) AND gsmin<=gs(nvo) AND gs(nvo)<=gsmax)
  	   OR
  	   member(x,gsfs))

    gs_bands(s,vo,vi) : {fs: (gs_fseq?) | increasing?(fs)} =
      sort(
      LET fs2 : (gs_fseq?) = 
        IF horizontal_sep?(s) THEN
          gs_critical(gs_line_eps(s,vo,vi,-1)) o 
          gs_critical(gs_line_eps(s,vo,vi, 1)) o
  	gs_critical(gs_only_circle(s,vo,vi,T,Entry,-1)) o
  	gs_critical(gs_only_circle(s,vo,vi,T,Entry, 1)) 
        ELSE
  	emptyseq
        ENDIF,
          fs3 : (gs_fseq?) =
        IF B > 0 THEN
          gs_critical(gs_only_circle(s,vo,vi,B,Exit,-1)) o
      	gs_critical(gs_only_circle(s,vo,vi,B,Exit, 1))
        ELSE
          emptyseq 
        ENDIF 
      IN
  	(fs2 o fs3) o
      	(addend(gsmin,emptyseq) o addend(gsmax,emptyseq)))

    gs_bands_not_empty : LEMMA
      gs_bands(s,vo,vi)`length > 1


    gs_bands_critical: LEMMA
       (gs_critical?(s,vo,vi)(gsp) OR gsp = gsmin OR gsp = gsmax) IFF
       member(gsp,gs_bands(s,vo,vi))

    %------------%
    % THEOREMS   %
    %------------%

    red_trk_band?(s,vo,vi,trkb)(i:subrange(0,trkb`length-2)) : bool =
      LET mp = (trkb`seq(i)+trkb`seq(i+1))/2 in
      cd2d?(s,Vtrk(vo,vi)(mp))

    trk_red_bands : THEOREM
      LET trkb = trk_bands(s,vo,vi) IN
       FORALL (i:{ii: subrange(0,trkb`length-2)| trkb`seq(ii) /= trkb`seq(ii+1)}) : 
         red_trk_band?(s,vo,vi,trkb)(i) IFF
         (FORALL (x | trkb`seq(i) < x AND x < trkb`seq(i+1)):
           conflict_2D?(s,Vtrk(vo,vi)(x)))

    trk_green_bands : THEOREM
      LET trkb = trk_bands(s,vo,vi) IN
       FORALL (i:{ii: subrange(0,trkb`length-2)| trkb`seq(ii) /= trkb`seq(ii+1)}) : 
         NOT red_trk_band?(s,vo,vi,trkb)(i) IFF
         (FORALL (x | trkb`seq(i) < x AND x < trkb`seq(i+1)):
           NOT conflict_2D?(s,Vtrk(vo,vi)(x)))



    red_gs_band?(s,vo,vi,gsb)(i:subrange(0,gsb`length-2)) : bool =
      LET mp = (gsb`seq(i)+gsb`seq(i+1))/2 in
      cd2d?(s,Vgs(vo,vi)(mp))  

    gs_red_bands : THEOREM
      LET gsb = gs_bands(s,vo,vi) IN
       FORALL (i:{ii: subrange(0,gsb`length-2)| gsb`seq(ii) /= gsb`seq(ii+1)}) :  
         red_gs_band?(s,vo,vi,gsb)(i) IFF
         (FORALL (x | gsb`seq(i) < x AND x < gsb`seq(i+1)):
           conflict_2D?(s,Vgs(vo,vi)(x)))

    gs_green_bands : THEOREM
      LET gsb = gs_bands(s,vo,vi) IN
       FORALL (i:{ii: subrange(0,gsb`length-2)| gsb`seq(ii) /= gsb`seq(ii+1)}) :  
         NOT red_gs_band?(s,vo,vi,gsb)(i) IFF
         (FORALL (x | gsb`seq(i) < x AND x < gsb`seq(i+1)):
           NOT conflict_2D?(s,Vgs(vo,vi)(x)))


  END bands_2D

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

  % Subtype TCC generated (at line 30, column 24) for
      % addend(track(nvo), empty_seq)
      % expected type  (trk_fseq?)
  trk_critical_TCC1: OBLIGATION
    FORALL (nvo: Vect2):
      nvo /= zero IMPLIES
       trk_fseq?[gsmin, gsmax](addend[real](track(nvo), empty_seq[real]));

  % Subtype TCC generated (at line 31, column 9) for  emptyseq
      % expected type  (trk_fseq?)
  trk_critical_TCC2: OBLIGATION
    FORALL (nvo: Vect2):
      NOT nvo /= zero IMPLIES
       (FORALL (i: nat):
          i >= emptyseq[real]`length IMPLIES
           emptyseq[real]`seq(i) = default[real])
        AND trk_fseq?[gsmin, gsmax](emptyseq[real]);

  % Subtype TCC generated (at line 42, column 19) for  nvo
      % expected type  Nz_vect2
  member_trk_critical_TCC1: OBLIGATION
    FORALL (nvo: Vect2, x: real):
      member(x, trk_critical(nvo)) IMPLIES nvo /= zero;

  % Subtype TCC generated (at line 53, column 4) for
      % sort(LET fs2: (trk_fseq?) =
      %            IF sqv(s) >= sq(D)
      %              THEN trk_critical(trk_line_eps_irt(s, vo, vi, -1, -1)) o
      %                    trk_critical(trk_line_eps_irt(s, vo, vi, -1, 1))
      %                    o trk_critical(trk_line_eps_irt(s, vo, vi, 1, -1))
      %                    o trk_critical(trk_line_eps_irt(s, vo, vi, 1, 1))
      %                    o
      %                    trk_critical(trk_only_circle
      %                                 (s, vo, vi, T, -1, -1))
      %                    o
      %                    trk_critical(trk_only_circle(s, vo, vi, T, -1, 1))
      %            ELSE empty_seq
      %            ENDIF,
      %          fs3: (trk_fseq?) =
      %            IF B > 0
      %              THEN trk_critical(trk_only_circle(s, vo, vi, B, 1, -1))
      %                    o
      %                    trk_critical(trk_only_circle(s, vo, vi, B, 1, 1))
      %            ELSE empty_seq
      %            ENDIF
      %        IN
      %        (fs2 o fs3) o
      %         (addend(0, empty_seq) o addend(2 * pi, empty_seq)))
      % expected type  {fs: (trk_fseq?) | increasing?(fs)}
  trk_bands_TCC1: OBLIGATION
    FORALL (s: Vect2, vo: Nz_vect2, vi: Nz_vect2):
      trk_fseq?[gsmin, gsmax]
          (sort[real, <=]
               (LET fs2: (trk_fseq?[gsmin, gsmax]) =
                      IF sqv(s) >= sq(D)
                        THEN o[real]
                                 (o[real]
                                      (o[real]
                                       (o[real]
                                        (o[real]
                                         (trk_critical
                                          (trk_line_eps_irt[D]
                                           (s, vo, vi, -1, -1)),
                                          trk_critical
                                          (trk_line_eps_irt[D]
                                           (s, vo, vi, -1, 1))),
                                         trk_critical
                                         (trk_line_eps_irt[D]
                                          (s, vo, vi, 1, -1))),
                                        trk_critical
                                        (trk_line_eps_irt[D]
                                         (s, vo, vi, 1, 1))),
                                       trk_critical
                                       (trk_only_circle[D]
                                        (s, vo, vi, T, -1, -1))),
                                  trk_critical(trk_only_circle[D]
                                               (s, vo, vi, T, -1, 1)))
                      ELSE empty_seq[real]
                      ENDIF,
                    fs3: (trk_fseq?[gsmin, gsmax]) =
                      IF B > 0
                        THEN o[real]
                                 (trk_critical(trk_only_circle[D]
                                               (s, vo, vi, B, 1, -1)),
                                  trk_critical(trk_only_circle[D]
                                               (s, vo, vi, B, 1, 1)))
                      ELSE empty_seq[real]
                      ENDIF
                  IN
                  o[real]
                      ((o[real](fs2, fs3)),
                       (o[real]
                            (addend[real](0, empty_seq[real]),
                             addend[real](2 * pi, empty_seq[real]))))))
       AND
       increasing?[real, <=]
           (sort[real, <=]
                (LET fs2: (trk_fseq?[gsmin, gsmax]) =
                       IF sqv(s) >= sq(D)
                         THEN o[real]
                                  (o[real]
                                       (o[real]
                                        (o[real]
                                         (o[real]
                                          (trk_critical
                                           (trk_line_eps_irt[D]
                                            (s, vo, vi, -1, -1)),
                                           trk_critical
                                           (trk_line_eps_irt[D]
                                            (s, vo, vi, -1, 1))),
                                          trk_critical
                                          (trk_line_eps_irt[D]
                                           (s, vo, vi, 1, -1))),
                                         trk_critical
                                         (trk_line_eps_irt[D]
                                          (s, vo, vi, 1, 1))),
                                        trk_critical
                                        (trk_only_circle[D]
                                         (s, vo, vi, T, -1, -1))),
                                   trk_critical(trk_only_circle[D]
                                                (s, vo, vi, T, -1, 1)))
                       ELSE empty_seq[real]
                       ENDIF,
                     fs3: (trk_fseq?[gsmin, gsmax]) =
                       IF B > 0
                         THEN o[real]
                                  (trk_critical(trk_only_circle[D]
                                                (s, vo, vi, B, 1, -1)),
                                   trk_critical(trk_only_circle[D]
                                                (s, vo, vi, B, 1, 1)))
                       ELSE empty_seq[real]
                       ENDIF
                   IN
                   o[real]
                       ((o[real](fs2, fs3)),
                        (o[real]
                             (addend[real](0, empty_seq[real]),
                              addend[real](2 * pi, empty_seq[real]))))));

  % Subtype TCC generated (at line 88, column 60) for
      % addend(gs(nvo), empty_seq)
      % expected type  (gs_fseq?)
  gs_critical_TCC1: OBLIGATION
    FORALL (nvo: Vect2):
      nvo /= zero AND gsmin <= gs(nvo) AND gs(nvo) <= gsmax IMPLIES
       gs_fseq?[gsmin, gsmax](addend[real](gs(nvo), empty_seq[real]));

  % Subtype TCC generated (at line 89, column 9) for  emptyseq
      % expected type  (gs_fseq?)
  gs_critical_TCC2: OBLIGATION
    FORALL (nvo: Vect2):
      NOT (nvo /= zero AND gsmin <= gs(nvo) AND gs(nvo) <= gsmax) IMPLIES
       (FORALL (i: nat):
          i >= emptyseq[real]`length IMPLIES
           emptyseq[real]`seq(i) = default[real])
        AND gs_fseq?[gsmin, gsmax](emptyseq[real]);

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  (gs_fseq?)
  gs_bands_TCC1: OBLIGATION
    FORALL (s: Vect2, vo: Nz_vect2, vi: Nz_vect2):
      NOT sqv(s) >= sq(D) IMPLIES
       (FORALL (i: nat):
          i >= empty_seq[real]`length IMPLIES
           empty_seq[real]`seq(i) = default[real])
        AND gs_fseq?[gsmin, gsmax](empty_seq[real]);

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  (gs_fseq?)
  gs_bands_TCC2: OBLIGATION
    FORALL (s: Vect2, vo: Nz_vect2, vi: Nz_vect2,
            fs2: (gs_fseq?[gsmin, gsmax])):
      NOT B > 0 AND
       fs2 =
        IF sqv(s) >= sq(D)
          THEN gs_critical(gs_line_eps(s, vo, vi, -1)) o
                gs_critical(gs_line_eps(s, vo, vi, 1))
                o gs_critical(gs_only_circle(s, vo, vi, T, -1, -1))
                o gs_critical(gs_only_circle(s, vo, vi, T, -1, 1))
        ELSE empty_seq
        ENDIF
       IMPLIES
       (FORALL (i: nat):
          i >= empty_seq[real]`length IMPLIES
           empty_seq[real]`seq(i) = default[real])
        AND gs_fseq?[gsmin, gsmax](empty_seq[real]);

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  fseq[real]
  gs_bands_TCC3: OBLIGATION
    FORALL (s: Vect2, vo: Nz_vect2, vi: Nz_vect2,
            fs2: (gs_fseq?[gsmin, gsmax])):
      fs2 =
       IF sqv(s) >= sq(D)
         THEN gs_critical(gs_line_eps(s, vo, vi, -1)) o
               gs_critical(gs_line_eps(s, vo, vi, 1))
               o gs_critical(gs_only_circle(s, vo, vi, T, -1, -1))
               o gs_critical(gs_only_circle(s, vo, vi, T, -1, 1))
       ELSE empty_seq
       ENDIF
       IMPLIES
       (FORALL (fs3: (gs_fseq?[gsmin, gsmax])):
          fs3 =
           IF B > 0
             THEN gs_critical(gs_only_circle(s, vo, vi, B, 1, -1)) o
                   gs_critical(gs_only_circle(s, vo, vi, B, 1, 1))
           ELSE empty_seq
           ENDIF
           IMPLIES
           (FORALL (i: nat):
              i >= empty_seq[real]`length IMPLIES
               empty_seq[real]`seq(i) = default[real]));

  % Subtype TCC generated (at line 113, column 4) for
      % sort(LET fs2: (gs_fseq?) =
      %            IF sqv(s) >= sq(D)
      %              THEN gs_critical(gs_line_eps(s, vo, vi, -1)) o
      %                    gs_critical(gs_line_eps(s, vo, vi, 1))
      %                    o
      %                    gs_critical(gs_only_circle(s, vo, vi, T, -1, -1))
      %                    o gs_critical(gs_only_circle(s, vo, vi, T, -1, 1))
      %            ELSE empty_seq
      %            ENDIF,
      %          fs3: (gs_fseq?) =
      %            IF B > 0
      %              THEN gs_critical(gs_only_circle(s, vo, vi, B, 1, -1)) o
      %                    gs_critical(gs_only_circle(s, vo, vi, B, 1, 1))
      %            ELSE empty_seq
      %            ENDIF
      %        IN
      %        (fs2 o fs3) o
      %         (addend(gsmin, empty_seq) o addend(gsmax, empty_seq)))
      % expected type  {fs: (gs_fseq?) | increasing?(fs)}
  gs_bands_TCC4: OBLIGATION
    FORALL (s: Vect2, vo: Nz_vect2, vi: Nz_vect2):
      gs_fseq?[gsmin, gsmax]
          (sort[real, <=]
               (LET fs2: (gs_fseq?[gsmin, gsmax]) =
                      IF sqv(s) >= sq(D)
                        THEN o[real]
                                 (o[real]
                                      (o[real]
                                       (gs_critical
                                        (gs_line_eps[D](s, vo, vi, -1)),
                                        gs_critical
                                        (gs_line_eps[D](s, vo, vi, 1))),
                                       gs_critical
                                       (gs_only_circle[D]
                                        (s, vo, vi, T, -1, -1))),
                                  gs_critical(gs_only_circle[D]
                                              (s, vo, vi, T, -1, 1)))
                      ELSE empty_seq[real]
                      ENDIF,
                    fs3: (gs_fseq?[gsmin, gsmax]) =
                      IF B > 0
                        THEN o[real]
                                 (gs_critical(gs_only_circle[D]
                                              (s, vo, vi, B, 1, -1)),
                                  gs_critical(gs_only_circle[D]
                                              (s, vo, vi, B, 1, 1)))
                      ELSE empty_seq[real]
                      ENDIF
                  IN
                  o[real]
                      ((o[real](fs2, fs3)),
                       (o[real]
                            (addend[real](gsmin, empty_seq[real]),
                             addend[real](gsmax, empty_seq[real]))))))
       AND
       increasing?[real, <=]
           (sort[real, <=]
                (LET fs2: (gs_fseq?[gsmin, gsmax]) =
                       IF sqv(s) >= sq(D)
                         THEN o[real]
                                  (o[real]
                                       (o[real]
                                        (gs_critical
                                         (gs_line_eps[D](s, vo, vi, -1)),
                                         gs_critical
                                         (gs_line_eps[D](s, vo, vi, 1))),
                                        gs_critical
                                        (gs_only_circle[D]
                                         (s, vo, vi, T, -1, -1))),
                                   gs_critical(gs_only_circle[D]
                                               (s, vo, vi, T, -1, 1)))
                       ELSE empty_seq[real]
                       ENDIF,
                     fs3: (gs_fseq?[gsmin, gsmax]) =
                       IF B > 0
                         THEN o[real]
                                  (gs_critical(gs_only_circle[D]
                                               (s, vo, vi, B, 1, -1)),
                                   gs_critical(gs_only_circle[D]
                                               (s, vo, vi, B, 1, 1)))
                       ELSE empty_seq[real]
                       ENDIF
                   IN
                   o[real]
                       ((o[real](fs2, fs3)),
                        (o[real]
                             (addend[real](gsmin, empty_seq[real]),
                              addend[real](gsmax, empty_seq[real]))))));

  % Subtype TCC generated (at line 139, column 28) for  gsp
      % expected type  posreal
  gs_bands_critical_TCC1: OBLIGATION
    FORALL (gsp: {r: real | gsmin <= r AND r <= gsmax}): gsp >= 0 AND gsp > 0;

  % Subtype TCC generated (at line 147, column 23) for  i
      % expected type  nat
  red_trk_band?_TCC1: OBLIGATION
    FORALL (vo: Nz_vect2, vi: Nz_vect2, trkb: (trk_fseq?[gsmin, gsmax]),
            i: subrange(0, trkb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 147, column 35) for  i + 1
      % expected type  nat
  red_trk_band?_TCC2: OBLIGATION
    FORALL (vo: Nz_vect2, vi: Nz_vect2, trkb: (trk_fseq?[gsmin, gsmax]),
            i: subrange(0, trkb`length - 2)):
      i + 1 >= 0;

  % Subtype TCC generated (at line 167, column 22) for  i
      % expected type  nat
  red_gs_band?_TCC1: OBLIGATION
    FORALL (vo: Nz_vect2, vi: Nz_vect2, gsb: (gs_fseq?[gsmin, gsmax]),
            i: subrange(0, gsb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 167, column 33) for  i + 1
      % expected type  nat
  red_gs_band?_TCC2: OBLIGATION
    FORALL (vo: Nz_vect2, vi: Nz_vect2, gsb: (gs_fseq?[gsmin, gsmax]),
            i: subrange(0, gsb`length - 2)):
      i + 1 >= 0;


body:
  bands_3D[D,H:posreal,B:nnreal,T:{x:posreal | x > B},
           gsmin:posreal,gsmax:{x:posreal | x > gsmin},
           vsmin:real,vsmax:{x:real | x > vsmin}] : THEORY
  BEGIN
    
    IMPORTING bands_2D,
    	    bands_1D,
  	    cd3d[D,H,B,T],
              bands_util

    s	  : VAR Vect3
    vo,vi   : VAR Nzv2_vect3
    trkb    : VAR (trk_fseq?[gsmin,gsmax])
    gsb     : VAR (gs_fseq?[gsmin,gsmax])
    vsb	  : VAR (vs_fseq?[vsmin,vsmax])
    x,k,y   : VAR real
    trk	  : VAR nnreal_lt_2pi
    trk2	  : VAR {r: real | 0<=r AND r<=2*pi}
    gsp	  : VAR {r: real | gsmin<=r AND r<=gsmax}
    vsp	  : VAR {r: real | vsmin<=r AND r<=vsmax}

    %-------------%
    % Definitions %
    %-------------%

    % Track %

  %  trk2v3(vo)(trkz:real) : (trk_only_3D?(vo)) =
  %    trkgs2vect(trkz,norm(vect2(vo))) WITH [z |-> vo`z] 

  %  vect2_trk2v3 : LEMMA
  %    vect2(trk2v3(vo)(trk)) = trk2v2[D,B,T](vo)(trk)

  %  trk2v3_Nzv : JUDGEMENT
  %    trk2v3(vo)(trk) HAS_TYPE Nzv2_vect3

  %  Vtrk_3D(vo,vi)(trkz:real):(horizontal_only?(vo-vi)) =
  %    trk2v3(vo)(trkz) - vi

  %  trk2v3_trk2v3 : LEMMA
  %    trk2v3(trk2v3(vo)(trk))(trk)=trk2v3(vo)(trk)

  %  trk2v3_0 : LEMMA
  %    vect2(vo) /= zero AND x >= 0 AND x < 2 * pi IMPLIES vect2(trk2v3(vo)(x)) /= zero

    % Ground Speed %

  %  gs2v3(vo)(k) : Vect3 = gs2v2[D,B,T](vo)(k) WITH [z |-> vo`z]

  %  gs2v3_gs_only : JUDGEMENT
  %    gs2v3(vo)(gsp) HAS_TYPE (gs_only_3D?(vo))

  %  vect2_gs2v3 : LEMMA
  %    vect2(gs2v3(vo)(gsp)) = gs2v2[D,B,T](vo)(gsp)

  %  Vgs_3D(vo,vi)(k) : (horizontal_only?(vo-vi)) = 
  %    gs2v3(vo)(k)-vi

    % Vertical Speed %

  %  vs2v3(vo)(vsp) : (vs_only?(vo)) = vo WITH [z := vsp]

  %  vect2_vs2v3 : LEMMA
  %    vect2(vs2v3(vo)(vsp)) = vect2(vo)

  %  Vs(vo,vi)(vsp) : (vs_only?(vo-vi)) = 
  %    vs2v3(vo)(vsp)-vi

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

    trk_bands_3D(s,vo,vi) : {fs : (trk_fseq?[gsmin,gsmax]) | increasing?(fs)} =
      IF vo`z = vi`z AND abs(s`z) < H
         THEN trk_bands[D,B,T,gsmin,gsmax](s,vo,vi)
      ELSIF vo`z /= vi`z THEN
        LET BB = max(Theta_H(s`z,vo`z-vi`z,Entry),B),
            TT = min(Theta_H(s`z,vo`z-vi`z,Exit),T) IN
   	  IF BB < TT THEN trk_bands[D,BB,TT,gsmin,gsmax](s,vo,vi)
            ELSE add(0,add(2*pi,emptyseq))
            ENDIF
      ELSE
       add(0,add(2*pi,emptyseq))
      ENDIF

    gs_bands_3D(s,vo,vi) : {fs : (gs_fseq?[gsmin,gsmax]) | increasing?(fs)} =
      IF vo`z = vi`z AND abs(s`z) < H
         THEN gs_bands[D,B,T,gsmin,gsmax](s,vo,vi)
      ELSIF vo`z /= vi`z THEN
        LET BB = max(Theta_H(s`z,vo`z-vi`z,Entry),B),
            TT = min(Theta_H(s`z,vo`z-vi`z,Exit),T) IN
   	  IF BB < TT THEN gs_bands[D,BB,TT,gsmin,gsmax](s,vo,vi)
            ELSE add(gsmin,add(gsmax,emptyseq))
            ENDIF
      ELSE
       add(gsmin,add(gsmax,emptyseq))
      ENDIF

    vs_bands_3D(s,vo,vi) : {fs : (vs_fseq?[vsmin,vsmax]) | increasing?(fs)} =
      IF vect2(vo-vi) = zero AND sqv(vect2(s)) < sq(D)
         THEN vs_bands[H,B,T,vsmin,vsmax](s`z,vi`z)
      ELSIF Delta(s,vo-vi) > 0 THEN
        LET BB = max(Theta_D(s,vo-vi,Entry),B),
            TT = min(Theta_D(s,vo-vi,Exit),T) IN
  	  IF BB < TT THEN vs_bands[H,BB,TT,vsmin,vsmax](s`z,vi`z)
  	  ELSE add(vsmin,add(vsmax,emptyseq))
  	  ENDIF
     ELSE
       add(vsmin,add(vsmax,emptyseq))
     ENDIF

    trk_bands_3D_not_empty : LEMMA
      trk_bands_3D(s,vo,vi)`length > 1

    trk_bands_last: LEMMA LET trkb = trk_bands_3D(s,vo,vi) IN
      trkb`seq(trkb`length-1) = 2*pi

    trk_bands_first: LEMMA LET trkb = trk_bands_3D(s,vo,vi) IN
      trkb`seq(0) = 0

    gs_bands_3D_not_empty : LEMMA
      gs_bands_3D(s,vo,vi)`length > 1

    gs_bands_last: LEMMA LET gsb = gs_bands_3D(s,vo,vi) IN
      gsb`seq(gsb`length-1) = gsmax

    gs_bands_first: LEMMA LET gsb = gs_bands_3D(s,vo,vi) IN
      gsb`seq(0) = gsmin

    vs_bands_3D_not_empty : LEMMA
      vs_bands_3D(s,vo,vi)`length > 1

    vs_bands_last: LEMMA LET vsb = vs_bands_3D(s,vo,vi) IN
      vsb`seq(vsb`length-1) = vsmax

    vs_bands_first: LEMMA LET vsb = vs_bands_3D(s,vo,vi) IN
      vsb`seq(0) = vsmin

    %-------------%
    % Definitions %
    %-------------%

    red_trk_band_3D?(s,vo,vi,trkb)(i:subrange(0,trkb`length-2)) : bool =
      LET mp = (trkb`seq(i)+trkb`seq(i+1))/2 in
      cd3d?(s,Vtrk_3D(vo,vi)(mp))

    red_gs_band_3D?(s,vo,vi,gsb)(i:subrange(0,gsb`length-2)) : bool =
      LET mp = (gsb`seq(i)+gsb`seq(i+1))/2 in
      cd3d?(s,Vgs_3D(vo,vi)(mp))  

    red_vs_band_3D?(s,vo,vi,vsb)(i:subrange(0,vsb`length-2)) : bool =
      LET mp = (vsb`seq(i)+vsb`seq(i+1))/2 in
      cd3d?(s,Vs(vo,vi)(mp))  

    %-------------%
    % THEOREMS    %
    %-------------%

    % Track %

    trk_red_bands_3D : THEOREM
      LET trkb = trk_bands_3D(s,vo,vi) IN
       FORALL (i:subrange(0,trkb`length-2) | trkb`seq(i) /= trkb`seq(i+1)) : 
         red_trk_band_3D?(s,vo,vi,trkb)(i) IFF
         (FORALL (x | trkb`seq(i) < x AND x < trkb`seq(i+1)):
           conflict_3D?(s,Vtrk_3D(vo,vi)(x)))

    trk_green_bands_3D : THEOREM
      LET trkb = trk_bands_3D(s,vo,vi) IN
       FORALL (i:subrange(0,trkb`length-2) | trkb`seq(i) /= trkb`seq(i+1)) : 
         NOT red_trk_band_3D?(s,vo,vi,trkb)(i) IFF
         (FORALL (x | trkb`seq(i) < x AND x < trkb`seq(i+1)):
           NOT conflict_3D?(s,Vtrk_3D(vo,vi)(x)))

    trk_bands_equivalence: LEMMA
       LET trkb = trk_bands_3D(s,vo,vi) IN
         FORALL (x,y): (0<=x AND x<=y AND y<=2*pi AND
           (FORALL (i:subrange(0,trkb`length-1)): trkb`seq(i)<x OR y<trkb`seq(i)))
  	 IMPLIES
           (conflict_3D?(s,Vtrk_3D(vo,vi)(x)) IFF conflict_3D?(s,Vtrk_3D(vo,vi)(y)))

    % Ground Speed %

    gs_red_bands_3D : THEOREM
      LET gsb = gs_bands_3D(s,vo,vi) IN
       FORALL (i:subrange(0,gsb`length-2) | gsb`seq(i) /= gsb`seq(i+1)) :  
         red_gs_band_3D?(s,vo,vi,gsb)(i) IFF
         (FORALL (x | gsb`seq(i) < x AND x < gsb`seq(i+1)):
           conflict_3D?(s,Vgs_3D(vo,vi)(x)))

    gs_green_bands_3D : THEOREM
      LET gsb = gs_bands_3D(s,vo,vi) IN
       FORALL (i:subrange(0,gsb`length-2) | gsb`seq(i) /= gsb`seq(i+1)) :  
         NOT red_gs_band_3D?(s,vo,vi,gsb)(i) IFF
         (FORALL (x | gsb`seq(i) < x AND x < gsb`seq(i+1)):
           NOT conflict_3D?(s,Vgs_3D(vo,vi)(x)))

    gs_bands_equivalence: LEMMA
       LET gsb = gs_bands_3D(s,vo,vi) IN
         FORALL (x,y): (gsmin<=x AND x<=y AND y<=gsmax AND
           (FORALL (i:subrange(0,gsb`length-1)): gsb`seq(i)<x OR y<gsb`seq(i)))
  	 IMPLIES
           (conflict_3D?(s,Vgs_3D(vo,vi)(x)) IFF conflict_3D?(s,Vgs_3D(vo,vi)(y)))

    % Vertical Seed %

    vs_red_bands_3D : THEOREM
      LET vsb = vs_bands_3D(s,vo,vi) IN
       FORALL (i:subrange(0,vsb`length-2) | vsb`seq(i) /= vsb`seq(i+1)) : 
         red_vs_band_3D?(s,vo,vi,vsb)(i) IFF
         (FORALL (x | vsb`seq(i) < x AND x < vsb`seq(i+1)):
           conflict_3D?(s,Vs(vo,vi)(x)))

    vs_green_bands_3D : THEOREM
      LET vsb = vs_bands_3D(s,vo,vi) IN
       FORALL (i:subrange(0,vsb`length-2) | vsb`seq(i) /= vsb`seq(i+1)) : 
         NOT red_vs_band_3D?(s,vo,vi,vsb)(i) IFF
         (FORALL (x | vsb`seq(i) < x AND x < vsb`seq(i+1)):
           NOT conflict_3D?(s,Vs(vo,vi)(x)))

    vs_bands_equivalence: LEMMA
       LET vsb = vs_bands_3D(s,vo,vi) IN
         FORALL (x,y): (vsmin<=x AND x<=y AND y<=vsmax AND
           (FORALL (i:subrange(0,vsb`length-1)): vsb`seq(i)<x OR y<vsb`seq(i)))
  	 IMPLIES
           (conflict_3D?(s,Vs(vo,vi)(x)) IFF conflict_3D?(s,Vs(vo,vi)(y)))

  END bands_3D

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

  % Assuming TCC generated (at line 5, column 4) for
      % bands_2D[D, B, T, gsmin, gsmax]
      % generated from assumption bands_2D.gs_min_lt_max
  trk_bands_3D_TCC1: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z = vi`z AND abs(s`z) < H IMPLIES gsmin < gsmax;

  % Subtype TCC generated (at line 77, column 31) for  vo`z - vi`z
      % expected type  nzreal
  trk_bands_3D_TCC2: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       vo`z - vi`z /= 0;

  % Subtype TCC generated (at line 79, column 32) for  BB
      % expected type  nnreal
  trk_bands_3D_TCC3: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_H[H](s`z, vo`z - vi`z, -1) AND
                            p >= B}):
          BB = max(Theta_H(s`z, vo`z - vi`z, -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_H[H](s`z, vo`z - vi`z, 1) AND
                                p <= T}):
              BB < TT AND TT = min(Theta_H(s`z, vo`z - vi`z, 1), T) IMPLIES
               BB >= 0));

  % Subtype TCC generated (at line 79, column 35) for  TT
      % expected type  {AB: posreal | AB > BB}
  trk_bands_3D_TCC4: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_H[H](s`z, vo`z - vi`z, -1) AND
                            p >= B}):
          BB = max(Theta_H(s`z, vo`z - vi`z, -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_H[H](s`z, vo`z - vi`z, 1) AND
                                p <= T}):
              BB < TT AND TT = min(Theta_H(s`z, vo`z - vi`z, 1), T) IMPLIES
               TT >= 0 AND TT > 0 AND TT > BB));

  % Assuming TCC generated (at line 5, column 4) for
      % bands_2D[D, BB, TT, gsmin, gsmax]
      % generated from assumption bands_2D.gs_min_lt_max
  trk_bands_3D_TCC5: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_H[H](s`z, vo`z - vi`z, -1) AND
                            p >= B}):
          BB = max(Theta_H(s`z, vo`z - vi`z, -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_H[H](s`z, vo`z - vi`z, 1) AND
                                p <= T}):
              BB < TT AND TT = min(Theta_H(s`z, vo`z - vi`z, 1), T) IMPLIES
               gsmin < gsmax));

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  fseq[real]
  trk_bands_3D_TCC6: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_H[H](s`z, vo`z - vi`z, -1) AND
                            p >= B}):
          BB = max(Theta_H(s`z, vo`z - vi`z, -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_H[H](s`z, vo`z - vi`z, 1) AND
                                p <= T}):
              NOT BB < TT AND TT = min(Theta_H(s`z, vo`z - vi`z, 1), T)
               IMPLIES
               (FORALL (i: nat):
                  i >= empty_seq[real]`length IMPLIES
                   empty_seq[real]`seq(i) = default[real])));

  % Subtype TCC generated (at line 80, column 15) for
      % add(0, add(2 * pi, empty_seq))
      % expected type  {fs: (trk_fseq?[gsmin, gsmax]) | increasing?(fs)}
  trk_bands_3D_TCC7: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_H[H](s`z, vo`z - vi`z, -1) AND
                            p >= B}):
          BB = max(Theta_H(s`z, vo`z - vi`z, -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_H[H](s`z, vo`z - vi`z, 1) AND
                                p <= T}):
              NOT BB < TT AND TT = min(Theta_H(s`z, vo`z - vi`z, 1), T)
               IMPLIES
               trk_fseq?[gsmin, gsmax]
                   (add[real](0, add[real](2 * pi, empty_seq[real])))
                AND
                increasing?[real, <=]
                    (add[real](0, add[real](2 * pi, empty_seq[real])))));

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  fseq[real]
  trk_bands_3D_TCC8: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      NOT vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       (FORALL (i: nat):
          i >= empty_seq[real]`length IMPLIES
           empty_seq[real]`seq(i) = default[real]);

  % Subtype TCC generated (at line 83, column 5) for
      % add(0, add(2 * pi, empty_seq))
      % expected type  {fs: (trk_fseq?[gsmin, gsmax]) | increasing?(fs)}
  trk_bands_3D_TCC9: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      NOT vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       trk_fseq?[gsmin, gsmax]
           (add[real](0, add[real](2 * pi, empty_seq[real])))
        AND
        increasing?[real, <=]
            (add[real](0, add[real](2 * pi, empty_seq[real])));

  % Subtype TCC generated (at line 93, column 15) for
      % add(gsmin, add(gsmax, empty_seq))
      % expected type  {fs: (gs_fseq?[gsmin, gsmax]) | increasing?(fs)}
  gs_bands_3D_TCC1: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_H[H](s`z, vo`z - vi`z, -1) AND
                            p >= B}):
          BB = max(Theta_H(s`z, vo`z - vi`z, -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_H[H](s`z, vo`z - vi`z, 1) AND
                                p <= T}):
              NOT BB < TT AND TT = min(Theta_H(s`z, vo`z - vi`z, 1), T)
               IMPLIES
               gs_fseq?[gsmin, gsmax]
                   (add[real](gsmin, add[real](gsmax, empty_seq[real])))
                AND
                increasing?[real, <=]
                    (add[real](gsmin, add[real](gsmax, empty_seq[real])))));

  % Subtype TCC generated (at line 96, column 5) for
      % add(gsmin, add(gsmax, empty_seq))
      % expected type  {fs: (gs_fseq?[gsmin, gsmax]) | increasing?(fs)}
  gs_bands_3D_TCC2: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      NOT vo`z /= vi`z AND NOT (vo`z = vi`z AND abs(s`z) < H) IMPLIES
       gs_fseq?[gsmin, gsmax]
           (add[real](gsmin, add[real](gsmax, empty_seq[real])))
        AND
        increasing?[real, <=]
            (add[real](gsmin, add[real](gsmax, empty_seq[real])));

  % Assuming TCC generated (at line 5, column 4) for
      % bands_1D[H, B, T, vsmin, vsmax]
      % generated from assumption bands_1D.vs_min_lt_max
  vs_bands_3D_TCC1: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D) IMPLIES vsmin < vsmax;

  % Subtype TCC generated (at line 103, column 29) for  vect2(vo - vi)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  vs_bands_3D_TCC2: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      Delta(vect2(s), vect2(vo - vi)) > 0 AND
       NOT (vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       vect2(vo - vi) /= zero AND Delta[D](vect2(s), vect2(vo - vi)) >= 0;

  % Subtype TCC generated (at line 105, column 30) for  BB
      % expected type  nnreal
  vs_bands_3D_TCC3: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      Delta(vect2(s), vect2(vo - vi)) > 0 AND
       NOT (vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_D[D](vect2(s), vect2(vo - vi), -1) AND
                            p >= B}):
          BB = max(Theta_D(vect2(s), vect2(vo - vi), -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_D[D](vect2(s), vect2(vo - vi), 1)
                                AND p <= T}):
              BB < TT AND TT = min(Theta_D(vect2(s), vect2(vo - vi), 1), T)
               IMPLIES BB >= 0));

  % Subtype TCC generated (at line 105, column 33) for  TT
      % expected type  {AB: posreal | AB > BB}
  vs_bands_3D_TCC4: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      Delta(vect2(s), vect2(vo - vi)) > 0 AND
       NOT (vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_D[D](vect2(s), vect2(vo - vi), -1) AND
                            p >= B}):
          BB = max(Theta_D(vect2(s), vect2(vo - vi), -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_D[D](vect2(s), vect2(vo - vi), 1)
                                AND p <= T}):
              BB < TT AND TT = min(Theta_D(vect2(s), vect2(vo - vi), 1), T)
               IMPLIES TT >= 0 AND TT > 0 AND TT > BB));

  % Assuming TCC generated (at line 5, column 4) for
      % bands_1D[H, BB, TT, vsmin, vsmax]
      % generated from assumption bands_1D.vs_min_lt_max
  vs_bands_3D_TCC5: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      Delta(vect2(s), vect2(vo - vi)) > 0 AND
       NOT (vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_D[D](vect2(s), vect2(vo - vi), -1) AND
                            p >= B}):
          BB = max(Theta_D(vect2(s), vect2(vo - vi), -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_D[D](vect2(s), vect2(vo - vi), 1)
                                AND p <= T}):
              BB < TT AND TT = min(Theta_D(vect2(s), vect2(vo - vi), 1), T)
               IMPLIES vsmin < vsmax));

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  fseq[real]
  vs_bands_3D_TCC6: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      Delta(vect2(s), vect2(vo - vi)) > 0 AND
       NOT (vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_D[D](vect2(s), vect2(vo - vi), -1) AND
                            p >= B}):
          BB = max(Theta_D(vect2(s), vect2(vo - vi), -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_D[D](vect2(s), vect2(vo - vi), 1)
                                AND p <= T}):
              NOT BB < TT AND
               TT = min(Theta_D(vect2(s), vect2(vo - vi), 1), T)
               IMPLIES
               (FORALL (i: nat):
                  i >= empty_seq[real]`length IMPLIES
                   empty_seq[real]`seq(i) = default[real])));

  % Subtype TCC generated (at line 106, column 8) for
      % add(vsmin, add(vsmax, empty_seq))
      % expected type  {fs: (vs_fseq?[vsmin, vsmax]) | increasing?(fs)}
  vs_bands_3D_TCC7: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      Delta(vect2(s), vect2(vo - vi)) > 0 AND
       NOT (vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (BB:
                  {p: real |
                           p >= Theta_D[D](vect2(s), vect2(vo - vi), -1) AND
                            p >= B}):
          BB = max(Theta_D(vect2(s), vect2(vo - vi), -1), B) IMPLIES
           (FORALL (TT:
                      {p: real |
                               p <= Theta_D[D](vect2(s), vect2(vo - vi), 1)
                                AND p <= T}):
              NOT BB < TT AND
               TT = min(Theta_D(vect2(s), vect2(vo - vi), 1), T)
               IMPLIES
               vs_fseq?[vsmin, vsmax]
                   (add[real](vsmin, add[real](vsmax, empty_seq[real])))
                AND
                increasing?[real, <=]
                    (add[real](vsmin, add[real](vsmax, empty_seq[real])))));

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  fseq[real]
  vs_bands_3D_TCC8: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      NOT Delta(vect2(s), vect2(vo - vi)) > 0 AND
       NOT (vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       (FORALL (i: nat):
          i >= empty_seq[real]`length IMPLIES
           empty_seq[real]`seq(i) = default[real]);

  % Subtype TCC generated (at line 109, column 5) for
      % add(vsmin, add(vsmax, empty_seq))
      % expected type  {fs: (vs_fseq?[vsmin, vsmax]) | increasing?(fs)}
  vs_bands_3D_TCC9: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3):
      NOT Delta(vect2(s), vect2(vo - vi)) > 0 AND
       NOT (vect2(vo - vi) = zero AND sqv(vect2(s)) < sq(D))
       IMPLIES
       vs_fseq?[vsmin, vsmax]
           (add[real](vsmin, add[real](vsmax, empty_seq[real])))
        AND
        increasing?[real, <=]
            (add[real](vsmin, add[real](vsmax, empty_seq[real])));

  % Subtype TCC generated (at line 116, column 13) for  trkb`length - 1
      % expected type  nat
  trk_bands_last_TCC1: OBLIGATION
    FORALL (s: Vect3, vi, vo: Nzv2_vect3,
            trkb:
              {fs: (trk_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)}):
      trkb = trk_bands_3D(s, vo, vi) IMPLIES trkb`length - 1 >= 0;

  % Subtype TCC generated (at line 125, column 12) for  gsb`length - 1
      % expected type  nat
  gs_bands_last_TCC1: OBLIGATION
    FORALL (s: Vect3, vi, vo: Nzv2_vect3,
            gsb: {fs: (gs_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)}):
      gsb = gs_bands_3D(s, vo, vi) IMPLIES gsb`length - 1 >= 0;

  % Subtype TCC generated (at line 134, column 12) for  vsb`length - 1
      % expected type  nat
  vs_bands_last_TCC1: OBLIGATION
    FORALL (s: Vect3, vi, vo: Nzv2_vect3,
            vsb: {fs: (vs_fseq?[vsmin, vsmax]) | increasing?[real, <=](fs)}):
      vsb = vs_bands_3D(s, vo, vi) IMPLIES vsb`length - 1 >= 0;

  % Subtype TCC generated (at line 144, column 23) for  i
      % expected type  nat
  red_trk_band_3D?_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3, trkb: (trk_fseq?[gsmin, gsmax]),
            i: subrange(0, trkb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 144, column 35) for  i + 1
      % expected type  nat
  red_trk_band_3D?_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3, trkb: (trk_fseq?[gsmin, gsmax]),
            i: subrange(0, trkb`length - 2)):
      i + 1 >= 0;

  % Subtype TCC generated (at line 148, column 22) for  i
      % expected type  nat
  red_gs_band_3D?_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3, gsb: (gs_fseq?[gsmin, gsmax]),
            i: subrange(0, gsb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 148, column 33) for  i + 1
      % expected type  nat
  red_gs_band_3D?_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3, gsb: (gs_fseq?[gsmin, gsmax]),
            i: subrange(0, gsb`length - 2)):
      i + 1 >= 0;

  % Subtype TCC generated (at line 152, column 22) for  i
      % expected type  nat
  red_vs_band_3D?_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3, vsb: (vs_fseq?[vsmin, vsmax]),
            i: subrange(0, vsb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 152, column 33) for  i + 1
      % expected type  nat
  red_vs_band_3D?_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3, vsb: (vs_fseq?[vsmin, vsmax]),
            i: subrange(0, vsb`length - 2)):
      i + 1 >= 0;

  % Subtype TCC generated (at line 178, column 57) for  i
      % expected type  nat
  trk_bands_equivalence_TCC1: OBLIGATION
    FORALL (s: Vect3, vi, vo: Nzv2_vect3,
            trkb:
              {fs: (trk_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)}):
      trkb = trk_bands_3D(s, vo, vi) IMPLIES
       (FORALL (x: real, y: real):
          y <= 2 * pi AND x <= y AND 0 <= x IMPLIES
           (FORALL (i: subrange(0, trkb`length - 1)): i >= 0));

  % Subtype TCC generated (at line 201, column 55) for  i
      % expected type  nat
  gs_bands_equivalence_TCC1: OBLIGATION
    FORALL (s: Vect3, vi, vo: Nzv2_vect3,
            gsb: {fs: (gs_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)}):
      gsb = gs_bands_3D(s, vo, vi) IMPLIES
       (FORALL (x: real, y: real):
          y <= gsmax AND x <= y AND gsmin <= x IMPLIES
           (FORALL (i: subrange(0, gsb`length - 1)): i >= 0));

  % Subtype TCC generated (at line 224, column 55) for  i
      % expected type  nat
  vs_bands_equivalence_TCC1: OBLIGATION
    FORALL (s: Vect3, vi, vo: Nzv2_vect3,
            vsb: {fs: (vs_fseq?[vsmin, vsmax]) | increasing?[real, <=](fs)}):
      vsb = vs_bands_3D(s, vo, vi) IMPLIES
       (FORALL (x: real, y: real):
          y <= vsmax AND x <= y AND vsmin <= x IMPLIES
           (FORALL (i: subrange(0, vsb`length - 1)): i >= 0));


body:
  flightplan[N:above[1]]  : THEORY 
  BEGIN

     IMPORTING definitions_3D,
               finite_sets@finite_sets_minmax

    k,i,ki	  : VAR below[N]
    j		  : VAR below[N-1]

    % The following type is a flight plan. It consists of pairs (t (time),p (position)), where t is a time and 
    % p is a vector. At the corresponding segement of the flight plan, the aircraft will have 
    % position p at time t.
    % Times are strictly increasing, but may be negative.
    FlightPlan: TYPE+ = {fp: [below[N] -> [# time: real,position: Vect3 #]] | 
    	      	      FORALL (i: below[N]): i-1 >= 0 IMPLIES fp(i)`time > fp(i-1)`time}

    flp: VAR FlightPlan

    start_time(flp): real = flp(0)`time

    end_time(flp): real = flp(N-1)`time

    %%%%%%%%% < over flightplan times is transitive  
    flight_plan_ascending_time: LEMMA
      k < i IMPLIES flp(k)`time < flp(i)`time

    flight_plan_unique_times: LEMMA
      flp(k)`time = flp(i)`time IFF k=i

    % the times that the flightplan covers (range)
    FlightTimes(flp): TYPE+ ={a: real | start_time(flp) <= a AND a <= end_time(flp)}

    % the velocity after leaving the k-th waypoint and on the way to the k+1-st waypoint
    velocity(flp: FlightPlan)(j: below[N-1]): Vect3 = 
      		(1/(flp(j+1)`time-flp(j)`time))*(flp(j+1)`position - flp(j)`position)


    velocity_def: LEMMA 
    		flp(j)`position + (flp(j+1)`time-flp(j)`time)*velocity(flp)(j) = flp(j+1)`position


    % bands require that flightplans have nonzero horizontal velocities
    FlightPlan_nz: TYPE+ = {flp: FlightPlan | FORALL(i:below[N-1]): nz_vect2?(velocity(flp)(i))}


    segment_max: [SS: non_empty_finite_set[nat] -> {a: nat | SS(a) AND (FORALL (x: nat): SS(x) IMPLIES x <= a)}] =
    	       finite_sets@finite_sets_minmax[naturalnumbers.nat,restrict[[real, real], [nat, nat], boolean].restrict(reals.<=)].max

    % Lookup of the flightplan segment index, given a time
    segment(flp: FlightPlan)(tt: FlightTimes(flp)): below[N] = segment_max({j: below[N] | tt >= flp(j)`time})

    % time tt is either between two indices or after the last one
    segment_def: LEMMA 
    	       FORALL (tt: FlightTimes(flp)):
    	       flp(segment(flp)(tt))`time <= tt AND 
  	       (segment(flp)(tt) < N-1 IMPLIES tt < flp(segment(flp)(tt) + 1)`time)

    % if we have index bounds on the time, we have the segment
    segment_index: LEMMA
      FORALL (tt:FlightTimes(flp)):
      flp(j)`time <= tt AND tt < flp(j+1)`time IFF segment(flp)(tt) = j

    segment_max : LEMMA
      FORALL (tt:FlightTimes(flp)): segment(flp)(tt) = N-1 IFF tt = flp(N-1)`time

    segment_ident : LEMMA
      FORALL (tt:FlightTimes(flp)):segment(flp)(flp(segment(flp)(tt))`time) = segment(flp)(tt)

    % the position at a given time tt in the flightplan
    location_at(flp)(tt: FlightTimes(flp)): Vect3 = 
      Let seg = segment(flp)(tt) IN
        IF seg = N-1 THEN flp(N-1)`position
        ELSE
          flp(seg)`position + (tt - flp(seg)`time)*velocity(flp)(seg)
        ENDIF


    location_at_check: LEMMA
      location_at(flp)(flp(k)`time) = flp(k)`position

  END flightplan

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

  % Subtype TCC generated (at line 8, column 13) for  below[N - 1]
      % expected type  nat
  j_TCC1: OBLIGATION N - 1 >= 0;

  % Subtype TCC generated (at line 15, column 71) for  i - 1
      % expected type  below[N]
  FlightPlan_TCC1: OBLIGATION
    FORALL (i: below[N]): i - 1 >= 0 IMPLIES i - 1 < N;

  % Existence TCC generated (at line 14, column 2) for
      % FlightPlan: TYPE+ =
      %       {fp: [below[N] -> [# time: real, position: Vect3 #]] |
      %                FORALL (i: below[N]):
      %                  i - 1 >= 0 IMPLIES fp(i)`time > fp(i - 1)`time}
  FlightPlan_TCC2: OBLIGATION
    EXISTS (x:
              {fp: [below[N] -> [# position: Vect3, time: real #]] |
                       FORALL (i: below[N]):
                         i - 1 >= 0 IMPLIES fp(i)`time > fp(i - 1)`time}):
      TRUE;

  % Subtype TCC generated (at line 19, column 30) for  0
      % expected type  below[N]
  start_time_TCC1: OBLIGATION 0 < N;

  % Subtype TCC generated (at line 21, column 28) for  N - 1
      % expected type  below[N]
  end_time_TCC1: OBLIGATION N - 1 >= 0 AND N - 1 < N;

  % Existence TCC generated (at line 31, column 2) for
      % FlightTimes(flp): TYPE+ =
      %       {a: real | start_time(flp) <= a AND a <= end_time(flp)}
  FlightTimes_TCC1: OBLIGATION
    FORALL (flp: FlightPlan):
      EXISTS (x: {a: real | start_time(flp) <= a AND a <= end_time(flp)}):
        TRUE;

  % Subtype TCC generated (at line 35, column 14) for  j + 1
      % expected type  below[N]
  velocity_TCC1: OBLIGATION FORALL (j: below[N - 1]): j + 1 < N;

  % Subtype TCC generated (at line 35, column 28) for  j
      % expected type  below[N]
  velocity_TCC2: OBLIGATION FORALL (j: below[N - 1]): j < N;

  % Subtype TCC generated (at line 35, column 10) for
      % (flp(j + 1)`time - flp(j)`time)
      % expected type  nznum
  velocity_TCC3: OBLIGATION
    FORALL (flp: FlightPlan, j: below[N - 1]):
      (flp(j + 1)`time - flp(j)`time) /= 0;

  % Existence TCC generated (at line 43, column 2) for
      % FlightPlan_nz: TYPE+ =
      %       {flp: FlightPlan |
      %                FORALL (i: below[N - 1]):
      %                  vect2(velocity(flp)(i)) /= zero}
  FlightPlan_nz_TCC1: OBLIGATION
    EXISTS (x:
              {flp: FlightPlan |
                       FORALL (i: below[N - 1]):
                         vect2(velocity(flp)(i)) /= zero}):
      TRUE;

  % Subtype TCC generated (at line 47, column 10) for
      % finite_sets@finite_sets_minmax
      %     [naturalnumbers.nat,
      %      restrict[[real, real], [nat, nat], boolean].restrict
      %          (reals.<=)].max
      % expected type  [SS: non_empty_finite_set[nat] ->
                     %    {a: nat |
                     %             SS(a) AND
                     %              (FORALL (x: nat): SS(x) IMPLIES x <= a)}]
  segment_max_TCC1: OBLIGATION
    FORALL (x1: non_empty_finite_set[naturalnumbers.nat]):
      x1(finite_sets@finite_sets_minmax
             [naturalnumbers.nat,
              restrict[[real, real], [nat, nat], boolean].restrict
                  (reals.<=)].max
             (x1))
       AND
       (FORALL (x: nat):
          x1(x) IMPLIES
           x <=
            finite_sets@finite_sets_minmax
                [naturalnumbers.nat,
                 restrict[[real, real], [nat, nat], boolean].restrict
                     (reals.<=)].max
                (x1));

  % Subtype TCC generated (at line 50, column 73) for
      % extend[nat, below[N], bool, FALSE]({j: below[N] | tt >= flp(j)`time})
      % expected type  SS: non_empty_finite_set[nat]
  segment_TCC1: OBLIGATION
    FORALL (flp: FlightPlan, tt: FlightTimes(flp)):
      is_finite[nat]
          (extend[nat, below[N], bool, FALSE]
               ({j: below[N] | tt >= flp(j)`time}))
       AND
       NOT empty?[nat]
               (extend[nat, below[N], bool, FALSE]
                    ({j: below[N] | tt >= flp(j)`time}));

  % Subtype TCC generated (at line 50, column 61) for
      % segment_max(extend[nat, below[N], bool, FALSE]
      %                 ({j: below[N] | tt >= flp(j)`time}))
      % expected type  below[N]
  segment_TCC2: OBLIGATION
    FORALL (flp: FlightPlan, tt: FlightTimes(flp)):
      segment_max(extend[nat, below[N], bool, FALSE]
                      ({j: below[N] | tt >= flp(j)`time}))
       < N;

  % Subtype TCC generated (at line 56, column 49) for  segment(flp)(tt) + 1
      % expected type  below[N]
  segment_def_TCC1: OBLIGATION
    FORALL (flp: FlightPlan, tt: FlightTimes(flp)):
      segment(flp)(tt) < N - 1 AND flp(segment(flp)(tt))`time <= tt IMPLIES
       segment(flp)(tt) + 1 < N;

  % Subtype TCC generated (at line 67, column 46) for
      % flp(segment(flp)(tt))`time
      % expected type  FlightTimes(flp)
  segment_ident_TCC1: OBLIGATION
    FORALL (flp: FlightPlan, tt: FlightTimes(flp)):
      start_time(flp) <= flp(segment(flp)(tt))`time AND
       flp(segment(flp)(tt))`time <= end_time(flp);

  % Subtype TCC generated (at line 74, column 63) for  seg
      % expected type  below[N - 1]
  location_at_TCC1: OBLIGATION
    FORALL (flp: FlightPlan, tt: FlightTimes(flp), seg: below[N]):
      NOT seg = N - 1 AND seg = segment(flp)(tt) IMPLIES seg < N - 1;

  % Subtype TCC generated (at line 79, column 21) for  flp(k)`time
      % expected type  FlightTimes(flp)
  location_at_check_TCC1: OBLIGATION
    FORALL (flp: FlightPlan, k: below[N]):
      start_time(flp) <= flp(k)`time AND flp(k)`time <= end_time(flp);


body:
  cd3d_si[D,H:posreal,B:nnreal,T: {AB: posreal|AB>B},N:above[1]]  : THEORY 
  BEGIN

    IMPORTING cd3d,
              flightplan[N]

    s,v,vo,vi,so,si : VAR Vect3       
    k,i,ki	  : VAR below[N]
    j		  : VAR below[N-1]
    to		  : VAR real

    % The following type is a flight plan. It consists of pairs (t (time),p (position)), where t is a time and 
    % p is a vector. At the corresponding segement of the flight plan, the aircraft will have 
    % position p at time t.
    % Times are strictly increasing, but may be negative.

    % A flightplan where there is some actual overlap with the lookahead range [B+to,T+to]
    FlightPlanRelevant(to): TYPE+ = {flp: FlightPlan | flp(0)`time < to+T AND to+B < flp(N-1)`time}


    flp: VAR FlightPlan

    % sequence of all times listed in a flightplan that overlap wth the lookahead range
    FlightTimesRelevant(to,flp): TYPE = {aa: FlightTimes(flp) | to+B <= aa AND aa <= to+T}

    % Conflict
    
    % There exists a conflict (at time tt)
    % so, vo are position & velocity at time to
    conflict_3D?(so,to,vo,flp): bool =
      EXISTS (tt: FlightTimesRelevant(to,flp)): 
  			   horizontal_los?[D]((so + (tt-to)*vo) - location_at(flp)(tt)) AND
  			   vertical_los?[H](so`z + (tt-to)*vo`z - location_at(flp)(tt)`z)

    % returns the time from beginning of segment to the end of the time range of interest
    % the (relative) segment lookahead end time
    % a negative result indicates the segment starts after the lookahead time
    seg_lh_top(flp,to)(j: below[N-1]): real = min(flp(j+1)`time,to+T)-flp(j)`time

    % returns the time from beginning of segment to the start of the time range of interest
    % the (relative) segment lookahead start time
    % a time > flp(j+1)`time indicates the segment ends before the lookahead range starts
    seg_lh_bottom(flp,to)(j: below[N-1]): nnreal = max(flp(j)`time,to+B)-flp(j)`time

    % if the segment lookahead start time < the segment lookahead end time, the seg lookahead end time will be positive
    seg_lh_top_positive: LEMMA FORALL (j:below[N-1],to:real,flpl:FlightPlanRelevant(to)): 
    		       seg_lh_bottom(flpl,to)(j) < seg_lh_top(flpl,to)(j) IMPLIES seg_lh_top(flpl,to)(j)>0


    % returns the flightplan position at which the lookahead range starts
    lh_start_position(flp,to)(j: below[N-1]): Vect3 = 
      flp(j)`position + (seg_lh_bottom(flp,to)(j)-flp(j)`time)*velocity(flp)(j)


    % for a relevant flightplan, if a segment k's start time is within the lookahead range, then either
    % seg_lh_top > seg_lh_bottom for k (if T+to > k`time) or k-1 (if T+to = k`time)
    nontrivial_lookahead: 
      LEMMA FORALL (k: below[N],to:real,flpl:FlightPlanRelevant(to)): 
                          to+B<=flpl(k)`time AND flpl(k)`time<=to+T
       	     	 	  IMPLIES
  			    (k<N-1 AND seg_lh_top(flpl,to)(k) - seg_lh_bottom(flpl,to)(k) > 0) OR  % k < N-1
        	     	 	    (k > 0 AND seg_lh_top(flpl,to)(k-1) - seg_lh_bottom(flpl,to)(k-1) > 0) % k can equal N-1

    % There is a conflict IFF there exists some segment j where you have a conflict.
    conflict_3D_rew: LEMMA
      FORALL (so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to)):
      conflict_3D?(so,to,vo,flpl) IFF
      EXISTS (j: below[N-1]): 
      (seg_lh_bottom(flpl,to)(j) < seg_lh_top(flpl,to)(j)
      AND
      conflict_3D?[D,H,seg_lh_bottom(flpl,to)(j),seg_lh_top(flpl,to)(j)]((so + (flpl(j)`time-to)*vo)-flpl(j)`position,vo-velocity(flpl)(j)))

    conflict_3D_flightplan_open_interval: LEMMA
      FORALL (so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to)):
      conflict_3D?(so,to,vo,flpl) IFF
      (EXISTS (tt: FlightTimesRelevant(to,flpl)):
          to+B < tt AND tt<to+T AND tt < flpl(N-1)`time AND
  	horizontal_los?[D]((so + (tt-to)*vo) - location_at(flpl)(tt)) AND
  	vertical_los?[H](so`z + (tt-to)*vo`z - location_at(flpl)(tt)`z))

    % There is a conflict IFF there exists some segment j where you have a conflict (uses absolute time)
    conflict_3D_rew_absolute_time: LEMMA
      FORALL (so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to)):
      conflict_3D?(so,to,vo,flpl) IFF
      EXISTS (j: below[N-1]): 
      LET
        lb = seg_lh_bottom(flpl,to)(j)+flpl(j)`time-to,
        ub = seg_lh_top(flpl,to)(j)+flpl(j)`time-to
      IN
      (lb < ub
      AND
      conflict_3D?[D,H,lb,ub](so - (flpl(j)`position - (flpl(j)`time-to)*velocity(flpl)(j)),vo-velocity(flpl)(j)))

    % conflict_3D inductive definition version
    cd3d_ind?(so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to))(j: below[N-1]): INDUCTIVE bool =
      (seg_lh_bottom(flpl,to)(j) < seg_lh_top(flpl,to)(j)
      AND
      cd3d?[D,H,seg_lh_bottom(flpl,to)(j),seg_lh_top(flpl,to)(j)]((so + (flpl(j)`time-to)*vo)-flpl(j)`position,vo-velocity(flpl)(j))) OR
      (j>0 AND cd3d_ind?(so,vo,to,flpl)(j-1))


    % conflict_3D based on inductive definition
    % algorithm that is equivalent to conflict_3D?
    cd3d_si?(so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to)): bool = cd3d_ind?(so,vo,to,flpl)(N-2)

    % if cd3d_ind says it is in conflict at or below some segement i, then there is a segment j<=i where 
    % conflict_3d? says it is in conflict
    cd3d_ind_correct: LEMMA 
      FORALL (so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to)):
      	   (FORALL (i: below[N-1]): cd3d_ind?(so,vo,to,flpl)(i) IMPLIES
      	   EXISTS (j: below[N-1]): 
  	   (j<=i AND seg_lh_bottom(flpl,to)(j) < seg_lh_top(flpl,to)(j) AND
  	   conflict_3D?[D,H,seg_lh_bottom(flpl,to)(j),seg_lh_top(flpl,to)(j)]
               ((so + (flpl(j)`time-to)*vo)-flpl(j)`position,vo-velocity(flpl)(j))))

    % if there is a segment j where conflict_3d? says it is in conflict, then cd3d_ind says it is in conflict at
    % segment i >= j 
    cd3d_ind_complete: LEMMA
      FORALL (so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to)):
      	   (FORALL (i: below[N-1]):
  	       	   (EXISTS (j: below[N-1]): 
  	   	   (j<=i AND seg_lh_bottom(flpl,to)(j) < seg_lh_top(flpl,to)(j) AND
  	   	   conflict_3D?[D,H,seg_lh_bottom(flpl,to)(j),seg_lh_top(flpl,to)(j)]
                       ((so + (flpl(j)`time-to)*vo)-flpl(j)`position,vo-velocity(flpl)(j))))
  	   IMPLIES  
  	   	   cd3d_ind?(so,vo,to,flpl)(i))

    cd3d_si_correct: THEOREM
      FORALL (so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to)):
      	   cd3d_si?(so,vo,to,flpl) IMPLIES
  	   conflict_3D?(so,to,vo,flpl)

    cd3d_si_complete: Theorem
      FORALL (so,vo:Vect3,to:real,flpl:FlightPlanRelevant(to)):
      	   conflict_3D?(so,to,vo,flpl) IMPLIES
  	   cd3d_si?(so,vo,to,flpl)

  END cd3d_si

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

  cd3d_ind?_weak_induction: AXIOM
    FORALL (so, vo: Vect3, to: real, flpl: FlightPlanRelevant(to),
            P: [below[N - 1] -> boolean]):
      (FORALL (j: below[N - 1]):
         (seg_lh_bottom(flpl, to)(j) < seg_lh_top(flpl, to)(j) AND
           cd3d?[D, H, seg_lh_bottom(flpl, to)(j), seg_lh_top(flpl, to)(j)]
               ((so + (flpl(j)`time - to) * vo) - flpl(j)`position,
                vo - velocity(flpl)(j)))
          OR (j > 0 AND P(j - 1))
          IMPLIES P(j))
       IMPLIES
       (FORALL (j: below[N - 1]):
          cd3d_ind?(so, vo, to, flpl)(j) IMPLIES P(j));

  cd3d_ind?_induction: AXIOM
    FORALL (so, vo: Vect3, to: real, flpl: FlightPlanRelevant(to),
            P: [below[N - 1] -> boolean]):
      (FORALL (j: below[N - 1]):
         (seg_lh_bottom(flpl, to)(j) < seg_lh_top(flpl, to)(j) AND
           cd3d?[D, H, seg_lh_bottom(flpl, to)(j), seg_lh_top(flpl, to)(j)]
               ((so + (flpl(j)`time - to) * vo) - flpl(j)`position,
                vo - velocity(flpl)(j)))
          OR (j > 0 AND cd3d_ind?(so, vo, to, flpl)(j - 1) AND P(j - 1))
          IMPLIES P(j))
       IMPLIES
       (FORALL (j: below[N - 1]):
          cd3d_ind?(so, vo, to, flpl)(j) IMPLIES P(j));

  % Subtype TCC generated (at line 9, column 13) for  below[N - 1]
      % expected type  nat
  j_TCC1: OBLIGATION N - 1 >= 0;

  % Subtype TCC generated (at line 18, column 57) for  0
      % expected type  below[N]
  FlightPlanRelevant_TCC1: OBLIGATION 0 < N;

  % Subtype TCC generated (at line 18, column 87) for  N - 1
      % expected type  below[N]
  FlightPlanRelevant_TCC2: OBLIGATION
    FORALL (to: real, flp: FlightPlan[N]):
      flp(0)`time < to + T IMPLIES N - 1 >= 0 AND N - 1 < N;

  % Subtype TCC generated (at line 15, column 71) for  i - 1
      % expected type  below[N]
  FlightPlanRelevant_TCC3: OBLIGATION
    FORALL (i: below[N]): i - 1 >= 0 IMPLIES i - 1 < N;

  % Existence TCC generated (at line 18, column 2) for
      % FlightPlanRelevant(to): TYPE+ =
      %       {flp: FlightPlan |
      %                flp(0)`time < to + T AND to + B < flp(N - 1)`time}
  FlightPlanRelevant_TCC4: OBLIGATION
    FORALL (to: real):
      EXISTS (x:
                {flp: FlightPlan[N] |
                         flp(0)`time < to + T AND to + B < flp(N - 1)`time}):
        TRUE;

  % Subtype TCC generated (at line 38, column 52) for  j + 1
      % expected type  below[N]
  seg_lh_top_TCC1: OBLIGATION FORALL (j: below[N - 1]): j + 1 < N;

  % Subtype TCC generated (at line 38, column 72) for  j
      % expected type  below[N]
  seg_lh_top_TCC2: OBLIGATION FORALL (j: below[N - 1]): j < N;

  % Subtype TCC generated (at line 43, column 49) for
      % max(flp(j)`time, to + B) - flp(j)`time
      % expected type  nnreal
  seg_lh_bottom_TCC1: OBLIGATION
    FORALL (flp: FlightPlan[N], to: real, j: below[N - 1]):
      max(flp(j)`time, to + B) - flp(j)`time >= 0;

  % Subtype TCC generated (at line 62, column 50) for  k - 1
      % expected type  below[N - 1]
  nontrivial_lookahead_TCC1: OBLIGATION
    FORALL (k: below[N], to: real, flpl: FlightPlanRelevant(to)):
      k > 0 AND
       NOT (k < N - 1 AND
             seg_lh_top(flpl, to)(k) - seg_lh_bottom(flpl, to)(k) > 0)
        AND to + B <= flpl(k)`time AND flpl(k)`time <= to + T
       IMPLIES k - 1 >= 0 AND k - 1 < N - 1;

  % Subtype TCC generated (at line 71, column 47) for  seg_lh_top(flpl, to)(j)
      % expected type  {AB: posreal | AB > seg_lh_bottom(flpl, to)(j)}
  conflict_3D_rew_TCC1: OBLIGATION
    FORALL (to: real, flpl: FlightPlanRelevant(to), j: below[N - 1]):
      seg_lh_bottom(flpl, to)(j) < seg_lh_top(flpl, to)(j) IMPLIES
       seg_lh_top(flpl, to)(j) >= 0 AND
        seg_lh_top(flpl, to)(j) > 0 AND
         seg_lh_top(flpl, to)(j) > seg_lh_bottom(flpl, to)(j);

  % Subtype TCC generated (at line 77, column 44) for  N - 1
      % expected type  below[N]
  conflict_3D_flightplan_open_interval_TCC1: OBLIGATION
    FORALL (to: real, flpl: FlightPlanRelevant(to),
            tt: FlightTimesRelevant(to, flpl)):
      tt < to + T AND to + B < tt IMPLIES N - 1 >= 0 AND N - 1 < N;

  % Subtype TCC generated (at line 92, column 21) for  lb
      % expected type  nnreal
  conflict_3D_rew_absolute_time_TCC1: OBLIGATION
    FORALL (to: real, flpl: FlightPlanRelevant(to), j: below[N - 1],
            lb: real):
      lb = seg_lh_bottom(flpl, to)(j) + flpl(j)`time - to IMPLIES
       (FORALL (ub: real):
          lb < ub AND ub = seg_lh_top(flpl, to)(j) + flpl(j)`time - to
           IMPLIES lb >= 0);

  % Subtype TCC generated (at line 92, column 24) for  ub
      % expected type  {AB: posreal | AB > lb}
  conflict_3D_rew_absolute_time_TCC2: OBLIGATION
    FORALL (to: real, flpl: FlightPlanRelevant(to), j: below[N - 1],
            lb: real):
      lb = seg_lh_bottom(flpl, to)(j) + flpl(j)`time - to IMPLIES
       (FORALL (ub: real):
          lb < ub AND ub = seg_lh_top(flpl, to)(j) + flpl(j)`time - to
           IMPLIES ub >= 0 AND ub > 0 AND ub > lb);

  % Subtype TCC generated (at line 99, column 38) for  j - 1
      % expected type  below[N - 1]
  cd3d_ind?_TCC1: OBLIGATION
    FORALL (so, vo: Vect3, to: real, flpl: FlightPlanRelevant(to),
            j: below[N - 1]):
      j > 0 AND
       NOT (seg_lh_bottom(flpl, to)(j) < seg_lh_top(flpl, to)(j) AND
             cd3d?[D, H, seg_lh_bottom(flpl, to)(j), seg_lh_top(flpl, to)(j)]
                 ((so + (flpl(j)`time - to) * vo) - flpl(j)`position,
                  vo - velocity(flpl)(j)))
       IMPLIES j - 1 >= 0 AND j - 1 < N - 1;

  % Subtype TCC generated (at line 104, column 93) for  N - 2
      % expected type  below[N - 1]
  cd3d_si?_TCC1: OBLIGATION N - 2 >= 0 AND N - 2 < N - 1;


body:
  bands_si[D,H:posreal,B:nnreal,T: {AB: posreal|AB>B},N:above[1],
           gsmin:posreal,gsmax:{x:posreal | x > gsmin},
           vsmin:real,vsmax:{x:real | x > vsmin}] : THEORY
  BEGIN

    %% Work in progress
    
    IMPORTING cd3d_si[D,H,B,T,N],
              bands_3D

     so	    : VAR Vect3
     vo	    : VAR Nzv2_vect3
     to	    : VAR real
     x,y	    : VAR real
     fp	    : VAR FlightPlan_nz
     trkb	    : VAR {fs : (trk_fseq?[gsmin,gsmax]) | increasing?(fs)}
     gsb	    : VAR {fs : (gs_fseq?[gsmin,gsmax]) | increasing?(fs)}
     vsb	    : VAR {fs : (vs_fseq?[vsmin,vsmax]) | increasing?(fs)}

     rs	    : VAR {fs : fseq[real] | increasing?(fs)}

     % bands require that relevant flightplans have nonzero horizontal velocities
     FlightPlanRelevant_nz(to): TYPE+ = {flp: FlightPlanRelevant(to) | FORALL(i:below[N-1]): nz_vect2?(velocity(flp)(i))}

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

    % return bands for a given segment i
    % i <= N-2 because we need a next point to calculate the velocity
    trk_bands_si_i(so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz) (i : below[N-1]) 
    : {fs : (trk_fseq?[gsmin,gsmax]) | increasing?(fs)} =
      LET
        fi_st = fp(i)`time,		% assume 0 <= fi_st <= to
        fi_et = fp(i+1)`time,		% assume fist < fi_et
        vi = velocity(fp)(i),		% intruder velocity for segment i
        Bo = B+to,			% absolute range bottom
        To = T+to				% absolute range bottom
      IN
      IF fi_et <= Bo OR fi_st >= To THEN
        emptyseq
      ELSE
          LET
            st = max(fi_st,Bo),		% start of range time
            et = min(fi_et,To),		% end of range time
            si = fp(i)`position,		% intruder position for segment i
            si_o = si-(fi_st-to)*vi,      % projected intruder position back to to
            s = so-si_o,			% relative position at start time
            rel_st = st-to,		% relative start time
            rel_et = et-to		% relative end time
          IN
          trk_bands_3D[D,H,rel_st,rel_et,gsmin,gsmax,vsmin,vsmax](s, vo, vi)
      ENDIF

    % stupid parameters
    expand_trk_bands_si_i : LEMMA
      FORALL (i:below[N-1]):
      fp(i+1)`time > B+to AND fp(i)`time < T+to IMPLIES
        trk_bands_si_i(so,vo,to,fp)(i) = 
            LET
              LB = max(fp(i)`time,B+to)-to,
              UB = min(fp(1+i)`time,T+to)-to
            IN
            trk_bands_3D[D,H,LB,UB,gsmin,gsmax,vsmin,vsmax](so-(fp(i)`position-(fp(i)`time-to)*velocity(fp)(i)), vo, velocity(fp)(i))


    % returns track bands for a flightplan
    trk_bands_si(so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz) (i : below[N-1]) 
    : RECURSIVE {fs : (trk_fseq?[gsmin,gsmax]) | increasing?(fs)} =
      IF i=0 THEN
        trk_bands_si_i(so,vo,to,fp)(i)
      ELSE
        sort (trk_bands_si_i(so,vo,to,fp)(i) o trk_bands_si(so,vo,to,fp)(i-1))
      ENDIF
    MEASURE i


    % return bands for a given segment i
    % i <= N-2 because we need a next point to calculate the velocity
    gs_bands_si_i(so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz) (i : below[N-1]) 
    : {fs : (gs_fseq?[gsmin,gsmax]) | increasing?(fs)} =
      LET
        fi_st = fp(i)`time,		% assume 0 <= fi_st <= to
        fi_et = fp(i+1)`time,		% assume fist < fi_et
        vi = velocity(fp)(i),		% intruder velocity for segment i
        Bo = B+to,			% absolute range bottom
        To = T+to				% absolute range bottom
      IN
      IF fi_et <= Bo OR fi_st >= To THEN
        emptyseq
      ELSE
          LET
            st = max(fi_st,Bo),		% start of range time
            et = min(fi_et,To),		% end of range time
            si = fp(i)`position,		% intruder position for segment i
            si_o = si-(fi_st-to)*vi,      % projected intruder position back to to
            s = so-si_o,			% relative position at start time
            rel_st = st-to,		% relative start time
            rel_et = et-to		% relative end time
          IN
          gs_bands_3D[D,H,rel_st,rel_et,gsmin,gsmax,vsmin,vsmax](s, vo, vi)
      ENDIF

    % returns gs bands for a flightplan
    gs_bands_si(so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz) (i : below[N-1]) 
    : RECURSIVE {fs : (gs_fseq?[gsmin,gsmax]) | increasing?(fs)} =
      IF i=0 THEN
        gs_bands_si_i(so,vo,to,fp)(i)
      ELSE
        sort (gs_bands_si_i(so,vo,to,fp)(i) o gs_bands_si(so,vo,to,fp)(i-1))
      ENDIF
    MEASURE i


    % return bands for a given segment i
    % i <= N-2 because we need a next point to calculate the velocity
    vs_bands_si_i(so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz) (i : below[N-1]) 
    : {fs : (vs_fseq?[vsmin,vsmax]) | increasing?(fs)} =
      LET
        fi_st = fp(i)`time,		% assume 0 <= fi_st <= to
        fi_et = fp(i+1)`time,		% assume fist < fi_et
        vi = velocity(fp)(i),		% intruder velocity for segment i
        Bo = B+to,			% absolute range bottom
        To = T+to				% absolute range bottom
      IN
      IF fi_et <= Bo OR fi_st >= To THEN
        emptyseq
      ELSE
          LET
            st = max(fi_st,Bo),		% start of range time
            et = min(fi_et,To),		% end of range time
            si = fp(i)`position,		% intruder position for segment i
            si_o = si-(fi_st-to)*vi,      % projected intruder position back to to
            s = so-si_o,			% relative position at start time
            rel_st = st-to,		% relative start time
            rel_et = et-to		% relative end time
          IN
          vs_bands_3D[D,H,rel_st,rel_et,gsmin,gsmax,vsmin,vsmax](s, vo, vi)
      ENDIF

    % returns gs bands for a flightplan
    vs_bands_si(so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz) (i : below[N-1]) 
    : RECURSIVE {fs : (vs_fseq?[vsmin,vsmax]) | increasing?(fs)} =
      IF i=0 THEN
        vs_bands_si_i(so,vo,to,fp)(i)
      ELSE
        sort (vs_bands_si_i(so,vo,to,fp)(i) o vs_bands_si(so,vo,to,fp)(i-1))
      ENDIF
    MEASURE i

    %-------------%
    % Definitions %
    %-------------%

    % is a track band red?
    red_trk_band_fp?(so,vo,to,fp,trkb)(i:subrange(0,trkb`length-2)) : bool =
      LET
        mp = (trkb`seq(i)+trkb`seq(i+1))/2,
        trk = trk2v3(vo)(mp) 
      IN
      conflict_3D?(so,to,trk,fp)

    red_gs_band_fp?(so,vo,to,fp,gsb)(i:subrange(0,gsb`length-2)) : bool =
      LET
        mp = (gsb`seq(i)+gsb`seq(i+1))/2,
        gs = gs2v3(vo)(mp) 
      IN
      conflict_3D?(so,to,gs,fp)

    red_vs_band_fp?(so,vo,to,fp,vsb)(i:subrange(0,vsb`length-2)) : bool =
      LET
        mp = (vsb`seq(i)+vsb`seq(i+1))/2,
        vs = vs2v3(vo)(mp) 
      IN
      conflict_3D?(so,to,vs,fp)


    %------------%
    % Utilities  %
    %------------%

    % just to save a bit of typing
    segdefs : LEMMA
      FORALL (j:subrange(0,N-2)):
        seg_lh_bottom(fp,to)(j)+fp(j)`time-to = max(fp(j)`time,B+to)-to AND
        seg_lh_top(fp,to)(j)+fp(j)`time-to = min(fp(1+j)`time,T+to)-to

    %------------%
    % Theorems   %
    %------------%

    %%%%%%%%%%%%%%%%%%%%%%%%%%%% TRK %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    % a critical point occurs in a trk_bands_si result iff it occurs in some trk_bands_si_i subcall result
    trk_bands_si_combines : LEMMA
      FORALL (i:subrange(0,N-2), x:real):
        member(x,trk_bands_si(so,vo,to,fp)(i)) IFF
          EXISTS (j:subrange(0,i)): member(x,trk_bands_si_i(so,vo,to,fp)(j))

    % not used - practice
    empty_no_members : LEMMA
      NOT member(x,emptyseq)

    % a critical point occurs in a trk_bands_si result iff it occurs in some trk_bands_3D on a relevant segment j
    % note: delay asserting to preserve the local variables -- once they become theory parameters it    may not be possible
    % to easily unify them
    trk_bands_si_component : LEMMA
      FORALL (i:subrange(0,N-2), x:real):
        member(x,trk_bands_si(so,vo,to,fp)(i)) IFF
          EXISTS (j:subrange(0,i)): 
            LET
              LB = max(fp(j)`time,B+to)-to,
              UB = min(fp(1+j)`time,T+to)-to
            IN
            fp(j+1)`time > B+to AND fp(j)`time < T+ to AND 
            member(x,trk_bands_3D[D,H,LB,UB,gsmin,gsmax,vsmin,vsmax]
  		   (so-(fp(j)`position - (fp(j)`time-to)*velocity(fp)(j)), vo, velocity(fp)(j)))

     % the overall bands have at least as many critical points as any of the segments
     trk_bands_si_length : LEMMA
       FORALL (i:subrange(0,N-2), j: subrange(0,i)):
         trk_bands_si(so,vo,to,fp)(i)`length >= trk_bands_si_i(so,vo,to,fp)(j)`length

     % we got something from trk_bands_si_i iff the flightplan segment is relevant
     trk_bands_si_i_relevant : LEMMA
       FORALL (i:subrange(0,N-2)):
         trk_bands_si_i(so,vo,to,fp)(i)`length > 0 IFF fp(i)`time < to+T AND to+B < fp(i+1)`time

     % if the flightplan segment has any points, it will have at least 2 points
     trk_bands_si_i_relevant_has_2 : LEMMA
       FORALL (i:subrange(0,N-2)):
         trk_bands_si_i(so,vo,to,fp)(i)`length > 0 IFF trk_bands_si_i(so,vo,to,fp)(i)`length > 1

     % we got something from trk_bands_si iff the flightplan is relevant
     trk_bands_si_relevant : LEMMA
       FORALL (i:subrange(0,N-2)):
         trk_bands_si(so,vo,to,fp)(i)`length > 0 IFF fp(0)`time < to+T AND to+B < fp(i+1)`time

     % relevant bands have at least 2 critical points
     trk_bands_si_relevant_has_2 : LEMMA
       FORALL (i:subrange(0,N-2)):
         trk_bands_si(so,vo,to,fp)(i)`length > 0 IFF trk_bands_si(so,vo,to,fp)(i)`length > 1

     % if a point is conflicting for the flightplan, it must be conflicting for one of the segments
     % (this is conflict_3D_rew_absolute_time)
    trk_bands_si_equivalence: LEMMA
      FORALL (fpr:FlightPlanRelevant_nz(to)):
         LET
           trkb = trk_bands_si(so,vo,to,fpr)(N-2),
           trk = trk2v3(vo) 
         IN
         FORALL (x,y): (0<=x AND x<=y AND y<=2*pi AND
           (FORALL (i:subrange(0,trkb`length-1)): trkb`seq(i) < x OR y < trkb`seq(i)))
  	 IMPLIES
           (conflict_3D?(so,to,trk(x),fpr) IFF conflict_3D?(so,to,trk(y),fpr))

     trk_red_bands_si : THEOREM
      FORALL (fpr:FlightPlanRelevant_nz(to)):
      LET trkb = trk_bands_si(so,vo,to,fpr)(N-2) IN
       FORALL (i:subrange(0,trkb`length-2) | trkb`seq(i) /= trkb`seq(i+1)) : 
         red_trk_band_fp?(so,vo,to,fpr,trkb)(i) IFF
         (FORALL (x | trkb`seq(i) < x AND x < trkb`seq(i+1)):
           LET trk = trk2v3(vo)(x) IN
           conflict_3D?(so,to,trk,fpr))

    trk_green_bands_si : THEOREM
      FORALL (fpr:FlightPlanRelevant_nz(to)):
      LET trkb = trk_bands_si(so,vo,to,fpr)(N-2) IN
       FORALL (i:subrange(0,trkb`length-2) | trkb`seq(i) /= trkb`seq(i+1)) : 
         NOT red_trk_band_fp?(so,vo,to,fpr,trkb)(i) IFF
         (FORALL (x | trkb`seq(i) < x AND x < trkb`seq(i+1)):
           LET trk = trk2v3(vo)(x) IN
           NOT conflict_3D?(so,to,trk,fpr))

    %%%%%%%%%%%%%%%%%%%%%%%%%%%% GS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    gs_bands_si_combines : LEMMA
      FORALL (i:subrange(0,N-2), x:real):
        member(x,gs_bands_si(so,vo,to,fp)(i)) IFF
          EXISTS (j:subrange(0,i)): member(x,gs_bands_si_i(so,vo,to,fp)(j))

    gs_bands_si_component : LEMMA
      FORALL (i:subrange(0,N-2), x:real):
        member(x,gs_bands_si(so,vo,to,fp)(i)) IFF
          EXISTS (j:subrange(0,i)): 
            LET
              LB = max(fp(j)`time,B+to)-to,
              UB = min(fp(1+j)`time,T+to)-to
            IN
            fp(j+1)`time > B+to AND fp(j)`time < T+ to AND 
            member(x,gs_bands_3D[D,H,LB,UB,gsmin,gsmax,vsmin,vsmax]
  		   (so-(fp(j)`position - (fp(j)`time-to)*velocity(fp)(j)), vo, velocity(fp)(j)))


    gs_bands_si_equivalence: LEMMA
      FORALL (fpr:FlightPlanRelevant_nz(to)):
         LET
           gsb = gs_bands_si(so,vo,to,fpr)(N-2),
           gs = gs2v3(vo) 
         IN
         FORALL (x,y): (gsmin<=x AND x<=y AND y<=gsmax AND
           (FORALL (i:subrange(0,gsb`length-1)): gsb`seq(i) < x OR y < gsb`seq(i)))
  	 IMPLIES
           (conflict_3D?(so,to,gs(x),fpr) IFF conflict_3D?(so,to,gs(y),fpr))

     gs_red_bands_si : THEOREM
      FORALL (fpr:FlightPlanRelevant_nz(to)):
      LET gsb = gs_bands_si(so,vo,to,fpr)(N-2) IN
       FORALL (i:subrange(0,gsb`length-2) | gsb`seq(i) /= gsb`seq(i+1)) : 
         red_gs_band_fp?(so,vo,to,fpr,gsb)(i) IFF
         (FORALL (x | gsb`seq(i) < x AND x < gsb`seq(i+1)):
           LET gs = gs2v3(vo)(x) IN
           conflict_3D?(so,to,gs,fpr))

    gs_green_bands_si : THEOREM
      FORALL (fpr:FlightPlanRelevant_nz(to)):
      LET gsb = gs_bands_si(so,vo,to,fpr)(N-2) IN
       FORALL (i:subrange(0,gsb`length-2) | gsb`seq(i) /= gsb`seq(i+1)) : 
         NOT red_gs_band_fp?(so,vo,to,fpr,gsb)(i) IFF
         (FORALL (x | gsb`seq(i) < x AND x < gsb`seq(i+1)):
           LET gs = gs2v3(vo)(x) IN
           NOT conflict_3D?(so,to,gs,fpr))


    %%%%%%%%%%%%%%%%%%%%%%%%%%%% VS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    vs_bands_si_combines : LEMMA
      FORALL (i:subrange(0,N-2), x:real):
        member(x,vs_bands_si(so,vo,to,fp)(i)) IFF
          EXISTS (j:subrange(0,i)): member(x,vs_bands_si_i(so,vo,to,fp)(j))

    vs_bands_si_component : LEMMA
      FORALL (i:subrange(0,N-2), x:real):
        member(x,vs_bands_si(so,vo,to,fp)(i)) IFF
          EXISTS (j:subrange(0,i)): 
            LET
              LB = max(fp(j)`time,B+to)-to,
              UB = min(fp(1+j)`time,T+to)-to
            IN
            fp(j+1)`time > B+to AND fp(j)`time < T+ to AND 
            member(x,vs_bands_3D[D,H,LB,UB,gsmin,gsmax,vsmin,vsmax]
  		   (so-(fp(j)`position - (fp(j)`time-to)*velocity(fp)(j)), vo, velocity(fp)(j)))


    vs_bands_si_equivalence: LEMMA
      FORALL (fpr:FlightPlanRelevant_nz(to)):
         LET
           vsb = vs_bands_si(so,vo,to,fpr)(N-2),
           vs = vs2v3(vo) 
         IN
         FORALL (x,y): (vsmin<=x AND x<=y AND y<=vsmax AND
           (FORALL (i:subrange(0,vsb`length-1)): vsb`seq(i) < x OR y < vsb`seq(i)))
  	 IMPLIES
           (conflict_3D?(so,to,vs(x),fpr) IFF conflict_3D?(so,to,vs(y),fpr))

     vs_red_bands_si : THEOREM
      FORALL (fpr:FlightPlanRelevant_nz(to)):
      LET vsb = vs_bands_si(so,vo,to,fpr)(N-2) IN
       FORALL (i:subrange(0,vsb`length-2) | vsb`seq(i) /= vsb`seq(i+1)) : 
         red_vs_band_fp?(so,vo,to,fpr,vsb)(i) IFF
         (FORALL (x | vsb`seq(i) < x AND x < vsb`seq(i+1)):
           LET vs = vs2v3(vo)(x) IN
           conflict_3D?(so,to,vs,fpr))

    vs_green_bands_si : THEOREM
      FORALL (fpr:FlightPlanRelevant_nz(to)):
      LET vsb = vs_bands_si(so,vo,to,fpr)(N-2) IN
       FORALL (i:subrange(0,vsb`length-2) | vsb`seq(i) /= vsb`seq(i+1)) : 
         NOT red_vs_band_fp?(so,vo,to,fpr,vsb)(i) IFF
         (FORALL (x | vsb`seq(i) < x AND x < vsb`seq(i+1)):
           LET vs = vs2v3(vo)(x) IN
           NOT conflict_3D?(so,to,vs,fpr))


  END bands_si

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

  % Subtype TCC generated (at line 23, column 84) for  N - 1
      % expected type  nat
  FlightPlanRelevant_nz_TCC1: OBLIGATION FORALL (to: real): N - 1 >= 0;

  % Subtype TCC generated (at line 15, column 71) for  i - 1
      % expected type  below[N]
  FlightPlanRelevant_nz_TCC2: OBLIGATION
    FORALL (i: below[N]): i - 1 >= 0 IMPLIES i - 1 < N;

  % Subtype TCC generated (at line 15, column 45) for  0
      % expected type  below[N]
  FlightPlanRelevant_nz_TCC3: OBLIGATION 0 < N;

  % Subtype TCC generated (at line 18, column 87) for  N - 1
      % expected type  below[N]
  FlightPlanRelevant_nz_TCC4: OBLIGATION
    FORALL (to: real, flp: FlightPlan[N]):
      flp(0)`time < to + T IMPLIES N - 1 >= 0 AND N - 1 < N;

  % Existence TCC generated (at line 23, column 3) for
      % FlightPlanRelevant_nz(to): TYPE+ =
      %       {flp: FlightPlanRelevant(to) |
      %                FORALL (i: below[N - 1]):
      %                  vect2(velocity(flp)(i)) /= zero}
  FlightPlanRelevant_nz_TCC5: OBLIGATION
    FORALL (to: real):
      EXISTS (x:
                {flp: FlightPlanRelevant[D, H, B, T, N](to) |
                         FORALL (i: below[N - 1]):
                           vect2(velocity[N](flp)(i)) /= zero}):
        TRUE;

  % Subtype TCC generated (at line 35, column 17) for  i
      % expected type  below[N]
  trk_bands_si_i_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3, i: below[N - 1]): i < N;

  % Subtype TCC generated (at line 36, column 17) for  i + 1
      % expected type  below[N]
  trk_bands_si_i_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3, fp: FlightPlan_nz[N], i: below[N - 1],
            fi_st: real):
      fi_st = fp(i)`time IMPLIES i + 1 < N;

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  {fs: (trk_fseq?[gsmin, gsmax]) | increasing?(fs)}
  trk_bands_si_i_TCC3: OBLIGATION
    FORALL (vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N], i: below[N - 1],
            fi_st: real):
      fi_st = fp(i)`time IMPLIES
       (FORALL (fi_et: real):
          fi_et = fp(i + 1)`time IMPLIES
           (FORALL (vi: Vect3):
              vi = velocity(fp)(i) IMPLIES
               (FORALL (Bo: real):
                  Bo = B + to IMPLIES
                   (FORALL (To: real):
                      (fi_et <= Bo OR fi_st >= To) AND To = T + to IMPLIES
                       (FORALL (i: nat):
                          i >= empty_seq[real]`length IMPLIES
                           empty_seq[real]`seq(i) = default[real])
                        AND
                        trk_fseq?[gsmin, gsmax](empty_seq[real]) AND
                         increasing?[real, <=](empty_seq[real])))));

  % Subtype TCC generated (at line 53, column 71) for  vi
      % expected type  Nzv2_vect3
  trk_bands_si_i_TCC4: OBLIGATION
    FORALL (so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N],
            i: below[N - 1], fi_st: real):
      fi_st = fp(i)`time IMPLIES
       (FORALL (fi_et: real):
          fi_et = fp(i + 1)`time IMPLIES
           (FORALL (vi: Vect3):
              vi = velocity(fp)(i) IMPLIES
               (FORALL (Bo: real):
                  Bo = B + to IMPLIES
                   (FORALL (To: real):
                      NOT fi_et <= Bo AND NOT fi_st >= To AND To = T + to
                       IMPLIES
                       (FORALL (st: {p: real | p >= fi_st AND p >= Bo}):
                          st = max(fi_st, Bo) IMPLIES
                           (FORALL (et: {p: real | p <= fi_et AND p <= To}):
                              et = min(fi_et, To) IMPLIES
                               (FORALL (si: Vect3):
                                  si = fp(i)`position IMPLIES
                                   (FORALL (si_o: Vector):
                                      si_o = si - (fi_st - to) * vi
                                      IMPLIES
                                      (FORALL
                                       (s: Vector):
                                       s = so - si_o
                                       IMPLIES
                                       (FORALL
                                        (rel_st: real):
                                        rel_st = st - to
                                        IMPLIES
                                        (FORALL
                                         (rel_et: real):
                                         rel_et = et - to
                                         IMPLIES
                                         vect2(vi) /= zero)))))))))));

  % Subtype TCC generated (at line 53, column 25) for  rel_st
      % expected type  nnreal
  trk_bands_si_i_TCC5: OBLIGATION
    FORALL (so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N],
            i: below[N - 1], fi_st: real):
      fi_st = fp(i)`time IMPLIES
       (FORALL (fi_et: real):
          fi_et = fp(i + 1)`time IMPLIES
           (FORALL (vi: Vect3):
              vi = velocity(fp)(i) IMPLIES
               (FORALL (Bo: real):
                  Bo = B + to IMPLIES
                   (FORALL (To: real):
                      NOT fi_et <= Bo AND NOT fi_st >= To AND To = T + to
                       IMPLIES
                       (FORALL (st: {p: real | p >= fi_st AND p >= Bo}):
                          st = max(fi_st, Bo) IMPLIES
                           (FORALL (et: {p: real | p <= fi_et AND p <= To}):
                              et = min(fi_et, To) IMPLIES
                               (FORALL (si: Vect3):
                                  si = fp(i)`position IMPLIES
                                   (FORALL (si_o: Vector):
                                      si_o = si - (fi_st - to) * vi
                                      IMPLIES
                                      (FORALL
                                       (s: Vector):
                                       s = so - si_o
                                       IMPLIES
                                       (FORALL
                                        (rel_st: real):
                                        rel_st = st - to
                                        IMPLIES
                                        (FORALL
                                         (rel_et: real):
                                         rel_et = et - to
                                         IMPLIES
                                         rel_st >= 0)))))))))));

  % Subtype TCC generated (at line 53, column 32) for  rel_et
      % expected type  {x: posreal | x > rel_st}
  trk_bands_si_i_TCC6: OBLIGATION
    FORALL (so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N],
            i: below[N - 1], fi_st: real):
      fi_st = fp(i)`time IMPLIES
       (FORALL (fi_et: real):
          fi_et = fp(i + 1)`time IMPLIES
           (FORALL (vi: Vect3):
              vi = velocity(fp)(i) IMPLIES
               (FORALL (Bo: real):
                  Bo = B + to IMPLIES
                   (FORALL (To: real):
                      NOT fi_et <= Bo AND NOT fi_st >= To AND To = T + to
                       IMPLIES
                       (FORALL (st: {p: real | p >= fi_st AND p >= Bo}):
                          st = max(fi_st, Bo) IMPLIES
                           (FORALL (et: {p: real | p <= fi_et AND p <= To}):
                              et = min(fi_et, To) IMPLIES
                               (FORALL (si: Vect3):
                                  si = fp(i)`position IMPLIES
                                   (FORALL (si_o: Vector):
                                      si_o = si - (fi_st - to) * vi
                                      IMPLIES
                                      (FORALL
                                       (s: Vector):
                                       s = so - si_o
                                       IMPLIES
                                       (FORALL
                                        (rel_st: real):
                                        rel_st = st - to
                                        IMPLIES
                                        (FORALL
                                         (rel_et: real):
                                         rel_et = et - to
                                         IMPLIES
                                         rel_et >= 0
                                         AND
                                         rel_et > 0
                                         AND
                                         rel_et > rel_st)))))))))));

  % Subtype TCC generated (at line 59, column 7) for  i + 1
      % expected type  below[N]
  expand_trk_bands_si_i_TCC1: OBLIGATION FORALL (i: below[N - 1]): i + 1 < N;

  % Subtype TCC generated (at line 59, column 31) for  i
      % expected type  below[N]
  expand_trk_bands_si_i_TCC2: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: below[N - 1]):
      fp(i + 1)`time > B + to IMPLIES i < N;

  % Subtype TCC generated (at line 63, column 24) for  1 + i
      % expected type  below[N]
  expand_trk_bands_si_i_TCC3: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: below[N - 1]):
      fp(i + 1)`time > B + to AND fp(i)`time < T + to IMPLIES
       (FORALL (LB: real):
          LB = max(fp(i)`time, B + to) - to IMPLIES 1 + i < N);

  % Subtype TCC generated (at line 65, column 115) for  velocity(fp)(i)
      % expected type  Nzv2_vect3
  expand_trk_bands_si_i_TCC4: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: below[N - 1]):
      fp(i + 1)`time > B + to AND fp(i)`time < T + to IMPLIES
       (FORALL (LB: real):
          LB = max(fp(i)`time, B + to) - to IMPLIES
           (FORALL (UB: real):
              UB = min(fp(1 + i)`time, T + to) - to IMPLIES
               vect2(velocity[N](fp)(i)) /= zero));

  % Subtype TCC generated (at line 65, column 27) for  LB
      % expected type  nnreal
  expand_trk_bands_si_i_TCC5: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: below[N - 1]):
      fp(i + 1)`time > B + to AND fp(i)`time < T + to IMPLIES
       (FORALL (LB: real):
          LB = max(fp(i)`time, B + to) - to IMPLIES
           (FORALL (UB: real):
              UB = min(fp(1 + i)`time, T + to) - to IMPLIES LB >= 0));

  % Subtype TCC generated (at line 65, column 30) for  UB
      % expected type  {x: posreal | x > LB}
  expand_trk_bands_si_i_TCC6: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: below[N - 1]):
      fp(i + 1)`time > B + to AND fp(i)`time < T + to IMPLIES
       (FORALL (LB: real):
          LB = max(fp(i)`time, B + to) - to IMPLIES
           (FORALL (UB: real):
              UB = min(fp(1 + i)`time, T + to) - to IMPLIES
               UB >= 0 AND UB > 0 AND UB > LB));

  % Subtype TCC generated (at line 69, column 82) for  N - 1
      % expected type  nat
  trk_bands_si_TCC1: OBLIGATION FORALL (vo: Nzv2_vect3): N - 1 >= 0;

  % Subtype TCC generated (at line 74, column 71) for  i - 1
      % expected type  below[N - 1]
  trk_bands_si_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3, i: below[N - 1]):
      NOT i = 0 IMPLIES i - 1 >= 0 AND i - 1 < N - 1;

  % Termination TCC generated (at line 74, column 45) for
      % trk_bands_si(so, vo, to, fp)(i - 1)
  trk_bands_si_TCC3: OBLIGATION
    FORALL (vo: Nzv2_vect3, i: below[N - 1]): NOT i = 0 IMPLIES i - 1 < i;

  % Subtype TCC generated (at line 74, column 6) for
      % sort(trk_bands_si_i(so, vo, to, fp)(i) o
      %       trk_bands_si(so, vo, to, fp)(i - 1))
      % expected type  {fs: (trk_fseq?[gsmin, gsmax]) | increasing?(fs)}
  trk_bands_si_TCC4: OBLIGATION
    FORALL (so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N],
            i: below[N - 1],
            v:
              [[Vect3, Nzv2_vect3, real, FlightPlan_nz[N]] ->
                 [{z1: below[N - 1] | z1 < i} ->
                    {fs: (trk_fseq?[gsmin, gsmax]) | increasing?(fs)}]]):
      NOT i = 0 IMPLIES
       trk_fseq?[gsmin, gsmax]
           (sort[real, <=]
                (o[real]
                     (trk_bands_si_i(so, vo, to, fp)(i),
                      v(so, vo, to, fp)(i - 1))))
        AND
        increasing?[real, <=]
            (sort[real, <=]
                 (o[real]
                      (trk_bands_si_i(so, vo, to, fp)(i),
                       v(so, vo, to, fp)(i - 1))));

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  {fs: (gs_fseq?[gsmin, gsmax]) | increasing?(fs)}
  gs_bands_si_i_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N], i: below[N - 1],
            fi_st: real):
      fi_st = fp(i)`time IMPLIES
       (FORALL (fi_et: real):
          fi_et = fp(i + 1)`time IMPLIES
           (FORALL (vi: Vect3):
              vi = velocity(fp)(i) IMPLIES
               (FORALL (Bo: real):
                  Bo = B + to IMPLIES
                   (FORALL (To: real):
                      (fi_et <= Bo OR fi_st >= To) AND To = T + to IMPLIES
                       (FORALL (i: nat):
                          i >= empty_seq[real]`length IMPLIES
                           empty_seq[real]`seq(i) = default[real])
                        AND
                        gs_fseq?[gsmin, gsmax](empty_seq[real]) AND
                         increasing?[real, <=](empty_seq[real])))));

  % Subtype TCC generated (at line 111, column 6) for
      % sort(gs_bands_si_i(so, vo, to, fp)(i) o
      %       gs_bands_si(so, vo, to, fp)(i - 1))
      % expected type  {fs: (gs_fseq?[gsmin, gsmax]) | increasing?(fs)}
  gs_bands_si_TCC1: OBLIGATION
    FORALL (so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N],
            i: below[N - 1],
            v:
              [[Vect3, Nzv2_vect3, real, FlightPlan_nz[N]] ->
                 [{z1: below[N - 1] | z1 < i} ->
                    {fs: (gs_fseq?[gsmin, gsmax]) | increasing?(fs)}]]):
      NOT i = 0 IMPLIES
       gs_fseq?[gsmin, gsmax]
           (sort[real, <=]
                (o[real]
                     (gs_bands_si_i(so, vo, to, fp)(i),
                      v(so, vo, to, fp)(i - 1))))
        AND
        increasing?[real, <=]
            (sort[real, <=]
                 (o[real]
                      (gs_bands_si_i(so, vo, to, fp)(i),
                       v(so, vo, to, fp)(i - 1))));

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  {fs: (vs_fseq?[vsmin, vsmax]) | increasing?(fs)}
  vs_bands_si_i_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N], i: below[N - 1],
            fi_st: real):
      fi_st = fp(i)`time IMPLIES
       (FORALL (fi_et: real):
          fi_et = fp(i + 1)`time IMPLIES
           (FORALL (vi: Vect3):
              vi = velocity(fp)(i) IMPLIES
               (FORALL (Bo: real):
                  Bo = B + to IMPLIES
                   (FORALL (To: real):
                      (fi_et <= Bo OR fi_st >= To) AND To = T + to IMPLIES
                       (FORALL (i: nat):
                          i >= empty_seq[real]`length IMPLIES
                           empty_seq[real]`seq(i) = default[real])
                        AND
                        vs_fseq?[vsmin, vsmax](empty_seq[real]) AND
                         increasing?[real, <=](empty_seq[real])))));

  % Subtype TCC generated (at line 148, column 6) for
      % sort(vs_bands_si_i(so, vo, to, fp)(i) o
      %       vs_bands_si(so, vo, to, fp)(i - 1))
      % expected type  {fs: (vs_fseq?[vsmin, vsmax]) | increasing?(fs)}
  vs_bands_si_TCC1: OBLIGATION
    FORALL (so: Vect3, vo: Nzv2_vect3, to: real, fp: FlightPlan_nz[N],
            i: below[N - 1],
            v:
              [[Vect3, Nzv2_vect3, real, FlightPlan_nz[N]] ->
                 [{z1: below[N - 1] | z1 < i} ->
                    {fs: (vs_fseq?[vsmin, vsmax]) | increasing?(fs)}]]):
      NOT i = 0 IMPLIES
       vs_fseq?[vsmin, vsmax]
           (sort[real, <=]
                (o[real]
                     (vs_bands_si_i(so, vo, to, fp)(i),
                      v(so, vo, to, fp)(i - 1))))
        AND
        increasing?[real, <=]
            (sort[real, <=]
                 (o[real]
                      (vs_bands_si_i(so, vo, to, fp)(i),
                       v(so, vo, to, fp)(i - 1))));

  % Subtype TCC generated (at line 159, column 21) for  i
      % expected type  nat
  red_trk_band_fp?_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3,
            trkb:
              {fs: (trk_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)},
            i: subrange(0, trkb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 159, column 33) for  i + 1
      % expected type  nat
  red_trk_band_fp?_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3,
            trkb:
              {fs: (trk_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)},
            i: subrange(0, trkb`length - 2)):
      i + 1 >= 0;

  % Subtype TCC generated (at line 166, column 20) for  i
      % expected type  nat
  red_gs_band_fp?_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3,
            gsb: {fs: (gs_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)},
            i: subrange(0, gsb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 166, column 31) for  i + 1
      % expected type  nat
  red_gs_band_fp?_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3,
            gsb: {fs: (gs_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)},
            i: subrange(0, gsb`length - 2)):
      i + 1 >= 0;

  % Subtype TCC generated (at line 173, column 20) for  i
      % expected type  nat
  red_vs_band_fp?_TCC1: OBLIGATION
    FORALL (vo: Nzv2_vect3,
            vsb: {fs: (vs_fseq?[vsmin, vsmax]) | increasing?[real, <=](fs)},
            i: subrange(0, vsb`length - 2)):
      i >= 0;

  % Subtype TCC generated (at line 173, column 31) for  i + 1
      % expected type  nat
  red_vs_band_fp?_TCC2: OBLIGATION
    FORALL (vo: Nzv2_vect3,
            vsb: {fs: (vs_fseq?[vsmin, vsmax]) | increasing?[real, <=](fs)},
            i: subrange(0, vsb`length - 2)):
      i + 1 >= 0;

  % Subtype TCC generated (at line 186, column 27) for  j
      % expected type  below[N - 1]
  segdefs_TCC1: OBLIGATION
    FORALL (j: subrange(0, N - 2)): j >= 0 AND j < N - 1;

  % Subtype TCC generated (at line 186, column 33) for  j
      % expected type  below[N]
  segdefs_TCC2: OBLIGATION FORALL (j: subrange(0, N - 2)): j >= 0 AND j < N;

  % Subtype TCC generated (at line 187, column 50) for  1 + j
      % expected type  below[N]
  segdefs_TCC3: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, j: subrange(0, N - 2)):
      seg_lh_bottom(fp, to)(j) + fp(j)`time - to =
       max(fp(j)`time, B + to) - to
       IMPLIES 1 + j >= 0 AND 1 + j < N;

  % Subtype TCC generated (at line 199, column 71) for  j
      % expected type  below[N - 1]
  trk_bands_si_combines_TCC1: OBLIGATION
    FORALL (i: subrange(0, N - 2), j: subrange(0, i)): j >= 0 AND j < N - 1;

  % Subtype TCC generated (at line 53, column 24) for  empty_seq
      % expected type  fseq[real]
  empty_no_members_TCC1: OBLIGATION
    FORALL (i: nat):
      i >= empty_seq[real]`length IMPLIES
       empty_seq[real]`seq(i) = default[real];

  % Subtype TCC generated (at line 213, column 24) for  j
      % expected type  below[N]
  trk_bands_si_component_TCC1: OBLIGATION
    FORALL (i: subrange(0, N - 2), j: subrange(0, i)): j >= 0 AND j < N;

  % Subtype TCC generated (at line 214, column 24) for  1 + j
      % expected type  below[N]
  trk_bands_si_component_TCC2: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: subrange(0, N - 2),
            j: subrange(0, i), LB: real):
      LB = max(fp(j)`time, B + to) - to IMPLIES 1 + j >= 0 AND 1 + j < N;

  % Subtype TCC generated (at line 216, column 13) for  j + 1
      % expected type  below[N]
  trk_bands_si_component_TCC3: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: subrange(0, N - 2),
            j: subrange(0, i), LB: real):
      LB = max(fp(j)`time, B + to) - to IMPLIES
       (FORALL (UB: real):
          UB = min(fp(1 + j)`time, T + to) - to IMPLIES
           j + 1 >= 0 AND j + 1 < N);

  % Subtype TCC generated (at line 218, column 65) for  velocity(fp)(j)
      % expected type  Nzv2_vect3
  trk_bands_si_component_TCC4: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: subrange(0, N - 2),
            j: subrange(0, i), LB: real):
      LB = max(fp(j)`time, B + to) - to IMPLIES
       (FORALL (UB: real):
          fp(j)`time < T + to AND
           fp(j + 1)`time > B + to AND UB = min(fp(1 + j)`time, T + to) - to
           IMPLIES vect2(velocity[N](fp)(j)) /= zero);

  % Subtype TCC generated (at line 217, column 36) for  LB
      % expected type  nnreal
  trk_bands_si_component_TCC5: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: subrange(0, N - 2),
            j: subrange(0, i), LB: real):
      LB = max(fp(j)`time, B + to) - to IMPLIES
       (FORALL (UB: real):
          fp(j)`time < T + to AND
           fp(j + 1)`time > B + to AND UB = min(fp(1 + j)`time, T + to) - to
           IMPLIES LB >= 0);

  % Subtype TCC generated (at line 217, column 39) for  UB
      % expected type  {x: posreal | x > LB}
  trk_bands_si_component_TCC6: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: subrange(0, N - 2),
            j: subrange(0, i), LB: real):
      LB = max(fp(j)`time, B + to) - to IMPLIES
       (FORALL (UB: real):
          fp(j)`time < T + to AND
           fp(j + 1)`time > B + to AND UB = min(fp(1 + j)`time, T + to) - to
           IMPLIES UB >= 0 AND UB > 0 AND UB > LB);

  % Subtype TCC generated (at line 228, column 85) for  i + 1
      % expected type  below[N]
  trk_bands_si_i_relevant_TCC1: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: subrange(0, N - 2)):
      fp(i)`time < to + T IMPLIES i + 1 >= 0 AND i + 1 < N;

  % Subtype TCC generated (at line 238, column 83) for  i + 1
      % expected type  below[N]
  trk_bands_si_relevant_TCC1: OBLIGATION
    FORALL (fp: FlightPlan_nz[N], to: real, i: subrange(0, N - 2)):
      fp(0)`time < to + T IMPLIES i + 1 >= 0 AND i + 1 < N;

  % Subtype TCC generated (at line 250, column 43) for  N - 2
      % expected type  below[N - 1]
  trk_bands_si_equivalence_TCC1: OBLIGATION N - 2 >= 0 AND N - 2 < N - 1;

  % Subtype TCC generated (at line 254, column 57) for  i
      % expected type  nat
  trk_bands_si_equivalence_TCC2: OBLIGATION
    FORALL (so: Vect3, to: real, vo: Nzv2_vect3,
            fpr: FlightPlanRelevant_nz(to),
            trkb:
              {fs: (trk_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)}):
      trkb = trk_bands_si(so, vo, to, fpr)(N - 2) IMPLIES
       (FORALL (trk:
                  [real ->
                     (LAMBDA (vo2):
                        trk_only?(vect2(vo))(vect2(vo2)) AND vo`z = vo2`z)]):
          trk = trk2v3(vo) IMPLIES
           (FORALL (x: real, y: real):
              y <= 2 * pi AND x <= y AND 0 <= x IMPLIES
               (FORALL (i: subrange(0, trkb`length - 1)): i >= 0)));

  % Subtype TCC generated (at line 303, column 55) for  i
      % expected type  nat
  gs_bands_si_equivalence_TCC1: OBLIGATION
    FORALL (so: Vect3, to: real, vo: Nzv2_vect3,
            fpr: FlightPlanRelevant_nz(to),
            gsb: {fs: (gs_fseq?[gsmin, gsmax]) | increasing?[real, <=](fs)}):
      gsb = gs_bands_si(so, vo, to, fpr)(N - 2) IMPLIES
       (FORALL (gs: [real -> Vect3]):
          gs = gs2v3(vo) IMPLIES
           (FORALL (x: real, y: real):
              y <= gsmax AND x <= y AND gsmin <= x IMPLIES
               (FORALL (i: subrange(0, gsb`length - 1)): i >= 0)));

  % Subtype TCC generated (at line 353, column 55) for  i
      % expected type  nat
  vs_bands_si_equivalence_TCC1: OBLIGATION
    FORALL (so: Vect3, to: real, vo: Nzv2_vect3,
            fpr: FlightPlanRelevant_nz(to),
            vsb: {fs: (vs_fseq?[vsmin, vsmax]) | increasing?[real, <=](fs)}):
      vsb = vs_bands_si(so, vo, to, fpr)(N - 2) IMPLIES
       (FORALL (vs: [real -> (vs_only?(vo))]):
          vs = vs2v3(vo) IMPLIES
           (FORALL (x: real, y: real):
              y <= vsmax AND x <= y AND vsmin <= x IMPLIES
               (FORALL (i: subrange(0, vsb`length - 1)): i >= 0)));


body:
  cd3d_ii[D,H:posreal,T:posreal,N,M:above[1]]  : THEORY 
  BEGIN

    % note: T is the absolute max lookahead time (relative to the ownship's first waypoint time)
    %       N is the size of the ownship flightplan
    %	  M is the size of the intruder flightplan

    % So, effectively, both T and N are limits on the ownship flightplan

    IMPORTING flightplan,
              cd3d_si

    fp : VAR FlightPlan[N]

    % A flightplan where there is some actual overlap with the ownship plan fp (within lookahead time T)
    FlightPlanRelevant2(fp): 
          TYPE+ = {flp: FlightPlan[M] | flp(0)`time < fp(N-1)`time AND fp(0)`time < flp(M-1)`time AND flp(0)`time < fp(0)`time + T}

    % A time is relevant if there is more than 1 point of overlap between the two flightplans within the lookahead time
    % Does not consider the last points of either plan (velocities cannot be calculated here)
    FlightTimesRelevant2(fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)): 
          TYPE = {aa: real | fp(0)`time <= aa AND aa < fp(N-1)`time AND aa < fp(0)`time + T AND
                             fp2(0)`time <= aa AND aa < fp2(M-1)`time}

    % A limited time is a waypoint on the ownship's flight plan that occurs within or before the overlap of the two plans.
    FlightTimesLimited2(fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)):
          TYPE = {aa: FlightTimes[N](fp) | 
                  EXISTS(j:below[N-1]): aa = fp(j)`time AND fp(j+1)`time > fp2(0)`time AND aa < fp(0)`time + T AND aa < fp(N-1)`time 
                                                                                                               AND aa < fp2(M-1)`time}

    % There exists a conflict
    % so, vo are position & velocity at time to
    conflict_3D_ii?(fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)): bool =
      EXISTS (tt: FlightTimesRelevant2(fp,fp2)):
        horizontal_los?[D](location_at[N](fp)(tt) - location_at[M](fp2)(tt)) AND
        vertical_los?[H](location_at[N](fp)(tt)`z - location_at[M](fp2)(tt)`z)


    % various properties of segments and types
    seg_allowable: LEMMA
      FORALL (fp:FlightPlan[N], fp2:FlightPlanRelevant2(fp), t1: FlightTimesLimited2(fp,fp2), j:below[N]):
        j = segment(fp)(t1) IMPLIES 
        j < N-1 AND min(fp(1 + j)`time - fp(j)`time, fp(0)`time - fp(j)`time + T) > 0

    time_in_range: LEMMA
      FORALL (fp:FlightPlan[N], fp2:FlightPlanRelevant2(fp), t1: FlightTimesLimited2(fp,fp2)):
        LET 
          j = segment(fp)(t1)
        IN
        FORALL(t2: FlightTimesRelevant[D, H, 0, min(fp(1 + j)`time - fp(j)`time, fp(0)`time - fp(j)`time + T), M](fp(j)`time, fp2)):
          t2 <= fp(j+1)`time AND t2 <= fp(0)`time + T AND fp(0)`time <= t2 AND t1 = fp(j)`time

    limited_bounds: LEMMA
      FORALL (fp:FlightPlan[N], fp2:FlightPlanRelevant2(fp), jt: FlightTimesLimited2(fp,fp2), j:below[N]):
        segment(fp)(jt) = j IMPLIES
          fp2(0)`time < jt + min(fp(j+1)`time-fp(j)`time, fp(0)`time - fp(j)`time + T) AND
          jt < fp2(M-1)`time

    upper_seg_bounds: LEMMA
      FORALL (fp:FlightPlan[N], fp2:FlightPlanRelevant2(fp), jt: FlightTimesLimited2(fp,fp2), j:below[N]):
        segment(fp)(jt) = j IMPLIES
        min(fp(1 + j)`time - fp(j)`time, fp(0)`time - fp(j)`time + T) + jt <= fp(j+1)`time

    
    % rewriting conflict_3D_ii? in terms of cd3d_si.conflict_3D?
    cd3d_ii_rew: LEMMA
      FORALL (fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)):
      conflict_3D_ii?(fp,fp2) IFF
      EXISTS (tt:FlightTimesLimited2(fp,fp2)): 
        LET
          j = segment(fp)(tt),
          relT = T - (fp(j)`time - fp(0)`time),		% remaining overall lookahead time
  	t = min(fp(j+1)`time - fp(j)`time, relT),	% relative end time of ownship segment
  	so = fp(j)`position,
        	vo = velocity[N](fp)(j)
        IN
        conflict_3D?[D,H,0,t,M](so,tt,vo,fp2)


    % conflict_3D inductive definition version
    cd3d_ii_ind?(fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp))(j: below[N-1]): INDUCTIVE bool =
      LET
        relT = T - (fp(j)`time - fp(0)`time),	% remaining overall lookahead time
        t = min(fp(j+1)`time - fp(j)`time, relT),	% relative end time of ownship segment
        so = fp(j)`position,
        to = fp(j)`time,
        vo = velocity[N](fp)(j)
      IN
      IF relT > 0 AND (fp2(0)`time < min(fp(j+1)`time, fp(j)`time+relT) AND fp2(M-1)`time > fp(j)`time) THEN 
        cd3d_si?[D,H,0,t,M](so,vo,to,fp2)
      ELSE 
        FALSE 
      ENDIF 
      OR 
      (j>0 AND cd3d_ii_ind?(fp,fp2)(j-1))

    % if cd3d holds for some i, it holds for some j <= i
    some_cd3d_ii: LEMMA
      FORALL (fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp), i: below[N-1]):
      cd3d_ii_ind?(fp, fp2)(i) IFF 
      EXISTS (j: below[N-1]) :
      j <= i AND cd3d_ii_ind?(fp,fp2)(j)

    % main function
    cd3d_ii?(fp:FlightPlan[N], fp2:FlightPlanRelevant2(fp)): bool = cd3d_ii_ind?(fp,fp2)(N-2)

    % if cd3d_ii_ind says it is in conflict at or below some segement i, then there is a segment j<=i where 
    % conflict_ii_3d? says it is in conflict
    cd3d_ii_ind_correct: LEMMA 
      FORALL (fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)):
      	   (FORALL (i: below[N-1]): cd3d_ii_ind?(fp,fp2)(i) IMPLIES
      	   EXISTS (j: below[N-1]): 
             LET
  	     relT = T - (fp(j)`time - fp(0)`time),	% remaining overall lookahead time
  	     t = min(fp(j+1)`time - fp(j)`time, relT),	% relative end time of ownship segment
  	     so = fp(j)`position,
  	     to = fp(j)`time,
        	     vo = velocity[N](fp)(j)
             IN
  	   (j<=i AND 
             IF relT > 0 AND fp2(0)`time < min(fp(j+1)`time, fp(j)`time+relT) AND fp2(M-1)`time > fp(j)`time THEN
               conflict_3D?[D,H,0,t,M](so,to,vo,fp2)
             ELSE
               FALSE
             ENDIF))

    % if there is a segment j where conflict_3d? says it is in conflict, then cd3d_ind says it is in conflict at
    % segment i >= j 
    cd3d_ii_ind_complete: LEMMA
      FORALL (fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)):
      	   (FORALL (i: below[N-1]):
  	     EXISTS (j: below[N-1]): 
               LET
    	       relT = T - (fp(j)`time - fp(0)`time),	% remaining overall lookahead time
    	       t = min(fp(j+1)`time - fp(j)`time, relT),	% relative end time of ownship segment
  	       so = fp(j)`position,
  	       to = fp(j)`time,
        	       vo = velocity[N](fp)(j)
               IN
  	     (j<=i AND 
                 IF relT > 0 AND fp2(0)`time < min(fp(j+1)`time, fp(j)`time+relT) AND fp2(M-1)`time > fp(j)`time THEN
                   conflict_3D?[D,H,0,t,M](so,to,vo,fp2)
                 ELSE
                   FALSE
                 ENDIF)
  	     IMPLIES  
  	       cd3d_ii_ind?(fp,fp2)(i))

    % a version allowing unification of parameters
    cd3d_si_complete_parameters: LEMMA
      FORALL (so,vo:Vect3,to:real,t1: posreal, fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)):
             LET
               t2=t1
             IN
             fp2(0)`time < t2 + to AND to < fp2(M - 1)`time AND
      	   conflict_3D?[D,H,0,t1,M](so,to,vo,fp2) IMPLIES
  	   cd3d_si?[D,H,0,t2,M](so,vo,to,fp2)

    % main theorem, part 1
    cd3d_ii_correct: THEOREM
      FORALL (fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)):
      	   cd3d_ii?(fp,fp2) IMPLIES
  	   conflict_3D_ii?(fp,fp2)

    % main theorem, part 2
    cd3d_ii_complete: THEOREM
      FORALL (fp:FlightPlan[N],fp2:FlightPlanRelevant2(fp)):
      	   conflict_3D_ii?(fp,fp2) IMPLIES
  	   cd3d_ii?(fp,fp2)

  END cd3d_ii

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

  cd3d_ii_ind?_weak_induction: AXIOM
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            P: [below[N - 1] -> bool]):
      (FORALL (j: below[N - 1]):
         IF T - (fp(j)`time - fp(0)`time) > 0 AND
             (fp2(0)`time <
               min(fp(j + 1)`time,
                   fp(j)`time + (T - (fp(j)`time - fp(0)`time)))
               AND fp2(M - 1)`time > fp(j)`time)
           THEN cd3d_si?
                    [D, H, 0,
                     min(fp(1 + j)`time - fp(j)`time,
                         fp(0)`time - fp(j)`time + T),
                     M]
                    (fp(j)`position, velocity[N](fp)(j), fp(j)`time, fp2)
         ELSE FALSE
         ENDIF
          OR (j > 0 AND P(j - 1))
          IMPLIES P(j))
       IMPLIES
       (FORALL (j: below[N - 1]): cd3d_ii_ind?(fp, fp2)(j) IMPLIES P(j));

  cd3d_ii_ind?_induction: AXIOM
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            P: [below[N - 1] -> bool]):
      (FORALL (j: below[N - 1]):
         IF T - (fp(j)`time - fp(0)`time) > 0 AND
             (fp2(0)`time <
               min(fp(j + 1)`time,
                   fp(j)`time + (T - (fp(j)`time - fp(0)`time)))
               AND fp2(M - 1)`time > fp(j)`time)
           THEN cd3d_si?
                    [D, H, 0,
                     min(fp(1 + j)`time - fp(j)`time,
                         fp(0)`time - fp(j)`time + T),
                     M]
                    (fp(j)`position, velocity[N](fp)(j), fp(j)`time, fp2)
         ELSE FALSE
         ENDIF
          OR (j > 0 AND cd3d_ii_ind?(fp, fp2)(j - 1) AND P(j - 1))
          IMPLIES P(j))
       IMPLIES
       (FORALL (j: below[N - 1]): cd3d_ii_ind?(fp, fp2)(j) IMPLIES P(j));

  % Subtype TCC generated (at line 17, column 42) for  0
      % expected type  below[M]
  FlightPlanRelevant2_TCC1: OBLIGATION 0 < M;

  % Subtype TCC generated (at line 17, column 55) for  N - 1
      % expected type  below[N]
  FlightPlanRelevant2_TCC2: OBLIGATION N - 1 >= 0 AND N - 1 < N;

  % Subtype TCC generated (at line 17, column 72) for  0
      % expected type  below[N]
  FlightPlanRelevant2_TCC3: OBLIGATION
    FORALL (fp: FlightPlan[N], flp: FlightPlan[M]):
      flp(0)`time < fp(N - 1)`time IMPLIES 0 < N;

  % Subtype TCC generated (at line 17, column 86) for  M - 1
      % expected type  below[M]
  FlightPlanRelevant2_TCC4: OBLIGATION
    FORALL (fp: FlightPlan[N], flp: FlightPlan[M]):
      flp(0)`time < fp(N - 1)`time IMPLIES M - 1 >= 0 AND M - 1 < M;

  % Subtype TCC generated (at line 15, column 71) for  i - 1
      % expected type  below[M]
  FlightPlanRelevant2_TCC5: OBLIGATION
    FORALL (i: below[M]): i - 1 >= 0 IMPLIES i - 1 < M;

  % Existence TCC generated (at line 16, column 2) for
      % FlightPlanRelevant2(fp): TYPE+ =
      %       {flp: FlightPlan[M] |
      %                flp(0)`time < fp(N - 1)`time AND
      %                 fp(0)`time < flp(M - 1)`time AND
      %                  flp(0)`time < fp(0)`time + T}
  FlightPlanRelevant2_TCC6: OBLIGATION
    FORALL (fp: FlightPlan[N]):
      EXISTS (x:
                {flp: FlightPlan[M] |
                         flp(0)`time < fp(N - 1)`time AND
                          fp(0)`time < flp(M - 1)`time AND
                           flp(0)`time < fp(0)`time + T}):
        TRUE;

  % Subtype TCC generated (at line 22, column 30) for  0
      % expected type  below[N]
  FlightTimesRelevant2_TCC1: OBLIGATION 0 < N;

  % Subtype TCC generated (at line 23, column 58) for  M - 1
      % expected type  below[M]
  FlightTimesRelevant2_TCC2: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp), aa: real):
      fp2(0)`time <= aa AND
       aa < fp(0)`time + T AND aa < fp(N - 1)`time AND fp(0)`time <= aa
       IMPLIES M - 1 >= 0 AND M - 1 < M;

  % Subtype TCC generated (at line 28, column 31) for  N - 1
      % expected type  nat
  FlightTimesLimited2_TCC1: OBLIGATION N - 1 >= 0;

  % Subtype TCC generated (at line 28, column 46) for  j
      % expected type  below[N]
  FlightTimesLimited2_TCC2: OBLIGATION FORALL (j: below[N - 1]): j < N;

  % Subtype TCC generated (at line 28, column 61) for  j + 1
      % expected type  below[N]
  FlightTimesLimited2_TCC3: OBLIGATION
    FORALL (fp: FlightPlan[N], aa: FlightTimes[N](fp), j: below[N - 1]):
      aa = fp(j)`time IMPLIES j + 1 < N;

  % Subtype TCC generated (at line 29, column 122) for  M - 1
      % expected type  below[M]
  FlightTimesLimited2_TCC4: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            aa: FlightTimes[N](fp), j: below[N - 1]):
      aa < fp(N - 1)`time AND
       aa < fp(0)`time + T AND
        fp(j + 1)`time > fp2(0)`time AND aa = fp(j)`time
       IMPLIES M - 1 >= 0 AND M - 1 < M;

  % Subtype TCC generated (at line 35, column 44) for  tt
      % expected type  FlightTimes[N](fp)
  conflict_3D_ii?_TCC1: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            tt: FlightTimesRelevant2(fp, fp2)):
      start_time[N](fp) <= tt AND tt <= end_time[N](fp);

  % Subtype TCC generated (at line 35, column 70) for  tt
      % expected type  FlightTimes[M](fp2)
  conflict_3D_ii?_TCC2: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            tt: FlightTimesRelevant2(fp, fp2)):
      start_time[M](fp2) <= tt AND tt <= end_time[M](fp2);

  % Subtype TCC generated (at line 43, column 25) for  1 + j
      % expected type  below[N]
  seg_allowable_TCC1: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            t1: FlightTimesLimited2(fp, fp2), j: below[N]):
      j < N - 1 AND j = segment(fp)(t1) IMPLIES 1 + j < N;

  % Subtype TCC generated (at line 50, column 53) for  1 + j
      % expected type  below[N]
  time_in_range_TCC1: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            t1: FlightTimesLimited2(fp, fp2), j: below[N]):
      j = segment(fp)(t1) IMPLIES 1 + j < N;

  % Subtype TCC generated (at line 50, column 46) for
      % min(fp(1 + j)`time - fp(j)`time, fp(0)`time - fp(j)`time + T)
      % expected type  {AB: posreal | TRUE}
  time_in_range_TCC2: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            t1: FlightTimesLimited2(fp, fp2), j: below[N]):
      j = segment(fp)(t1) IMPLIES
       min(fp(1 + j)`time - fp(j)`time, fp(0)`time - fp(j)`time + T) >= 0 AND
        min(fp(1 + j)`time - fp(j)`time, fp(0)`time - fp(j)`time + T) > 0;

  % Subtype TCC generated (at line 51, column 17) for  j + 1
      % expected type  below[N]
  time_in_range_TCC3: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            t1: FlightTimesLimited2(fp, fp2), j: below[N]):
      j = segment(fp)(t1) IMPLIES
       (FORALL (t2:
                  FlightTimesRelevant
                      [D, H, 0,
                       min(fp(1 + j)`time - fp(j)`time,
                           fp(0)`time - fp(j)`time + T),
                       M](fp(j)`time, fp2)):
          j + 1 < N);

  % Subtype TCC generated (at line 56, column 34) for  j + 1
      % expected type  below[N]
  limited_bounds_TCC1: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            jt: FlightTimesLimited2(fp, fp2), j: below[N]):
      segment(fp)(jt) = j IMPLIES j + 1 < N;

  % Subtype TCC generated (at line 57, column 17) for  M - 1
      % expected type  below[M]
  limited_bounds_TCC2: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            jt: FlightTimesLimited2(fp, fp2), j: below[N]):
      fp2(0)`time <
       jt + min(fp(j + 1)`time - fp(j)`time, fp(0)`time - fp(j)`time + T)
       AND segment(fp)(jt) = j
       IMPLIES M - 1 >= 0 AND M - 1 < M;

  % Subtype TCC generated (at line 62, column 13) for  1 + j
      % expected type  below[N]
  upper_seg_bounds_TCC1: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            jt: FlightTimesLimited2(fp, fp2), j: below[N]):
      segment(fp)(jt) = j IMPLIES 1 + j < N;

  % Subtype TCC generated (at line 73, column 12) for  j + 1
      % expected type  below[N]
  cd3d_ii_rew_TCC1: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            tt: FlightTimesLimited2(fp, fp2), j: below[N]):
      j = segment(fp)(tt) IMPLIES
       (FORALL (relT: real):
          relT = T - (fp(j)`time - fp(0)`time) IMPLIES j + 1 < N);

  % Subtype TCC generated (at line 75, column 28) for  j
      % expected type  below[N - 1]
  cd3d_ii_rew_TCC2: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            tt: FlightTimesLimited2(fp, fp2), j: below[N]):
      j = segment(fp)(tt) IMPLIES
       (FORALL (relT: real):
          relT = T - (fp(j)`time - fp(0)`time) IMPLIES
           (FORALL (t:
                      {p: real |
                               p <= fp(1 + j)`time - fp(j)`time AND
                                p <= relT}):
              t = min(fp(j + 1)`time - fp(j)`time, relT) IMPLIES
               (FORALL (so: Vect3): so = fp(j)`position IMPLIES j < N - 1)));

  % Subtype TCC generated (at line 77, column 25) for  t
      % expected type  {AB: posreal | TRUE}
  cd3d_ii_rew_TCC3: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp),
            tt: FlightTimesLimited2(fp, fp2), j: below[N]):
      j = segment(fp)(tt) IMPLIES
       (FORALL (relT: real):
          relT = T - (fp(j)`time - fp(0)`time) IMPLIES
           (FORALL (t:
                      {p: real |
                               p <= fp(1 + j)`time - fp(j)`time AND
                                p <= relT}):
              t = min(fp(j + 1)`time - fp(j)`time, relT) IMPLIES
               (FORALL (so: Vect3):
                  so = fp(j)`position IMPLIES
                   (FORALL (vo: Vect3):
                      vo = velocity[N](fp)(j) IMPLIES t >= 0 AND t > 0))));

  % Subtype TCC generated (at line 84, column 17) for  j + 1
      % expected type  below[N]
  cd3d_ii_ind?_TCC1: OBLIGATION
    FORALL (fp: FlightPlan[N], j: below[N - 1], relT: real):
      relT = T - (fp(j)`time - fp(0)`time) IMPLIES j + 1 < N;

  % Subtype TCC generated (at line 89, column 78) for  M - 1
      % expected type  below[M]
  cd3d_ii_ind?_TCC2: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp), j: below[N - 1],
            relT: real):
      relT = T - (fp(j)`time - fp(0)`time) IMPLIES
       (FORALL (t:
                  {p: real |
                           p <= fp(1 + j)`time - fp(j)`time AND p <= relT}):
          t = min(fp(j + 1)`time - fp(j)`time, relT) IMPLIES
           (FORALL (so: Vect3):
              so = fp(j)`position IMPLIES
               (FORALL (to: real):
                  to = fp(j)`time IMPLIES
                   (FORALL (vo: Vect3):
                      fp2(0)`time < min(fp(j + 1)`time, fp(j)`time + relT)
                       AND relT > 0 AND vo = velocity[N](fp)(j)
                       IMPLIES M - 1 >= 0 AND M - 1 < M))));

  % Subtype TCC generated (at line 90, column 35) for  fp2
      % expected type  FlightPlanRelevant[D, H, 0, t, M](to)
  cd3d_ii_ind?_TCC3: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp), j: below[N - 1],
            relT: real):
      relT = T - (fp(j)`time - fp(0)`time) IMPLIES
       (FORALL (t:
                  {p: real |
                           p <= fp(1 + j)`time - fp(j)`time AND p <= relT}):
          t = min(fp(j + 1)`time - fp(j)`time, relT) IMPLIES
           (FORALL (so: Vect3):
              so = fp(j)`position IMPLIES
               (FORALL (to: real):
                  to = fp(j)`time IMPLIES
                   (FORALL (vo: Vect3):
                      relT > 0 AND
                       fp2(0)`time < min(fp(j + 1)`time, fp(j)`time + relT)
                        AND
                        fp2(M - 1)`time > fp(j)`time AND
                         vo = velocity[N](fp)(j)
                       IMPLIES
                       fp2(0)`time < t + to AND to < fp2(M - 1)`time))));

  % Subtype TCC generated (at line 90, column 21) for  t
      % expected type  {AB: posreal | TRUE}
  cd3d_ii_ind?_TCC4: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp), j: below[N - 1],
            relT: real):
      relT = T - (fp(j)`time - fp(0)`time) IMPLIES
       (FORALL (t:
                  {p: real |
                           p <= fp(1 + j)`time - fp(j)`time AND p <= relT}):
          t = min(fp(j + 1)`time - fp(j)`time, relT) IMPLIES
           (FORALL (so: Vect3):
              so = fp(j)`position IMPLIES
               (FORALL (to: real):
                  to = fp(j)`time IMPLIES
                   (FORALL (vo: Vect3):
                      relT > 0 AND
                       fp2(0)`time < min(fp(j + 1)`time, fp(j)`time + relT)
                        AND
                        fp2(M - 1)`time > fp(j)`time AND
                         vo = velocity[N](fp)(j)
                       IMPLIES t >= 0 AND t > 0))));

  % Subtype TCC generated (at line 95, column 34) for  j - 1
      % expected type  below[N - 1]
  cd3d_ii_ind?_TCC5: OBLIGATION
    FORALL (fp: FlightPlan[N], fp2: FlightPlanRelevant2(fp), j: below[N - 1],
            relT: real):
      relT = T - (fp(j)`time - fp(0)`time) IMPLIES
       (FORALL (t:
                  {p: real |
                           p <= fp(1 + j)`time - fp(j)`time AND p <= relT}):
          t = min(fp(j + 1)`time - fp(j)`time, relT) IMPLIES
           (FORALL (so: Vect3):
              so = fp(j)`position IMPLIES
               (FORALL (to: real):
                  to = fp(j)`time IMPLIES
                   (FORALL (vo: Vect3):
                      j > 0 AND
                       NOT ((relT > 0 AND
                              (fp2(0)`time <
                                min(fp(j + 1)`time, fp(j)`time + relT)
                                AND fp2(M - 1)`time > fp(j)`time))
                             AND cd3d_si?[D, H, 0, t, M](so, vo, to, fp2))
                        AND vo = velocity[N](fp)(j)
                       IMPLIES j - 1 >= 0 AND j - 1 < N - 1))));

  % Subtype TCC generated (at line 105, column 87) for  N - 2
      % expected type  below[N - 1]
  cd3d_ii?_TCC1: OBLIGATION N - 2 >= 0 AND N - 2 < N - 1;

  % Subtype TCC generated (at line 155, column 46) for  M - 1
      % expected type  below[M]
  cd3d_si_complete_parameters_TCC1: OBLIGATION
    FORALL (to: real, t1: posreal, fp: FlightPlan[N],
            fp2: FlightPlanRelevant2(fp), t2: posreal):
      fp2(0)`time < t2 + to AND t2 = t1 IMPLIES M - 1 >= 0 AND M - 1 < M;

  % Subtype TCC generated (at line 157, column 34) for  fp2
      % expected type  FlightPlanRelevant[D, H, 0, t2, M](to)
  cd3d_si_complete_parameters_TCC2: OBLIGATION
    FORALL (so, vo: Vect3, to: real, t1: posreal, fp: FlightPlan[N],
            fp2: FlightPlanRelevant2(fp), t2: posreal):
      fp2(0)`time < t2 + to AND
       to < fp2(M - 1)`time AND
        conflict_3D?[D, H, 0, t1, M](so, to, vo, fp2) AND t2 = t1
       IMPLIES fp2(0)`time < t2 + to AND to < fp2(M - 1)`time;


body:
  %
  % Repulsivity for horizontal vectors
  % This is a 2D theory. 
  % 

  repulsive : THEORY
  BEGIN

    IMPORTING horizontal,
    	    predicate_coordination_2D,
  	    vectors@basis_2D

    s,v,vo,vi,
    nv,nw,nh   : VAR Vect2
    nvo,nvi : VAR Vect2
    eps	  : VAR Sign
    cc	  : VAR posreal
    pt,px : VAR posreal
    

    % Time of closest approach
    tca(s,v) : real =
      IF zero_vect2?(v) THEN 0
      ELSE horizontal_tca(s,v)
      ENDIF

    repulsive?(s,v)(nv) : bool =
     LET tau1 = tca(s,v),
         tau2 = tca(s,nv) IN
       (s*v < 0 AND
       (tau2 <= 0 OR
       norm(s+tau1*v) < norm(s+tau2*nv)))
       OR
       (s*v>=0 AND (v = zero IMPLIES s*nv>=0) AND (v/=zero IMPLIES s*nv>s*v))

    repulsive_simple: LEMMA
      repulsive?(s,v)(nv) IMPLIES
      (s*v<0 AND tca(s,v)>0 AND
      (FORALL (t:nnreal): norm(s+t*nv)>=norm(s+tca(s,v)*v)))
      OR
      (s*v>=0 AND
      (FORALL (t:nnreal): norm(s+t*nv)>=norm(s))) 

    repulsive_transitive: LEMMA
      repulsive?(s,v)(nv) AND
      repulsive?(s,nv)(nw) IMPLIES
      repulsive?(s,v)(nw)

    not_repulsive_sum_closed: LEMMA
      sum_closed_2D?(LAMBDA (s,v): LAMBDA (nv): s*v<0 AND NOT repulsive?(s,v)(nv))

    repulsive_criteria(s,v,eps)(nv): bool =
      s  /= zero AND
      nv /= zero AND
      eps*det(s,v) <= 0 AND
      eps*det(s,nv) < 0 AND
      ((s*v < 0 AND
      eps*det(nv,v) < 0)
      OR
      (s*v>=0 AND (v = zero IMPLIES s*nv>=0) 
              AND (v/= zero IMPLIES s*nv> s*v)
  	    AND eps*det(nv,v) <= 0))

    repulsive_criteria_scal_s: LEMMA
      repulsive_criteria(s,v,eps)(nv) IFF
      repulsive_criteria(cc*s,v,eps)(nv)

    repulsive_criteria_scal_nv: LEMMA
      (s*v<0 AND (repulsive_criteria(s,v,eps)(cc*nv) IFF
      repulsive_criteria(s,v,eps)(nv)))
      OR
      (s*v>=0 AND (repulsive_criteria(s,v,eps)(cc*nv) IFF
      repulsive_criteria(s,(1/cc)*v,eps)(nv)))

    wedge_containment: LEMMA
      FORALL (e,f,g,h:Nz_vect2):
      (e*h>=0 AND f*h>0 AND g*h>0) AND
      (NOT (det(e,g)>=0 AND det(f,g)>0)) AND
      (NOT (det(e,g)<=0 AND det(f,g)<0)) AND
      e*v>=0 AND f*v>0 IMPLIES g*v>0

    repulsive_criteria_transitive: LEMMA
      repulsive_criteria(s,v,eps)(nv) AND
      repulsive_criteria(s,nv,eps)(nw) IMPLIES
      repulsive_criteria(s,v,eps)(nw)

    repulsive_criteria_transitive_odd1: LEMMA
      s*v<0 AND (s+pt*nv)*nv<0 AND
      repulsive_criteria(s,v,eps)(nv) AND
      repulsive_criteria(s+pt*nv,nv,eps)(nw) IMPLIES
      repulsive_criteria(s,v,eps)((s+pt*nv+px*nw)-s)

    rep_crit_odd2_ax: LEMMA
      FORALL(sx,sy,vx,vy,nvx,nvy,nwx,nwy:real,pt,px:posreal,eps:Sign) :
        px>0 AND pt>0
        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

    repulsive_criteria_transitive_odd2: LEMMA
      s*v<0 AND (s+pt*nv)*nv>=0  AND
      repulsive_criteria(s,v,eps)(nv) AND
      repulsive_criteria(s+pt*nv,nv,eps)(nw) AND eps*det(nw,v) < 0
      IMPLIES
      repulsive_criteria(s,v,eps)((s+pt*nv+px*nw)-s)

    repulsive_criteria_transitive_odd3: LEMMA
      s*v>=0 AND pt>=1 AND
      repulsive_criteria(s,v,eps)(nv) AND
      repulsive_criteria(s+pt*nv,nv,eps)(nw) IMPLIES
      repulsive_criteria(s,v,eps)((s+pt*nv+px*nw)-s)

    repulsive_criteria_sum_closed: LEMMA
      repulsive_criteria(s,v,eps)(nv) AND
      repulsive_criteria(s,v,eps)(nw) IMPLIES
      repulsive_criteria(s,v,eps)(nv+nw)

    repulsive_criteria_indep_of_length: LEMMA
      s*v < 0 IMPLIES
      FORALL (c:posreal):
      repulsive_criteria(s,v,eps)(nv) IFF
      repulsive_criteria(s,v,eps)(c*nv)

    repulsive_criteria_repulsive: LEMMA
      repulsive_criteria(s,v,eps)(nv)
      IMPLIES
      repulsive?(s,v)(nv)

    repulsive_criteria_repulsive2: LEMMA
      repulsive?(s,v)(nv)
      AND eps * det(s, v) <= 0 AND eps * det(s, nv) < 0 AND nv /= zero
      AND (s*v>=0 IMPLIES eps*det(nv,v)<=0)
      IMPLIES
      repulsive_criteria(s,v,eps)(nv)

    repulsive_criteria_symmetric: LEMMA
      repulsive_criteria(s,v,eps)(nv) IFF
      repulsive_criteria(-s,-v,eps)(-nv)

    repulsive_criteria_coordinately_repulsive: LEMMA
      repulsive_criteria(s,vo-vi,eps)(nvo-vi) AND
      repulsive_criteria(-s,vi-vo,eps)(nvi-vo)
      IMPLIES
      repulsive?(s,vo-vi)(nvo-nvi) 

    foo: LEMMA
      repulsive_criteria(s,vo-vi,eps)(nvo-vi) AND
      repulsive_criteria(-s,vi-vo,eps)(nvi-vo)
      IMPLIES
      repulsive?(s,vo-vi)(nvo-nvi) 

    repulsive_increases_dist: LEMMA
      repulsive?(s,v)(nv) IMPLIES
      (s*v<0 AND horizontal_tca(s,v)>0 AND v/=zero AND
        FORALL (nnt:nnreal): norm(s+nnt*nv)>norm(s+horizontal_tca(s,v)*v))
      OR
      (s*v>=0 AND v/=zero AND horizontal_tca(s,v)<=0 AND
        FORALL (pt:posreal): norm(s+pt*nv)>norm(s))
      OR
      (v=zero AND FORALL (nnt:nnreal): norm(s+nnt*nv)>=norm(s))

  END repulsive

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

  % Subtype TCC generated (at line 24, column 26) for  v
      % expected type  Nz_vect2
  tca_TCC1: OBLIGATION FORALL (v: Vect2): NOT v = zero IMPLIES v /= zero;

  % Subtype TCC generated (at line 161, column 32) for  v
      % expected type  Nz_vect2
  repulsive_increases_dist_TCC1: OBLIGATION
    FORALL (nv, s, v: Vect2):
      repulsive?(s, v)(nv) AND s * v < 0 IMPLIES v /= zero;


body:
  %
  % Karl Bilimoria's Geometric Optimization Algorithm
  % 

  kb[D:posreal] : THEORY
  BEGIN

    IMPORTING repulsive,
              track,
  	    trig_fnd@trig_values,
  	    trig_fnd@atan_values,
  	    horizontal[D],
  	    tangent_line[D]

    s       : VAR Ss_vect2
    vo,vi,v : VAR Nz_vect2
    nvo,nvi : VAR Vect2
    f,fo,fi : VAR nnreal
    eps,irt : VAR Sign
    p	  : VAR posreal
    x,y,r,
    phi	  : VAR real

    angle_from_to(x,y): {aa:real|aa>=-pi AND aa<pi} =
      to2pi((y-x) + pi)-pi

    % The next lemma proves with grind
    angle_from_to_id: LEMMA
      to2pi(x + angle_from_to(x,y)) = to2pi(y)

    angle_from_to_lt_pi: LEMMA abs(x-y)<pi IMPLIES
      angle_from_to(x,y) = y-x

    % The next lemma proves with (grind :exclude "pi")
    angle_from_to_test: LEMMA
      angle_from_to(2*pi,pi) = -pi AND
      angle_from_to(pi,2*pi) = -pi AND
      angle_from_to(pi/6,11*pi/6) = -pi/3 AND
      angle_from_to(pi/2,5*pi/3) = -5*pi/6 AND
      angle_from_to(pi/4,7*pi/6) = 11*pi/12 AND
      angle_from_to(7*pi/6,pi/4) = -11*pi/12 AND
      angle_from_to(0,2*pi) = 0 AND
      angle_from_to(2*pi,0) = 0 AND
      angle_from_to(3*pi/4,23*pi/12) = -5*pi/6 AND
      angle_from_to(23*pi/12,3*pi/4) = 5*pi/6 AND
      angle_from_to(17*pi/12,pi/6) = 3*pi/4 AND
      angle_from_to(pi/6,17*pi/12) = -3*pi/4 AND
      angle_from_to(34*pi + pi/4,-24*pi+7*pi/6) = 11*pi/12 AND
      angle_from_to(34*pi+17*pi/12,-18*pi+pi/6) = 3*pi/4

    chirel_star(s,v,f,eps) : nnreal_lt_2pi = 
      to2pi(track(v) + f*angle_from_to(track(v),track(-s) - eps*asin(D/norm(s))))

    chirel_star_equiv: LEMMA 
      abs(track(v) - (track(-s) - eps*asin(D/norm(s)))) < pi AND 
      f >= 0 AND 
      f<=1 
      IMPLIES
      chirel_star(s,v,f,eps) = to2pi(track(v)+f*(track(-s) - eps*asin(D/norm(s)) - track(v)))

    chirel_star_test: LEMMA
       D = 5 AND s = (-10/sqrt(3),0) AND
       vo = (2,0) AND
       vi = (1,0) IMPLIES
       track(vo) = pi/2 AND track(vi) = pi/2
       AND horizontal_conflict?(s,vo-vi) AND
       track(vo-vi) = pi/2 AND
       track(-s) = pi/2 AND
       norm(s) = 10/sqrt(3) AND
       chirel_star(s,vo-vi,1/2,-1) = 2*pi/3 AND
       chirel_star(s,vo-vi,1,-1) = 5*pi/6 AND
       chirel_star(s,vo-vi,0,-1) = pi/2

    chirel_star_0_id: LEMMA chirel_star(s,v,0,eps) = track(v)

    chirel_star_1_id: LEMMA chirel_star(s,v,1,eps) = to2pi(track(-s) - eps*asin(D/norm(s)))

    chirel_star_f_entry_scaf: LEMMA abs(phi)<=pi AND cos(r)<0 AND cos(r-phi)<0 AND f>=0 AND f<=1
      IMPLIES cos(r-f*phi)<0

    chirel_star_tangent: LEMMA line_solution?(s,trkgs2vect(chirel_star(s,v,1,eps),p),eps)

    chirel_star_f_entry: LEMMA f<1 AND s*v < 0 IMPLIES s*trkgs2vect(chirel_star(s,v,f,eps),p) < 0

    chi_hc(f,eps,irt)(s,vo,vi) : [nnreal_lt_2pi,bool] =
      LET v = vo - vi IN
        IF zero_vect2?(v) THEN (0,false) 
        ELSE 
          LET chirelstar = chirel_star(s,v,f,eps),
              expr       = (norm(vi)/norm(vo))*sin(chirelstar-track(vi)),
  	    asinex     = IF abs(expr) > 1 THEN FALSE ELSE asin(expr) ENDIF,
  	    exsign     = sign(asinex),	
  	    expidiff   = exsign*(pi/2)-asinex,
  	    arcsindir  = exsign*(pi/2)+irt*expidiff,
  	    theta      = to2pi(chirelstar - arcsindir),
  	    nvovect    = trkgs2vect(theta,norm(vo))
  	IN
            IF (abs(expr) > 1 OR s*(nvovect-vi)>=0) THEN (0,false)
            ELSE (theta,true)
            ENDIF
        ENDIF

    sin_track_minus: LEMMA
      vo-vi /= zero IMPLIES
      norm(vo)*sin(track(vo-vi)-track(vo)) = norm(vi)*sin(track(vo-vi)-track(vi))

    chi_hc_sin_equivalence_2: LEMMA
      LET ch = chi_hc(f,eps,irt)(s,vo,vi),
          nvo = trkgs2vect(ch`1,norm(vo))
      IN
      ch`2 IMPLIES
      norm(vi)*sin(chirel_star(s,vo-vi,f,eps) - track(vi)) = norm(vo)*sin(chirel_star(s,vo-vi,f,eps) - track(nvo))

    chi_hc_track_eq: LEMMA
      FORALL (v,w:Nz_vect2): v`y/=0 AND w`y/=0 AND v`x/v`y = w`x/w`y AND s*v<0 AND s*w<0 IMPLIES track(v) = track(w)

    chi_hc_1_chirel: LEMMA
      chi_hc(1,eps,irt)(s,vo,vi)`2 IMPLIES
      track(trkgs2vect(chi_hc(1,eps,irt)(s,vo,vi)`1,norm(vo)) - vi) = chirel_star(s,vo-vi,1,eps)

    chi_hc_f_chirel: LEMMA
      s*(vo-vi)<0 AND
      chi_hc(f,eps,irt)(s,vo,vi)`2 AND f < 1 IMPLIES
      track(trkgs2vect(chi_hc(f,eps,irt)(s,vo,vi)`1,norm(vo)) - vi) = chirel_star(s,vo-vi,f,eps)

    chi_hc_0_id: LEMMA 
        chi_hc(0,eps,-1)(s,vo,vi)`2 AND
        -pi/2 < track(vo-vi)-track(vo) AND
        track(vo-vi)-track(vo) < pi/2
      IMPLIES 
        chi_hc(0,eps,-1)(s,vo,vi)`1 = track(vo)

    chi_hc_0_id_rel: LEMMA
        chi_hc(0,eps,irt)(s,vo,vi)`2 AND
        -pi/2 < track(vo-vi)-track(vo) AND
        track(vo-vi)-track(vo) < pi/2 AND
        s*(vo-vi) < 0
      IMPLIES 
      LET
        nvo = trkgs2vect(chi_hc(0,eps,irt)(s,vo,vi)`1,norm(vo))
      IN
        track(nvo-vi) = track(vo-vi)

    kb(eps,irt,f)(s,vo,vi) : Vect2 =  
      LET (trk,b) = chi_hc(f,eps,irt)(s,vo,vi) IN
        IF b THEN trkgs2vect(trk,norm(vo)) 
        ELSE zero
        ENDIF

    kb_0_id : LEMMA
        chi_hc(0,eps,-1)(s,vo,vi)`2 AND
        -pi/2 < track(vo-vi)-track(vo) AND
        track(vo-vi)-track(vo) < pi/2 
      IMPLIES 
        kb(eps,-1,0)(s,vo,vi) = vo

    kb_tangent_line : LEMMA
          chi_hc(1,eps,irt)(s,vo,vi)`2 AND
          -pi/2 < track(vo-vi)-track(vo) AND
          track(vo-vi)-track(vo) < pi/2 
      IMPLIES
          line_solution?(s,kb(eps,irt,1)(s,vo,vi)-vi,eps)

    kb_is_independent : THEOREM
      horizontal_conflict?(s,vo-vi) AND
      abs(track(vo-vi)-track(vo)) < 0 AND
      abs(track(vi-vo)-track(vi)) < 0 AND
      nvo = kb(eps,irt,1)(s,vo,vi) AND
      nvo /= zero AND
      nvi = kb(eps,0,irt)(-s,vi,vo) AND
      nvi /= zero
      IMPLIES
        NOT horizontal_conflict?(s,nvo-vi)

    %% 3 Counterexamples to the claim that kb is coordinated with respect
    %% to the conflict-free safety property.

    kb_is_not_coordinated_1 : THEOREM
       D = 5 AND s = (-10/sqrt(3),0) AND
       vo = (2,0) AND
       vi = (1,0) AND
        nvo = kb(-1,-1,1/2)(s,vo,vi) AND
        nvi = kb(-1,-1,1/2)(-s,vi,vo)
        IMPLIES
        nvo /= zero AND
        nvi /= zero AND 
        horizontal_conflict?(s,vo-vi) AND
        horizontal_conflict?(s,nvo-nvi)

    kb_is_not_coordinated_2 : THEOREM
       D = 5 AND s = (-10/sqrt(3),0) AND
       vo = (500,0) AND
       vi = (250,0) AND
        nvo = kb(-1,-1,1/2)(s,vo,vi) AND
        nvi = kb(-1,-1,1/2)(-s,vi,vo)
        IMPLIES
        nvo /= zero AND
        nvi /= zero AND 
        horizontal_conflict?(s,vo-vi) AND
        horizontal_conflict?(s,nvo-nvi)

    % A different proof of the above result, this time showing
    % that minimum separation is less than 4.1
    kb_is_not_coordinated_3 : THEOREM
       D = 5 AND s = (-10/sqrt(3),0) AND
       vo = (500,0) AND
       vi = (250,0) AND
        nvo = kb(-1,-1,1/2)(s,vo,vi) AND
        nvi = kb(-1,-1,1/2)(-s,vi,vo)
        IMPLIES
        nvo /= zero AND
        nvi /= zero AND 
        horizontal_conflict?(s,vo-vi) AND
        horizontal_conflict?(s,nvo-nvi)

  END kb

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

  % Subtype TCC generated (at line 25, column 4) for  to2pi((y - x) + pi) - pi
      % expected type  {aa: real | aa >= -pi AND aa < pi}
  angle_from_to_TCC1: OBLIGATION
    FORALL (x: real, y: real):
      to2pi((y - x) + pi) - pi >= -pi AND to2pi((y - x) + pi) - pi < pi;

  % Subtype TCC generated (at line 52, column 67) for  D / norm(s)
      % expected type  real_abs_le1
  chirel_star_TCC1: OBLIGATION
    FORALL (s: Ss_vect2[D], v: Nz_vect2):
      -1 <= D / norm(s) AND D / norm(s) <= 1;

  % Subtype TCC generated (at line 55, column 41) for  D / norm(s)
      % expected type  real_abs_le1
  chirel_star_equiv_TCC1: OBLIGATION
    FORALL (s: Ss_vect2[D]): -1 <= D / norm(s) AND D / norm(s) <= 1;

  % Subtype TCC generated (at line 67, column 11) for  vo - vi
      % expected type  Nz_vect2
  chirel_star_test_TCC1: OBLIGATION
    FORALL (s: Ss_vect2[D], vi, vo: Nz_vect2):
           vi = (# x := 1, y := 0 #) AND vo = (# x := 2, y := 0 #)
       AND s = (# x := -10 / sqrt(3), y := 0 #) AND D = 5
       AND track(vo) = pi / 2 AND track(vi) = pi / 2
       AND horizontal_conflict?(s, vo - vi)
       IMPLIES vo - vi /= zero;

  % Subtype TCC generated (at line 87, column 30) for  0
      % expected type  nnreal_lt_2pi
  chi_hc_TCC1: OBLIGATION
    FORALL (s: Ss_vect2[D], vo: Nz_vect2, vi: Nz_vect2, v: Vector):
      v = zero AND v = vo - vi IMPLIES 0 < 2 * pi;

  % Subtype TCC generated (at line 89, column 39) for  v
      % expected type  Nz_vect2
  chi_hc_TCC2: OBLIGATION
    FORALL (s: Ss_vect2[D], vo: Nz_vect2, vi: Nz_vect2, v: Vector):
      NOT v = zero AND v = vo - vi IMPLIES v /= zero;

  % Subtype TCC generated (at line 91, column 56) for  expr
      % expected type  real_abs_le1
  chi_hc_TCC3: OBLIGATION
    FORALL (f: nnreal, eps: Sign, s: Ss_vect2[D], vo: Nz_vect2, vi: Nz_vect2,
            v: Vector):
      NOT v = zero AND v = vo - vi IMPLIES
       (FORALL (chirelstar: nnreal_lt_2pi):
          chirelstar = chirel_star(s, v, f, eps) IMPLIES
           (FORALL (expr: real):
              NOT abs(expr) > 1 AND
               expr = (norm(vi) / norm(vo)) * sin(chirelstar - track(vi))
               IMPLIES -1 <= expr AND expr <= 1));

  % Subtype TCC generated (at line 98, column 56) for  0
      % expected type  nnreal_lt_2pi
  chi_hc_TCC4: OBLIGATION
    FORALL (f: nnreal, eps: Sign, irt: Sign, s: Ss_vect2[D], vo: Nz_vect2,
            vi: Nz_vect2, v: Vector):
      NOT v = zero AND v = vo - vi IMPLIES
       (FORALL (chirelstar: nnreal_lt_2pi):
          chirelstar = chirel_star(s, v, f, eps) IMPLIES
           (FORALL (expr: real):
              expr = (norm(vi) / norm(vo)) * sin(chirelstar - track(vi))
               IMPLIES
               (FORALL (asinex: real):
                  asinex =
                   IF abs(expr) > 1 THEN b2n(FALSE) ELSE asin(expr) ENDIF
                   IMPLIES
                   (FORALL (exsign: Sign):
                      exsign = sign(asinex) IMPLIES
                       (FORALL (expidiff: real):
                          expidiff = exsign * (pi / 2) - asinex IMPLIES
                           (FORALL (arcsindir: real):
                              arcsindir = exsign * (pi / 2) + irt * expidiff
                               IMPLIES
                               (FORALL (theta: nnreal_lt_2pi):
                                  theta = to2pi(chirelstar - arcsindir)
                                   IMPLIES
                                   (FORALL (nvovect: Nz_vect2):
                                      (abs(expr) > 1
                                       OR
                                       s * (nvovect - vi) >= 0)
                                      AND
                                      nvovect = trkgs2vect(theta, norm(vo))
                                      IMPLIES
                                      0 < 2 * pi))))))));

  % Subtype TCC generated (at line 112, column 31) for  vo - vi
      % expected type  Nz_vect2
  chi_hc_sin_equivalence_2_TCC1: OBLIGATION
    FORALL (eps: Sign, f: nnreal, irt: Sign, s: Ss_vect2[D],
            vi, vo: Nz_vect2, ch: [nnreal_lt_2pi, bool]):
      ch = chi_hc(f, eps, irt)(s, vo, vi) IMPLIES
       (FORALL (nvo: Nz_vect2):
          ch`2 AND nvo = trkgs2vect(ch`1, norm(vo)) IMPLIES vo - vi /= zero);

  % Subtype TCC generated (at line 119, column 10) for
      % trkgs2vect(chi_hc(1, eps, irt)(s, vo, vi)`1, norm(vo)) - vi
      % expected type  Nz_vect2
  chi_hc_1_chirel_TCC1: OBLIGATION
    FORALL (eps, irt: Sign, s: Ss_vect2[D], vi, vo: Nz_vect2):
      chi_hc(1, eps, irt)(s, vo, vi)`2 IMPLIES
       trkgs2vect(chi_hc(1, eps, irt)(s, vo, vi)`1, norm(vo)) - vi /= zero;

  % Subtype TCC generated (at line 119, column 82) for  vo - vi
      % expected type  Nz_vect2
  chi_hc_1_chirel_TCC2: OBLIGATION
    FORALL (eps, irt: Sign, s: Ss_vect2[D], vi, vo: Nz_vect2):
      chi_hc(1, eps, irt)(s, vo, vi)`2 IMPLIES vo - vi /= zero;

  % Subtype TCC generated (at line 124, column 10) for
      % trkgs2vect(chi_hc(f, eps, irt)(s, vo, vi)`1, norm(vo)) - vi
      % expected type  Nz_vect2
  chi_hc_f_chirel_TCC1: OBLIGATION
    FORALL (eps: Sign, f: nnreal, irt: Sign, s: Ss_vect2[D],
            vi, vo: Nz_vect2):
      f < 1 AND chi_hc(f, eps, irt)(s, vo, vi)`2 AND s * (vo - vi) < 0
       IMPLIES
       trkgs2vect(chi_hc(f, eps, irt)(s, vo, vi)`1, norm(vo)) - vi /= zero;

  % Subtype TCC generated (at line 124, column 82) for  vo - vi
      % expected type  Nz_vect2
  chi_hc_f_chirel_TCC2: OBLIGATION
    FORALL (eps: Sign, f: nnreal, irt: Sign, s: Ss_vect2[D],
            vi, vo: Nz_vect2):
      f < 1 AND chi_hc(f, eps, irt)(s, vo, vi)`2 AND s * (vo - vi) < 0
       IMPLIES vo - vi /= zero;

  % Subtype TCC generated (at line 128, column 20) for  vo - vi
      % expected type  Nz_vect2
  chi_hc_0_id_TCC1: OBLIGATION
    FORALL (eps: Sign, s: Ss_vect2[D], vi, vo: Nz_vect2):
      chi_hc(0, eps, -1)(s, vo, vi)`2 IMPLIES vo - vi /= zero;

  % Subtype TCC generated (at line 135, column 20) for  vo - vi
      % expected type  Nz_vect2
  chi_hc_0_id_rel_TCC1: OBLIGATION
    FORALL (eps, irt: Sign, s: Ss_vect2[D], vi, vo: Nz_vect2):
      chi_hc(0, eps, irt)(s, vo, vi)`2 IMPLIES vo - vi /= zero;

  % Subtype TCC generated (at line 142, column 12) for  nvo - vi
      % expected type  Nz_vect2
  chi_hc_0_id_rel_TCC2: OBLIGATION
    FORALL (eps, irt: Sign, s: Ss_vect2[D], vi, vo: Nz_vect2):
      s * (vo - vi) < 0 AND
       track(vo - vi) - track(vo) < pi / 2 AND
        -pi / 2 < track(vo - vi) - track(vo) AND
         chi_hc(0, eps, irt)(s, vo, vi)`2
       IMPLIES
       (FORALL (nvo: Nz_vect2):
          nvo = trkgs2vect(chi_hc(0, eps, irt)(s, vo, vi)`1, norm(vo))
           IMPLIES nvo - vi /= zero);

  % Subtype TCC generated (at line 166, column 14) for  vo - vi
      % expected type  Nz_vect2
  kb_is_independent_TCC1: OBLIGATION
    FORALL (s: Ss_vect2[D], vi, vo: Nz_vect2):
      horizontal_conflict?(s, vo - vi) IMPLIES vo - vi /= zero;

  % Subtype TCC generated (at line 167, column 14) for  vi - vo
      % expected type  Nz_vect2
  kb_is_independent_TCC2: OBLIGATION
    FORALL (s: Ss_vect2[D], vi, vo: Nz_vect2):
      horizontal_conflict?(s, vo - vi) AND
       abs(track(vo - vi) - track(vo)) < 0
       IMPLIES vi - vo /= zero;

  % Subtype TCC generated (at line 170, column 17) for  0
      % expected type  Sign
  kb_is_independent_TCC3: OBLIGATION
    FORALL (eps, irt: Sign, nvo: Vect2, s: Ss_vect2[D], vi, vo: Nz_vect2):
           horizontal_conflict?(s, vo - vi)
       AND abs(track(vo - vi) - track(vo)) < 0
       AND abs(track(vi - vo) - track(vi)) < 0
       AND nvo = kb(eps, irt, 1)(s, vo, vi) AND nvo /= zero
       IMPLIES (0 = 1 OR 0 = -1) AND 0 /= 0;

  % Subtype TCC generated (at line 170, column 19) for  irt
      % expected type  nnreal
  kb_is_independent_TCC4: OBLIGATION
    FORALL (eps, irt: Sign, nvo: Vect2, s: Ss_vect2[D], vi, vo: Nz_vect2):
           horizontal_conflict?(s, vo - vi)
       AND abs(track(vo - vi) - track(vo)) < 0
       AND abs(track(vi - vo) - track(vi)) < 0
       AND nvo = kb(eps, irt, 1)(s, vo, vi) AND nvo /= zero
       IMPLIES irt >= 0;


body:
  % LOS recovery with an iterative algorithm

  losr_iterative : THEORY
  BEGIN

    IMPORTING repulsive,reals@sign3,trig@sincos

    s,v,vo,vi   : VAR Nz_vect2
    nvo,nvo2    : VAR Vect2
    minrelgs    : VAR nnreal
    step	      : VAR posreal
    eps,dir     : VAR Sign
    maxtrk, 
    maxgs,mings : VAR posreal 
    i 	      : VAR posnat

    %% dir = 1 is right
    incr_trk_vect(nvo,step,dir): {nvo2: Vect2 | trk_only?(nvo)(nvo2)} =
      cos(dir*step)*nvo + sin(dir*step)*perpR(nvo)

    losr_trk_iter_dir(s,vo,vi,step,eps): Sign3 =
      IF repulsive_criteria(s,vo-vi,eps)(incr_trk_vect(vo,step,1)-vi)
        THEN 1
      ELSIF repulsive_criteria(s,vo-vi,eps)(incr_trk_vect(vo,step,-1)-vi)
        THEN -1
      ELSE 0 ENDIF

    losr_trk_iter_i(s,vo,vi,minrelgs,maxtrk,step,i,dir,eps,
                   (nvo | trk_only?(vo)(nvo) AND
                          repulsive_criteria(s,vo-vi,eps)(nvo-vi))): 
      RECURSIVE {nvo2 | nz_vect2?(nvo2) => 
                   trk_only?(vo)(nvo2) AND
                   repulsive_criteria(s,vo-vi,eps)(nvo2-vi)} =
        LET nvop = incr_trk_vect(nvo,step,dir) IN 
        IF i*step >= maxtrk OR NOT repulsive_criteria(s,nvo-vi,eps)(nvop-vi) THEN
          nvo
        ELSIF divergent?(s,nvop-vi) AND norm(nvop-vi) >= minrelgs THEN
          nvop
        ELSE 
          losr_trk_iter_i(s,vo,vi,minrelgs,maxtrk,step,i+1,dir,eps,nvop)
        ENDIF
    MEASURE max(0,floor(maxtrk/step)-i+1)

    losr_trk_iter(s,vo,vi,minrelgs,maxtrk,step):  
      {nvo | nz_vect2?(nvo) => 
         trk_only?(vo)(nvo) AND
         repulsive_criteria(s,vo-vi,-sign(det(s,vo-vi)))(nvo-vi)} = 
      LET eps = -sign(det(s,vo-vi)),
          dir3 = losr_trk_iter_dir(s,vo,vi,step,eps) IN
      IF dir3 = 0 THEN
        zero
      ELSE LET nvo = incr_trk_vect(vo,step,dir3) IN 
        IF repulsive_criteria(s,vo-vi,eps)(nvo-vi) THEN
          losr_trk_iter_i(s,vo,vi,minrelgs,maxtrk,step,1,dir3,eps,nvo)
        ELSE 
          zero
        ENDIF
      ENDIF

    %% dir = 1 is right
    incr_gs_vect(vo,step,dir): {nvo: Vect2 | norm(vo)+dir*step > 0 IMPLIES gs_only?(vo)(nvo)} =
      (norm(vo)+dir*step)*^(vo)

    losr_gs_iter_dir(s,vo,vi,mings,maxgs,step,eps): Sign3 =
      IF norm(vo) + step <= maxgs AND repulsive_criteria(s,vo-vi,eps)(incr_gs_vect(vo,step,1)-vi)
        THEN 1
      ELSIF norm(vo) - step >= mings AND repulsive_criteria(s,vo-vi,eps)(incr_gs_vect(vo,step,-1)-vi)
        THEN -1
      ELSE 0 ENDIF

    losr_gs_iter_i(s,vo,vi,minrelgs,mings,maxgs,step,i,dir,eps,
                  (nvo | nvo = (norm(vo)+dir*i*step)*^(vo) AND norm(vo)+dir*i*step > 0 AND 
                          repulsive_criteria(s,vo-vi,eps)(nvo-vi))): 
      RECURSIVE {nvo2 | nz_vect2?(nvo2) => 
                   gs_only?(vo)(nvo2) AND
                   repulsive_criteria(s,vo-vi,eps)(nvo2-vi)} =
        LET nvop = incr_gs_vect(nvo,step,dir),
            nnorm = norm(nvo)+dir*step IN 
        IF nnorm > maxgs OR nnorm < mings OR NOT repulsive_criteria(s,nvo-vi,eps)(nvop-vi) THEN
          nvo
        ELSIF divergent?(s,nvop-vi) AND norm(nvop-vi) >= minrelgs THEN
          nvop
        ELSE 
          losr_gs_iter_i(s,vo,vi,minrelgs,mings,maxgs,step,i+1,dir,eps,nvop)
        ENDIF
    MEASURE max(0,floor(IF dir >= 0 THEN (maxgs-norm(vo))/step ELSE (norm(vo)-mings)/step ENDIF)-i+1)

    losr_gs_iter(s,vo,vi,minrelgs,mings,maxgs,step):  
      {nvo | nz_vect2?(nvo) => 
         gs_only?(vo)(nvo) AND
         repulsive_criteria(s,vo-vi,-sign(det(s,vo-vi)))(nvo-vi)} = 
      LET eps = -sign(det(s,vo-vi)),
          dir3 = losr_gs_iter_dir(s,vo,vi,mings,maxgs,step,eps) IN
      IF dir3 = 0 THEN
        zero
      ELSE LET nvo = incr_gs_vect(vo,step,dir3) IN
        IF repulsive_criteria(s,vo-vi,eps)(nvo-vi) THEN
          losr_gs_iter_i(s,vo,vi,minrelgs,mings,maxgs,step,1,dir3,eps,nvo)
        ELSE 
          zero
        ENDIF
      ENDIF

  END losr_iterative

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

  % Subtype TCC generated (at line 19, column 4) for
      % cos(dir * step) * nvo + sin(dir * step) * perpR(nvo)
      % expected type  {nvo2: Vect2 | trk_only?(nvo)(nvo2)}
  incr_trk_vect_TCC1: OBLIGATION
    FORALL (nvo: Vect2, step: posreal, dir: Sign):
      trk_only?(nvo)(cos(dir * step) * nvo + sin(dir * step) * perpR(nvo));

  % Subtype TCC generated (at line 42, column 10) for
      % max(0, floor(maxtrk / step) - i + 1)
      % expected type  naturalnumber
  losr_trk_iter_i_TCC1: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, maxtrk: posreal,
            step: posreal, i: posnat, eps: Sign,
            (nvo: Vect2
                 | trk_only?(vo)(nvo) AND
                    repulsive_criteria(s, vo - vi, eps)(nvo - vi))):
      max(0, floor(maxtrk / step) - i + 1) >= 0;

  % Subtype TCC generated (at line 36, column 8) for  nvo
      % expected type  {nvo2 |
                     %          nvo2 /= zero =>
                     %           trk_only?(vo)(nvo2) AND
                     %            repulsive_criteria(s, vo - vi, eps)
                     %                              (nvo2 - vi)}
  losr_trk_iter_i_TCC2: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, maxtrk: posreal,
            step: posreal, i: posnat, dir: Sign, eps: Sign,
            (nvo: Vect2
                 | trk_only?(vo)(nvo) AND
                    repulsive_criteria(s, vo - vi, eps)(nvo - vi)),
            nvop: {nvo2: Vect2 | trk_only?(nvo)(nvo2)}):
      (i * step >= maxtrk OR
        NOT repulsive_criteria(s, nvo - vi, eps)(nvop - vi))
       AND nvop = incr_trk_vect(nvo, step, dir)
       IMPLIES
       nvo /= zero =>
        trk_only?(vo)(nvo) AND repulsive_criteria(s, vo - vi, eps)(nvo - vi);

  % Subtype TCC generated (at line 38, column 8) for  nvop
      % expected type  {nvo2 |
                     %          nvo2 /= zero =>
                     %           trk_only?(vo)(nvo2) AND
                     %            repulsive_criteria(s, vo - vi, eps)
                     %                              (nvo2 - vi)}
  losr_trk_iter_i_TCC3: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, minrelgs: nnreal,
            maxtrk: posreal, step: posreal, i: posnat, dir: Sign, eps: Sign,
            (nvo: Vect2
                 | trk_only?(vo)(nvo) AND
                    repulsive_criteria(s, vo - vi, eps)(nvo - vi)),
            nvop: {nvo2: Vect2 | trk_only?(nvo)(nvo2)}):
           divergent?(s, zero, nvop - vi, zero)
       AND norm(nvop - vi) >= minrelgs AND NOT i * step >= maxtrk
       AND repulsive_criteria(s, nvo - vi, eps)(nvop - vi)
       AND nvop = incr_trk_vect(nvo, step, dir)
       IMPLIES
       nvop /= zero =>
        trk_only?(vo)(nvop) AND
         repulsive_criteria(s, vo - vi, eps)(nvop - vi);

  % Subtype TCC generated (at line 40, column 65) for  nvop
      % expected type  {nvo |
                     %          trk_only?(vo)(nvo) AND
                     %           repulsive_criteria(s, vo - vi, eps)
                     %                             (nvo - vi)}
  losr_trk_iter_i_TCC4: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, minrelgs: nnreal,
            maxtrk: posreal, step: posreal, i: posnat, dir: Sign, eps: Sign,
            (nvo: Vect2
                 | trk_only?(vo)(nvo) AND
                    repulsive_criteria(s, vo - vi, eps)(nvo - vi)),
            nvop: {nvo2: Vect2 | trk_only?(nvo)(nvo2)}):
      NOT (divergent?(s, zero, nvop - vi, zero) AND
            norm(nvop - vi) >= minrelgs)
       AND
       NOT i * step >= maxtrk AND
        repulsive_criteria(s, nvo - vi, eps)(nvop - vi) AND
         nvop = incr_trk_vect(nvo, step, dir)
       IMPLIES
       trk_only?(vo)(nvop) AND repulsive_criteria(s, vo - vi, eps)(nvop - vi);

  % Termination TCC generated (at line 40, column 8) for
      % losr_trk_iter_i(s, vo, vi, minrelgs, maxtrk, step, i + 1, dir, eps,
      %                 nvop)
  losr_trk_iter_i_TCC5: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, minrelgs: nnreal,
            maxtrk: posreal, step: posreal, i: posnat, dir: Sign, eps: Sign,
            (nvo: Vect2
                 | trk_only?(vo)(nvo) AND
                    repulsive_criteria(s, vo - vi, eps)(nvo - vi)),
            nvop: {nvo2: Vect2 | trk_only?(nvo)(nvo2)}):
      NOT (divergent?(s, zero, nvop - vi, zero) AND
            norm(nvop - vi) >= minrelgs)
       AND
       NOT i * step >= maxtrk AND
        repulsive_criteria(s, nvo - vi, eps)(nvop - vi) AND
         nvop = incr_trk_vect(nvo, step, dir)
       IMPLIES
       max(0, floor(maxtrk / step) - (i + 1) + 1) <
        max(0, floor(maxtrk / step) - i + 1);

  % Subtype TCC generated (at line 51, column 6) for  zero
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           trk_only?(vo)(nvo) AND
                     %            repulsive_criteria(s,
                     %                               vo - vi,
                     %                               -sign(det(s, vo - vi)))
                     %                              (nvo - vi)}
  losr_trk_iter_TCC1: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, step: posreal,
            eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          dir3 = 0 AND dir3 = losr_trk_iter_dir(s, vo, vi, step, eps) IMPLIES
           zero /= zero =>
            trk_only?(vo)(zero) AND
             repulsive_criteria(s, vo - vi, -sign(det(s, vo - vi)))
                               (zero - vi));

  % Subtype TCC generated (at line 52, column 41) for  dir3
      % expected type  Sign
  losr_trk_iter_TCC2: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, step: posreal,
            eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          NOT dir3 = 0 AND dir3 = losr_trk_iter_dir(s, vo, vi, step, eps)
           IMPLIES dir3 /= 0 AND (dir3 = 1 OR dir3 = -1));

  % Subtype TCC generated (at line 54, column 64) for  nvo
      % expected type  {nvo |
                     %          trk_only?(vo)(nvo) AND
                     %           repulsive_criteria(s, vo - vi, eps)
                     %                             (nvo - vi)}
  losr_trk_iter_TCC3: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, step: posreal,
            eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          NOT dir3 = 0 AND dir3 = losr_trk_iter_dir(s, vo, vi, step, eps)
           IMPLIES
           (FORALL (nvo: {nvo2: Vect2 | trk_only?(vo)(nvo2)}):
              repulsive_criteria(s, vo - vi, eps)(nvo - vi) AND
               nvo = incr_trk_vect(vo, step, dir3)
               IMPLIES
               trk_only?(vo)(nvo) AND
                repulsive_criteria(s, vo - vi, eps)(nvo - vi)));

  % Subtype TCC generated (at line 54, column 8) for
      % losr_trk_iter_i(s, vo, vi, minrelgs, maxtrk, step, 1, dir3, eps, nvo)
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           trk_only?(vo)(nvo) AND
                     %            repulsive_criteria(s,
                     %                               vo - vi,
                     %                               -sign(det(s, vo - vi)))
                     %                              (nvo - vi)}
  losr_trk_iter_TCC4: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, minrelgs: nnreal,
            maxtrk: posreal, step: posreal, eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          NOT dir3 = 0 AND dir3 = losr_trk_iter_dir(s, vo, vi, step, eps)
           IMPLIES
           (FORALL (nvo: {nvo2: Vect2 | trk_only?(vo)(nvo2)}):
              repulsive_criteria(s, vo - vi, eps)(nvo - vi) AND
               nvo = incr_trk_vect(vo, step, dir3)
               IMPLIES
               losr_trk_iter_i(s, vo, vi, minrelgs, maxtrk, step, 1, dir3,
                               eps, nvo)
                /= zero
                =>
                trk_only?(vo)
                         (losr_trk_iter_i(s,
                                          vo,
                                          vi,
                                          minrelgs,
                                          maxtrk,
                                          step,
                                          1,
                                          dir3,
                                          eps,
                                          nvo))
                 AND
                 repulsive_criteria(s, vo - vi, -sign(det(s, vo - vi)))
                                   (losr_trk_iter_i(s,
                                                    vo,
                                                    vi,
                                                    minrelgs,
                                                    maxtrk,
                                                    step,
                                                    1,
                                                    dir3,
                                                    eps,
                                                    nvo)
                                     - vi)));

  % Subtype TCC generated (at line 56, column 8) for  zero
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           trk_only?(vo)(nvo) AND
                     %            repulsive_criteria(s,
                     %                               vo - vi,
                     %                               -sign(det(s, vo - vi)))
                     %                              (nvo - vi)}
  losr_trk_iter_TCC5: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, step: posreal,
            eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          NOT dir3 = 0 AND dir3 = losr_trk_iter_dir(s, vo, vi, step, eps)
           IMPLIES
           (FORALL (nvo: {nvo2: Vect2 | trk_only?(vo)(nvo2)}):
              NOT repulsive_criteria(s, vo - vi, eps)(nvo - vi) AND
               nvo = incr_trk_vect(vo, step, dir3)
               IMPLIES
               zero /= zero =>
                trk_only?(vo)(zero) AND
                 repulsive_criteria(s, vo - vi, -sign(det(s, vo - vi)))
                                   (zero - vi)));

  % Subtype TCC generated (at line 62, column 4) for
      % (norm(vo) + dir * step) * ^(vo)
      % expected type  {nvo: Vect2 |
                     %          norm(vo) + dir * step > 0 IMPLIES
                     %           gs_only?(vo)(nvo)}
  incr_gs_vect_TCC1: OBLIGATION
    FORALL (vo: Nz_vect2, step: posreal, dir: Sign):
      norm(vo) + dir * step > 0 IMPLIES
       gs_only?(vo)((norm(vo) + dir * step) * ^(vo));

  % Subtype TCC generated (at line 86, column 10) for
      % max(0,
      %     floor(IF dir >= 0 THEN (maxgs - norm(vo)) / step
      %           ELSE (norm(vo) - mings) / step
      %           ENDIF)
      %      - i
      %      + 1)
      % expected type  naturalnumber
  losr_gs_iter_i_TCC1: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, mings: posreal,
            maxgs: posreal, step: posreal, i: posnat, dir: Sign, eps: Sign,
            (nvo: Vect2
                 | nvo = (norm(vo) + dir * i * step) * ^(vo) AND
                    norm(vo) + dir * i * step > 0 AND
                     repulsive_criteria(s, vo - vi, eps)(nvo - vi))):
      max(0,
          floor(IF dir >= 0 THEN (maxgs - norm(vo)) / step
                ELSE (norm(vo) - mings) / step
                ENDIF)
           - i
           + 1)
       >= 0;

  % Subtype TCC generated (at line 80, column 8) for  nvo
      % expected type  {nvo2 |
                     %          nvo2 /= zero =>
                     %           gs_only?(vo)(nvo2) AND
                     %            repulsive_criteria(s, vo - vi, eps)
                     %                              (nvo2 - vi)}
  losr_gs_iter_i_TCC2: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, mings: posreal,
            maxgs: posreal, step: posreal, i: posnat, dir: Sign, eps: Sign,
            (nvo: Vect2
                 | nvo = (norm(vo) + dir * i * step) * ^(vo) AND
                    norm(vo) + dir * i * step > 0 AND
                     repulsive_criteria(s, vo - vi, eps)(nvo - vi)),
            nvop:
              {nvo_1: Vect2 |
                       norm(nvo) + dir * step > 0 IMPLIES
                        gs_only?(nvo)(nvo_1)}):
      nvop = incr_gs_vect(nvo, step, dir) IMPLIES
       (FORALL (nnorm: real):
          (nnorm > maxgs OR
            nnorm < mings OR
             NOT repulsive_criteria(s, nvo - vi, eps)(nvop - vi))
           AND nnorm = norm(nvo) + dir * step
           IMPLIES
           nvo /= zero =>
            gs_only?(vo)(nvo) AND
             repulsive_criteria(s, vo - vi, eps)(nvo - vi));

  % Subtype TCC generated (at line 82, column 8) for  nvop
      % expected type  {nvo2 |
                     %          nvo2 /= zero =>
                     %           gs_only?(vo)(nvo2) AND
                     %            repulsive_criteria(s, vo - vi, eps)
                     %                              (nvo2 - vi)}
  losr_gs_iter_i_TCC3: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, minrelgs: nnreal,
            mings: posreal, maxgs: posreal, step: posreal, i: posnat,
            dir: Sign, eps: Sign,
            (nvo: Vect2
                 | nvo = (norm(vo) + dir * i * step) * ^(vo) AND
                    norm(vo) + dir * i * step > 0 AND
                     repulsive_criteria(s, vo - vi, eps)(nvo - vi)),
            nvop:
              {nvo_1: Vect2 |
                       norm(nvo) + dir * step > 0 IMPLIES
                        gs_only?(nvo)(nvo_1)}):
      nvop = incr_gs_vect(nvo, step, dir) IMPLIES
       (FORALL (nnorm: real):
               divergent?(s, zero, nvop - vi, zero)
           AND norm(nvop - vi) >= minrelgs AND NOT nnorm > maxgs
           AND NOT nnorm < mings
           AND repulsive_criteria(s, nvo - vi, eps)(nvop - vi)
           AND nnorm = norm(nvo) + dir * step
           IMPLIES
           nvop /= zero =>
            gs_only?(vo)(nvop) AND
             repulsive_criteria(s, vo - vi, eps)(nvop - vi));

  % Subtype TCC generated (at line 84, column 69) for  nvop
      % expected type  {nvo |
                     %          nvo =
                     %           (norm(vo) + step * dir + dir * i * step) *
                     %            ^(vo)
                     %           AND
                     %           norm(vo) + step * dir + dir * i * step > 0
                     %            AND
                     %            repulsive_criteria(s, vo - vi, eps)
                     %                              (nvo - vi)}
  losr_gs_iter_i_TCC4: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, minrelgs: nnreal,
            mings: posreal, maxgs: posreal, step: posreal, i: posnat,
            dir: Sign, eps: Sign,
            (nvo: Vect2
                 | nvo = (norm(vo) + dir * i * step) * ^(vo) AND
                    norm(vo) + dir * i * step > 0 AND
                     repulsive_criteria(s, vo - vi, eps)(nvo - vi)),
            nvop:
              {nvo_1: Vect2 |
                       norm(nvo) + dir * step > 0 IMPLIES
                        gs_only?(nvo)(nvo_1)}):
      nvop = incr_gs_vect(nvo, step, dir) IMPLIES
       (FORALL (nnorm: real):
               NOT (divergent?(s, zero, nvop - vi, zero) AND
                     norm(nvop - vi) >= minrelgs)
           AND NOT nnorm > maxgs AND NOT nnorm < mings
           AND repulsive_criteria(s, nvo - vi, eps)(nvop - vi)
           AND nnorm = norm(nvo) + dir * step
           IMPLIES
           nvop = (norm(vo) + step * dir + dir * i * step) * ^(vo) AND
            norm(vo) + step * dir + dir * i * step > 0 AND
             repulsive_criteria(s, vo - vi, eps)(nvop - vi));

  % Termination TCC generated (at line 84, column 8) for
      % losr_gs_iter_i(s, vo, vi, minrelgs, mings, maxgs, step, i + 1, dir,
      %                eps, nvop)
  losr_gs_iter_i_TCC5: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, minrelgs: nnreal,
            mings: posreal, maxgs: posreal, step: posreal, i: posnat,
            dir: Sign, eps: Sign,
            (nvo: Vect2
                 | nvo = (norm(vo) + dir * i * step) * ^(vo) AND
                    norm(vo) + dir * i * step > 0 AND
                     repulsive_criteria(s, vo - vi, eps)(nvo - vi)),
            nvop:
              {nvo_1: Vect2 |
                       norm(nvo) + dir * step > 0 IMPLIES
                        gs_only?(nvo)(nvo_1)}):
      nvop = incr_gs_vect(nvo, step, dir) IMPLIES
       (FORALL (nnorm: real):
               NOT (divergent?(s, zero, nvop - vi, zero) AND
                     norm(nvop - vi) >= minrelgs)
           AND NOT nnorm > maxgs AND NOT nnorm < mings
           AND repulsive_criteria(s, nvo - vi, eps)(nvop - vi)
           AND nnorm = norm(nvo) + dir * step
           IMPLIES
           max(0,
               floor(IF dir >= 0 THEN (maxgs - norm(vo)) / step
                     ELSE (norm(vo) - mings) / step
                     ENDIF)
                - (i + 1)
                + 1)
            <
            max(0,
                floor(IF dir >= 0 THEN (maxgs - norm(vo)) / step
                      ELSE (norm(vo) - mings) / step
                      ENDIF)
                 - i
                 + 1));

  % Subtype TCC generated (at line 77, column 30) for  nvo
      % expected type  Nz_vect2
  losr_gs_iter_i_TCC6: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, step: posreal,
            i: posnat, dir: Sign, eps: Sign,
            (nvo: Vect2
                 | nvo = (norm(vo) + dir * i * step) * ^(vo) AND
                    norm(vo) + dir * i * step > 0 AND
                     repulsive_criteria(s, vo - vi, eps)(nvo - vi))):
      nvo /= zero;

  % Subtype TCC generated (at line 95, column 6) for  zero
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           gs_only?(vo)(nvo) AND
                     %            repulsive_criteria(s,
                     %                               vo - vi,
                     %                               -sign(det(s, vo - vi)))
                     %                              (nvo - vi)}
  losr_gs_iter_TCC1: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, mings: posreal,
            maxgs: posreal, step: posreal, eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          dir3 = 0 AND
           dir3 = losr_gs_iter_dir(s, vo, vi, mings, maxgs, step, eps)
           IMPLIES
           zero /= zero =>
            gs_only?(vo)(zero) AND
             repulsive_criteria(s, vo - vi, -sign(det(s, vo - vi)))
                               (zero - vi));

  % Subtype TCC generated (at line 96, column 40) for  dir3
      % expected type  Sign
  losr_gs_iter_TCC2: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, mings: posreal,
            maxgs: posreal, step: posreal, eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          NOT dir3 = 0 AND
           dir3 = losr_gs_iter_dir(s, vo, vi, mings, maxgs, step, eps)
           IMPLIES dir3 /= 0 AND (dir3 = 1 OR dir3 = -1));

  % Subtype TCC generated (at line 98, column 68) for  nvo
      % expected type  {nvo |
                     %          nvo = (norm(vo) + step * dir3) * ^(vo) AND
                     %           norm(vo) + step * dir3 > 0 AND
                     %            repulsive_criteria(s, vo - vi, eps)
                     %                              (nvo - vi)}
  losr_gs_iter_TCC3: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, mings: posreal,
            maxgs: posreal, step: posreal, eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          NOT dir3 = 0 AND
           dir3 = losr_gs_iter_dir(s, vo, vi, mings, maxgs, step, eps)
           IMPLIES
           (FORALL (nvo:
                      {nvo: Vect2 |
                               norm(vo) + dir3 * step > 0 IMPLIES
                                gs_only?(vo)(nvo)}):
              repulsive_criteria(s, vo - vi, eps)(nvo - vi) AND
               nvo = incr_gs_vect(vo, step, dir3)
               IMPLIES
               nvo = (norm(vo) + step * dir3) * ^(vo) AND
                norm(vo) + step * dir3 > 0 AND
                 repulsive_criteria(s, vo - vi, eps)(nvo - vi)));

  % Subtype TCC generated (at line 98, column 8) for
      % losr_gs_iter_i(s, vo, vi, minrelgs, mings, maxgs, step, 1, dir3, eps,
      %                nvo)
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           gs_only?(vo)(nvo) AND
                     %            repulsive_criteria(s,
                     %                               vo - vi,
                     %                               -sign(det(s, vo - vi)))
                     %                              (nvo - vi)}
  losr_gs_iter_TCC4: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, minrelgs: nnreal,
            mings: posreal, maxgs: posreal, step: posreal, eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          NOT dir3 = 0 AND
           dir3 = losr_gs_iter_dir(s, vo, vi, mings, maxgs, step, eps)
           IMPLIES
           (FORALL (nvo:
                      {nvo: Vect2 |
                               norm(vo) + dir3 * step > 0 IMPLIES
                                gs_only?(vo)(nvo)}):
              repulsive_criteria(s, vo - vi, eps)(nvo - vi) AND
               nvo = incr_gs_vect(vo, step, dir3)
               IMPLIES
               losr_gs_iter_i(s, vo, vi, minrelgs, mings, maxgs, step, 1,
                              dir3, eps, nvo)
                /= zero
                =>
                gs_only?(vo)
                        (losr_gs_iter_i(s,
                                        vo,
                                        vi,
                                        minrelgs,
                                        mings,
                                        maxgs,
                                        step,
                                        1,
                                        dir3,
                                        eps,
                                        nvo))
                 AND
                 repulsive_criteria(s, vo - vi, -sign(det(s, vo - vi)))
                                   (losr_gs_iter_i(s,
                                                   vo,
                                                   vi,
                                                   minrelgs,
                                                   mings,
                                                   maxgs,
                                                   step,
                                                   1,
                                                   dir3,
                                                   eps,
                                                   nvo)
                                     - vi)));

  % Subtype TCC generated (at line 100, column 8) for  zero
      % expected type  {nvo |
                     %          nvo /= zero =>
                     %           gs_only?(vo)(nvo) AND
                     %            repulsive_criteria(s,
                     %                               vo - vi,
                     %                               -sign(det(s, vo - vi)))
                     %                              (nvo - vi)}
  losr_gs_iter_TCC5: OBLIGATION
    FORALL (s: Nz_vect2, vo: Nz_vect2, vi: Nz_vect2, mings: posreal,
            maxgs: posreal, step: posreal, eps: Sign):
      eps = -sign(det(s, vo - vi)) IMPLIES
       (FORALL (dir3: Sign3):
          NOT dir3 = 0 AND
           dir3 = losr_gs_iter_dir(s, vo, vi, mings, maxgs, step, eps)
           IMPLIES
           (FORALL (nvo:
                      {nvo: Vect2 |
                               norm(vo) + dir3 * step > 0 IMPLIES
                                gs_only?(vo)(nvo)}):
              NOT repulsive_criteria(s, vo - vi, eps)(nvo - vi) AND
               nvo = incr_gs_vect(vo, step, dir3)
               IMPLIES
               zero /= zero =>
                gs_only?(vo)(zero) AND
                 repulsive_criteria(s, vo - vi, -sign(det(s, vo - vi)))
                                   (zero - vi)));


body:
  repulsive_iterative : THEORY
  BEGIN

    IMPORTING repulsive

    s,so,si,v,vo,vi,
    nv,nw   : VAR Vect2
    nvo,nvi : VAR Nz_vect2
    eps	  : VAR Sign
    cc	  : VAR posreal
    t	  : VAR posreal
    i	  : VAR posnat
    n,m	  : VAR nat
    Nsteps  : VAR posnat % Number of maneuver segments
    	    	       % before turning straight

    VelSeq: TYPE = [posnat->Vect2]
    timestep: VAR posreal

    velseqo,velseqi,velseq: VAR VelSeq

    % Sequence of positions so

    man_pos_seq(so,timestep,velseqo)(i): RECURSIVE Vect2 =
      IF    i = 1 THEN so
      ELSE LET soprev = man_pos_seq(so,timestep,velseqo)(i-1),
      	     voprev = velseqo(i-1)
  	 IN soprev + timestep*voprev
      ENDIF MEASURE i

    man_pos_seq_test: LEMMA
      man_pos_seq(so,timestep,velseqo)(1) = so AND
      man_pos_seq(so,timestep,velseqo)(2) = so+timestep*velseqo(1) AND
      man_pos_seq(so,timestep,velseqo)(3) = so+timestep*velseqo(1)
      			+ timestep*velseqo(2) AND
      man_pos_seq(so,timestep,velseqo)(4) = so+timestep*velseqo(1)
      			+ timestep*velseqo(2) +timestep*velseqo(3)

    maneuver_position_at(so,timestep,velseqo,Nsteps)(t:nnreal): Vect2 =
      LET numsteps = min(floor(t/timestep)+1,Nsteps),
      	lastso    = man_pos_seq(so,timestep,velseqo)(numsteps),
  	lastvo	  = velseqo(numsteps)
      IN  lastso + (t-timestep*(numsteps-1))*lastvo

    manuever_position_at_def: LEMMA m+1<=Nsteps IMPLIES
      maneuver_position_at(so,timestep,velseqo,Nsteps)(m*timestep) =
      man_pos_seq(so,timestep,velseqo)(m+1)

    repulsive_iterative?(s,v,timestep,velseq,Nsteps): bool =
      (s*v<0 AND
      (FORALL (t): norm(maneuver_position_at(s,timestep,velseq,Nsteps)(t))>=norm(s+tca(s,v)*v)))
      OR
      (s*v>=0 AND
      (FORALL (t): norm(maneuver_position_at(s,timestep,velseq,Nsteps)(t))>=norm(s)))

    repulsive_criteria_iterative(s,v,timestep,velseq,Nsteps,eps): bool =
      repulsive_criteria(s,v,eps)(velseq(1)) AND
      FORALL (m:subrange(1,Nsteps-1)): repulsive_criteria(man_pos_seq(s,timestep,velseq)(m+1),velseq(m),eps)(velseq(m+1))

    repulsive_criteria_iterative_repulsive: LEMMA
      repulsive_criteria_iterative(s,v,timestep,velseq,Nsteps,eps)
      IMPLIES
      repulsive_iterative?(s,v,timestep,velseq,Nsteps)

    repulsive_criteria_iterative_reduces_seq: LEMMA s*v<0 AND
      repulsive_criteria_iterative(s,v,timestep,velseq,Nsteps,eps)
      IMPLIES
      FORALL (m:subrange(1,Nsteps)):
        repulsive_criteria(s,v,eps)(velseq(m))
        AND (m<Nsteps IMPLIES repulsive_criteria(s,v,eps)(man_pos_seq(s,timestep,velseq)(m+1)-s))

    repulsive_criteria_iterative_reduces: LEMMA s*v<0 AND
      repulsive_criteria_iterative(s,v,timestep,velseq,Nsteps,eps)
      IMPLIES
      repulsive_criteria(s,v,eps)(maneuver_position_at(s,timestep,velseq,Nsteps)(t)-s)

    repulsive_criteria_iterative_reduces_seq_divergent_special: LEMMA
      timestep = 1 AND s = (1,0) AND s * v >= 0 AND repulsive_criteria_iterative(s,v,timestep,velseq,Nsteps,eps)
      IMPLIES
      FORALL (m:subrange(1,Nsteps)):
        repulsive_criteria(s,v,eps)(velseq(m))
        AND (m<Nsteps IMPLIES repulsive_criteria(s,(m*timestep)*v,eps)((man_pos_seq(s,timestep,velseq)(m+1)-s)))

    repulsive_criteria_iterative_reduces_seq_divergent: LEMMA s/=zero AND s*v>=0 AND
      repulsive_criteria_iterative(s,v,timestep,velseq,Nsteps,eps)
      IMPLIES
      FORALL (m:subrange(1,Nsteps)):
        repulsive_criteria(s,v,eps)(velseq(m))
        AND (m<Nsteps IMPLIES repulsive_criteria(s,(m*timestep)*v,eps)((man_pos_seq(s,timestep,velseq)(m+1)-s)))

    repulsive_criteria_iterative_reduces_seq_div: LEMMA s*v>=0 AND
      repulsive_criteria_iterative(s,v,timestep,velseq,Nsteps,eps)
      IMPLIES
      FORALL (m:subrange(1,Nsteps)): s*velseq(m)>=0 AND
       (m<Nsteps IMPLIES 
        LET vv=man_pos_seq(s,timestep,velseq)(m+1)-s 
  	    IN  s*vv>=0)

    repulsive_criteria_iterative_reduces_div: LEMMA s*v>=0 AND
      repulsive_criteria_iterative(s,v,timestep,velseq,Nsteps,eps)
      IMPLIES
      s*(maneuver_position_at(s,timestep,velseq,Nsteps)(t)-s)>=t*(s*v)

    % Relative sequence of velocities

    relative_velseq_vel(velseqo,vi)(i): Vect2 =
      velseqo(i)-vi

    relative_velseq(velseqo,velseqi)(i): Vect2 =
      velseqo(i)-velseqi(i)

    repulsive_criteria_iterative_coordinated: LEMMA
      repulsive_criteria_iterative(s,vo-vi,timestep,
  	      relative_velseq_vel(velseqo,vi),Nsteps,eps) AND
      repulsive_criteria_iterative(-s,vi-vo,timestep,
  	      relative_velseq_vel(velseqi,vo),Nsteps,eps)
      IMPLIES
      repulsive_iterative?(s,vo-vi,timestep,relative_velseq(velseqo,velseqi),Nsteps)

  END repulsive_iterative

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

  % Subtype TCC generated (at line 27, column 27) for  i - 1
      % expected type  posnat
  man_pos_seq_TCC1: OBLIGATION
    FORALL (so: Vect2, timestep: posreal, velseqo: VelSeq, i: posnat,
            v:
              [[Vect2, posreal, VelSeq] ->
                 [{z1: posnat | z1 < i} -> Vect2]]):
      NOT i = 1 IMPLIES
       (FORALL (soprev: Vect2):
          soprev = v(so, timestep, velseqo)(i - 1) IMPLIES
           i - 1 >= 0 AND i - 1 > 0);

  % Subtype TCC generated (at line 26, column 55) for  i - 1
      % expected type  posnat
  man_pos_seq_TCC2: OBLIGATION
    FORALL (i: posnat): NOT i = 1 IMPLIES i - 1 >= 0 AND i - 1 > 0;

  % Termination TCC generated (at line 26, column 22) for
      % man_pos_seq(so, timestep, velseqo)(i - 1)
  man_pos_seq_TCC3: OBLIGATION
    FORALL (i: posnat): NOT i = 1 IMPLIES i - 1 < i;

  % Subtype TCC generated (at line 58, column 114) for  m + 1
      % expected type  posnat
  repulsive_criteria_iterative_TCC1: OBLIGATION
    FORALL (s: Vect2, v: Vect2, velseq: VelSeq, Nsteps: posnat, eps: Sign):
      repulsive_criteria(s, v, eps)(velseq(1)) IMPLIES
       (FORALL (m: subrange(1, Nsteps - 1)): m + 1 >= 0 AND m + 1 > 0);

  % Subtype TCC generated (at line 58, column 99) for  m
      % expected type  posnat
  repulsive_criteria_iterative_TCC2: OBLIGATION
    FORALL (s: Vect2, v: Vect2, velseq: VelSeq, Nsteps: posnat, eps: Sign):
      repulsive_criteria(s, v, eps)(velseq(1)) IMPLIES
       (FORALL (m: subrange(1, Nsteps - 1)): m >= 0 AND m > 0);


body:
  %------------------------------------------------------------------------------
  % horizontal_criterion_line.pvs
  % ACCoRD v1.0
  %
  % This theory simplifies the predicate horizontal_criterion and proves
  % a stronger coordination theorem.
  %------------------------------------------------------------------------------

  horizontal_criterion_line[D: posreal]: THEORY
  BEGIN

    IMPORTING horizontal_criteria[D],
              tangent_line[D], 
              vectors@linear_transformations_2D

    v,nv,nv1,nv2         : VAR Vect2
    sp        : VAR Sp_vect2
    vo,vi,
    nvo,nvi   : VAR Vect2
    eps       : VAR Sign
    
    horizontal_criterion_rewrite: THEOREM
      horizontal_criterion?(sp,eps)(v) IFF
      (eps*det(v,tangent_line(sp,eps)) <= 0 AND
       eps*det(sp,v)<=0)

    % horizontal_criterion_rewrite2: THEOREM
    %   norm(sp)>D IMPLIES
    %   (horizontal_criterion?(sp,eps)(v) IFF
    %   eps*det(sp,v) >= norm(v)*D)

    horizontal_criterion_special_coordination: LEMMA
      horizontal_criterion?(-sp,eps)(nvi-vo) AND
      horizontal_criterion?(sp,eps)(nvo-vo)
      IMPLIES
        NOT horizontal_conflict?(sp,nvo-nvi)

    horizontal_criterion_dot_equality: LEMMA
      line_solution?(sp,nvo-vi,eps) AND 
      line_solution?(sp,v,eps) IMPLIES
        det(vi-nvi,v) = det(nvo-nvi,v)

    horizontal_criterion_line_invariance: LEMMA
      line_solution?(sp,nvo-vi,eps) IMPLIES
       (horizontal_criterion?(sp,eps)(vi-nvi) IMPLIES
        horizontal_criterion?(sp,eps)(nvo-nvi))

    horizontal_criterion_line_coordination: LEMMA
      line_solution?(-sp,nvi-vo,eps) AND
      horizontal_criterion?(sp,eps)(nvo-vo)
      IMPLIES
        NOT horizontal_conflict?(sp,nvo-nvi)

    % The horizontal criterion is maximal!

    SCRIT: VAR SignedCrit2D


    % horizontal_criterion_maximal: LEMMA
    %   LET
    %       conflictpred = (LAMBDA (ss,v:Vect2): (LAMBDA (nv:Vect2): horizontal_conflict?(ss,nv)))
    %   IN
    %       (FORALL (sp:Sp_vect2,v:Vect2,eps:Sign):
    %       subset?(horizontal_criterion?(sp,eps),SCRIT(eps)(sp,v)) AND
    %       crit_symmetric_2D?(SCRIT(eps)) AND
    %       crit_independent_of_length_2D?(SCRIT(eps)) AND
    % 	coordinated_2D?(SCRIT(eps),SCRIT(eps),conflictpred))
    % 	IMPLIES
    % 	(FORALL (sp:Sp_vect2,v:Vect2,eps:Sign):
    %       horizontal_conflict?(sp,v) IMPLIES horizontal_criterion?(sp,eps)=SCRIT(eps)(sp,v))

    % The horizontal criterion is not coordinated if the
    % aircraft are not orginally in conflict. The following criteria,
    % which depends on s (original relative position), 
    % v (original relative velocity), nv (new relative velocity), and eps (+-1),
    % is coordinated even if the aircraft are not originally in conflict.
    % In fact, if the original aircraft are in conflict, then this criteria is
    % equal to the horizontal_criterion. An even stronger result is true which
    % states that as long as the original trajectory does not
    % satisfy horizontal_criterion, this new criterion is equal to 
    % the horizontal criterion.

    horizontal_criterion_ext?(sp,v,eps)(nv): bool =
      IF horizontal_criterion?(sp,eps)(v)
        THEN horizontal_criterion?(sp,eps)(nv-(1/2)*v)
      ELSIF 
           horizontal_criterion?(sp,eps)(-v) OR
           (NOT horizontal_criterion?(sp,-eps)(v))
         THEN horizontal_criterion?(sp,eps)(nv)
      ELSE 
        horizontal_criterion?(sp,eps)(nv) AND
        horizontal_criterion?(sp,eps)(nv-(1/2)*v) 
      ENDIF

    horizontal_criterion_ext_subset: LEMMA
      horizontal_criterion_ext?(sp,v,eps)(nv) IMPLIES
      horizontal_criterion?(sp,eps)(nv)

    horizontal_criterion_ext_restrict: LEMMA
      horizontal_conflict?(sp,v) IMPLIES
      (horizontal_criterion_ext?(sp,v,eps)(nv) IFF
       horizontal_criterion?(sp,eps)(nv))

    horizontal_criterion_ext_restrict_conflict: LEMMA
      horizontal_conflict?(sp,v) IMPLIES
      (horizontal_criterion_ext?(sp,v,eps)(nv) IFF
       horizontal_criterion?(sp,eps)(nv))

    horizontal_criterion_ext_independence: LEMMA
      horizontal_criterion_ext?(sp,v,eps)(nv) IMPLIES
      NOT horizontal_conflict?(sp,nv)

    % horizontal_criterion_ext_coordinated_criterion: LEMMA
    %   horizontal_criterion_ext?(sp,vo-vi,eps)(nvo-vi) AND
    %   horizontal_criterion_ext?(-sp,vi-vo,eps)(nvi-vo)
    %   IMPLIES
    %   horizontal_criterion?(sp,eps)(nvo-nvi)

    horizontal_criterion_ext_coordinated: LEMMA
      horizontal_criterion_ext?(sp,vo-vi,eps)(nvo-vi) AND
      horizontal_criterion_ext?(-sp,vi-vo,eps)(nvi-vo)
      IMPLIES
      NOT horizontal_conflict?(sp,nvo-nvi)

    %%%%%%%%%%%%%%%%%%%%%%%%%%%

    horizontal_criterion_ext_sum_closed: LEMMA
      horizontal_criterion_ext?(sp,v,eps)(nv1) AND
      horizontal_criterion_ext?(sp,v,eps)(nv2)
      IMPLIES
      horizontal_criterion_ext?(sp,v,eps)(nv1+nv2)

    horizontal_criterion_ext_scal: LEMMA
      FORALL (c:real): c>=1 AND
      horizontal_criterion_ext?(sp,v,eps)(nv)
      IMPLIES
      horizontal_criterion_ext?(sp,v,eps)(c*nv)

    horizontal_criterion_ext_seg_convex: LEMMA
      FORALL (eps: Sign, sp: Sp_vect2[D], v, nv1, nv2: Vect2):
        horizontal_criterion_ext?(sp, v, eps)(nv1) AND
        horizontal_criterion_ext?(sp, v, eps)(nv2)
        IMPLIES
        (FORALL (t: real):
          0 <= t AND t <= 1 IMPLIES
  	horizontal_criterion_ext?(sp,v,eps)((1-t)*nv1 + t *nv2))

    % In next lemma, sp1 = rel position at time t1,
         	    	 % sp2 = rel position at time t2

    horizontal_criterion_ext_seg_independence: LEMMA
      FORALL (sp1,sp2:Vect2,t1,t2:real): t1<t2 AND
      horizontal_criterion_ext?(sp,v,eps)(sp1-sp) AND
      horizontal_criterion_ext?(sp,v,eps)(sp2-sp) IMPLIES
      FORALL (t:real): t1 <= t AND t <= t2
        IMPLIES NOT horizontal_los?(sp1 + ((t-t1)/(t2-t1))*(sp2-sp1))

    % IMPORANT NOTE: nso - so = (nso-si) - (so-si)
    % 	     	   nsi - si = (nsi-so) - (si-so)

    horizontal_criterion_ext_seg_coordination: LEMMA
      FORALL (so,si,vo,vi,nso1,nso2,nsi1,nsi2:Vect2,t1,t2:real): 
      t1<t2 AND sqv(so-si) >= sq(D) AND
      horizontal_criterion_ext?(so-si,vo-vi,eps)(nso1-so) AND
      horizontal_criterion_ext?(so-si,vo-vi,eps)(nso2-so) AND
      horizontal_criterion_ext?(si-so,vi-vo,eps)(nsi1-si) AND
      horizontal_criterion_ext?(si-so,vi-vo,eps)(nsi2-si) IMPLIES
      FORALL (t:real):
        LET time01 = (t-t1)/(t2-t1),
        	  ownshippos = nso1 + time01*(nso2-nso1),
  	  intruderpos = nsi1 + time01*(nsi2-nsi1)
        IN
            t1 <= t AND t <= t2 IMPLIES NOT horizontal_los?(ownshippos-intruderpos)
      



  END horizontal_criterion_line

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

  % Subtype TCC generated (at line 156, column 49) for  (t2 - t1)
      % expected type  nznum
  horizontal_criterion_ext_seg_independence_TCC1: OBLIGATION
    FORALL (eps: Sign, sp: Sp_vect2[D], v, sp1, sp2: Vect2, t1, t2: real):
      t1 < t2 AND
       horizontal_criterion_ext?(sp, v, eps)(sp1 - sp) AND
        horizontal_criterion_ext?(sp, v, eps)(sp2 - sp)
       IMPLIES (FORALL (t: real): t1 <= t AND t <= t2 IMPLIES (t2 - t1) /= 0);

  % Subtype TCC generated (at line 166, column 30) for  si - so
      % expected type  Sp_vect2[D]
  horizontal_criterion_ext_seg_coordination_TCC1: OBLIGATION
    FORALL (eps: Sign, so, si, vo, vi, nso1, nso2: Vect2, t1, t2: real):
      horizontal_criterion_ext?(so - si, vo - vi, eps)(nso2 - so) AND
       horizontal_criterion_ext?(so - si, vo - vi, eps)(nso1 - so) AND
        sqv(so - si) >= sq(D) AND t1 < t2
       IMPLIES sqv(si - so) >= sq(D);

  % Subtype TCC generated (at line 169, column 27) for  (t2 - t1)
      % expected type  nznum
  horizontal_criterion_ext_seg_coordination_TCC2: OBLIGATION
    FORALL (eps: Sign, so, si, vo, vi, nso1, nso2, nsi1, nsi2: Vect2,
            t1, t2: real):
           t1 < t2 AND sqv(so - si) >= sq(D)
       AND horizontal_criterion_ext?(so - si, vo - vi, eps)(nso1 - so)
       AND horizontal_criterion_ext?(so - si, vo - vi, eps)(nso2 - so)
       AND horizontal_criterion_ext?(si - so, vi - vo, eps)(nsi1 - si)
       AND horizontal_criterion_ext?(si - so, vi - vo, eps)(nsi2 - si)
       IMPLIES (t2 - t1) /= 0;


body:
  %------------------------------------------------------------------------------
  % predicate_coordination.pvs - General Theory of Coordination for 3D Maneuvers
  %------------------------------------------------------------------------------

  predicate_coordination: THEORY
  BEGIN

    IMPORTING definitions_3D


    s,v,nv,
    nw,vo,nvo,
    vi,nvi  : VAR Vect3
    eps     : VAR Sign
    pr	  : VAR posreal
    l,l1,l2 : VAR real

    Criter: TYPE = [[Vect3,Vect3]->set[Vect3]]
    SignedCrit: TYPE = [Sign -> Criter]

    Vector_Predicate: TYPE+ = [[Vect3,Vect3]->set[Vect3]]

    Crit,Crit1,Crit2,Crit3: VAR Criter
    Scrit,Scrit1,Scrit2,Scrit3: VAR SignedCrit


    C : VAR Vector_Predicate



      % BASIC DEFINITIONS

      sum_closed?(C): bool =
          FORALL (s,v,nv,nw:Vect3):
  	C(s,v)(nv) AND C(s,v)(nw) IMPLIES C(s,v)(nv+nw)

      symmetric?(C) : bool = 
         FORALL (s,v,nv:Vect3):
  	C(s,v)(nv) IFF C(-s,-v)(-nv)


      crit_sum_closed?(Crit): bool =
          FORALL (s,v,nv,nw:Vect3):
  	Crit(s,v)(nv) AND Crit(s,v)(nw) IMPLIES Crit(s,v)(nv+nw)


      sum_independent?(Crit,C): bool = 
          FORALL (v,s,nv,nw: Vect3):
          (Crit(s,v)(nv) AND Crit(s,v)(nw) AND C(s,v)(v)
          IMPLIES
          NOT C(s,v)(nv+nw))

      open?(C): bool = 
          FORALL (s,v,nv: Vect3): C(s,v)(nv) IMPLIES
  	(EXISTS (epsilon:posreal):
  	FORALL (nw: Vect3):
  	norm(nw)<epsilon
  	IMPLIES
  	C(s,v)(nv+nw))


      crit_independent_of_length?(Crit): bool =
          FORALL (v,s,nv: Vect3,pr: posreal):
  	(Crit(s,v)(nv) IFF Crit(s,pr*v)(nv))

      independent_of_length?(C): bool = 
          FORALL (s,v,nv:Vect3,pr,pz:posreal):
  	(C(s,v)(nv) IFF C(s,pz*v)(pr*nv))

      coordinated?(Crit1,Crit2,C): bool =
          FORALL (vo,vi,nvo,nvi,s: Vect3):
          (C(s,vo-vi)(vo-vi) AND
          Crit1(s,vo-vi)(nvo-vi) AND
          Crit2(-s,vi-vo)(nvi-vo)
          IMPLIES
          NOT C(s,vo-vi)(nvo-nvi))

      coordinated_symmetric: LEMMA symmetric?(C) IMPLIES
      			   (coordinated?(Crit1,Crit2,C) IFF coordinated?(Crit2,Crit1,C))


      crit_symmetric?(Crit): bool =
          FORALL (v,s,nv: Vect3):
          (Crit(s,v)(nv) IFF Crit(-s,-v)(-nv))

      sum_indep_coordinated: LEMMA
          crit_symmetric?(Crit) AND
          sum_independent?(Crit,C) AND
  	sum_closed?(C)
          IMPLIES
          coordinated?(Crit,Crit,C)

      coordinated_sum_indep: LEMMA
      	crit_symmetric?(Crit) AND
          crit_independent_of_length?(Crit) AND
  	coordinated?(Crit,Crit,C) AND
  	open?(C) AND
  	independent_of_length?(C)
  	IMPLIES
  	sum_independent?(Crit,C)

      crit_antisymmetric?(Scrit): bool =
          FORALL (v,s,nv: Vect3, eps:Sign):
          (Scrit(eps)(s,v)(nv) IFF Scrit(-eps)(-s,-v)(-nv))

      sum_indep_coordinated_antisym: LEMMA
          crit_antisymmetric?(Scrit) AND
          sum_independent?(Scrit(eps),C) AND
  	sum_closed?(C)
          IMPLIES
          coordinated?(Scrit(eps),Scrit(-eps),C)

      coordinated_antisym_sum_indep: LEMMA
      	crit_antisymmetric?(Scrit) AND
          crit_independent_of_length?(Scrit(eps)) AND
  	coordinated?(Scrit(eps),Scrit(-eps),C) AND
  	open?(C) AND
  	independent_of_length?(C)
  	IMPLIES
  	sum_independent?(Scrit(eps),C)


    % The DERIVED Criterion

    deriv(Crit,l): Criter = (LAMBDA (s,v): (LAMBDA (nv): Crit(s,v)(nv-l*v)))

    deriv_0: LEMMA deriv(Crit,0) = Crit

    deriv_subset: LEMMA
      Crit(s,v)(-l*v) AND
      crit_sum_closed?(Crit)
       IMPLIES
      subset?(Crit(s,v),deriv(Crit,l)(s,v))

    deriv_coordinated: LEMMA
    			      l1+l2 = 1 IMPLIES
    			      crit_symmetric?(Crit) AND
    			      sum_independent?(Crit,C) IMPLIES
  			      coordinated?(deriv(Crit,l1),deriv(Crit,l2),C)

    deriv_coordinated_1: LEMMA
    			      crit_symmetric?(Crit) AND
    			      sum_independent?(Crit,C) IMPLIES
  			      coordinated?(deriv(Crit,1),Crit,C)

    Comb(Crit1,Crit2): Criter = (LAMBDA (s,v): (LAMBDA (nv): Crit1(s,v)(nv) OR (Crit2(s,v)(nv) AND deriv(Crit1,1)(s,v)(nv))))

    Comb_coordinated: LEMMA
      sum_independent?(Crit1,C) AND
      crit_symmetric?(Crit1) AND
      coordinated?(Crit2,Crit3,C) AND
      sum_closed?(C) AND
      symmetric?(C)
      IMPLIES
      coordinated?(Comb(Crit1,Crit2),Comb(Crit1,Crit3),C)





  END predicate_coordination


body:
  %------------------------------------------------------------------------------
  % vertical_criterion.pvs
  %------------------------------------------------------------------------------

  vertical_criterion[D,H: posreal]: THEORY
  BEGIN

    IMPORTING predicate_coordination,
    	    circle_criterion[D,H],
    	    analysis@interm_value_thm

    s,p	  : VAR Vect3 
    v,w,nv,
    nw,
    vo,nvo,
    vi,nvi  : VAR Vect3
    eps,dir : VAR Sign
    tztime,
    theta   : VAR real

    % p is a point on one of the two edges of the cylinder
    % eps = 1 for the top edge, eps = -1 for the bottom edge
    % Here, we define our 3-D region.

    closed_region_3D(s,p,eps,dir)(v): bool = 
      vect2(v)*vect2(p) /= 0 AND sign(vect2(v)*vect2(p)) = dir AND
      LET t = (sq(D)-vect2(s)*vect2(p))/(vect2(v)*vect2(p)) IN
      t >= 0 AND
      eps*(s`z + t*v`z) >= H AND
      (abs(s`z) >= H AND dir = eps*sign(s`z)
       OR
       abs(s`z) < H AND dir = -1)

    closed_region_3D_t_def: LEMMA
      vect2(v)*vect2(p) /= 0 IMPLIES
      LET t = (sq(D)-vect2(s)*vect2(p))/(vect2(v)*vect2(p)) IN
        (vect2(s) + t*vect2(v))*vect2(p) = sq(D)

    closed_region_3D_t_direction: LEMMA
      vect2(v)*vect2(p) /= 0 IMPLIES
      LET t = (sq(D)-vect2(s)*vect2(p))/(vect2(v)*vect2(p)) IN
      t /= tztime IMPLIES
      sign(vect2(v)*vect2(p))*sign(t-tztime) = sign(sq(D) - (vect2(s) + tztime*vect2(v))*vect2(p))

    closed_region_3D_sum_closed: LEMMA
      closed_region_3D(s,p,eps,dir)(v) AND
      closed_region_3D(s,p,eps,dir)(w)
      IMPLIES
      closed_region_3D(s,p,eps,dir)(v+w)

    % The previous predicate defines the half-sheet over (or under)
    % the point p. What we need now is to determine which points p
    % we want to consider for a given s and v.

    vertical_criterion?: SignedCrit = 
      LAMBDA (eps:Sign): (LAMBDA (s,v:Vect3): (LAMBDA (nv:Vect3):
      (vect2(v) = zero AND eps*nv`z >= 0 AND eps*s`z >= H
      OR
       Delta(s,v) > 0 AND
        LET dir : Sign = IF abs(s`z) >= H THEN eps*sign(s`z) ELSE Entry ENDIF,
            p          = (s + Theta_D(s,v,dir)*v) WITH [z := eps*H] IN
        Theta_D(s,v,dir) > 0
        AND
        closed_region_3D(s,p,eps,dir)(nv))))

    vertical_criterion_sum_closed: LEMMA
      crit_sum_closed?(vertical_criterion?(eps))

    vertical_criterion_antisymmetric: LEMMA
      crit_antisymmetric?(vertical_criterion?)

    vertical_criterion_independence: LEMMA
      vertical_criterion?(eps)(s,v)(nv) IMPLIES
      NOT conflict?(s,nv)

    vertical_criterion_coordination: LEMMA
      conflict?(s,vo-vi) AND
      vertical_criterion?(eps)(s,vo-vi)(nvo-vi) AND
      vertical_criterion?(-eps)(-s,vi-vo)(nvi-vo)
      IMPLIES
      NOT conflict?(s,nvo-nvi)

    horizontal_meets_vertical_criterion : LEMMA
      LET v = vo-vi,
          dir: Sign = IF abs(s`z) >= H THEN eps * sign(s`z) ELSE -1 ENDIF
      IN
        Delta(s,v) > 0 AND vo`z /= vi`z AND 
        Theta_D(s,v,dir) > 0 AND Theta_H(s`z,v`z,-dir) > 0 AND
        eps = sign(s`z + Theta_H(s`z,v`z,-dir)*v`z) AND
        (vect2(s)+Theta_H(s`z,v`z,-dir)*vect2(nvo-vi))*(vect2(s)+Theta_D(s,v,dir)*vect2(v)) = sq(D) AND
        horizontal_only?(vo)(nvo)
        IMPLIES
          vertical_criterion?(eps)(s,v)(nvo-vi)


    %%%%%%%%%%%%%%%%%% Simplified Version of Criterion for Executive Lever Paper %%%%%%%%%%%%%%%%%%

    intersects_half_plane?(s,v,p,eps) : bool =
      vect2(v)*vect2(p) /= 0 AND 
      LET t = (sq(D)-vect2(s)*vect2(p))/(vect2(v)*vect2(p)) IN
      t >= 0 AND
      eps*(s`z + t*v`z) >= eps*p`z

    safe_dir(s,v,eps) : Sign = IF abs(s`z) >= H THEN eps*sign(s`z) ELSE Entry ENDIF

    safe_p(s:Vect3,v | Delta(s,v) > 0,eps) : Vect3 = (s + Theta_D(s,v,safe_dir(s,v,eps))*v) WITH [z := eps*H]

    vertical_criterion_rewrite: LEMMA
      vertical_criterion?(eps)(s,v)(nv)
      IFF
      (vect2(v) = zero AND eps*nv`z >= 0 AND eps*s`z >= H
      OR
      Delta(s,v) > 0 AND Theta_D(s,v,safe_dir(s,v,eps)) > 0  AND intersects_half_plane?(s,nv,safe_p(s,v,eps),eps))

  END vertical_criterion

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

  % Subtype TCC generated (at line 61, column 38) for  vect2(v)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  vertical_criterion?_TCC1: OBLIGATION
    FORALL (eps: Sign, s, v, nv: Vect3):
      Delta(vect2(s), vect2(v)) > 0 AND
       NOT (vect2(v) = zero AND eps * nv`z >= 0 AND eps * s`z >= H)
       IMPLIES
       (FORALL (dir: Sign):
          dir = IF abs(s`z) >= H THEN eps * sign(s`z) ELSE -1 ENDIF IMPLIES
           vect2(v) /= zero AND Delta[D](vect2(s), vect2(v)) >= 0);

  % Subtype TCC generated (at line 88, column 16) for  vect2(v)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  horizontal_meets_vertical_criterion_TCC1: OBLIGATION
    FORALL (eps: Sign, s, vi, vo, v: Vect3):
      v = vo - vi IMPLIES
       (FORALL (dir: Sign):
          vo`z /= vi`z AND
           Delta(vect2(s), vect2(v)) > 0 AND
            dir = IF abs(s`z) >= H THEN eps * sign(s`z) ELSE -1 ENDIF
           IMPLIES vect2(v) /= zero AND Delta[D](vect2(s), vect2(v)) >= 0);

  % Subtype TCC generated (at line 88, column 43) for  v`z
      % expected type  nzreal
  horizontal_meets_vertical_criterion_TCC2: OBLIGATION
    FORALL (eps: Sign, s, vi, vo, v: Vect3):
      v = vo - vi IMPLIES
       (FORALL (dir: Sign):
          Theta_D(vect2(s), vect2(v), dir) > 0 AND
           vo`z /= vi`z AND
            Delta(vect2(s), vect2(v)) > 0 AND
             dir = IF abs(s`z) >= H THEN eps * sign(s`z) ELSE -1 ENDIF
           IMPLIES v`z /= 0);

  % Subtype TCC generated (at line 106, column 66) for  vect2(v)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  safe_p_TCC1: OBLIGATION
    FORALL (s: Vect3, v: Vect3 | Delta[D](vect2(s), vect2(v)) > 0):
      vect2(v) /= zero AND Delta[D](vect2(s), vect2(v)) >= 0;

  % Subtype TCC generated (at line 113, column 33) for  vect2(v)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  vertical_criterion_rewrite_TCC1: OBLIGATION
    FORALL (eps: Sign, nv, s, v: Vect3):
      NOT (vect2(v) = zero AND eps * nv`z >= 0 AND eps * s`z >= H) AND
       Delta(vect2(s), vect2(v)) > 0
       IMPLIES vect2(v) /= zero AND Delta[D](vect2(s), vect2(v)) >= 0;


body:
  %------------------------------------------------------------------------------
  % criteria_3D.pvs
  % ACCoRD v.1.0
  %------------------------------------------------------------------------------

  criteria_3D[D,H:posreal] : THEORY
  BEGIN

    IMPORTING vertical_criterion[D,H],
  	    horizontal_criterion_line[D]%,

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

    criterion_3D?(sp,v,epsh,epsv)(nv) : bool = 
      (horizontal_sep?(sp) AND horizontal_criterion?(sp,epsh)(nv)) OR
      (vertical_criterion?(epsv)(sp,v)(nv) AND
       (horizontal_los?(sp) OR
        horizontal_criterion?(sp,epsh)(nv-v)))

    criterion_3D_independence : THEOREM
      conflict?(sp,v) AND
      criterion_3D?(sp,v,epsh,epsv)(nv) 
      IMPLIES
        NOT conflict?(sp,nv)

    criterion_3D_coordination : THEOREM
      conflict?(sp,vo-vi) AND
      criterion_3D?(sp,vo-vi,epsh,epsv)(nvo-vi) AND
      criterion_3D?(-sp,vi-vo,epsh,-epsv)(nvi-vo) IMPLIES
      NOT  conflict?(sp,nvo-nvi)

  END criteria_3D

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

  % Subtype TCC generated (at line 22, column 28) for  vect2(sp)
      % expected type  Sp_vect2[D]
  criterion_3D?_TCC1: OBLIGATION
    FORALL (sp: Sp_vect3[D, H], v: Vect3, epsh: Sign, epsv: Sign, nv: Vect3):
      NOT sqv(vect2(sp)) < sq(D) AND
       vertical_criterion?(epsv)(sp, v)(nv) AND
        NOT (sqv(vect2(sp)) >= sq(D) AND
              horizontal_criterion?(vect2(sp), epsh)(vect2(nv)))
       IMPLIES sqv(vect2(sp)) >= sq(D);


body:
  %------------------------------------------------------------------------------
  % opt_trk_gs.pvs
  % ACCoRD v.1.0
  %
  % Solve the following equation on k:
  %   nv * (k*nv-v) = 0.
  %------------------------------------------------------------------------------

  opt_trk_gs[D:posreal] : THEORY
  BEGIN
    
    IMPORTING definitions,
              horizontal[D]

    u,nzv      : VAR Nz_vect2
    j          : VAR real
    vo,vi,nvo,
    s,v        : VAR Vect2
    t          : VAR posreal
    dir        : VAR Sign

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

    k_opt(nzv,v) : real =
      nzv*v/sqv(nzv)

    k_opt_tangent : LEMMA
      LET k = k_opt(nzv,v) IN
        nzv*(k*nzv-v) = 0

    % Vector nzv is a directional vector
    opt_trk_gs_line(nzv,vo,vi): {k:real,nvo:(optimal?(vo,nzv)) | 
                                 k*nzv = nvo-vi} = 
      LET  k  = k_opt(nzv,vo-vi) IN
        (k,k*nzv+vi)

    % Solve equation on nvo: u*(nvo-vi) = j, such that v+vi is optimal wrt trk/gs
    opt_trk_gs_dot(u,vo,vi,j) : {nvo:(optimal?(vo,Vdir(u,vo-vi))) |
                                     u*(nvo-vi) = j} =
      opt_trk_gs_line(Vdir(u,vo-vi),vo,vi+W0(u,j))`2 

    opt_trk_gs_vertical(s,vo,vi,t,dir) : Vect2 =
      LET v = vo-vi IN
      IF Delta(s,v) > 0 AND Theta_D(s,v,dir) > 0 THEN
        LET p = s + Theta_D(s,v,dir)*v IN
          opt_trk_gs_dot(t*p,vo,vi,sq(D)-s*p) 
      ELSE
        zero
      ENDIF

    opt_trk_gs_vertical?(s,vo,vi,t,dir)(nvo) : bool = 
      nz_vect2?(nvo) AND
      nvo =  opt_trk_gs_vertical(s,vo,vi,t,dir)

    opt_trk_gs_vertical_on_D: LEMMA
      LET v = vo-vi IN
      opt_trk_gs_vertical?(s,vo,vi,t,dir)(nvo) IMPLIES
        Delta(s,v) > 0 AND
        Theta_D(s,v,dir) > 0 AND
        (s+t*(nvo-vi))*(s+Theta_D(s,v,dir)*v) = sq(D) 

   END opt_trk_gs

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

  % Subtype TCC generated (at line 37, column 9) for  k * nzv + vi
      % expected type  (optimal?(vo, nzv))
  opt_trk_gs_line_TCC1: OBLIGATION
    FORALL (nzv: Nz_vect2, vo: Vect2, vi: Vect2, k: real):
      k = k_opt(nzv, vo - vi) IMPLIES optimal?(vo, nzv)(k * nzv + vi);

  % Subtype TCC generated (at line 37, column 6) for  (k, k * nzv + vi)
      % expected type  {k: real, nvo: (optimal?(vo, nzv)) |
                     %          k * nzv = nvo - vi}
  opt_trk_gs_line_TCC2: OBLIGATION
    FORALL (nzv: Nz_vect2, vo: Vect2, vi: Vect2, k: real):
      k = k_opt(nzv, vo - vi) IMPLIES k * nzv = k * nzv + vi - vi;

  % Subtype TCC generated (at line 42, column 4) for
      % opt_trk_gs_line(Vdir(u, vo - vi), vo, vi + W0(u, j))`2
      % expected type  {nvo: (optimal?(vo, Vdir(u, vo - vi))) |
                     %          u * (nvo - vi) = j}
  opt_trk_gs_dot_TCC1: OBLIGATION
    FORALL (u: Nz_vect2, vo: Vect2, vi: Vect2, j: real):
      u * (opt_trk_gs_line(Vdir(u, vo - vi), vo, vi + W0(u, j))`2 - vi) = j;

  % Subtype TCC generated (at line 46, column 36) for  v
      % expected type  {nzv | Delta(s, nzv) >= 0}
  opt_trk_gs_vertical_TCC1: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, v: Vect2):
      Delta(s, v) > 0 AND v = vo - vi IMPLIES
       v /= zero AND Delta[D](s, v) >= 0;

  % Subtype TCC generated (at line 48, column 23) for  t * p
      % expected type  Nz_vect2
  opt_trk_gs_vertical_TCC2: OBLIGATION
    FORALL (s: Vect2, vo: Vect2, vi: Vect2, t: posreal, dir: Sign, v: Vect2):
      Delta(s, v) > 0 AND Theta_D(s, v, dir) > 0 AND v = vo - vi IMPLIES
       (FORALL (p: Vector):
          p = s + Theta_D(s, v, dir) * v IMPLIES t * p /= zero);


body:
  %------------------------------------------------------------------------------
  % opt_vertical.pvs
  % ACCoRD v.1.0
  %------------------------------------------------------------------------------

  opt_vertical[D,H:posreal] : THEORY
  BEGIN

    IMPORTING opt_trk_gs[D],
              vertical_criterion[D,H]

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

    opt_vertical(s,vo,vi,epsh,epsv): {nvo | nz_vect2?(nvo) => 
                                            horizontal_only?(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 = opt_trk_gs_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

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

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

    opt_vertical_meets_horizontal_criterion : THEOREM
      opt_vertical?(sp,vo,vi,epsh,epsv)(nvo) IMPLIES
      horizontal_criterion?(sp,epsh)(nvo-vo)

    opt_vertical_meets_vertical_criterion : THEOREM
      opt_vertical?(s,vo,vi,epsh,epsv)(nvo) IMPLIES
      vertical_criterion?(epsv)(s,vo-vi)(nvo-vi)

  END opt_vertical

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

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

  % Subtype TCC generated (at line 23, column 33) for  v`z
      % expected type  nzreal
  opt_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 v`z /= 0));

  % Subtype TCC generated (at line 25, column 47) for  t
      % expected type  posreal
  opt_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 t >= 0)));

  % Subtype TCC generated (at line 26, column 57) for  vect2(s)
      % expected type  Sp_vect2[D]
  opt_vertical_TCC4: 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: Vect2):
                      NOT sqv(vect2(s)) < sq(D) AND
                       nvo2 =
                        opt_trk_gs_vertical(vect2(s),
                                            vect2(vo),
                                            vect2(vi),
                                            t,
                                            dir)
                       IMPLIES sqv(vect2(s)) >= sq(D)))));

  % Subtype TCC generated (at line 27, column 12) for  nvo2 WITH [z |-> vo`z]
      % expected type  {nvo | vect2(nvo) /= zero => vo`z = nvo`z}
  opt_vertical_TCC5: OBLIGATION FORALL (vo: Nzv2_vect3, vi: Nzv2_vect3): TRUE;

  % Subtype TCC generated (at line 29, column 12) for  zero
      % expected type  {nvo | vect2(nvo) /= zero => vo`z = nvo`z}
  opt_vertical_TCC6: 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: Vect2):
                      NOT sqv(vect2(s)) < sq(D) AND
                       NOT horizontal_criterion?(vect2(s), epsh)
                                                (nvo2 - vect2(vo))
                        AND
                        nvo2 =
                         opt_trk_gs_vertical(vect2(s),
                                             vect2(vo),
                                             vect2(vi),
                                             t,
                                             dir)
                       IMPLIES vect2(zero) /= zero => vo`z = zero`z))));

  % Subtype TCC generated (at line 32, column 9) for  zero
      % expected type  {nvo | vect2(nvo) /= zero => vo`z = nvo`z}
  opt_vertical_TCC7: 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 => vo`z = zero`z)));


body:
  %------------------------------------------------------------------------------
  % line_solutions.pvs
  % ACCoRD v1.0
  %
  % Circle solutions are vectors v such that at time t the ownship is on the 
  % circle of radius D and altitude H. If dir=-1, v points into the circle and 
  % outside the rectangle; if dir=1, v points outside the circle and inside the
  % rectangle.
  %------------------------------------------------------------------------------

  circle_solutions[D,H:posreal] : THEORY
  BEGIN

    IMPORTING circle_criterion[D,H]

    s,v     : VAR Vect3
    t       : VAR real
    dir,eps : VAR Sign
    pt      : VAR posreal

    circle_solution?(s,v,t,dir): bool =
      t > 0 AND
      circle_solution_2D?(s,v,t,dir) AND
      vertical_solution?(s`z,v`z,t,-dir)

    circle_solution_horizontal: LEMMA
      vertical_conflict?(s`z,v`z) AND
      circle_solution?(s,v,t,dir) 
      IMPLIES
        v`z /= 0 AND circle_solution?(s,v,Theta_H(s`z,v`z,-dir),dir)

    circle_solution_vertical: LEMMA
      horizontal_conflict?(s,v) AND
      circle_solution?(s,v,t,dir) 
      IMPLIES
        NOT zero_vect2?(v) AND circle_solution?(s,v,Theta_D(s,v,dir),dir)

    circle_solution_meets_criterion : LEMMA
      circle_solution?(s,v,t,dir) IMPLIES
      circle_criterion_at?(s,v,t,dir)

    circle_solution_independence : THEOREM
      circle_solution?(s,v,t,dir) IMPLIES
      NOT conflict_ever?(s,v)

    circle_solution?(s,v): MACRO bool =
      EXISTS (dir,t): circle_solution?(s,v,t,dir)


  END circle_solutions

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

  % Subtype TCC generated (at line 36, column 60) for  vect2(v)
      % expected type  {nzv | Delta(vect2(s), nzv) >= 0}
  circle_solution_vertical_TCC1: OBLIGATION
    FORALL (dir: Sign, s: Vect3, t: real, v: Vect3):
      circle_solution?(s, v, t, dir) AND
       horizontal_conflict?(vect2(s), vect2(v)) AND NOT vect2(v) = zero
       IMPLIES vect2(v) /= zero AND Delta[D](vect2(s), vect2(v)) >= 0;


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

  trk_circle[D,H: posreal] : THEORY
  BEGIN
    
    IMPORTING trk_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 track solution

    trk_circle(s,vo,vi,dir,irt): {nvo | nz_vect2?(nvo) => 
                                        trk_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 = trk_only_circle(s,vo,vi,t,dir,irt) IN
            nvo2 WITH [ z |-> vo`z ] 
        ELSE
           zero
        ENDIF
      ENDIF

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

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

    trk_vertical_irt(s,vo,vi,epsh,epsv,irt): {nvo | nz_vect2?(nvo) => 
                                                    trk_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 = trk_only_vertical(s,vo,vi,t,dir,irt) 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

    trk_vertical(s,vo,vi,epsh,epsv): {nvo | nz_vect2?(nvo) => 
                                            trk_only_3D?(vo)(nvo)} =
      LET vo1 = trk_vertical_irt(s,vo,vi,epsh,epsv,1),
          vo2 = trk_vertical_irt(s,vo,vi,epsh,epsv,-1) IN
      IF vo2 = zero THEN vo1
      ELSIF vo1 = zero OR
            le?(vo)(vo2,vo1) THEN vo2
      ELSE vo1
      ENDIF

    trk_vertical?(s,vo,vi,epsh,epsv)(nvo) : bool =
      nz_vect2?(nvo) AND
      EXISTS (irt): nvo = trk_vertical_irt(s,vo,vi,epsh,epsv,irt)

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

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

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

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

    trk_circle_independence: THEOREM
      trk_circle?(s,vo,vi,dir)(nvo) IMPLIES
        NOT conflict_ever?(s,nvo-vi)

    trk_circle_complete: THEOREM
      vo`z /= vi`z AND 
      trk_only_3D?(vo)(nvo) AND
      circle_solution?(s,nvo-vi,Theta_H(s`z,vo`z-vi`z,-dir),dir) AND
      NOT trk_special_case?(s,vo,vi,Theta_H(s`z,vo`z-vi`z,-dir))
      IMPLIES
        trk_circle?(s,vo,vi,dir)(nvo)

    trk_vertical_eps : LEMMA
      LET nvo = trk_vertical(s,vo,vi,epsh,epsv) IN
      nz_vect2?(nvo) IMPLIES
      trk_vertical?(s,vo,vi,epsh,epsv)(nvo)

    trk_vertical_meets_horizontal_criterion : THEOREM
      trk_vertical?(sp,vo,vi,epsh,epsv)(nvo) IMPLIES
      horizontal_criterion?(sp,epsh)(nvo-vo)

    trk_vertical_meets_vertical_criterion : THEOREM
      trk_vertical?(s,vo,vi,epsh,epsv)(nvo) IMPLIES
      vertical_criterion?(epsv)(s,vo-vi)(nvo-vi)

  END trk_circle

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

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

  % Subtype TCC generated (at line 40, column 26) for  vo`z - vi`z
      % expected type  nzreal
  trk_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 42, column 43) for  t
      % expected type  posreal
  trk_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 43, column 10) for  nvo2 WITH [z |-> vo`z]
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           trk_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  trk_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 => trk_only?(vect2(vo))(nvo)}):
              nvo2 =
               trk_only_circle(vect2(s), vect2(vo), vect2(vi), t, dir, irt)
               IMPLIES
               vect2((nvo2 WITH [z |-> vo`z])) /= zero =>
                trk_only?(vect2(vo))(vect2((nvo2 WITH [z |-> vo`z])))));

  % Subtype TCC generated (at line 45, column 9) for  zero
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           trk_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  trk_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 =>
            trk_only?(vect2(vo))(vect2(zero)) AND vo`z = zero`z);

  % Subtype TCC generated (at line 62, column 33) for  v`z
      % expected type  nzreal
  trk_vertical_irt_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 64, column 45) for  t
      % expected type  posreal
  trk_vertical_irt_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 65, column 57) for  vect2(s)
      % expected type  Sp_vect2[D]
  trk_vertical_irt_TCC3: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsv: Sign, irt: 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
                                       =>
                                       trk_only?(vect2(vo))(nvo)}):
                      NOT sqv(vect2(s)) < sq(D) AND
                       nvo2 =
                        trk_only_vertical(vect2(s),
                                          vect2(vo),
                                          vect2(vi),
                                          t,
                                          dir,
                                          irt)
                       IMPLIES sqv(vect2(s)) >= sq(D)))));

  % Subtype TCC generated (at line 66, column 12) for  nvo2 WITH [z |-> vo`z]
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           trk_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  trk_vertical_irt_TCC4: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsh: Sign, epsv: Sign,
            irt: 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
                                       =>
                                       trk_only?(vect2(vo))(nvo)}):
                      (sqv(vect2(s)) < sq(D) OR
                        horizontal_criterion?(vect2(s), epsh)
                                             (nvo2 - vect2(vo)))
                       AND
                       nvo2 =
                        trk_only_vertical(vect2(s),
                                          vect2(vo),
                                          vect2(vi),
                                          t,
                                          dir,
                                          irt)
                       IMPLIES
                       vect2((nvo2 WITH [z |-> vo`z])) /= zero =>
                        trk_only?(vect2(vo))
                                 (vect2((nvo2 WITH [z |-> vo`z])))))));

  % Subtype TCC generated (at line 68, column 12) for  zero
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           trk_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  trk_vertical_irt_TCC5: OBLIGATION
    FORALL (s: Vect3, vo: Nzv2_vect3, vi: Nzv2_vect3, epsh: Sign, epsv: Sign,
            irt: 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
                                       =>
                                       trk_only?(vect2(vo))(nvo)}):
                      NOT sqv(vect2(s)) < sq(D) AND
                       NOT horizontal_criterion?(vect2(s), epsh)
                                                (nvo2 - vect2(vo))
                        AND
                        nvo2 =
                         trk_only_vertical(vect2(s),
                                           vect2(vo),
                                           vect2(vi),
                                           t,
                                           dir,
                                           irt)
                       IMPLIES
                       vect2(zero) /= zero =>
                        trk_only?(vect2(vo))(vect2(zero)) AND
                         vo`z = zero`z))));

  % Subtype TCC generated (at line 71, column 9) for  zero
      % expected type  {nvo |
                     %          vect2(nvo) /= zero =>
                     %           trk_only?(vect2(vo))(vect2(nvo)) AND
                     %            vo`z = nvo`z}
  trk_vertical_irt_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 =>
                    trk_only?(vect2(vo))(vect2(zero)) AND vo`z = zero`z)));

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

  % Subtype TCC generated (at line 113, column 34) for
      % Theta_H(s`z, vo`z - vi`z, -dir)
      % expected type  posreal
  trk_circle_complete_TCC1: OBLIGATION
    FORALL (dir: Sign, nvo, s: Vect3, vi, vo: Nzv2_vect3):
      vo`z /= vi`z AND
       vo`z = nvo`z AND
        trk_only?(vect2(vo))(vect2(nvo)) AND
         circle_solution?(s, nvo - vi, Theta_H(s`z, vo`z - vi`z, -dir), dir)
       IMPLIES
       Theta_H[H](s`z, vo`z - vi`z, -dir) >= 0 AND
        Theta_H[H](s`z, vo`z - vi`z, -dir) > 0;


