# TheoryBodies

body:
  %
  %
  % Purpose : the validity and agreement properties of a reduce_select
  %           choice function in the exact communication case
  %
  %


  exact_reduce_stage[
    S:    posnat,
    D:    posnat,
    T:    TYPE+,
    <=: (total_order?[T]),
    error: T
  ]: THEORY  


    BEGIN

    IMPORTING 
      reduce_choice[S, D, T, <=, error],
      exact_comm_stage[S, D, T]

    s: VAR below(S)
    d, d1, d2: VAR below(D)
    v: VAR T
   
    src_set: VAR non_empty_finite_set[below(S)]
    dst_check: VAR non_empty_finite_set[below(D)]

    sent: VAR sent_vec_stage
    rcvd: VAR rcvd_matrix_stage
    check: VAR check_stage

    cf: VAR consensus_function

    tau: VAR tau_type

    n, n1, n2: VAR nat

    reduce_lower_validity: LEMMA
        quorum_correct?(sent, rcvd, check, tau) 
      IMPLIES
        EXISTS s: enabled(rcvd, check)(d)(s) AND
          sent(s) <= reduce_choice(tau, cf)(rcvd, check)(d)

    reduce_upper_validity: LEMMA
        quorum_correct?(sent, rcvd, check, tau) 
      IMPLIES
        EXISTS s: enabled(rcvd, check)(d)(s) AND
          reduce_choice(tau, cf)(rcvd, check)(d) <= sent(s)

    reduce_agreement_generation: LEMMA
        all_symmetric?(rcvd, check)
      IMPLIES
        reduce_choice(tau, cf)(rcvd, check)(d1) = reduce_choice(tau, cf)(rcvd, check)(d2)


    IMPORTING select_minmax[S, T, <=], select_minmax[D, T, <=]

    reduce_min_validity: LEMMA
        quorum_correct?(sent, rcvd, check, tau) AND
        enabled_within?(rcvd, check)(src_set)
      IMPLIES
        v_min(sent, src_set) 
         <= v_min(reduce_choice(tau, cf)(rcvd, check), dst_check)

    reduce_max_validity: LEMMA
        quorum_correct?(sent, rcvd, check, tau) AND
        enabled_within?(rcvd, check)(src_set)
      IMPLIES
        v_max(reduce_choice(tau, cf)(rcvd, check), dst_check)
          <= v_max(sent, src_set)

    reduce_consensus: LEMMA
        quorum_correct?(sent, rcvd, check, tau) AND
        enabled_within?(rcvd, check)(src_set) AND
        uniform?(sent, v)(src_set)
      IMPLIES
        uniform?(reduce_choice(tau, cf)(rcvd, check), v)(dst_check)

    reduce_min_eq_max: LEMMA
        all_symmetric?(rcvd, check)
      IMPLIES
        v_max(reduce_choice(tau, cf)(rcvd, check), dst_check) =
        v_min(reduce_choice(tau, cf)(rcvd, check), dst_check)

    END exact_reduce_stage


body:
  %
  %
  % Purpose : properties of the communication system passing exact information
  %           and operating in a fault-full environment.
  %
  %
  %

  exact_comm
  [
      N   : [nat -> posnat],  
      T   : TYPE+
  ] : THEORY

    BEGIN

    IMPORTING
      node_functions[N, T],
      exact_comm_stage

    i, j, k: VAR nat

    sources: VAR [j : nat -> finite_set[below(N(j))]] 

    sent:  VAR sent_vec
    rcvd:  VAR rcvd_matrix
    check: VAR check_function

    tau: VAR [i: nat -> tau_type]

    %
    % Abstracted fault assumptions
    %

    % same predicate is in inexact_comm
    enabled_within?(rcvd, check, j, k)(sources): bool = 
      FORALL i : j <= i AND i < k IMPLIES
        enabled_within?[N(i), N(i + 1), T](rcvd(i), check(i))(sources(i))

    % For every stage between j..k, and at every receiver, there is a
    % quorum (simple majority or more) of source nodes that exhibit correct communication
    quorum_correct?(sent, rcvd, check, tau, j, k): bool =
      FORALL i : j <= i AND i < k IMPLIES
        quorum_correct?[N(i), N(i+1), T](sent(i), rcvd(i), check(i), tau(i))

    % For every stage between j..k, and at every receiver, there is a
    % majority of source nodes that exhibit correct communication
    majority_correct?(sent, rcvd, check, j, k): bool =
      FORALL i : j <= i AND i < k IMPLIES
        majority_correct?[N(i), N(i+1), T](sent(i), rcvd(i), check(i))

    mid(i): tau_type = mid

    majority_correct_rw: LEMMA
      majority_correct?(sent, rcvd, check, j, k) IFF
        quorum_correct?(sent, rcvd, check, mid, j, k)


    % For some stage i (j<=i<k), there is a set of nodes
    % that exhibits only symmetric communication.  Furthermore,
    % a quorum (simply majority or more) are correct for 
    % all subsequent stages

    exists_all_symmetric?(sent, rcvd, check, tau, j, k): bool = 
      EXISTS i: j <= i AND i < k AND
        all_symmetric?(rcvd(i), check(i)) AND
        quorum_correct?(sent, rcvd, check, tau, i+1, k)

  %  exists_all_symmetric?(sent, rcvd, check, j, k): bool = 
  %    EXISTS i: j <= i AND i < k AND
  %      all_symmetric?(rcvd(i), check(i)) AND
  %      majority_correct?(sent, rcvd, check, i+1, k)

    % Specialization for the simple majority case.
    exists_all_symmetric?(sent, rcvd, check, j, k): bool = 
      exists_all_symmetric?(sent, rcvd, check, mid, j, k)

  END exact_comm


body:
  %
  %
  % Purpose : Validity and agreement properties for all destination
  %           nodes of a k-stage exact exchange.
  %           Assumes, no error is introduced during communication (this 
  %           is the definition of exact communication).
  %
  %


  exact_reduce
  [
      N   : [nat -> posnat],  
      T   : TYPE+,
      <=  : (total_order?[T]),              
      error: [nat -> T]
  ] : THEORY

    BEGIN

    IMPORTING
      exact_comm[N, T],
      protocol[N, T],
      k_ordered[N, T, <=, error],
      exact_reduce_stage

    i, j, k: VAR nat
    v: VAR T

    node_set: VAR [j : nat -> non_empty_finite_set[below(N(j))]] 

    check: VAR check_function
    sent:  VAR sent_vec
    rcvd:  VAR rcvd_matrix

    tau: VAR [j: nat -> tau_type]
    cf: VAR k_consensus_function

    %
    % Main results
    %

    lower_validity: THEOREM
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        quorum_correct?(sent, rcvd, check, tau, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set) 
      IMPLIES
        v_min(sent, node_set)(j) <= v_min(sent, node_set)(j + k)

    upper_validity: THEOREM
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        quorum_correct?(sent, rcvd, check, tau, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set) 
      IMPLIES
        v_max(sent, node_set)(j + k) <= v_max(sent, node_set)(j)

    consensus_validity: COROLLARY
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        quorum_correct?(sent, rcvd, check, tau, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set) AND
        uniform?(sent(j), v)(node_set(j))
      IMPLIES
        uniform?(sent(j + k), v)(node_set(j + k))

    exact_agreement_propagation: COROLLARY
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        quorum_correct?(sent, rcvd, check, tau, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set) AND
        v_max(sent, node_set)(j) = v_min(sent, node_set)(j)
      IMPLIES
        v_max(sent, node_set)(j + k) = v_min(sent, node_set)(j + k)

    agreement_generation: THEOREM
        protocol(reduce_choice(tau, cf), sent, rcvd, check, j, j + k) AND
        exists_all_symmetric?(sent, rcvd, check, tau, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(node_set)
      IMPLIES
        v_max(sent, node_set)(j + k) = v_min(sent, node_set)(j + k) 

  END exact_reduce


body:
  %
  % Purpose: abstract datatype representing a message.
  %
  %

  message[ T: TYPE+ ]: DATATYPE
    BEGIN
      garbled         : garbled?  % a message that never passes inline checks
      valid(value: T) : valid?      
    END message


body:
  %
  %
  % Purpose : communication model under the single-stage integration fault model
  %
  %

  comm_integration_stage
  [
     S : posnat,        % number of sources
     D : posnat,        % number of destinations
     T : TYPE+          % Value type
  ]: THEORY

    BEGIN
    
    IMPORTING
      message[T],
      integration_fault_model[S],
      exact_comm_stage[S, D, message]

    src_status: VAR node_status[S]       

    s: VAR below(S)
    d, d1, d2   : VAR below(D)

    msg: VAR message
    msg_checker: TYPE+ =
      {exp: [message -> bool] | NOT exp(garbled)}
      CONTAINING (LAMBDA msg: valid?(msg))
    valid_check_stage: TYPE = [below(D) -> [below(S) -> msg_checker]]

    msg_check:    VAR valid_check_stage
    common_check: VAR finite_set[below(S)]

    sent: VAR sent_vec_stage 
    rcvd: VAR rcvd_matrix_stage 

    tau: VAR tau_type

    m: VAR message

    %--communication

    osym_rcvd(sent, s): { m: message | m = sent(s) OR m = garbled }
    oasym_rcvd(sent, s, d): { m: message | m = sent(s) OR m = garbled }
    tsym_rcvd(sent, s): message
    sv_rcvd(sent, s, d): { m: message | m = tsym_rcvd(sent, s) OR m = garbled }
    tasym_rcvd(sent, s, d): message

    rcvd(sent, src_status)(d)(s): message =
      CASES src_status(s) OF
        good                     : sent(s),
        omissive_symmetric       : osym_rcvd(sent, s),
        omissive_asymmetric      : oasym_rcvd(sent, s, d),
        transmissive_symmetric   : tsym_rcvd(sent, s),
        single_error_asymmetric  : sv_rcvd(sent, s, d),
        transmissive_asymmetric  : tasym_rcvd(sent, s, d) 
      ENDCASES

    correct_denotation_send: LEMMA
        correct_denotation?(src_status(s)) AND
        msg_check(d)(s)(rcvd(sent, src_status)(d)(s))
      IMPLIES
        rcvd(sent, src_status)(d)(s) = sent(s)

    % A specific "check" function.  This one contains three
    % different types of checks.
    conforms(msg_check, common_check)(d)(s)(m): bool = 
      msg_check(d)(s)(m) AND common_check(s)

    conforms_type: JUDGEMENT 
      conforms(msg_check,common_check) HAS_TYPE valid_check_stage

    check: VAR check_stage

    only_valid_conform?(check): bool =
      FORALL d: FORALL s: FORALL m:check(d)(s)(m) => valid?(m)


    scheduled_conform: LEMMA
      enabled_within?(rcvd, conforms(msg_check, common_check))(common_check)

    correct_denotation(src_status)(d): [below(S) -> bool] = 
      correct_denotation(src_status)

    exact_correct_denotation: LEMMA
      exact_correct_denotation?(sent, rcvd(sent, src_status), msg_check)(correct_denotation(src_status))

    quorum_correct?(sent, msg_check, src_status, tau): bool = 
      quorum?(rcvd(sent, src_status), msg_check, tau)(correct_denotation(src_status))

    quorum_correct_integration: LEMMA
        quorum_correct?(sent, msg_check, src_status, tau)
      IMPLIES
        quorum_correct?(sent, rcvd(sent, src_status), msg_check, tau)

    majority_correct?(sent, msg_check, src_status): bool = 
      majority?(rcvd(sent, src_status), msg_check)(correct_denotation(src_status))

    majority_correct_rw: LEMMA
        majority_correct?(sent, msg_check, src_status) IFF
          quorum_correct?(sent, msg_check, src_status, mid)



    exact_single_denotation: LEMMA
      exact_single_denotation?(rcvd(sent, src_status), msg_check)(single_denotation(src_status))

    uniformly_enabled: LEMMA
        uniform?(msg_check)(symmetric_denotation(src_status))
      IMPLIES
        uniformly_enabled?(rcvd(sent, src_status), msg_check)(symmetric_denotation(src_status))

    exact_symmetric_single: LEMMA
      exact_single_denotation?(rcvd(sent, src_status), msg_check)(symmetric_denotation(src_status))

    all_symmetric?(sent, msg_check, src_status): bool =
      uniform?(msg_check)(symmetric_denotation(src_status)) AND
      enabled_within?(rcvd(sent, src_status), msg_check)(symmetric_denotation(src_status))

    all_symmetric_integration: LEMMA
        all_symmetric?(sent, msg_check, src_status)
      IMPLIES
        all_symmetric?(rcvd(sent, src_status), msg_check)

    % diagnostics

    good_conforms: LEMMA
        good(src_status)(s) AND
        msg_check(d)(s)(sent(s))
      IMPLIES
        enabled(rcvd(sent, src_status), msg_check)(d)(s)

  END comm_integration_stage

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

  % Subtype TCC generated (at line 29, column 16) for
      % (LAMBDA msg: valid?(msg))
      % expected type  msg_checker
  msg_checker_TCC1: OBLIGATION NOT valid?[T](garbled[T]);

  % Existence TCC generated (at line 44, column 2) for
      % osym_rcvd(sent, s): {m: message | m = sent(s) OR m = garbled}
  osym_rcvd_TCC1: OBLIGATION
    EXISTS (x:
              [d: [sent_vec_stage[S, D, message], below(S)] ->
                 {m: message[T] | m = d`1(d`2) OR m = garbled[T]}]):
      TRUE;

  % Existence TCC generated (at line 45, column 2) for
      % oasym_rcvd(sent, s, d): {m: message | m = sent(s) OR m = garbled}
  oasym_rcvd_TCC1: OBLIGATION
    EXISTS (x:
              [d1: [sent_vec_stage[S, D, message], below(S), below(D)] ->
                 {m: message[T] | m = d1`1(d1`2) OR m = garbled[T]}]):
      TRUE;

  % Existence TCC generated (at line 47, column 2) for
      % sv_rcvd(sent, s, d):
      %       {m: message | m = tsym_rcvd(sent, s) OR m = garbled}
  sv_rcvd_TCC1: OBLIGATION
    EXISTS (x:
              [d1: [sent_vec_stage[S, D, message], below(S), below(D)] ->
                 {m: message[T] |
                          m = tsym_rcvd(d1`1, d1`2) OR m = garbled[T]}]):
      TRUE;

  % Judgement subtype TCC generated (at line 72, column 4) for
      % conforms(msg_check, common_check)
      % expected type  valid_check_stage
  conforms_type: OBLIGATION
    FORALL (common_check, msg_check, x1: below(D), x2: below(S)):
      NOT conforms(msg_check, common_check)(x1)(x2)(garbled[T]);


body:
  %
  %
  % Purpose : communication model with the integration fault model
  %
  %

  comm_integration
  [
    N: [nat -> posnat],     % the number of nodes at each stage
    T: TYPE+
  ] : THEORY

    BEGIN

    i, j, k: VAR nat

    IMPORTING
      comm_integration_stage,
      exact_comm[N, message[T]]

    UT: TYPE = message[T]

    v: VAR UT

    tau: VAR [i: nat -> tau_type]

    valid_check_function: TYPE = [i: nat -> valid_check_stage[N(i),N(i+1),T]]

    status:       VAR [i: nat -> node_status[N(i)]]
    sent:         VAR [i: nat -> [below(N(i)) -> UT]]
    check:        VAR valid_check_function
    common_check: VAR [i: nat -> non_empty_finite_set[below(N(i))]]

    rcvd(sent, status)(i): [below(N(i+1)) -> [below(N(i)) -> UT]] =
      rcvd[N(i), N(i+1), T](sent(i), status(i))

    correct_denotation(status)(i): finite_set[below(N(i))] = correct_denotation(status(i))
    symmetric_denotation(status)(i): finite_set[below(N(i))] = symmetric_denotation(status(i))
    single_denotation(status)(i): finite_set[below(N(i))] = single_denotation(status(i))

    conforms(check, common_check)(i): check_stage[N(i),N(i+1),UT] =
      conforms[N(i),N(i+1),T](check(i), common_check(i))

  %  conforms_type: JUDGEMENT conforms(check, common_check) HAS_TYPE valid_check_function

    uniform?(check, status, j, k): bool =
      FORALL i: j <= i AND i < k IMPLIES
        uniform?[N(i), N(i + 1), UT](check(i))(symmetric_denotation(status(i)))

    quorum_correct?(sent, check, status, tau, j, k): bool =
      FORALL i: j <= i AND i < k IMPLIES
        quorum_correct?[N(i), N(i + 1), T](sent(i), check(i), status(i), tau(i))

    quorum_correct_integration: LEMMA
        quorum_correct?(sent, check, status, tau, j, k)
      IMPLIES
        quorum_correct?(sent, rcvd(sent, status), check, tau, j, k)

    majority_correct?(sent, check, status, j, k): bool =
      FORALL i: j <= i AND i < k IMPLIES
        majority_correct?[N(i), N(i + 1), T](sent(i), check(i), status(i))

    majority_correct_rw: LEMMA
        majority_correct?(sent, check, status, j, k) IFF
          quorum_correct?(sent, check, status, mid, j, k)

    exists_all_symmetric?(sent, check, status, tau, j, k): bool =
      EXISTS i: j <= i AND i < k AND 
        all_symmetric?(sent(i), check(i), status(i)) AND
        quorum_correct?(sent, check, status, tau, i + 1, k)

  %      majority_correct?(sent, check, status, i + 1, k)

    exists_all_symmetric?(sent, check, status, j, k): bool =
      exists_all_symmetric?(sent, check, status, mid, j, k)


    all_symmetric_integration: LEMMA
        exists_all_symmetric?(sent, check, status, tau, j, k)
      IMPLIES
        exists_all_symmetric?(sent, rcvd(sent, status), check, tau, j, k)

  END comm_integration


body:
  %
  %
  % Purpose: The protocol (relationship between what is received and 
  %          what is sent) when the message datatype is used with
  %          the integration fault model.
  %
  %


  protocol_integration
  [
    N: [nat -> posnat],
    T: TYPE+
  ] : THEORY

    BEGIN

    i, j, k: VAR nat
    element: T % to eliminate TCC's

    IMPORTING
      comm_integration[N, T],
      protocol[N, message[T]]

    status:       VAR [i: nat -> node_status[N(i)]]
    sent:         VAR [i: nat -> [below(N(i)) -> message[T]]]
    common_check: VAR [i: nat -> non_empty_finite_set[below(N(i))]]
    msg_check:    VAR valid_check_function
    check:        VAR check_function
    vf:           VAR choice_function
  %  cf:           VAR compute_function

    protocol(sent, check, vf, status, j, k): bool = 
      protocol(vf, sent, rcvd(sent, status), check, j, k)

  %  protocol(sent, check, vf, cf, status, j, k): bool = 
  %    protocol(cf, vf, sent, rcvd(sent, status), check, j, k)


  END protocol_integration


body:
  %
  %
  % Purpose : a message with a linear order.
  %
  %


  ordered_message[T: TYPE+, leq: (total_order?[T])]: THEORY

  BEGIN

    IMPORTING message[T]

    d1, d2: VAR message

    valid_iff_ord1: LEMMA (valid?(d1) IFF ord(d1) = 1)

    d3: VAR message

    <=(d1, d2): bool =
      IF valid?(d1) & valid?(d2)
        THEN leq(value(d1), value(d2))
        ELSE ord(d1) <= ord(d2)
      ENDIF

    eq_iff: LEMMA d1 = d2 IFF
      (valid?(d1) AND valid?(d2) AND value(d1) = value(d2)) OR
      (ord(d1) = ord(d2) AND ord(d1) /= 1 )

    message_total_order: JUDGEMENT <= HAS_TYPE (total_order?[message[T]])

  END ordered_message

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

  % Judgement subtype TCC generated (at line 30, column 33) for  <=
      % expected type  (total_order?[message[T]])
  message_total_order: OBLIGATION total_order?[message[T]](<=);


body:
  %
  %
  % Purpose : a reduce-select choice multiple-stage exchange
  %           under an integration fault model and exact communication.
  %
  %


  exact_reduce_integration
  [
    N: [nat -> posnat],
    T: TYPE+,
    <= : (total_order?[T]),
    (IMPORTING ordered_message[T,<=])
    source_error: [nat -> message]
  ] : THEORY

  BEGIN

    i, j, k: VAR nat

    IMPORTING
      ordered_message[T,<=],
      protocol_integration[N, T],
      exact_reduce[N, message, ordered_message.<=, source_error]

    status:       VAR [i : nat -> node_status[N(i)]]
    sent:         VAR [i : nat -> [below(N(i)) -> message]]
    local:        VAR [i : nat -> [below(N(i)) -> T]]
    common_check: VAR [i: nat -> non_empty_finite_set[below(N(i))]]
    msg_check:    VAR valid_check_function
    check:        VAR valid_check_function

    tau: VAR [j: nat -> tau_type]
    cf: VAR k_consensus_function

    lower_validity: THEOREM
        check = conforms(msg_check, common_check) AND
        protocol(sent, check, reduce_choice(tau, cf), status, j, j + k) AND
        quorum_correct?(sent, check, status, tau, j, j + k)
      IMPLIES
        v_min(sent, common_check)(j) <= v_min(sent, common_check)(j + k)

    upper_validity: THEOREM
        check = conforms(msg_check, common_check) AND
        protocol(sent, check, reduce_choice(tau, cf), status, j, j + k) AND
        quorum_correct?(sent, check, status, tau, j, j + k)
      IMPLIES
        v_max(sent, common_check)(j + k) <= v_max(sent, common_check)(j)

    agreement_generation: THEOREM
        check = conforms(msg_check, common_check) AND
        protocol(sent, check, reduce_choice(tau, cf), status, j, j + k) AND
        exists_all_symmetric?(sent, check, status, tau, j, j + k)
      IMPLIES
        v_max(sent, common_check)(j + k) = v_min(sent, common_check)(j + k)

  END exact_reduce_integration


body:
  %
  %
  % Purpose : core "majority" results, including a majority choice
  %           function, validity and agreement properties
  %
  %


  majority_properties[N: posnat, T:TYPE+]: THEORY

  BEGIN

    IMPORTING 
      finite_seqs[T],
      finite_sets@finite_sets_card_eq,
      pigeonhole[below(N)],
      node[N, T]

    v, v1, v2: VAR vec
    e, node_set: VAR nodeid_set
    d, t: VAR T

    mf: VAR majority_function

    majority(mf)(v, e): T = mf(vec2seq(v, e))

    majority_exists?(v, e): bool = maj_exists(vec2seq(v, e))

    majority_value_set(e, v)(t) : bool = 
      2 * card(uniform_nodes(e, v, t)) > card(e)

    is_majority: LEMMA  majority_value_set(e, v)(t) IFF is_majority(t, vec2seq(v, e))

    majority_value_subset: LEMMA
        majority_value_set(e, v)(t)
      IFF 
        majority_subset?(uniform_nodes(e, v, t), e)

    uniform_majority: LEMMA
        majority_subset?(node_set, e) AND
        uniform?(v, t)(node_set) 
      IMPLIES
        majority_value_set(e, v)(t)

    majority_validity: LEMMA
        majority_value_set(e, v)(t) 
      IMPLIES 
        majority(mf)(v, e) = t

    agreement_generation: THEOREM
        enabled_symmetric?(e, v1, v2)
      IMPLIES
        majority(mf)(v1, e) = majority(mf)(v2, e)

  END majority_properties


body:
  %
  %
  % Purpose : a single stage majority voter with 
  %           validity and agreement properties.
  %
  %

  majority_stage
  [
    S: posnat,  % Number of sources 
    D: posnat,  % Number of destinations 
    T: TYPE+    % Message type
  ] : THEORY

    BEGIN

    IMPORTING
      exact_comm_stage[S, D, T],
      majority_properties[S, T]

    s: VAR below(S)
    d, d1, d2: VAR below(D)
    v: VAR T

    src_set: VAR non_empty_finite_set[below(S)]
    dst_set: VAR non_empty_finite_set[below(D)]

    sent: VAR [below(S) -> T]
    rcvd: VAR [below(D) -> [below(S) -> T]]
    check: VAR [below(D) -> [below(S) -> [T -> bool]]]

    mf: VAR majority_function

    majority_vote(mf)(rcvd, check)(d): T =
      majority(mf)(rcvd(d), enabled(rcvd, check)(d))

    majority_at_destination: LEMMA
        majority_correct?(sent, rcvd, check) AND
        enabled_within?(rcvd, check)(src_set) AND
        uniform?(sent, v)(src_set)
      IMPLIES
        majority_value_set(enabled(rcvd, check)(d), rcvd(d))(v)

    majority_validity: THEOREM
        majority_correct?(sent, rcvd, check) AND
        enabled_within?(rcvd, check)(src_set) AND
        uniform?(sent, v)(src_set)
      IMPLIES
        majority_vote(mf)(rcvd, check)(d) = v

    consensus_validity: COROLLARY
        majority_correct?(sent, rcvd, check) AND
        enabled_within?(rcvd, check)(src_set) AND
        uniform?(sent, v)(src_set)
      IMPLIES
        uniform?(majority_vote(mf)(rcvd, check), v)(dst_set)

    agreement_generation_alt: THEOREM
        all_symmetric?(rcvd, check)
      IMPLIES
        majority_vote(mf)(rcvd, check)(d1) = majority_vote(mf)(rcvd, check)(d2)

    agreement_generation: THEOREM
        all_symmetric?(rcvd, check)
      IMPLIES
        EXISTS v:
           uniform?(majority_vote(mf)(rcvd, check), v)(dst_set)

    % diagnostic evidence

    % if all good sources agree then a source that votes for a different value
    % cannot be good
    faulty_source: LEMMA
        enabled_within?(rcvd, check)(src_set) AND
        uniform?(sent, v)(src_set) AND
        enabled(rcvd, check)(d)(s) AND
        NOT majority_vote(mf)(rcvd, check)(d) = rcvd(d)(s)
      IMPLIES
        NOT majority_correct_element?(sent, rcvd, check)(s)

    % if destination d observes the absence of a majority and a majority
    % of sources are correct, then the correct sources do not agree
    sources_disagree: COROLLARY
        majority_correct?(sent, rcvd, check) AND
        enabled_within?(rcvd, check)(src_set) AND
        NOT majority_exists?(rcvd(d), enabled(rcvd, check)(d))
      IMPLIES
        NOT (EXISTS v: uniform?(sent, v)(src_set))

    % Either all destinations agree or at least one of the participating
    % sources is asymmetric 
    asymmetric_source: COROLLARY
        (EXISTS v:
          uniform?(majority_vote(mf)(rcvd, check), v)(dst_set))
      OR
        (EXISTS s: NOT symmetric_source?(rcvd, check)(s))

  END majority_stage


body:
  %
  %
  % Purpose : validity and agreement properties for a multi-stage majority 
  %           exchange using the results-based fault model.
  %
  %

  majority
  [
      N   : [nat -> posnat],  
      T   : TYPE+
  ] : THEORY

    BEGIN

    IMPORTING
      majority_stage,
      exact_comm[N, T],
      protocol[N, T]

    i, j, k: VAR nat
    v: VAR T

    common_check: VAR [j : nat -> non_empty_finite_set[below(N(j))]] 

    check: VAR check_function
    sent:  VAR sent_vec
    rcvd:  VAR rcvd_matrix

    mf: VAR [nat -> majority_function[T]]

    majority_vote(mf): choice_function =
      LAMBDA i: majority_vote[N(i), N(i + 1), T](mf(i))
                                                                              
    % Main results
    consensus_validity: THEOREM
        protocol(majority_vote(mf), sent, rcvd, check, j, j + k) AND
        majority_correct?(sent, rcvd, check, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(common_check) AND
        uniform?(sent(j), v)(common_check(j)) 
      IMPLIES
        uniform?(sent(j + k), v)(common_check(j + k))

    agreement_generation: THEOREM
        protocol(majority_vote(mf), sent, rcvd, check, j, j + k) AND
        exists_all_symmetric?(sent, rcvd, check, j, j + k) AND
        enabled_within?(rcvd, check, j, j + k)(common_check)
      IMPLIES
        EXISTS v: uniform?(sent(j + k), v)(common_check(j + k))

    % diagnostic results

    faulty_source: THEOREM % cross-channel compare at any stage
      FORALL (s: below(N(j)), d: below(N(j + 1))):
        protocol(majority_vote(mf), sent, rcvd, check, j, j + 1) AND
        enabled_within?(rcvd, check, j, j + 1)(common_check) AND
        uniform?(sent(j), v)(common_check(j)) AND
        enabled(rcvd(j), check(j))(d)(s) AND
        rcvd(j)(d)(s) /= sent(j + 1)(d)
      IMPLIES
        NOT majority_correct_element?(sent(j), rcvd(j), check(j))(s)

    faulty_stage: COROLLARY  % to consensus_validity
        protocol(majority_vote(mf), sent, rcvd, check, j, j + k) AND
        majority_correct?(sent, rcvd, check, j, j + k) AND
        enabled_within?(rcvd, check, j, j+ k)(common_check) AND
        (EXISTS (d: (common_check(j + k))): sent(j + k)(d) /= v)
      IMPLIES
        NOT uniform?(sent(j), v)(common_check(j))


    asymmetric_source: THEOREM % 
        protocol(majority_vote(mf), sent, rcvd, check, j, j + 2) AND
        majority_correct?(sent, rcvd, check, j + 1, j + 2) AND
        enabled_within?(rcvd, check, j, j + 2)(common_check) AND
        (EXISTS (d: below(N(j + 2))):
          NOT majority_exists?(rcvd(j + 1)(d), 
                               enabled(rcvd(j + 1), check(j + 1))(d)))
      IMPLIES
        EXISTS (s: below(N(j))): NOT symmetric_source?(rcvd(j), check(j))(s)

  END majority


body:
  %
  % Purpose : instantiation of multiple-stage majority exchange with 
  %           the integration fault model.
  %
  %


  majority_integration
  [
    N: [nat -> posnat],
    T: TYPE+
  ] : THEORY

    BEGIN

    i, j, k: VAR nat


    IMPORTING
      protocol_integration[N, T],
      majority[N, message[T]]

    v: VAR message[T]

    status:       VAR [i : nat -> node_status[N(i)]]
    sent:         VAR [i : nat -> [below(N(i)) -> message[T]]]
    common_check: VAR [i: nat -> non_empty_finite_set[below(N(i))]]
    msg_check:    VAR valid_check_function
    check:        VAR valid_check_function
    mf:           VAR [nat -> majority_function[message[T]]]

    consensus_validity: THEOREM
        check = conforms(msg_check, common_check) AND
        protocol(sent, check, majority_vote(mf), status, j, j + k) AND
        majority_correct?(sent, check, status, j, j + k) AND
        uniform?(sent(j), v)(common_check(j))
      IMPLIES
        uniform?(sent(j + k), v)(common_check(j + k))

    agreement_generation: THEOREM
        check = conforms(msg_check, common_check) AND
        protocol(sent, check, majority_vote(mf), status, j, j + k) AND
        exists_all_symmetric?(sent, check, status, j, j + k)
      IMPLIES
        EXISTS v:
          uniform?(sent(j + k), v)(common_check(j + k))

  END majority_integration


body:
  %
  % Purpose: The theory hierarchy for the core building blocks
  % for the PVS fault-tolerance library.  This building blocks
  % can be used in the analysis of many types of fault-tolerant
  % systems.
  %
  % These theories are an extension of the work reported in:
  %
  %    Paul Miner, Alfons Geser, Lee Pike, and Jeffrey Maddalon. A
  %    unified fault-tolerance protocol. In Yassine Lakhnech and Sergio
  %    Yovine, editors, Formal Techniques, Modeling and Analysis of
  %    Timed and Fault-Tolerant Systems (FORMATS-FTRTFT), volume 3253 of
  %    Lecture Notes in Computer Science, pages 167--182. Springer,
  %    2004.
  %
  % Significant differences include a more expressive fault model
  % (building on the work of Kieckhafer), introduction of multi-stage
  % convergence results, and generalization to incorporate more voting
  % functions.
  %
  % 

  core_top: THEORY

  BEGIN

    IMPORTING
      majority_integration,
      exact_reduce_integration,
      reduce_synch,
      inexact_reduce,
      convergence_top


  END core_top


body:
  %%% ADT file generated from message

  message_adt[T: TYPE+]: THEORY
   BEGIN
    ASSUMING
     T_TCC1: ASSUMPTION EXISTS (x: T): TRUE;
    ENDASSUMING

    message: TYPE

    garbled?, valid?: [message -> boolean]

    value: [(valid?) -> T]

    garbled: (garbled?)

    valid: [T -> (valid?)]

    message_ord: [message -> upto(1)]

    message_ord_defaxiom: AXIOM
      message_ord(garbled) = 0 AND
       (FORALL (value: T): message_ord(valid(value)) = 1);

    ord(x: message): [message -> upto(1)] =
        CASES x OF garbled: 0, valid(valid1_var): 1 ENDCASES

    message_garbled_extensionality: AXIOM
      FORALL (garbled?_var: (garbled?), garbled?_var2: (garbled?)):
        garbled?_var = garbled?_var2;

    message_valid_extensionality: AXIOM
      FORALL (valid?_var: (valid?), valid?_var2: (valid?)):
        value(valid?_var) = value(valid?_var2) IMPLIES
         valid?_var = valid?_var2;

    message_valid_eta: AXIOM
      FORALL (valid?_var: (valid?)): valid(value(valid?_var)) = valid?_var;

    message_value_valid: AXIOM
      FORALL (valid1_var: T): value(valid(valid1_var)) = valid1_var;

    message_inclusive: AXIOM
      FORALL (message_var: message):
        garbled?(message_var) OR valid?(message_var);

    message_induction: AXIOM
      FORALL (p: [message -> boolean]):
        (p(garbled) AND (FORALL (valid1_var: T): p(valid(valid1_var))))
         IMPLIES (FORALL (message_var: message): p(message_var));

    every(p: PRED[T])(a: message):  boolean =
        CASES a OF garbled: TRUE, valid(valid1_var): p(valid1_var) ENDCASES;

    every(p: PRED[T], a: message):  boolean =
        CASES a OF garbled: TRUE, valid(valid1_var): p(valid1_var) ENDCASES;

    some(p: PRED[T])(a: message):  boolean =
        CASES a OF garbled: FALSE, valid(valid1_var): p(valid1_var) ENDCASES;

    some(p: PRED[T], a: message):  boolean =
        CASES a OF garbled: FALSE, valid(valid1_var): p(valid1_var) ENDCASES;

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

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

    message_well_founded: AXIOM strict_well_founded?[message](<<);

    reduce_nat(garbled?_fun: nat, valid?_fun: [T -> nat]):
          [message -> nat] =
        LAMBDA (message_adtvar: message):
          LET red: [message -> nat] = reduce_nat(garbled?_fun, valid?_fun) IN
            CASES message_adtvar
              OF garbled: garbled?_fun,
                 valid(valid1_var): valid?_fun(valid1_var)
              ENDCASES;

    REDUCE_nat(garbled?_fun: [message -> nat],
               valid?_fun: [[T, message] -> nat]):
          [message -> nat] =
        LAMBDA (message_adtvar: message):
          LET red: [message -> nat] = REDUCE_nat(garbled?_fun, valid?_fun) IN
            CASES message_adtvar
              OF garbled: garbled?_fun(message_adtvar),
                 valid(valid1_var): valid?_fun(valid1_var, message_adtvar)
              ENDCASES;

    reduce_ordinal(garbled?_fun: ordinal, valid?_fun: [T -> ordinal]):
          [message -> ordinal] =
        LAMBDA (message_adtvar: message):
          LET red: [message -> ordinal] =
                reduce_ordinal(garbled?_fun, valid?_fun)
            IN
            CASES message_adtvar
              OF garbled: garbled?_fun,
                 valid(valid1_var): valid?_fun(valid1_var)
              ENDCASES;

    REDUCE_ordinal(garbled?_fun: [message -> ordinal],
                   valid?_fun: [[T, message] -> ordinal]):
          [message -> ordinal] =
        LAMBDA (message_adtvar: message):
          LET red: [message -> ordinal] =
                REDUCE_ordinal(garbled?_fun, valid?_fun)
            IN
            CASES message_adtvar
              OF garbled: garbled?_fun(message_adtvar),
                 valid(valid1_var): valid?_fun(valid1_var, message_adtvar)
              ENDCASES;
   END message_adt


body:
  message_adt_map[T: TYPE+, T1: TYPE+]: THEORY
   BEGIN
    ASSUMING
     T_TCC1: ASSUMPTION EXISTS (x: T): TRUE;

     T1_TCC1: ASSUMPTION EXISTS (x: T1): TRUE;
    ENDASSUMING

    IMPORTING message_adt

    map(f: [T -> T1])(a: message[T]):  message[T1] =
        CASES a OF garbled: garbled, valid(valid1_var): valid(f(valid1_var))
          ENDCASES;

    map(f: [T -> T1], a: message[T]):  message[T1] =
        CASES a OF garbled: garbled, valid(valid1_var): valid(f(valid1_var))
          ENDCASES;

    every(R: [[T, T1] -> boolean])(x: message[T], y: message[T1]):  boolean =
        garbled?(x) AND garbled?(y) OR
         valid?(x) AND valid?(y) AND R(value(x), value(y));
   END message_adt_map


body:
  message_adt_reduce[T: TYPE+, range: TYPE]: THEORY
   BEGIN
    ASSUMING
     T_TCC1: ASSUMPTION EXISTS (x: T): TRUE;
    ENDASSUMING

    IMPORTING message_adt[T]

    reduce(garbled?_fun: range, valid?_fun: [T -> range]):
          [message[T] -> range] =
        LAMBDA (message_adtvar: message[T]):
          LET red: [message[T] -> range] = reduce(garbled?_fun, valid?_fun)
            IN
            CASES message_adtvar
              OF garbled: garbled?_fun,
                 valid(valid1_var): valid?_fun(valid1_var)
              ENDCASES;

    REDUCE(garbled?_fun: [message[T] -> range],
           valid?_fun: [[T, message[T]] -> range]):
          [message[T] -> range] =
        LAMBDA (message_adtvar: message[T]):
          LET red: [message[T] -> range] = REDUCE(garbled?_fun, valid?_fun)
            IN
            CASES message_adtvar
              OF garbled: garbled?_fun(message_adtvar),
                 valid(valid1_var): valid?_fun(valid1_var, message_adtvar)
              ENDCASES;
   END message_adt_reduce


body:
  top: THEORY
  %------------------------------------------------------------------------
  % Formalization of Floating Point numbers in PVS
  %  
  % The hardware level model was developed by Paul Miner (NASA LaRC). 
  %   P. Miner, Defining the IEEE-854 floating-point standard in PVS, 
  %   NASA/TM-95-110167, NASA Langley Research Center, 1995.
  %   http://techreports.larc.nasa.gov/ltrs/dublincore/1995/NASA-95-tm110167.html
  %
  % The high level model was developed by Sylvie Boldo (ENS-Lyon) while
  % visiting NIA.
  %   S. Boldo, Preuves formelles en arithmetiques a virgule flottante, 
  %   PhD. Thesis, Ecole Normale Superieure de Lyon, 2004.
  %   http://www.ens-lyon.fr/LIP/Pub/Rapports/PhD/PhD2004/PhD2004-05.pdf
  % This work has been partially funded by
  % * NASA LaRC under the Research Cooperative Agreement No. NCC-1-02043
  %   awarded to the National Institute of Aerospace
  % * French CNRS under PICS 2533
  %   awarded to the Laboratoire de l'Informatique du Parallelisme
  %
  % Users are invited to send feedback information to the authors  
  % and to Marc.Daumas@ENS-Lyon.Fr
  %
  % Version 1.1    11/30/2005
  %
  % Note: This library currently links with lnexp (non-foundational).
  %       If you want,  you can change this to lnexp_fnd in theory float.
  %------------------------------------------------------------------------
  BEGIN

    IMPORTING % High-level model (SB)

              float, axpy, 

              % Hardware-level (PyM)

              IEEE_854, IEEE_854_defs, infinity_arithmetic,
              comparison1, NaN_ops, arithmetic_ops, IEEE_854_remainder,
              IEEE_854_fp_int, real_to_fp, over_under, 
              IEEE_854_values, round, fp_round_aux,
              sum_lemmas, enumerated_type_defs, sum_hack,

              % Equivalence between the two models (SB)

              IEEE_link   
  END top


body:
  float[radix:above(1)]: THEORY
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  This theory defines the representation and basic operations for 
  %  floating point numbers for a given radix. 
  %  Author: 
  %  Sylvie Boldo (ENS-Lyon)
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  BEGIN

  IMPORTING lnexp_fnd@ln_exp,      % Currently links with "lnexp" (non-foundational).
            lnexp_fnd@expt,         % You change this to "lnexp_fnd" if you wish.
  	  lnexp_fnd@ln_approx

  % Type definitions
  float: TYPE = [# Fnum:int, Fexp:int #]

  float_pair(fn:int,fexp:int): float = (# Fnum := fn, Fexp := fexp #)

  Format: TYPE = [# Prec:above(1), dExp:nat #]
            
  vNum(b:Format):posnat = radix^Prec(b)  

  f,g: VAR float
  e1 : VAR int
  b  : VAR Format

  radix_div_vNum : lemma integer_pred(vNum(b) / radix)
  radix_less_vNum: lemma radix <= vNum(b)


  % First functions

  FtoR(f):real=Fnum(f)*radix^(Fexp(f))
  %CONVERSION FtoR

  float_int(j:int): float = (# Fnum := j, Fexp := 0 #)

  float_int_def: LEMMA FORALL (j:int): FtoR(float_int(j)) = j


  Fabs(f):float= (# Fnum:=abs(Fnum(f)), Fexp:=Fexp(f) #)
  Fopp(f):float= (# Fnum:=-(Fnum(f)), Fexp:=Fexp(f) #)

  Fplus(f,g):float= (# Fnum:=Fnum(f)*radix^(Fexp(f)-min(Fexp(f),Fexp(g))) 
     + Fnum(g)*radix^(Fexp(g)-min(Fexp(f),Fexp(g))), Fexp:=min(Fexp(f),Fexp(g)) #)
  Fminus(f,g):float= (# Fnum:=Fnum(f)*radix^(Fexp(f)-min(Fexp(f),Fexp(g))) 
     - Fnum(g)*radix^(Fexp(g)-min(Fexp(f),Fexp(g))), Fexp:=min(Fexp(f),Fexp(g)) #)
  Fmult(f,g):float= (# Fnum:=Fnum(f)*Fnum(g), Fexp:=Fexp(f)+Fexp(g) #)

  Fle?(f,g):bool = Fnum(Fminus(f,g)) <= 0
  Flt?(f,g):bool = Fnum(Fminus(f,g)) <  0

  Fmin(f,g):float = if Fle?(f,g) then f else g endif
  Fmax(f,g):float = if Fle?(f,g) then g else f endif

  % Real Number Symbols on Floats

  ; +(f,g): float = Fplus(f,g)
  ; -(f,g): float = Fminus(f,g)
  ; *(f,g): float = Fmult(f,g)
  ; -(f)  : float = Fopp(f)
  ; <(f,g): bool = Flt?(f,g)
  ; <=(f,g): bool = Fle?(f,g)
  ; >(f,g): bool = Flt?(g,f)
  ; >=(f,g): bool = Fle?(g,f)

  rrr: VAR real
  ; <(f,rrr): bool = (FtoR(f) < rrr)
  ; <=(f,rrr): bool = (FtoR(f) <= rrr)
  ; >(f,rrr): bool = (FtoR(f) > rrr)
  ; >=(f,rrr): bool = (FtoR(f) >= rrr)
  ; >(rrr,f): bool = (f < rrr)
  ; >=(rrr,f): bool = (f <= rrr)
  ; <(rrr,f): bool = (f > rrr)
  ; <=(rrr,f): bool = (f >= rrr)
  ; /=(f,rrr): bool = (FtoR(f) /= rrr)
  ; /=(rrr,f): bool = (f /= rrr)

  % arithmetic properties

  sum_float_commutes: LEMMA f+g=g+f

  mult_float_commutes: LEMMA f*g=g*f

  % exponent

  Fexpt(f, (n:nat)): float = (# Fnum:=expt(Fnum(f),n), Fexp:=n*Fexp(f) #)
  ;^(f,(n:nat)): float = Fexpt(f,n)

  FexptCorrect: LEMMA FORALL (n:nat): FtoR(f^n) = FtoR(f)^n

  sq(f): float = Fmult(f,f)

  sigma(ii:nat,jj:nat,FF:[nat->float]): RECURSIVE float =
    IF ii > jj THEN float_int(0)
    ELSIF jj = 0 THEN FF(0)
    ELSE Fplus(FF(jj),sigma(ii,jj-1,FF))
    ENDIF MEASURE jj


  % Division by an integer that divides the radix

  FDivInt(f,(i:nzint | mod(radix,i)=0)) : float =
    (# Fnum:=Fnum(f)*(radix/i), Fexp:=Fexp(f)-1 #)


  FDivInt_def: LEMMA  FORALL (i:nzint): mod(radix,i)=0 IMPLIES
  	     FtoR(FDivInt(f,i)) = FtoR(f)/i



  % A bounded float
  Fbounded?(b)(f):bool= abs(Fnum(f))<vNum(b) AND -dExp(b) <= Fexp(f)

  % Canonical representation
  Fnormal?(b)(f):bool= Fbounded?(b)(f) AND vNum(b)<=abs(radix*Fnum(f))

  Fsubnormal?(b)(f):bool= Fbounded?(b)(f) AND Fexp(f)=-dExp(b)
                        AND abs(radix*Fnum(f)) < vNum(b)

  Fcanonic?(b)(f):bool= Fnormal?(b)(f) OR Fsubnormal?(b)(f)

  % A few needed theorems

  hathatln: lemma (forall (r:posreal):
    radix^^(-(ln(r)/ln(radix)))=1/r)

  hathat_int: lemma 
    radix^^e1=radix^e1

  % Functions to get the predecessor, successor or canonical of a float 

  Fsucc(b)(f):float = IF Fnum(f)=vNum(b)-1 
      THEN (# Fnum:=vNum(b)/radix, Fexp:=Fexp(f)+1 #) 
      ELSIF  Fnum(f)=-vNum(b)/radix AND Fexp(f)>-dExp(b)
           THEN  (# Fnum:=-(vNum(b)-1), Fexp:=Fexp(f)-1 #) 
           ELSE  (# Fnum:=Fnum(f)+1, Fexp:=Fexp(f) #) 
      ENDIF

  Fpred(b)(f):float = IF Fnum(f)=-(vNum(b)-1) 
      THEN (# Fnum:=-vNum(b)/radix, Fexp:=Fexp(f)+1 #) 
      ELSIF  Fnum(f)=vNum(b)/radix AND Fexp(f)>-dExp(b)
           THEN  (# Fnum:=vNum(b)-1, Fexp:=Fexp(f)-1 #) 
           ELSE  (# Fnum:=Fnum(f)-1, Fexp:=Fexp(f) #) 
      ENDIF

  Fnormalize(b)(f:(Fbounded?(b))): recursive
  	{x : (Fcanonic?(b)) | FtoR(x)=FtoR(f)::real AND Fexp(x) <=  Fexp(f)} =
     if Fnum(f) = 0 then 
       (# Fnum:=0, Fexp:= -dExp(b)#)
     elsif Fexp(f) = -dExp(b) or 
                      abs(radix*Fnum(f)) >= vNum(b) then f
     else Fnormalize(b)((# Fnum:=radix*Fnum(f), Fexp:=Fexp(f)-1 #))
     endif
     measure vNum(b) - abs(Fnum(f))

  % Definition of the ulp

  Fulp(b)(f:(Fbounded?(b))):real = radix^(Fexp(Fnormalize(b)(f)))


  % Definition of the rounding modes

  RND : TYPE = [b:Format -> [[real,(Fbounded?(b))]->bool]]

  P : VAR RND

  % Common rounding modes
  isMin?(b)(r:real,min:(Fbounded?(b))):bool =  (FtoR(min) <= r) AND
    (forall (f:(Fbounded?(b))): FtoR(f) <= r => FtoR(f) <= FtoR(min))

  isMax?(b)(r:real,max:(Fbounded?(b))):bool =  (r <= FtoR(max)) AND
    (forall (f:(Fbounded?(b))): r <= FtoR(f) => FtoR(max) <= FtoR(f))

  ToZero?(b)(r:real,c:(Fbounded?(b))):bool =  
      if 0 <= r then isMin?(b)(r,c)
                else isMax?(b)(r,c)
      endif

  Closest?(b)(r:real,c:(Fbounded?(b))):bool =  
    (forall (f:(Fbounded?(b))): abs(FtoR(c)-r) <= abs(FtoR(f)-r))

  EvenClosest?(b)(r:real,c:(Fbounded?(b))):bool =  Closest?(b)(r,c) AND
    (even?(Fnum(Fnormalize(b)(c))) OR 
        (forall (f:(Fbounded?(b))): Closest?(b)(r,f) => FtoR(f)=FtoR(c)::real))

  AFZClosest?(b)(r:real,c:(Fbounded?(b))):bool =  Closest?(b)(r,c) AND
    (abs(r) <= abs(FtoR(c)) OR 
        (forall (f:(Fbounded?(b))): Closest?(b)(r,f) => FtoR(f)=FtoR(c)::real))

  % Generic rounding mode
  Total?(b)(P):bool = (forall (r:real): 
          (exists (f:(Fbounded?(b))): P(b)(r,f)))

  Compatible?(b)(P):bool = (forall (r1,r2:real, f1,f2:(Fbounded?(b))): 
     P(b)(r1,f1) => r1=r2 => FtoR(f1)=FtoR(f2)::real => P(b)(r2,f2))

  MinOrMax?(b)(P):bool = (forall (r:real,f:(Fbounded?(b))):
      P(b)(r,f) => isMin?(b)(r,f) OR isMax?(b)(r,f))

  Monotone?(b)(P):bool = (forall (r1,r2:real, f1,f2:(Fbounded?(b))):
     r1 < r2 => P(b)(r1,f1) =>  P(b)(r2,f2) => FtoR(f1) <= FtoR(f2))

  RoundedMode?(b)(P):bool = 
    Total?(b)(P) AND Compatible?(b)(P) AND MinOrMax?(b)(P) AND Monotone?(b)(P)

  Unique?(b)(P):bool = (forall (r:real,f1,f2:(Fbounded?(b))): 
         P(b)(r,f1) => P(b)(r,f2) => FtoR(f1)=FtoR(f2)::real)

  % A few needed theorems
  FcanonicOpp: lemma
     Fcanonic?(b)(f) IFF Fcanonic?(b)(Fopp(f))

  FcanonicBounded: lemma
     Fcanonic?(b)(f) => Fbounded?(b)(f)

  FpredCanonic: lemma
     Fcanonic?(b)(f) => Fcanonic?(b)(Fpred(b)(f))

  % Function to get the rounding down or up of a real

  RND_log_compute: LEMMA FORALL (x:real): x>=radix^(-dExp(b)-1)*vNum(b) IMPLIES floor(ln(x*radix/vNum(b))/ln(radix)) = log_nat(x * radix ^ (1 + dExp(b) - Prec(b)),radix)`1-dExp(b)

  RND_aux(b)(x:nonneg_real): (Fcanonic?(b)) =
    if (x < radix^(-dExp(b)-1)*vNum(b))
       then (# Fnum:=floor(x*radix^(dExp(b))), Fexp:=-dExp(b) #)
       else let e=log_nat(x * radix ^ (1 + dExp(b) - Prec(b)),radix)`1-dExp(b) in
            (# Fnum:=floor(x*radix^(-e)), Fexp:=e #)
    endif

  RND_aux_alt(b)(x:nonneg_real): (Fcanonic?(b)) =
    if (x < radix^(-dExp(b)-1)*vNum(b))
       then (# Fnum:=floor(x*radix^(dExp(b))), Fexp:=-dExp(b) #)
       else let e=floor(ln(x*radix/vNum(b))/ln(radix)) in
            (# Fnum:=floor(x*radix^(-e)), Fexp:=e #)
    endif

  RND_aux_alt_def: LEMMA RND_aux=RND_aux_alt

  RND_Min(b)(x:real): (Fcanonic?(b)) =
    if (0 <= x) 
      then RND_aux(b)(x)
      elsif FtoR(Fopp(RND_aux(b)(-x)))=x then Fopp(RND_aux(b)(-x))
      else  Fpred(b)(Fopp(RND_aux(b)(-x)))
    endif

  RND_Max(b)(x:real): (Fcanonic?(b)) = Fopp(RND_Min(b)(-x))


  % Computable Rounding Functions

  % Function to get the even closest rounding

  RND_EClosest(b)(x:real): (Fcanonic?(b)) =
   if     abs(FtoR(RND_Min(b)(x))-x) < abs(FtoR(RND_Max(b)(x))-x) then RND_Min(b)(x)
    elsif abs(FtoR(RND_Max(b)(x))-x) < abs(FtoR(RND_Min(b)(x))-x) then RND_Max(b)(x)
    elsif FtoR(RND_Min(b)(x))=FtoR(RND_Max(b)(x))::real then RND_Min(b)(x)
    elsif even?(Fnum(RND_Min(b)(x))) then RND_Min(b)(x)
    else  RND_Max(b)(x)
   endif



  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% End of definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%
  n          : VAR nat
  e2         : VAR int
  q,p        : VAR float
  z1,z2,z3,r : VAR real

  % lemmas about exp
  Exp_incr_1: lemma
    e1 < e2 => radix^e1 < radix^e2

  Exp_incr_2: lemma
    radix^e1 < radix^e2 => e1 < e2

  Exp_increq_1: lemma
    e1 <= e2 => radix^e1 <= radix^e2

  Exp_increq_2: lemma
    radix^e1 <= radix^e2 => e1 <= e2

  Exp_1 : lemma
    radix^e1 = 1 => e1 = 0

  EqExpEq: lemma
    radix^e1=radix^e2 => e1=e2

  expt_odd: lemma
      (odd?(radix) IFF odd?(radix^(n+1)))

  expt_even: lemma
      (even?(radix) IFF even?(radix^(n+1)))




  % First lemmas about floats
  FoppCorrect: lemma
    FtoR(Fopp(f))=-FtoR(f)

  FoppFopp: LEMMA
  	  Fopp(Fopp(f)) = f

  Fopp_mult_left: LEMMA
  		(-f)*g = -(f*g)

  Fopp_mult_right: LEMMA
  		f*(-g) = -(f*g)

  FabsCorrect: lemma
     FtoR(Fabs(f))=abs(FtoR(f))

  FplusCorrect: lemma
     FtoR(Fplus(p,q))=FtoR(p)+FtoR(q)

  FplusAssociative: LEMMA associative?[float](Fplus)

  FmultAssociative: LEMMA associative?[float](Fmult)

  FminusCorrect: lemma
     FtoR(Fminus(p,q))=FtoR(p)-FtoR(q)

  FmultCorrect: lemma
     FtoR(Fmult(p,q))=FtoR(p)*FtoR(q)

  Fmult_1_r: LEMMA f*float_int(1) = f

  Fmult_1_l: LEMMA float_int(1)*f = f

  Fmult_2_r: LEMMA f*float_int(2) = f+f

  Fmult_2_l: LEMMA float_int(2)*f = f+f

  FDivKexpt(f,(k:nzint | mod(radix,k)=0),(i:nat)): float =
    (# Fnum:=Fnum(f)*((radix^i)/(k^i)), Fexp:=Fexp(f)-i #)

  FDivKexpt_def: LEMMA FORALL (i:nat,(k:nzint | mod(radix,k)=0)):
  	       FtoR(FDivKexpt(f,k,i)) = FtoR(f)/k^i


  FoppBounded: lemma 
     Fbounded?(b)(f) => Fbounded?(b)(Fopp(f))

  FabsBounded: lemma 
     Fbounded?(b)(f) => Fbounded?(b)(Fabs(f))

  FabsCanonic: lemma 
     Fcanonic?(b)(f) => Fcanonic?(b)(Fabs(f))

  LeR0Fnum: lemma  
     0 <= FtoR(p) => 0 <= Fnum(p)

  LeFnumZERO: lemma 
     0 <= Fnum(p) => 0 <= FtoR(p)

  FleCorrect: lemma
     Fle?(p,q) IFF FtoR(p) <= FtoR(q)

  FltCorrect: lemma
     Flt?(p,q) IFF FtoR(p) < FtoR(q)

  FminCorrect: lemma
     FtoR(Fmin(p,q))=min(FtoR(p),FtoR(q))

  FmaxCorrect: lemma
     FtoR(Fmax(p,q))=max(FtoR(p),FtoR(q))

  % Unicity of the canonical representant
  FsubnormalUnique: lemma
      Fsubnormal?(b)(p) => Fsubnormal?(b)(q) => FtoR(p)=FtoR(q)::real => p=q

  FnormalUnique: lemma
      Fnormal?(b)(p) => Fnormal?(b)(q) => FtoR(p)=FtoR(q)::real => p=q

  NormalAndSubNormalNotEq: lemma
      Fnormal?(b)(p) => Fsubnormal?(b)(q) => FtoR(p) /= FtoR(q)::real

  FcanonicUnique: lemma
      Fcanonic?(b)(p) => Fcanonic?(b)(q) => FtoR(p)=FtoR(q)::real => p=q

  % A few properties on canonical representations
  FnormalizeCorrect: lemma 
      Fbounded?(b)(p) => FtoR(Fnormalize(b)(p))=FtoR(p)::real

  FulpCanonic: lemma
     Fcanonic?(b)(p) => Fulp(b)(p)=radix^(Fexp(p))

  Lexico: lemma
     Fcanonic?(b)(p) => Fcanonic?(b)(q) => 0 <= FtoR(p) => FtoR(p) <= FtoR(q)
       => Fexp(p) <= Fexp(q)

  CanonicLeastExp: lemma
     Fcanonic?(b)(p) => Fbounded?(b)(q) => FtoR(p)=FtoR(q)::real
       => Fexp(p) <= Fexp(q)

  Fast_canonic: lemma
     Fbounded?(b)(p) => Fexp(p)=-dExp(b) OR vNum(b)<=abs(radix*Fnum(p))
          => Fcanonic?(b)(p)

  % properties about the ulp
  FulpOpp: lemma Fbounded?(b)(f) => Fulp(b)(Fopp(f))=Fulp(b)(f)

  FulpAbs: lemma Fbounded?(b)(f) => Fulp(b)(Fabs(f))=Fulp(b)(f)

  FulpMonotone: lemma Fbounded?(b)(p) => Fbounded?(b)(q) =>
     0 <= FtoR(p) => FtoR(p) <= FtoR(q) => Fulp(b)(p) <= Fulp(b)(q)

  FulpMonotoneAbs: lemma Fbounded?(b)(p) => Fbounded?(b)(q) =>
     abs(FtoR(p)) <= abs(FtoR(q)) => Fulp(b)(p) <= Fulp(b)(q)

  FloatPlusUlpBounded: lemma
     Fbounded?(b)(p) => (exists (f:(Fbounded?(b))): FtoR(f)=FtoR(p)+Fulp(b)(p))

  FloatMinusUlpBounded: lemma
     Fbounded?(b)(p) => (exists (f:(Fbounded?(b))): FtoR(f)=FtoR(p)-Fulp(b)(p))

  % properties of Fpred and Fsucc
  FpredFoppFsucc: lemma 
      Fpred(b)(Fopp(f))=Fopp(Fsucc(b)(f))

  FsuccFoppFpred: lemma 
      Fsucc(b)(Fopp(f))=Fopp(Fpred(b)(f))

  FsuccFpred: lemma 
      Fcanonic?(b)(f) => Fsucc(b)(Fpred(b)(f))=f

  FpredFsucc: lemma 
      Fcanonic?(b)(f) => Fpred(b)(Fsucc(b)(f))=f

  FpredBounded: lemma
     Fbounded?(b)(f) => Fbounded?(b)(Fpred(b)(f))

  FsuccBounded: lemma
     Fbounded?(b)(f) => Fbounded?(b)(Fsucc(b)(f))

  FsuccCanonic: lemma
     Fcanonic?(b)(f) => Fcanonic?(b)(Fsucc(b)(f))

  FpredPos: lemma
    Fcanonic?(b)(p) => 0 < FtoR(p) => 0 <= FtoR(Fpred(b)(p))

  FsuccPos: lemma
    Fcanonic?(b)(p) => 0 <= FtoR(p) => 0 < FtoR(Fsucc(b)(p))

  FpredDiff: lemma
     Fcanonic?(b)(f) => 0 < FtoR(f)
        => FtoR(f)-FtoR(Fpred(b)(f))=Fulp(b)(Fpred(b)(f))

  FsuccDiff: lemma
     Fcanonic?(b)(f) => 0 <= FtoR(f)
        => FtoR(Fsucc(b)(f))-FtoR(f)=Fulp(b)(f)

  FpredLt: lemma
      FtoR(Fpred(b)(f)) < FtoR(f)

  FpredLe_aux: lemma
     Fcanonic?(b)(p) => Fcanonic?(b)(q) => 0 < FtoR(p) =>
       FtoR(p) <= FtoR(q) => FtoR(Fpred(b)(p)) <= FtoR(Fpred(b)(q))

  FpredLe_aux2: lemma
     Fcanonic?(b)(p) => Fcanonic?(b)(q) => 0 <= FtoR(p) =>
       FtoR(p) <= FtoR(q) => FtoR(Fsucc(b)(p)) <= FtoR(Fsucc(b)(q))

  FpredLe: lemma
     Fcanonic?(b)(p) => Fcanonic?(b)(q) =>
      (FtoR(p) <= FtoR(q) IFF FtoR(Fpred(b)(p)) <= FtoR(Fpred(b)(q)))

  FsuccLe: lemma
     Fcanonic?(b)(p) => Fcanonic?(b)(q) =>
      (FtoR(p) <= FtoR(q) IFF FtoR(Fsucc(b)(p)) <= FtoR(Fsucc(b)(q)))

  FpredProp_aux: lemma
    Fcanonic?(b)(p) => Fcanonic?(b)(q) => 0 <= FtoR(p) => FtoR(p) < FtoR(q) 
           => FtoR(p) <= FtoR(Fpred(b)(q))

  FpredProp: lemma
    Fcanonic?(b)(p) => Fcanonic?(b)(q) => FtoR(p) < FtoR(q) 
        => FtoR(p) <= FtoR(Fpred(b)(q))

  FsuccLt: lemma
    FtoR(f) < FtoR(Fsucc(b)(f))

  FsuccProp: lemma
    Fcanonic?(b)(p) => Fcanonic?(b)(q) =>
       FtoR(p) < FtoR(q) => FtoR(Fsucc(b)(p)) <= FtoR(q)

  FsuccZleEq_aux: lemma
      e1 <= r => r < e1+1 => rational_pred(r) => integer_pred(r) => e1=r

  FsuccZleEq: lemma
      FtoR(p) <= FtoR(q) => FtoR(q) < FtoR(Fsucc(b)(p)) => Fexp(p) <= Fexp(q) => FtoR(p)=FtoR(q)::real

  % properties of odd and even
  EvenFsuccOdd_aux: lemma
    even?(vNum(b)-1) => odd?(vNum(b)/radix)

  EvenFsuccOdd: lemma
    Fcanonic?(b)(p) => even?(Fnum(p)) => odd?(Fnum(Fsucc(b)(p)))

  OddFsuccEven_aux: lemma
    odd?(vNum(b)-1) => even?(vNum(b)/radix)

  OddFsuccEven: lemma
    Fcanonic?(b)(p) => odd?(Fnum(p)) => even?(Fnum(Fsucc(b)(p)))

  % Rounding modes properties
  MinOppMax :  lemma Fbounded?(b)(p) => isMin?(b)(r,p)  => isMax?(b)(-r,Fopp(p))
  MaxOppMin :  lemma Fbounded?(b)(p) => isMax?(b)(r,p)  => isMin?(b)(-r,Fopp(p))
  ClosestFopp: lemma Fbounded?(b)(p) => Closest?(b)(r,p)=> Closest?(b)(-r,Fopp(p))

  RleRoundedR0 : lemma Fbounded?(b)(f) =>
    RoundedMode?(b)(P) => P(b)(r,f) => 0 <= r => 0 <= FtoR(f)

  RleRoundedLessR0 : lemma Fbounded?(b)(f) => 
    RoundedMode?(b)(P) => P(b)(r,f) => r <= 0 => FtoR(f) <= 0

  RND_aux_le   : lemma (forall (x:nonneg_real): FtoR(RND_aux(b)(x)) <= x)
  RND_aux_ge   : lemma (forall (x:nonneg_real): x < FtoR(Fsucc(b)(RND_aux(b)(x))))

  RND_Min_isMin: lemma isMin?(b)(r,RND_Min(b)(r))
  RND_Max_isMax: lemma isMax?(b)(r,RND_Max(b)(r))

  % Rounding floats to bounded

  RND_aux_float(b)((f|Fnum(f)>=0)): (Fcanonic?(b)) =
    IF (Fnum(f) < radix^(Prec(b)-Fexp(f)-dExp(b)-1))
    THEN (# Fnum := floor(Fnum(f)*radix^(dExp(b)+Fexp(f))),Fexp := -dExp(b) #)
    ELSE LET e =log_nat(Fnum(f)*radix^(Fexp(f)+1+dExp(b)-Prec(b)),
  			radix)`1-dExp(b)
         IN (# Fnum := floor(Fnum(f)*radix^(Fexp(f)-e)),Fexp := e #)
    ENDIF

  RND_aux_float_def: LEMMA Fnum(f)>=0 IMPLIES
    RND_aux_float(b)(f) = RND_aux(b)(FtoR(f))

  RND_float_Min(b)(f): (Fcanonic?(b)) =
    if (0 <= Fnum(f)) 
      then RND_aux_float(b)(f)
      elsif FtoR(Fopp(RND_aux_float(b)(-f)))=FtoR(f) then Fopp(RND_aux_float(b)(-f))
      else  Fpred(b)(Fopp(RND_aux_float(b)(-f)))
    endif

  RND_float_Min_def: LEMMA
    RND_float_Min(b)(f) = RND_Min(b)(FtoR(f))

  RND_float_Max(b)(f): (Fcanonic?(b)) = Fopp(RND_float_Min(b)(-f))

  RND_float_Max_def: LEMMA
    RND_float_Max(b)(f) = RND_Max(b)(FtoR(f))

  RND_float_Min_ge_canonic: LEMMA Fcanonic?(b)(g) IMPLIES
  	    (RND_float_Min(b)(f) >= g IFF f>=g)

  RND_float_Max_le_canonic: LEMMA Fcanonic?(b)(g) IMPLIES
  	    (RND_float_Max(b)(f) <= g IFF f<=g)

  RND_float_Min_canonic: LEMMA Fcanonic?(b)(f) IMPLIES
              RND_float_Min(b)(f) = f

  RND_float_Max_canonic: LEMMA Fcanonic?(b)(f) IMPLIES
              RND_float_Max(b)(f) = f

  RND_float_Min_ge: LEMMA
  	    f>=g IMPLIES RND_float_Min(b)(f)>=RND_float_Min(b)(g)

  RND_float_Min_le: LEMMA
  	    f<=g IMPLIES RND_float_Min(b)(f)<=RND_float_Min(b)(g)

  RND_float_Max_ge: LEMMA
  	    f>=g IMPLIES RND_float_Max(b)(f)>=RND_float_Max(b)(g)

  RND_float_Max_le: LEMMA
  	    f<=g IMPLIES RND_float_Max(b)(f)<=RND_float_Max(b)(g)

  RND_float_Min_lt_canonic: LEMMA Fcanonic?(b)(g) IMPLIES
  	    (RND_float_Min(b)(f) < g IFF f<g)

  RND_float_Min_gt_canonic: LEMMA Fcanonic?(b)(g) IMPLIES
  	    (RND_float_Max(b)(f) > g IFF f>g)

  RND_float_Min_ge_0: LEMMA RND_float_Min(b)(f) >= 0 IFF f>=0

  RND_float_Min_lt_0: LEMMA RND_float_Min(b)(f) < 0 IFF f<0

  RND_float_Max_le_0: LEMMA RND_float_Max(b)(f) <= 0 IFF f<=0

  RND_float_Max_gt_0: LEMMA RND_float_Max(b)(f) > 0 IFF f>0

  Fmult_canonic_id_Min: LEMMA Fcanonic?(b)(f) IMPLIES RND_float_Min(b)(f*Fnormalize(b)(float_int(1))) = f

  Fmult_canonic_id_Max: LEMMA Fcanonic?(b)(f) IMPLIES RND_float_Max(b)(f*Fnormalize(b)(float_int(1))) = f

  Fplus_canonic_id_Min: LEMMA Fcanonic?(b)(f) IMPLIES RND_float_Min(b)(f+Fnormalize(b)(float_int(0))) = f

  Fplus_canonic_id_Max: LEMMA Fcanonic?(b)(f) IMPLIES RND_float_Max(b)(f+Fnormalize(b)(float_int(0))) = f

  MaxSuccMin: lemma 
    Fcanonic?(b)(q) => Fcanonic?(b)(p) =>
    isMin?(b)(r,p) => isMax?(b)(r,q) => NOT FtoR(p)=FtoR(q)::real 
      => q=Fsucc(b)(p)

  LeMinMaxClosest: lemma Fbounded?(b)(f) =>  Fbounded?(b)(p) =>  Fbounded?(b)(q) => 
       isMin?(b)(r,p) =>  abs(FtoR(f)-r) <= abs(FtoR(p)-r) => isMax?(b)(r,q) =>  abs(FtoR(f)-r) <= abs(FtoR(q)-r)
        => Closest?(b)(r,f)

  isMin_Total       : lemma Total?(b)(isMin?)
  isMin_Compatible  : lemma Compatible?(b)(isMin?)
  isMin_Monotone    : lemma Monotone?(b)(isMin?)
  isMin_RoundedMode : lemma RoundedMode?(b)(isMin?)
  isMin_Unique      : lemma Unique?(b)(isMin?)

  isMax_Total       : lemma Total?(b)(isMax?)
  isMax_Compatible  : lemma Compatible?(b)(isMax?)
  isMax_Monotone    : lemma Monotone?(b)(isMax?)
  isMax_RoundedMode : lemma RoundedMode?(b)(isMax?)
  isMax_Unique      : lemma Unique?(b)(isMax?)

  ToZero_Total       : lemma Total?(b)(ToZero?)
  ToZero_Compatible  : lemma Compatible?(b)(ToZero?)
  ToZero_MinOrMax    : lemma MinOrMax?(b)(ToZero?)
  ToZero_Monotone    : lemma Monotone?(b)(ToZero?)
  ToZero_RoundedMode : lemma RoundedMode?(b)(ToZero?)
  ToZero_Unique      : lemma Unique?(b)(ToZero?)

  Closest_Total       : lemma Total?(b)(Closest?)
  Closest_Compatible  : lemma Compatible?(b)(Closest?)
  Closest_MinOrMax    : lemma MinOrMax?(b)(Closest?)
  Closest_Monotone    : lemma Monotone?(b)(Closest?)
  Closest_RoundedMode : lemma RoundedMode?(b)(Closest?)

  RND_EClosest_isEclosest : lemma EvenClosest?(b)(r,RND_EClosest(b)(r))
  EvenClosest_Total       : lemma Total?(b)(EvenClosest?)
  EvenClosest_Compatible  : lemma Compatible?(b)(EvenClosest?)
  EvenClosest_MinOrMax    : lemma MinOrMax?(b)(EvenClosest?)
  EvenClosest_Monotone    : lemma Monotone?(b)(EvenClosest?)
  EvenClosest_RoundedMode : lemma RoundedMode?(b)(EvenClosest?)
  EvenClosest_Unique      : lemma Unique?(b)(EvenClosest?)

  AFZClosest_Total       : lemma Total?(b)(AFZClosest?)
  AFZClosest_Compatible  : lemma Compatible?(b)(AFZClosest?)
  AFZClosest_MinOrMax    : lemma MinOrMax?(b)(AFZClosest?)
  AFZClosest_Monotone    : lemma Monotone?(b)(AFZClosest?)
  AFZClosest_RoundedMode : lemma RoundedMode?(b)(AFZClosest?)
  AFZClosest_Unique      : lemma Unique?(b)(AFZClosest?)



  RoundedProjectorEq : lemma Fbounded?(b)(f) => Fbounded?(b)(p) => 
    RoundedMode?(b)(P) => P(b)(FtoR(f),p) => FtoR(p)=FtoR(f)::real

  RoundedProjector : lemma Fbounded?(b)(f) =>
    RoundedMode?(b)(P) => P(b)(FtoR(f),f)

  isMin_Rep :  lemma Fbounded?(b)(f) => isMin?(b)(FtoR(p),f) 
      => (exists (m:int): FtoR(f)=FtoR((# Fnum:=m, Fexp:=Fexp(p) #))::real) 

  RoundedModeRep : lemma Fbounded?(b)(f) => RoundedMode?(b)(P) =>  
    P(b)(FtoR(p),f) => (exists (m:int): FtoR(f)=FtoR((# Fnum:=m, Fexp:=Fexp(p) #))::real) 

  RoundedModeUlp : lemma Fbounded?(b)(p) =>
    RoundedMode?(b)(P) => P(b)(r,p) => abs(FtoR(p)-r) < Fulp(b)(p)

  ClosestUlp : lemma Fbounded?(b)(p) => 
      Closest?(b)(r,p) => abs(FtoR(p)-r) <= Fulp(b)(p)/2

  RoundedModeNonDecreasing : lemma 
     Fbounded?(b)(p) => Fbounded?(b)(q) =>  RoundedMode?(b)(P) => Unique?(b)(P) 
       => P(b)(z1,p) =>  P(b)(z2,q)  =>  z1 <= z2 => FtoR(p) <= FtoR(q)

  ClosestUlp2 : lemma 
      Fcanonic?(b)(p) => Closest?(b)(r,p) => 
      abs(r) <= abs(FtoR(p)) + Fulp(b)(Fpred(b)(Fabs(p)))/2  => abs(FtoR(p)-r) <= Fulp(b)(Fpred(b)(Fabs(p)))/2

  ClosestFabs: lemma Fbounded?(b)(p) => Closest?(b)(r,p)=> Closest?(b)(abs(r),Fabs(p))

  % Representable floats are computed exactly
  SterbenzAux : lemma
   Fbounded?(b)(p) => Fbounded?(b)(q) => 
     FtoR(p) <= FtoR(q) =>  FtoR(q) <= 2*FtoR(p) => Fbounded?(b)(Fminus(q,p)) 

  Sterbenz : lemma
   Fbounded?(b)(p) => Fbounded?(b)(q) => 
     FtoR(p)/2 <= FtoR(q) =>  FtoR(q) <= 2*FtoR(p) => Fbounded?(b)(Fminus(q,p)) 

  errorBoundedPlus : lemma
     Fbounded?(b)(p) => Fbounded?(b)(q) => Fbounded?(b)(f) => 
     Closest?(b)(FtoR(p)+FtoR(q),f) => 
     (exists (e:(Fbounded?(b))): FtoR(e)=FtoR(p)+FtoR(q)-FtoR(f) AND Fexp(e)=min(Fexp(p),Fexp(q)))

  errorBoundedMult_aux : lemma
     Fbounded?(b)(p) => Fbounded?(b)(q) => Fbounded?(b)(f) => 
        0 <= FtoR(p) => 0 <= FtoR(q) => 0 <= FtoR(f) =>
          isMin?(b)(FtoR(p)*FtoR(q),f) => -dExp(b) <= Fexp(p)+Fexp(q) =>
          (exists (e:(Fbounded?(b))): FtoR(e)=FtoR(p)*FtoR(q)-FtoR(f) AND Fexp(e)=Fexp(p)+Fexp(q))
   
  errorBoundedMult_aux2 : lemma
     Fbounded?(b)(p) => Fbounded?(b)(q) => Fbounded?(b)(f) => 
        0 <= FtoR(p) => 0 <= FtoR(q) => 0 <= FtoR(f) =>
          isMax?(b)(FtoR(p)*FtoR(q),f) => -dExp(b) <= Fexp(p)+Fexp(q) =>
          (exists (e:(Fbounded?(b))): FtoR(e)=FtoR(p)*FtoR(q)-FtoR(f) AND Fexp(e)=Fexp(p)+Fexp(q))

  errorBoundedMult : lemma
     Fbounded?(b)(p) => Fbounded?(b)(q) => Fbounded?(b)(f) => 
     RoundedMode?(b)(P) => P(b)(FtoR(p)*FtoR(q),f) => -dExp(b) <= Fexp(p)+Fexp(q) =>
     (exists (e:(Fbounded?(b))): FtoR(e)=FtoR(p)*FtoR(q)-FtoR(f) AND Fexp(e)=Fexp(p)+Fexp(q))

  % Properties on the ulp
  FulpLeN : lemma
    Fnormal?(b)(p)  => Fulp(b)(p) <= abs(FtoR(p)) * radix/vNum(b)

  FulpGe  : lemma
    Fbounded?(b)(p) => abs(FtoR(p))/(vNum(b)-1) <= Fulp(b)(p)

  FulpLe  : lemma
    Fbounded?(b)(p) => Fulp(b)(p) <= max(abs(FtoR(p)) * radix/vNum(b), radix^(-dExp(b)))

  FulpFpred1 : lemma
    Fcanonic?(b)(p) => 0 <= FtoR(p) => Fulp(b)(Fpred(b)(p)) <= Fulp(b)(p)

  FulpFpred2 : lemma
    Fcanonic?(b)(p) => 0 <= FtoR(p) => Fulp(b)(p) <= radix*Fulp(b)(Fpred(b)(p))


  END float

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

  % Subtype TCC generated (at line 21, column 30) for  Prec(b)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  vNum_TCC1: OBLIGATION FORALL (b: Format): radix /= 0 OR Prec(b) >= 0;

  % Subtype TCC generated (at line 33, column 28) for  (Fexp(f))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  FtoR_TCC1: OBLIGATION FORALL (f: float): radix /= 0 OR (Fexp(f)) >= 0;

  % Subtype TCC generated (at line 44, column 42) for
      % (Fexp(f) - min(Fexp(f), Fexp(g)))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Fplus_TCC1: OBLIGATION
    FORALL (f: float, g: float):
      radix /= 0 OR (Fexp(f) - min(Fexp(f), Fexp(g))) >= 0;

  % Subtype TCC generated (at line 45, column 20) for
      % (Fexp(g) - min(Fexp(f), Fexp(g)))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Fplus_TCC2: OBLIGATION
    FORALL (f: float, g: float):
      radix /= 0 OR (Fexp(g) - min(Fexp(f), Fexp(g))) >= 0;

  % Subtype TCC generated (at line 44, column 27) for
      % Fnum(f) * radix ^ (Fexp(f) - min(Fexp(f), Fexp(g))) +
      %  Fnum(g) * radix ^ (Fexp(g) - min(Fexp(f), Fexp(g)))
      % expected type  int
  Fplus_TCC3: OBLIGATION
    FORALL (f: float, g: float):
      integer_pred(Fnum(f) * radix ^ (Fexp(f) - min(Fexp(f), Fexp(g))) +
                    Fnum(g) * radix ^ (Fexp(g) - min(Fexp(f), Fexp(g))));

  % Subtype TCC generated (at line 46, column 28) for
      % Fnum(f) * radix ^ (Fexp(f) - min(Fexp(f), Fexp(g))) -
      %  Fnum(g) * radix ^ (Fexp(g) - min(Fexp(f), Fexp(g)))
      % expected type  int
  Fminus_TCC1: OBLIGATION
    FORALL (f: float, g: float):
      integer_pred(Fnum(f) * radix ^ (Fexp(f) - min(Fexp(f), Fexp(g))) -
                    Fnum(g) * radix ^ (Fexp(g) - min(Fexp(f), Fexp(g))));

  % Subtype TCC generated (at line 90, column 56) for  n
      % expected type  {i: int | FtoR(f) /= 0 OR i >= 0}
  FexptCorrect_TCC1: OBLIGATION
    FORALL (f: float, n: nat): FtoR(f) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 97, column 29) for  jj - 1
      % expected type  nat
  sigma_TCC1: OBLIGATION
    FORALL (ii, jj: nat): NOT jj = 0 AND NOT ii > jj IMPLIES jj - 1 >= 0;

  % Termination TCC generated (at line 97, column 20) for
      % sigma(ii, jj - 1, FF)
  sigma_TCC2: OBLIGATION
    FORALL (ii, jj: nat): NOT jj = 0 AND NOT ii > jj IMPLIES jj - 1 < jj;

  % Subtype TCC generated (at line 104, column 11) for  Fnum(f) * (radix / i)
      % expected type  int
  FDivInt_TCC1: OBLIGATION
    FORALL (f: float, (i: nzint | mod(radix, i) = 0)):
      integer_pred(Fnum(f) * (radix / i));

  % Subtype TCC generated (at line 126, column 18) for  ln(radix)
      % expected type  nznum
  hathatln_TCC1: OBLIGATION ln(radix) /= 0;

  % Subtype TCC generated (at line 126, column 10) for  (-(ln(r) / ln(radix)))
      % expected type  {r: real | radix /= 0 OR r /= 0}
  hathatln_TCC2: OBLIGATION
    FORALL (r: posreal): radix /= 0 OR (-(ln(r) / ln(radix))) /= 0;

  % Subtype TCC generated (at line 129, column 9) for  e1
      % expected type  {r: real | radix /= 0 OR r /= 0}
  hathat_int_TCC1: OBLIGATION FORALL (e1: int): radix /= 0 OR e1 /= 0;

  % Subtype TCC generated (at line 129, column 18) for  e1
      % expected type  {i: int | radix /= 0 OR i >= 0}
  hathat_int_TCC2: OBLIGATION FORALL (e1: int): radix /= 0 OR e1 >= 0;

  % Subtype TCC generated (at line 134, column 18) for  vNum(b) / radix
      % expected type  int
  Fsucc_TCC1: OBLIGATION
    FORALL (b: Format, f: float):
      Fnum(f) = vNum(b) - 1 IMPLIES integer_pred(vNum(b) / radix);

  % Subtype TCC generated (at line 141, column 18) for  -vNum(b) / radix
      % expected type  int
  Fpred_TCC1: OBLIGATION
    FORALL (b: Format, f: float):
      Fnum(f) = -(vNum(b) - 1) IMPLIES integer_pred(-vNum(b) / radix);

  % Subtype TCC generated (at line 155, column 11) for  vNum(b) - abs(Fnum(f))
      % expected type  naturalnumber
  Fnormalize_TCC1: OBLIGATION
    FORALL (b: Format, f: (Fbounded?(b))): vNum(b) - abs(Fnum(f)) >= 0;

  % Subtype TCC generated (at line 150, column 5) for
      % (# Fnum := 0, Fexp := -dExp(b) #)
      % expected type  {x: (Fcanonic?(b)) |
                     %          FtoR(x) = FtoR(f) AND Fexp(x) <= Fexp(f)}
  Fnormalize_TCC2: OBLIGATION
    FORALL (b: Format, f: (Fbounded?(b))):
      Fnum(f) = 0 IMPLIES
       Fcanonic?(b)((# Fnum := 0, Fexp := -dExp(b) #)) AND
        FtoR((# Fnum := 0, Fexp := -dExp(b) #)) = FtoR(f) AND
         -dExp(b) <= Fexp(f);

  % Subtype TCC generated (at line 152, column 55) for  f
      % expected type  {x: (Fcanonic?(b)) |
                     %          FtoR(x) = FtoR(f) AND Fexp(x) <= Fexp(f)}
  Fnormalize_TCC3: OBLIGATION
    FORALL (b: Format, f: (Fbounded?(b))):
      (Fexp(f) = -dExp(b) OR abs(radix * Fnum(f)) >= vNum(b)) AND
       NOT Fnum(f) = 0
       IMPLIES Fcanonic?(b)(f) AND Fexp(f) <= Fexp(f);

  % Subtype TCC generated (at line 153, column 22) for
      % (# Fnum := radix * Fnum(f), Fexp := Fexp(f) - 1 #)
      % expected type  f: (Fbounded?(b))
  Fnormalize_TCC4: OBLIGATION
    FORALL (b: Format, f: (Fbounded?(b))):
      NOT Fexp(f) = -dExp(b) AND
       NOT abs(radix * Fnum(f)) >= vNum(b) AND NOT Fnum(f) = 0
       IMPLIES
       Fbounded?(b)((# Fnum := radix * Fnum(f), Fexp := Fexp(f) - 1 #));

  % Termination TCC generated (at line 153, column 8) for
      % Fnormalize(b)((# Fnum := radix * Fnum(f), Fexp := Fexp(f) - 1 #))
  Fnormalize_TCC5: OBLIGATION
    FORALL (b: Format, f: (Fbounded?(b))):
      NOT Fexp(f) = -dExp(b) AND
       NOT abs(radix * Fnum(f)) >= vNum(b) AND NOT Fnum(f) = 0
       IMPLIES vNum(b) - abs(radix * Fnum(f)) < vNum(b) - abs(Fnum(f));

  % Subtype TCC generated (at line 153, column 8) for
      % Fnormalize(b)((# Fnum := radix * Fnum(f), Fexp := Fexp(f) - 1 #))
      % expected type  {x: (Fcanonic?(b)) |
                     %          FtoR(x) = FtoR(f) AND Fexp(x) <= Fexp(f)}
  Fnormalize_TCC6: OBLIGATION
    FORALL (b: Format, f: (Fbounded?(b)),
            v:
              [b1: Format ->
                 [f1:
                    {z: (Fbounded?(b1)) |
                             vNum(b1) - abs(Fnum(z)) <
                              vNum(b) - abs(Fnum(f))} ->
                    {x: (Fcanonic?(b1)) |
                             FtoR(x) = FtoR(f1) AND Fexp(x) <= Fexp(f1)}]]):
      NOT Fexp(f) = -dExp(b) AND
       NOT abs(radix * Fnum(f)) >= vNum(b) AND NOT Fnum(f) = 0
       IMPLIES
       FtoR(v(b)((# Fnum := radix * Fnum(f), Fexp := Fexp(f) - 1 #))) =
        FtoR(f)
        AND
        Fexp(v(b)((# Fnum := radix * Fnum(f), Fexp := Fexp(f) - 1 #))) <=
         Fexp(f);

  % Subtype TCC generated (at line 159, column 40) for
      % (Fexp(Fnormalize(b)(f)))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Fulp_TCC1: OBLIGATION
    FORALL (b: Format, f: (Fbounded?(b))):
      radix /= 0 OR (Fexp(Fnormalize(b)(f))) >= 0;

  % Subtype TCC generated (at line 222, column 50) for  (-dExp(b) - 1)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_log_compute_TCC1: OBLIGATION
    FORALL (b: Format): radix /= 0 OR (-dExp(b) - 1) >= 0;

  % Subtype TCC generated (at line 222, column 87) for  x * radix / vNum(b)
      % expected type  posreal
  RND_log_compute_TCC2: OBLIGATION
    FORALL (b: Format, x: real):
      x >= radix ^ (-dExp(b) - 1) * vNum(b) IMPLIES
       x * radix / vNum(b) >= 0 AND x * radix / vNum(b) > 0;

  % Subtype TCC generated (at line 222, column 138) for
      % (1 + dExp(b) - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_log_compute_TCC3: OBLIGATION
    FORALL (b: Format, x: real):
      x >= radix ^ (-dExp(b) - 1) * vNum(b) IMPLIES
       radix /= 0 OR (1 + dExp(b) - Prec(b)) >= 0;

  % Subtype TCC generated (at line 222, column 125) for
      % x * radix ^ (1 + dExp(b) - Prec(b))
      % expected type  {x: real | x >= 1}
  RND_log_compute_TCC4: OBLIGATION
    FORALL (b: Format, x: real):
      x >= radix ^ (-dExp(b) - 1) * vNum(b) IMPLIES
       x * radix ^ (1 + dExp(b) - Prec(b)) >= 1;

  % Subtype TCC generated (at line 226, column 34) for  (dExp(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_aux_TCC1: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       radix /= 0 OR (dExp(b)) >= 0;

  % Subtype TCC generated (at line 226, column 10) for
      % (# Fnum := floor(x * radix ^ (dExp(b))), Fexp := -dExp(b) #)
      % expected type  (Fcanonic?(b))
  RND_aux_TCC2: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       Fcanonic?(b)
                ((# Fnum := floor(x * radix ^ (dExp(b))),
                    Fexp := -dExp(b) #));

  % Subtype TCC generated (at line 227, column 37) for
      % (1 + dExp(b) - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_aux_TCC3: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      NOT (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       radix /= 0 OR (1 + dExp(b) - Prec(b)) >= 0;

  % Subtype TCC generated (at line 227, column 24) for
      % x * radix ^ (1 + dExp(b) - Prec(b))
      % expected type  {x: real | x >= 1}
  RND_aux_TCC4: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      NOT (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       x * radix ^ (1 + dExp(b) - Prec(b)) >= 1;

  % Subtype TCC generated (at line 228, column 34) for  (-e)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_aux_TCC5: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      NOT (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       (FORALL (e: int):
          e = log_nat(x * radix ^ (1 + dExp(b) - Prec(b)), radix)`1 - dExp(b)
           IMPLIES radix /= 0 OR (-e) >= 0);

  % Subtype TCC generated (at line 228, column 10) for
      % (# Fnum := floor(x * radix ^ (-e)), Fexp := e #)
      % expected type  (Fcanonic?(b))
  RND_aux_TCC6: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      NOT (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       (FORALL (e: int):
          e = log_nat(x * radix ^ (1 + dExp(b) - Prec(b)), radix)`1 - dExp(b)
           IMPLIES
           Fcanonic?(b)((# Fnum := floor(x * radix ^ (-e)), Fexp := e #)));

  % Subtype TCC generated (at line 234, column 25) for  x * radix / vNum(b)
      % expected type  posreal
  RND_aux_alt_TCC1: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      NOT (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       x * radix / vNum(b) > 0;

  % Subtype TCC generated (at line 235, column 34) for  (-e)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_aux_alt_TCC2: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      NOT (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       (FORALL (e:
                  {i |
                           i <= ln(x * radix / vNum(b)) / ln(radix) &
                            ln(x * radix / vNum(b)) / ln(radix) < 1 + i}):
          e = floor(ln(x * radix / vNum(b)) / ln(radix)) IMPLIES
           radix /= 0 OR (-e) >= 0);

  % Subtype TCC generated (at line 235, column 10) for
      % (# Fnum := floor(x * radix ^ (-e)), Fexp := e #)
      % expected type  (Fcanonic?(b))
  RND_aux_alt_TCC3: OBLIGATION
    FORALL (b: Format, x: nonneg_real):
      NOT (x < radix ^ (-dExp(b) - 1) * vNum(b)) IMPLIES
       (FORALL (e:
                  {i |
                           i <= ln(x * radix / vNum(b)) / ln(radix) &
                            ln(x * radix / vNum(b)) / ln(radix) < 1 + i}):
          e = floor(ln(x * radix / vNum(b)) / ln(radix)) IMPLIES
           Fcanonic?(b)((# Fnum := floor(x * radix ^ (-e)), Fexp := e #)));

  % Subtype TCC generated (at line 242, column 20) for  x
      % expected type  nonneg_real
  RND_Min_TCC1: OBLIGATION FORALL (x: real): (0 <= x) IMPLIES x >= 0;

  % Subtype TCC generated (at line 243, column 31) for  -x
      % expected type  nonneg_real
  RND_Min_TCC2: OBLIGATION FORALL (x: real): NOT (0 <= x) IMPLIES -x >= 0;

  % Subtype TCC generated (at line 243, column 44) for  Fopp(RND_aux(b)(-x))
      % expected type  (Fcanonic?(b))
  RND_Min_TCC3: OBLIGATION
    FORALL (b: Format, x: real):
      FtoR(Fopp(RND_aux(b)(-x))) = x AND NOT (0 <= x) IMPLIES
       Fcanonic?(b)(Fopp(RND_aux(b)(-x)));

  % Subtype TCC generated (at line 244, column 10) for
      % Fpred(b)(Fopp(RND_aux(b)(-x)))
      % expected type  (Fcanonic?(b))
  RND_Min_TCC4: OBLIGATION
    FORALL (b: Format, x: real):
      NOT FtoR(Fopp(RND_aux(b)(-x))) = x AND NOT (0 <= x) IMPLIES
       Fcanonic?(b)(Fpred(b)(Fopp(RND_aux(b)(-x))));

  % Subtype TCC generated (at line 247, column 37) for  Fopp(RND_Min(b)(-x))
      % expected type  (Fcanonic?(b))
  RND_Max_TCC1: OBLIGATION
    FORALL (b: Format, x: real): Fcanonic?(b)(Fopp(RND_Min(b)(-x)));

  % Subtype TCC generated (at line 272, column 30) for  e2
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Exp_incr_1_TCC1: OBLIGATION
    FORALL (e1, e2: int): e1 < e2 IMPLIES radix /= 0 OR e2 >= 0;

  % Subtype TCC generated (at line 278, column 32) for  e2
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Exp_increq_1_TCC1: OBLIGATION
    FORALL (e1, e2: int): e1 <= e2 IMPLIES radix /= 0 OR e2 >= 0;

  % Subtype TCC generated (at line 290, column 33) for  (n + 1)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  expt_odd_TCC1: OBLIGATION FORALL (n: nat): radix /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 336, column 27) for  i
      % expected type  {i: int | radix /= 0 OR i >= 0}
  FDivKexpt_TCC1: OBLIGATION
    FORALL ((k: nzint | mod(radix, k) = 0), (i: nat)): radix /= 0 OR i >= 0;

  % Subtype TCC generated (at line 336, column 33) for  i
      % expected type  {i: int | k /= 0 OR i >= 0}
  FDivKexpt_TCC2: OBLIGATION
    FORALL ((k: nzint | mod(radix, k) = 0), (i: nat)): k /= 0 OR i >= 0;

  % Subtype TCC generated (at line 336, column 11) for
      % Fnum(f) * ((radix ^ i) / (k ^ i))
      % expected type  int
  FDivKexpt_TCC3: OBLIGATION
    FORALL (f: float, (k: nzint | mod(radix, k) = 0), (i: nat)):
      integer_pred(Fnum(f) * ((radix ^ i) / (k ^ i)));

  % Subtype TCC generated (at line 387, column 30) for  p
      % expected type  (Fbounded?(b))
  FulpCanonic_TCC1: OBLIGATION
    FORALL (b: Format, p: float): Fcanonic?(b)(p) IMPLIES Fbounded?(b)(p);

  % Subtype TCC generated (at line 402, column 42) for  Fopp(f)
      % expected type  (Fbounded?(b))
  FulpOpp_TCC1: OBLIGATION
    FORALL (b: Format, f: float):
      Fbounded?(b)(f) IMPLIES Fbounded?(b)(Fopp(f));

  % Subtype TCC generated (at line 404, column 42) for  Fabs(f)
      % expected type  (Fbounded?(b))
  FulpAbs_TCC1: OBLIGATION
    FORALL (b: Format, f: float):
      Fbounded?(b)(f) IMPLIES Fbounded?(b)(Fabs(f));

  % Subtype TCC generated (at line 448, column 43) for  Fpred(b)(f)
      % expected type  (Fbounded?(b))
  FpredDiff_TCC1: OBLIGATION
    FORALL (b: Format, f: float):
      Fcanonic?(b)(f) AND 0 < FtoR(f) IMPLIES Fbounded?(b)(Fpred(b)(f));

  % Subtype TCC generated (at line 496, column 27) for  vNum(b) / radix
      % expected type  int
  EvenFsuccOdd_aux_TCC1: OBLIGATION
    FORALL (b: Format):
      even?(vNum(b) - 1) IMPLIES integer_pred(vNum(b) / radix);

  % Subtype TCC generated (at line 502, column 27) for  vNum(b) / radix
      % expected type  int
  OddFsuccEven_aux_TCC1: OBLIGATION
    FORALL (b: Format):
      odd?(vNum(b) - 1) IMPLIES integer_pred(vNum(b) / radix);

  % Subtype TCC generated (at line 521, column 33) for  RND_Min(b)(r)
      % expected type  (Fbounded?(b))
  RND_Min_isMin_TCC1: OBLIGATION
    FORALL (b: Format, r: real): Fbounded?(b)(RND_Min(b)(r));

  % Subtype TCC generated (at line 522, column 33) for  RND_Max(b)(r)
      % expected type  (Fbounded?(b))
  RND_Max_isMax_TCC1: OBLIGATION
    FORALL (b: Format, r: real): Fbounded?(b)(RND_Max(b)(r));

  % Subtype TCC generated (at line 527, column 23) for
      % (Prec(b) - Fexp(f) - dExp(b) - 1)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_aux_float_TCC1: OBLIGATION
    FORALL (b: Format, (f: float | Fnum(f) >= 0)):
      radix /= 0 OR (Prec(b) - Fexp(f) - dExp(b) - 1) >= 0;

  % Subtype TCC generated (at line 528, column 39) for  (dExp(b) + Fexp(f))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_aux_float_TCC2: OBLIGATION
    FORALL (b: Format, (f: float | Fnum(f) >= 0)):
      (Fnum(f) < radix ^ (Prec(b) - Fexp(f) - dExp(b) - 1)) IMPLIES
       radix /= 0 OR (dExp(b) + Fexp(f)) >= 0;

  % Subtype TCC generated (at line 528, column 7) for
      % (# Fnum := floor(Fnum(f) * radix ^ (dExp(b) + Fexp(f))),
      %    Fexp := -dExp(b) #)
      % expected type  (Fcanonic?(b))
  RND_aux_float_TCC3: OBLIGATION
    FORALL (b: Format, (f: float | Fnum(f) >= 0)):
      (Fnum(f) < radix ^ (Prec(b) - Fexp(f) - dExp(b) - 1)) IMPLIES
       Fcanonic?(b)
                ((# Fnum := floor(Fnum(f) * radix ^ (dExp(b) + Fexp(f))),
                    Fexp := -dExp(b) #));

  % Subtype TCC generated (at line 529, column 37) for
      % (Fexp(f) + 1 + dExp(b) - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_aux_float_TCC4: OBLIGATION
    FORALL (b: Format, (f: float | Fnum(f) >= 0)):
      NOT (Fnum(f) < radix ^ (Prec(b) - Fexp(f) - dExp(b) - 1)) IMPLIES
       radix /= 0 OR (Fexp(f) + 1 + dExp(b) - Prec(b)) >= 0;

  % Subtype TCC generated (at line 529, column 22) for
      % Fnum(f) * radix ^ (Fexp(f) + 1 + dExp(b) - Prec(b))
      % expected type  {x: real | x >= 1}
  RND_aux_float_TCC5: OBLIGATION
    FORALL (b: Format, (f: float | Fnum(f) >= 0)):
      NOT (Fnum(f) < radix ^ (Prec(b) - Fexp(f) - dExp(b) - 1)) IMPLIES
       Fnum(f) * radix ^ (Fexp(f) + 1 + dExp(b) - Prec(b)) >= 1;

  % Subtype TCC generated (at line 531, column 42) for  (Fexp(f) - e)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_aux_float_TCC6: OBLIGATION
    FORALL (b: Format, (f: float | Fnum(f) >= 0)):
      NOT (Fnum(f) < radix ^ (Prec(b) - Fexp(f) - dExp(b) - 1)) IMPLIES
       (FORALL (e: int):
          e =
           log_nat(Fnum(f) * radix ^ (Fexp(f) + 1 + dExp(b) - Prec(b)),
                   radix)`1
            - dExp(b)
           IMPLIES radix /= 0 OR (Fexp(f) - e) >= 0);

  % Subtype TCC generated (at line 531, column 10) for
      % (# Fnum := floor(Fnum(f) * radix ^ (Fexp(f) - e)), Fexp := e #)
      % expected type  (Fcanonic?(b))
  RND_aux_float_TCC7: OBLIGATION
    FORALL (b: Format, (f: float | Fnum(f) >= 0)):
      NOT (Fnum(f) < radix ^ (Prec(b) - Fexp(f) - dExp(b) - 1)) IMPLIES
       (FORALL (e: int):
          e =
           log_nat(Fnum(f) * radix ^ (Fexp(f) + 1 + dExp(b) - Prec(b)),
                   radix)`1
            - dExp(b)
           IMPLIES
           Fcanonic?(b)
                    ((# Fnum := floor(Fnum(f) * radix ^ (Fexp(f) - e)),
                        Fexp := e #)));

  % Subtype TCC generated (at line 535, column 35) for  FtoR(f)
      % expected type  nonneg_real
  RND_aux_float_def_TCC1: OBLIGATION
    FORALL (f: float): Fnum(f) >= 0 IMPLIES FtoR(f) >= 0;

  % Subtype TCC generated (at line 539, column 26) for  f
      % expected type  {f | Fnum(f) >= 0}
  RND_float_Min_TCC1: OBLIGATION
    FORALL (f: float): (0 <= Fnum(f)) IMPLIES Fnum(f) >= 0;

  % Subtype TCC generated (at line 540, column 37) for  -f
      % expected type  {f | Fnum(f) >= 0}
  RND_float_Min_TCC2: OBLIGATION
    FORALL (f: float): NOT (0 <= Fnum(f)) IMPLIES Fnum(-f) >= 0;

  % Subtype TCC generated (at line 540, column 56) for
      % Fopp(RND_aux_float(b)(-f))
      % expected type  (Fcanonic?(b))
  RND_float_Min_TCC3: OBLIGATION
    FORALL (b: Format, f: float):
      FtoR(Fopp(RND_aux_float(b)(-f))) = FtoR(f) AND NOT (0 <= Fnum(f))
       IMPLIES Fcanonic?(b)(Fopp(RND_aux_float(b)(-f)));

  % Subtype TCC generated (at line 541, column 10) for
      % Fpred(b)(Fopp(RND_aux_float(b)(-f)))
      % expected type  (Fcanonic?(b))
  RND_float_Min_TCC4: OBLIGATION
    FORALL (b: Format, f: float):
      NOT FtoR(Fopp(RND_aux_float(b)(-f))) = FtoR(f) AND NOT (0 <= Fnum(f))
       IMPLIES Fcanonic?(b)(Fpred(b)(Fopp(RND_aux_float(b)(-f))));

  % Subtype TCC generated (at line 547, column 38) for
      % Fopp(RND_float_Min(b)(-f))
      % expected type  (Fcanonic?(b))
  RND_float_Max_TCC1: OBLIGATION
    FORALL (b: Format, f: float): Fcanonic?(b)(Fopp(RND_float_Min(b)(-f)));

  % Subtype TCC generated (at line 590, column 85) for  float_int(1)
      % expected type  f: (Fbounded?(b))
  Fmult_canonic_id_Min_TCC1: OBLIGATION
    FORALL (b: Format, f: float):
      Fcanonic?(b)(f) IMPLIES Fbounded?(b)(float_int(1));

  % Subtype TCC generated (at line 594, column 85) for  float_int(0)
      % expected type  f: (Fbounded?(b))
  Fplus_canonic_id_Min_TCC1: OBLIGATION
    FORALL (b: Format, f: float):
      Fcanonic?(b)(f) IMPLIES Fbounded?(b)(float_int(0));

  % Subtype TCC generated (at line 600, column 32) for  q
      % expected type  (Fbounded?(b))
  MaxSuccMin_TCC1: OBLIGATION
    FORALL (b: Format, p, q: float, r: real):
      Fcanonic?(b)(q) AND Fcanonic?(b)(p) AND isMin?(b)(r, p) IMPLIES
       Fbounded?(b)(q);

  % Subtype TCC generated (at line 632, column 50) for  RND_EClosest(b)(r)
      % expected type  (Fbounded?(b))
  RND_EClosest_isEclosest_TCC1: OBLIGATION
    FORALL (b: Format, r: real): Fbounded?(b)(RND_EClosest(b)(r));

  % Subtype TCC generated (at line 673, column 37) for  Fpred(b)(Fabs(p))
      % expected type  (Fbounded?(b))
  ClosestUlp2_TCC1: OBLIGATION
    FORALL (b: Format, p: float, r: real):
      Fcanonic?(b)(p) AND Closest?(b)(r, p) IMPLIES
       Fbounded?(b)(Fpred(b)(Fabs(p)));

  % Subtype TCC generated (at line 710, column 29) for  p
      % expected type  (Fbounded?(b))
  FulpLeN_TCC1: OBLIGATION
    FORALL (b: Format, p: float): Fnormal?(b)(p) IMPLIES Fbounded?(b)(p);

  % Subtype TCC generated (at line 713, column 35) for  (vNum(b) - 1)
      % expected type  nznum
  FulpGe_TCC1: OBLIGATION
    FORALL (b: Format, p: float): Fbounded?(b)(p) IMPLIES (vNum(b) - 1) /= 0;

  % Subtype TCC generated (at line 716, column 76) for  (-dExp(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  FulpLe_TCC1: OBLIGATION
    FORALL (b: Format, p: float):
      Fbounded?(b)(p) IMPLIES radix /= 0 OR (-dExp(b)) >= 0;

  % Subtype TCC generated (at line 719, column 45) for  Fpred(b)(p)
      % expected type  (Fbounded?(b))
  FulpFpred1_TCC1: OBLIGATION
    FORALL (b: Format, p: float):
      Fcanonic?(b)(p) AND 0 <= FtoR(p) IMPLIES Fbounded?(b)(Fpred(b)(p));


body:
  enumerated_type_defs: THEORY

    BEGIN

    sign_rep: type = {n:nat| n = 0 or n = 1}
    pos:sign_rep = 0
    neg:sign_rep = 1


    NaN_type: type = {signal,quiet}
    NaN_data: NONEMPTY_TYPE
    invalid_data: NaN_data

    fp_ops        : type = {add,sub,mult,div}
    rounding_mode : type = {to_nearest,to_zero,to_pos,to_neg}  

     exception: DATATYPE
       BEGIN
         invalid_operation      : invalid?
         division_by_zero       : div_by_zero?
         overflow               : overflow?
         underflow(exact?:bool) : underflow?
         inexact                : inexact?
         no_exceptions          : no_exceptions?
       END exception

    trap_enabled?(e:exception) : bool

    END enumerated_type_defs

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

  NaN_type_ord_defaxiom: AXIOM
    NaN_type_ord(signal) = 0 AND NaN_type_ord(quiet) = 1;

  NaN_type_inclusive: AXIOM
    FORALL (NaN_type_var: NaN_type):
      signal?(NaN_type_var) OR quiet?(NaN_type_var);

  NaN_type_induction: AXIOM
    FORALL (p: [NaN_type -> boolean]):
      p(signal) AND p(quiet) IMPLIES
       (FORALL (NaN_type_var: NaN_type): p(NaN_type_var));

  NaN_type_well_founded: AXIOM strict_well_founded?[NaN_type](<<);

  NaN_data_nonempty: AXIOM EXISTS (x: NaN_data): TRUE;

  fp_ops_ord_defaxiom: AXIOM
    fp_ops_ord(add) = 0 AND
     fp_ops_ord(sub) = 1 AND fp_ops_ord(mult) = 2 AND fp_ops_ord(div) = 3;

  fp_ops_inclusive: AXIOM
    FORALL (fp_ops_var: fp_ops):
      add?(fp_ops_var) OR
       sub?(fp_ops_var) OR mult?(fp_ops_var) OR div?(fp_ops_var);

  fp_ops_induction: AXIOM
    FORALL (p: [fp_ops -> boolean]):
      p(add) AND p(sub) AND p(mult) AND p(div) IMPLIES
       (FORALL (fp_ops_var: fp_ops): p(fp_ops_var));

  fp_ops_well_founded: AXIOM strict_well_founded?[fp_ops](<<);

  rounding_mode_ord_defaxiom: AXIOM
    rounding_mode_ord(to_nearest) = 0 AND
     rounding_mode_ord(to_zero) = 1 AND
      rounding_mode_ord(to_pos) = 2 AND rounding_mode_ord(to_neg) = 3;

  rounding_mode_inclusive: AXIOM
    FORALL (rounding_mode_var: rounding_mode):
      to_nearest?(rounding_mode_var) OR
       to_zero?(rounding_mode_var) OR
        to_pos?(rounding_mode_var) OR to_neg?(rounding_mode_var);

  rounding_mode_induction: AXIOM
    FORALL (p: [rounding_mode -> boolean]):
      p(to_nearest) AND p(to_zero) AND p(to_pos) AND p(to_neg) IMPLIES
       (FORALL (rounding_mode_var: rounding_mode): p(rounding_mode_var));

  rounding_mode_well_founded: AXIOM strict_well_founded?[rounding_mode](<<);

  exception_ord_defaxiom: AXIOM
         exception_ord(invalid_operation) = 0
     AND exception_ord(division_by_zero) = 1 AND exception_ord(overflow) = 2
     AND (FORALL (exact?: bool): exception_ord(underflow(exact?)) = 3)
     AND exception_ord(inexact) = 4 AND exception_ord(no_exceptions) = 5;

  exception_invalid_operation_extensionality: AXIOM
    FORALL (invalid?_var: (invalid?), invalid?_var2: (invalid?)):
      invalid?_var = invalid?_var2;

  exception_division_by_zero_extensionality: AXIOM
    FORALL (div_by_zero?_var: (div_by_zero?),
            div_by_zero?_var2: (div_by_zero?)):
      div_by_zero?_var = div_by_zero?_var2;

  exception_overflow_extensionality: AXIOM
    FORALL (overflow?_var: (overflow?), overflow?_var2: (overflow?)):
      overflow?_var = overflow?_var2;

  exception_underflow_extensionality: AXIOM
    FORALL (underflow?_var: (underflow?), underflow?_var2: (underflow?)):
      exact?(underflow?_var) = exact?(underflow?_var2) IMPLIES
       underflow?_var = underflow?_var2;

  exception_underflow_eta: AXIOM
    FORALL (underflow?_var: (underflow?)):
      underflow(exact?(underflow?_var)) = underflow?_var;

  exception_inexact_extensionality: AXIOM
    FORALL (inexact?_var: (inexact?), inexact?_var2: (inexact?)):
      inexact?_var = inexact?_var2;

  exception_no_exceptions_extensionality: AXIOM
    FORALL (no_exceptions?_var: (no_exceptions?),
            no_exceptions?_var2: (no_exceptions?)):
      no_exceptions?_var = no_exceptions?_var2;

  exception_exact?_underflow: AXIOM
    FORALL (underflow1_var: bool):
      exact?(underflow(underflow1_var)) = underflow1_var;

  exception_inclusive: AXIOM
    FORALL (exception_var: exception):
          invalid?(exception_var) OR div_by_zero?(exception_var)
       OR overflow?(exception_var) OR underflow?(exception_var)
       OR inexact?(exception_var) OR no_exceptions?(exception_var);

  exception_induction: AXIOM
    FORALL (p: [exception -> boolean]):
           p(invalid_operation) AND p(division_by_zero) AND p(overflow)
       AND FORALL (underflow1_var: bool): p(underflow(underflow1_var))
       AND p(inexact) AND p(no_exceptions)
       IMPLIES (FORALL (exception_var: exception): p(exception_var));

  exception_well_founded: AXIOM strict_well_founded?[exception](<<);

  NaN_type: TYPE

  fp_ops: TYPE

  rounding_mode: TYPE

  exception: TYPE

  signal?: [NaN_type -> boolean]

  quiet?: [NaN_type -> boolean]

  NaN_type_ord: [NaN_type -> upto(1)]

  ord(x: NaN_type): [NaN_type -> upto(1)] =
      CASES x OF signal: 0, quiet: 1 ENDCASES

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

  add?: [fp_ops -> boolean]

  sub?: [fp_ops -> boolean]

  mult?: [fp_ops -> boolean]

  div?: [fp_ops -> boolean]

  fp_ops_ord: [fp_ops -> upto(3)]

  ord(x: fp_ops): [fp_ops -> upto(3)] =
      CASES x OF add: 0, sub: 1, mult: 2, div: 3 ENDCASES

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

  to_nearest?: [rounding_mode -> boolean]

  to_zero?: [rounding_mode -> boolean]

  to_pos?: [rounding_mode -> boolean]

  to_neg?: [rounding_mode -> boolean]

  rounding_mode_ord: [rounding_mode -> upto(3)]

  ord(x: rounding_mode): [rounding_mode -> upto(3)] =
      CASES x OF to_nearest: 0, to_zero: 1, to_pos: 2, to_neg: 3 ENDCASES

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

  invalid?: [exception -> boolean]

  div_by_zero?: [exception -> boolean]

  overflow?: [exception -> boolean]

  underflow?: [exception -> boolean]

  inexact?: [exception -> boolean]

  no_exceptions?: [exception -> boolean]

  exact?: [(underflow?) -> boolean]

  underflow: [boolean -> (underflow?)]

  exception_ord: [exception -> upto(5)]

  ord(x: exception): [exception -> upto(5)] =
      CASES x
        OF invalid_operation: 0,
           division_by_zero: 1,
           overflow: 2,
           underflow(underflow1_var): 3,
           inexact: 4,
           no_exceptions: 5
        ENDCASES

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

  reduce_nat(invalid?_fun: nat, div_by_zero?_fun: nat, overflow?_fun: nat,
             underflow?_fun: [bool -> nat], inexact?_fun: nat,
             no_exceptions?_fun: nat):
        [exception -> nat] =
      LAMBDA (exception_adtvar: exception):
        LET red: [exception -> nat] =
              reduce_nat(invalid?_fun, div_by_zero?_fun, overflow?_fun,
                         underflow?_fun, inexact?_fun, no_exceptions?_fun)
          IN
          CASES exception_adtvar
            OF invalid_operation: invalid?_fun,
               division_by_zero: div_by_zero?_fun,
               overflow: overflow?_fun,
               underflow(underflow1_var): underflow?_fun(underflow1_var),
               inexact: inexact?_fun,
               no_exceptions: no_exceptions?_fun
            ENDCASES;

  REDUCE_nat(invalid?_fun: [exception -> nat],
             div_by_zero?_fun: [exception -> nat],
             overflow?_fun: [exception -> nat],
             underflow?_fun: [[bool, exception] -> nat],
             inexact?_fun: [exception -> nat],
             no_exceptions?_fun: [exception -> nat]):
        [exception -> nat] =
      LAMBDA (exception_adtvar: exception):
        LET red: [exception -> nat] =
              REDUCE_nat(invalid?_fun, div_by_zero?_fun, overflow?_fun,
                         underflow?_fun, inexact?_fun, no_exceptions?_fun)
          IN
          CASES exception_adtvar
            OF invalid_operation: invalid?_fun(exception_adtvar),
               division_by_zero: div_by_zero?_fun(exception_adtvar),
               overflow: overflow?_fun(exception_adtvar),
               underflow(underflow1_var):
                 underflow?_fun(underflow1_var, exception_adtvar),
               inexact: inexact?_fun(exception_adtvar),
               no_exceptions: no_exceptions?_fun(exception_adtvar)
            ENDCASES;

  reduce_ordinal(invalid?_fun: ordinal, div_by_zero?_fun: ordinal,
                 overflow?_fun: ordinal, underflow?_fun: [bool -> ordinal],
                 inexact?_fun: ordinal, no_exceptions?_fun: ordinal):
        [exception -> ordinal] =
      LAMBDA (exception_adtvar: exception):
        LET red: [exception -> ordinal] =
              reduce_ordinal(invalid?_fun, div_by_zero?_fun, overflow?_fun,
                             underflow?_fun, inexact?_fun,
                             no_exceptions?_fun)
          IN
          CASES exception_adtvar
            OF invalid_operation: invalid?_fun,
               division_by_zero: div_by_zero?_fun,
               overflow: overflow?_fun,
               underflow(underflow1_var): underflow?_fun(underflow1_var),
               inexact: inexact?_fun,
               no_exceptions: no_exceptions?_fun
            ENDCASES;

  REDUCE_ordinal(invalid?_fun: [exception -> ordinal],
                 div_by_zero?_fun: [exception -> ordinal],
                 overflow?_fun: [exception -> ordinal],
                 underflow?_fun: [[bool, exception] -> ordinal],
                 inexact?_fun: [exception -> ordinal],
                 no_exceptions?_fun: [exception -> ordinal]):
        [exception -> ordinal] =
      LAMBDA (exception_adtvar: exception):
        LET red: [exception -> ordinal] =
              REDUCE_ordinal(invalid?_fun, div_by_zero?_fun, overflow?_fun,
                             underflow?_fun, inexact?_fun,
                             no_exceptions?_fun)
          IN
          CASES exception_adtvar
            OF invalid_operation: invalid?_fun(exception_adtvar),
               division_by_zero: div_by_zero?_fun(exception_adtvar),
               overflow: overflow?_fun(exception_adtvar),
               underflow(underflow1_var):
                 underflow?_fun(underflow1_var, exception_adtvar),
               inexact: inexact?_fun(exception_adtvar),
               no_exceptions: no_exceptions?_fun(exception_adtvar)
            ENDCASES;

  signal: (signal?)

  quiet: (quiet?)

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

  add: (add?)

  sub: (sub?)

  mult: (mult?)

  div: (div?)

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

  to_nearest: (to_nearest?)

  to_zero: (to_zero?)

  to_pos: (to_pos?)

  to_neg: (to_neg?)

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

  invalid_operation: (invalid?)

  division_by_zero: (div_by_zero?)

  overflow: (overflow?)

  inexact: (inexact?)

  no_exceptions: (no_exceptions?)

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


body:
  sum_hack  % [ parameters ]
  		: THEORY

    BEGIN

    % ASSUMING
     % assuming declarations
    % ENDASSUMING

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Some stuff that will eventually be loaded from a library,
  %  once the PVS library mechanism works.
    i,j,k:var nat
    F: var [nat->real]

    Sum(j,F):recursive real =
     if j=0 then 0 else F(j-1)+Sum(j-1,F) endif
     measure j

    F1,F2: var [nat->nonneg_real]

    Sum_nonneg: lemma  Sum(j,F1)>=0

  %%%%%%% Modif S. Boldo
  %  JUDGEMENT Sum HAS_TYPE [nat,[nat->nonneg_real]->nonneg_real]
  %%%%%%% Fin modif  

    Sum_zero: lemma Sum(j,F1)=0 iff forall (i:below(j)): F1(i)=0

    Sum_pos: lemma  Sum(j,F1)>0 iff (exists (i:below(j)): F1(i)>0)

    Sum_le:  lemma (forall (i:below(j)): F1(i) <= F2(i)) => Sum(j,F1)<=Sum(j,F2)

    Sum_ge1: lemma (exists (i:below(j)): F1(i)>=1) => Sum(j,F1)>=1

    pz: var posreal

    Sum_ge: lemma (exists (i:below(j)): F1(i)>= pz) => Sum(j,F1)>=pz

    Sum_split: lemma forall (i:upto(j)):
      Sum(j,F) = Sum(i,F) + Sum(j-i,lambda k: F(k+i)) 

    END sum_hack

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

  % Subtype TCC generated (at line 17, column 24) for  j - 1
      % expected type  nat
  Sum_TCC1: OBLIGATION FORALL (j: nat): NOT j = 0 IMPLIES j - 1 >= 0;

  % Termination TCC generated (at line 17, column 29) for  Sum(j - 1, F)
  Sum_TCC2: OBLIGATION FORALL (j: nat): NOT j = 0 IMPLIES j - 1 < j;

  % Subtype TCC generated (at line 41, column 30) for  j - i
      % expected type  nat
  Sum_split_TCC1: OBLIGATION FORALL (j: nat, i: upto(j)): j - i >= 0;


body:
  sum_lemmas [b:above(1)]: THEORY

    BEGIN

    importing sum_hack

    i: var nat

    F1: var [nat->nonneg_real]

    mant_digit_fun: type = {F1| forall i: F1(i)<=(b-1)*b^(-i-1)}

    d: var mant_digit_fun

    Sum_pos_less_1: lemma
        0<=Sum(i,d) & Sum(i,d)<= 1-b^(-i)

    floor_Sum_mant: lemma 
       floor(Sum(i,d))=0

    END sum_lemmas

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

  % Subtype TCC generated (at line 11, column 56) for  (-i - 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  mant_digit_fun_TCC1: OBLIGATION FORALL (i): b /= 0 OR (-i - 1) >= 0;

  % Subtype TCC generated (at line 16, column 36) for  (-i)
      % expected type  {i: int | b /= 0 OR i >= 0}
  Sum_pos_less_1_TCC1: OBLIGATION
    FORALL (d: mant_digit_fun, i: nat):
      0 <= Sum(i, d) IMPLIES b /= 0 OR (-i) >= 0;


body:
  IEEE_854_values 
    [b,p:above(1),
     E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % This file defines the set of values that must be represented in each
  % supported precision of an instance of IEEE-854
  % 
  % Author:
  %  Paul S. Miner                | email: p.s.miner@larc.nasa.gov
  %  1 South Wright St. / MS 130  |   fax: (757) 864-4234
  %  NASA Langley Research Center | phone: (757) 864-6201
  %  Hampton, Virginia 23681      |
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    BEGIN

    IMPORTING sum_hack, %for use until we have good summation library
              sum_lemmas[b], % these are more specialized
  %            ints@mod_, %% note _ to avoid prelude version
              enumerated_type_defs



    Exponent: type = {i:int| E_min <= i & i <= E_max}

    digits: type = [below(p)->below(b)]

   
    fp_num: datatype
     begin
      finite(sign:sign_rep,Exp:Exponent,d:digits):finite?
      infinite(i_sign:sign_rep): infinite?
      NaN(status:NaN_type, data:NaN_data): NaN?
     end fp_num

  % A mapping from finite floating point numbers to real numbers
  %  This corresponds to the interpretation given in the standard
  %  section 3.1
    fin : var (finite?)


    value_digit(d:digits)(n:nat):nonneg_real = 
       if n<p then d(n)*b^(-n) else 0 endif

    value(fin): real =
      (-1) ^ sign(fin) * b ^ Exp(fin) * Sum(p, value_digit(d(fin)))


  % Predicate testing whether an fp_num is 0
    zero?(fp:fp_num):bool = if finite?(fp) then value(fp)=0 else false endif

    shift_left((d: digits)): digits =
      LAMBDA (i: below(p)): IF (i + 1 = p) THEN 0 ELSE d(i + 1) ENDIF

  % Function normalize takes a finite and returns the finite of 
  % equivalent value with the smallest possible exponent.
    normalize(fin:(finite?)): recursive (finite?) = 
       IF Exp(fin) = E_min or d(fin)(0) /= 0 then
          fin
       ELSE
          normalize(finite(sign(fin),Exp(fin)-1,shift_left(d(fin))))
       ENDIF
    measure lambda (fin:(finite?)): Exp(fin) - E_min

    normalize_idempotent: FACT
          FORALL (fin: (finite?)): normalize(normalize(fin)) = normalize(fin)

  % Predicate testing whether an fp_num is subnormal:
  % Section 2 of the standard defines a subnormal (denormal in IEEE-754)
  % number as a nonzero finite number whose exponent is the precision's 
  % minimum and whose leading significant digit is zero.
    subnormal?(fp: fp_num): bool =
      IF finite?(fp)  THEN 
          not zero?(fp)
          & Exp(normalize(fp)) = E_min
          & d(normalize(fp))(0) = 0
      ELSE FALSE
      ENDIF

  % Predicate testing whether an fp_num is normal:
  % Section 2 of the standard defines a normal number as 
  % a nonzero finite number that is not subnormal
    normal?((fp: fp_num)): bool =
      IF finite?(fp) THEN d(normalize(fp))(0) > 0 ELSE FALSE ENDIF

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Some definitions and theorems to help illustrate the correctness
  %  of the definition of value.

  % Maximum and Minimum representable values
    max_significand:digits = 
      (lambda (i:below(p)): b-1)
    min_significand: digits =
      (LAMBDA (i: below(p)): IF i < p - 1 THEN 0 ELSE 1 ENDIF)
    d_zero: digits = LAMBDA (i: below(p)): 0

    m,n: var nat

    Sum_value0: lemma Sum(n,value_digit(d_zero)) = 0

    s: var sign_rep
    E: var Exponent

    zero_finite_d_zero: lemma zero?(finite(s,E,d_zero))

    max_fp_pos : fp_num = finite(pos,E_max,max_significand)
    min_fp_pos : fp_num = finite(pos,E_min,min_significand)
    pos_zero   : {fin|zero?(fin)}= finite(pos,E_min,d_zero)

    max_fp_neg : fp_num = finite(neg,E_max,max_significand)
    min_fp_neg : fp_num = finite(neg,E_min,min_significand)
    neg_zero   : {fin|zero?(fin)} = finite(neg,E_min,d_zero)

    max_pos: posreal = value(max_fp_pos)
    min_pos: posreal = value(min_fp_pos)

    max_neg: negreal = value(max_fp_neg)
    min_neg: negreal = value(min_fp_neg)

    max_fp_correct: THEOREM 
       max_pos = b ^ (E_max +1) - b ^ (E_max + 1 - p)

    min_fp_correct: THEOREM 
       value(min_fp_pos) = b ^ (E_min + 1 - p)


  % Value of zero

    value0: lemma value(fin)=0 iff d(fin)=d_zero

    value_of_zero: THEOREM 
       value(pos_zero) = 0

  % Normalization preserves the value

    normal_value: lemma 
       value(fin) = value(normalize(fin))

  % sign determines algebraic sign of value
    value_positive: lemma

      (sign(fin)=pos & not zero?(fin)) <=> value(fin)>0

    value_negative: lemma
      (sign(fin)=neg & not zero?(fin)) <=> value(fin)<0

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    finite_cover: lemma zero?(fin) or normal?(fin) or subnormal?(fin)

    finite_disjoint1: lemma not (zero?(fin) & normal?(fin))

    finite_disjoint2: lemma not (zero?(fin) & subnormal?(fin))

    finite_disjoint3: lemma not (normal?(fin) & subnormal?(fin))


  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % 
    fp,fp1,fp2: var fp_num

  % reverse the sign of a floating point number
    toggle_sign(fp): fp_num
      =
      cases fp of
        finite(s,e,d): finite(1-s,e,d),
        infinite(s): infinite(1-s),
        NaN(sig,data): fp
      endcases

    toggle_finite: lemma finite?(toggle_sign(fp)) iff finite?(fp)
    toggle_infinite: lemma infinite?(toggle_sign(fp)) iff infinite?(fp)
    toggle_NaN: lemma NaN?(toggle_sign(fp)) iff NaN?(fp)

    value_toggle: lemma value(toggle_sign(fin)) = -value(fin) 
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    toggle_d_normalize: lemma 
       d(normalize(toggle_sign(fin))) = d(normalize(fin))

    toggle_Exp_normalize: lemma 
       Exp(normalize(toggle_sign(fin))) = Exp(normalize(fin))

    toggle_zero?: lemma zero?(toggle_sign(fin)) iff zero?(fin)

    toggle_normal?: lemma normal?(toggle_sign(fin)) iff normal?(fin)

    toggle_subnormal?: lemma subnormal?(toggle_sign(fin)) iff subnormal?(fin)

  % Sum lemmas

    d: var digits

    j : var nat

    value_digit_le: lemma value_digit(d)(j) <= (b-1) * b^(-j)

    Sum_d_lt_b: lemma Sum(j+1,value_digit(d)) <= b - b^(-j)

    Sum_d_lt1: lemma d(0)=0 => Sum(j+1,value_digit(d)) <= 1-b^(-j)

    Sum_d_ge1: lemma d(0)>0 => Sum(j+1,value_digit(d)) >= 1

    value_sig_lt_b: lemma Sum(p,value_digit(d)) < b

    value_sig_lt1: lemma d(0)=0 => Sum(p,value_digit(d)) < 1

    value_sig_ge1: lemma d(0)>0 => Sum(p,value_digit(d)) >= 1

    abs_value_fin: lemma 
        abs(value(fin)) = b^(Exp(fin)) * Sum(p,value_digit(d(fin)))

    min_significand_min: lemma d/=d_zero => 
              Sum(p,value_digit(min_significand))<= Sum(p,value_digit(d))

    sign_normal: lemma sign(fin) = sign(normalize(fin))

    value_normal: lemma normal?(fin) => 
              b^E_min <= abs(value(fin)) & abs(value(fin)) <= max_pos

    value_subnormal: lemma subnormal?(fin) => 
              min_pos <= abs(value(fin)) & abs(value(fin)) < b^E_min 

    value_nonzero: lemma not zero?(fin) =>
              min_pos <= abs(value(fin)) & abs(value(fin)) <= max_pos


  %mod(floor(Sum(p, value_digit(d(normalize(fin!1)))) * b ^ x!1), b)
  %        = d(normalize(fin!1))(x!1)

      scale_value(d,m)(n): nonneg_real = value_digit(d)(n) * b^m

      scaled_Sum_int: lemma forall d,n:
         forall (m:upto(n+1)): integer?(Sum(m,scale_value(d,n)))

      scale_value_p(d)(n): nat = scale_value(d,p-1)(n)

      i: var below(p)

      scaled_Sum_i: lemma 
          Sum(n,value_digit(d))*b^(i) = Sum(n,scale_value(d,i))

      scaled_Sum: lemma 
          Sum(n,value_digit(d))*b^(p-1) = Sum(n,scale_value_p(d))

      floor_Sum: lemma 
          floor(Sum(p,value_digit(d)) * b^i) = 
               Sum(i+1,scale_value(d,i))

      mod_Sum: lemma mod(Sum(i+1,scale_value(d,i)),b)=d(i)

  %%%%%%%%%
  %
  %  The next two declarations are here for importing purposes.

  % A dummy fp_num to be used as a place holder.  Any definition that 
  % returns holder is not yet finished.
    holder:fp_num

  % An undefined NaN for functions to return when the invalid exception
  % should be raised.  This serves as a placeholder until this specification 
  % accounts for exceptions.
  %
    invalid: (NaN?) = NaN(quiet,invalid_data)

    END IEEE_854_values

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

  fp_num_ord_defaxiom: AXIOM
    (FORALL (sign: sign_rep, Exp: Exponent, d: digits):
       fp_num_ord(finite(sign, Exp, d)) = 0)
     AND
     (FORALL (i_sign: sign_rep): fp_num_ord(infinite(i_sign)) = 1) AND
      (FORALL (status: NaN_type, data: NaN_data):
         fp_num_ord(NaN(status, data)) = 2);

  fp_num_finite_extensionality: AXIOM
    FORALL (finite?_var: (finite?), finite?_var2: (finite?)):
      sign(finite?_var) = sign(finite?_var2) AND
       Exp(finite?_var) = Exp(finite?_var2) AND
        d(finite?_var) = d(finite?_var2)
       IMPLIES finite?_var = finite?_var2;

  fp_num_finite_eta: AXIOM
    FORALL (finite?_var: (finite?)):
      finite(sign(finite?_var), Exp(finite?_var), d(finite?_var)) =
       finite?_var;

  fp_num_infinite_extensionality: AXIOM
    FORALL (infinite?_var: (infinite?), infinite?_var2: (infinite?)):
      i_sign(infinite?_var) = i_sign(infinite?_var2) IMPLIES
       infinite?_var = infinite?_var2;

  fp_num_infinite_eta: AXIOM
    FORALL (infinite?_var: (infinite?)):
      infinite(i_sign(infinite?_var)) = infinite?_var;

  fp_num_NaN_extensionality: AXIOM
    FORALL (NaN?_var: (NaN?), NaN?_var2: (NaN?)):
      status(NaN?_var) = status(NaN?_var2) AND
       data(NaN?_var) = data(NaN?_var2)
       IMPLIES NaN?_var = NaN?_var2;

  fp_num_NaN_eta: AXIOM
    FORALL (NaN?_var: (NaN?)):
      NaN(status(NaN?_var), data(NaN?_var)) = NaN?_var;

  fp_num_sign_finite: AXIOM
    FORALL (finite1_var: sign_rep, finite2_var: Exponent,
            finite3_var: digits):
      sign(finite(finite1_var, finite2_var, finite3_var)) = finite1_var;

  fp_num_Exp_finite: AXIOM
    FORALL (finite1_var: sign_rep, finite2_var: Exponent,
            finite3_var: digits):
      Exp(finite(finite1_var, finite2_var, finite3_var)) = finite2_var;

  fp_num_d_finite: AXIOM
    FORALL (finite1_var: sign_rep, finite2_var: Exponent,
            finite3_var: digits):
      d(finite(finite1_var, finite2_var, finite3_var)) = finite3_var;

  fp_num_i_sign_infinite: AXIOM
    FORALL (infinite1_var: sign_rep):
      i_sign(infinite(infinite1_var)) = infinite1_var;

  fp_num_status_NaN: AXIOM
    FORALL (NaN1_var: NaN_type, NaN2_var: NaN_data):
      status(NaN(NaN1_var, NaN2_var)) = NaN1_var;

  fp_num_data_NaN: AXIOM
    FORALL (NaN1_var: NaN_type, NaN2_var: NaN_data):
      data(NaN(NaN1_var, NaN2_var)) = NaN2_var;

  fp_num_inclusive: AXIOM
    FORALL (fp_num_var: fp_num):
      finite?(fp_num_var) OR infinite?(fp_num_var) OR NaN?(fp_num_var);

  fp_num_induction: AXIOM
    FORALL (p: [fp_num -> boolean]):
      ((FORALL (finite1_var: sign_rep, finite2_var: Exponent,
                finite3_var: digits):
          p(finite(finite1_var, finite2_var, finite3_var)))
        AND
        (FORALL (infinite1_var: sign_rep): p(infinite(infinite1_var))) AND
         (FORALL (NaN1_var: NaN_type, NaN2_var: NaN_data):
            p(NaN(NaN1_var, NaN2_var))))
       IMPLIES (FORALL (fp_num_var: fp_num): p(fp_num_var));

  fp_num_well_founded: AXIOM strict_well_founded?[fp_num](<<);

  fp_num: TYPE

  finite?: [fp_num -> boolean]

  infinite?: [fp_num -> boolean]

  NaN?: [fp_num -> boolean]

  sign: [(finite?) -> sign_rep]

  Exp: [(finite?) -> Exponent]

  d: [(finite?) -> [below(p) -> below(b)]]

  i_sign: [(infinite?) -> sign_rep]

  status: [(NaN?) -> NaN_type]

  data: [(NaN?) -> NaN_data]

  finite: [[sign_rep, Exponent, [below(p) -> below(b)]] -> (finite?)]

  infinite: [sign_rep -> (infinite?)]

  NaN: [[NaN_type, NaN_data] -> (NaN?)]

  fp_num_ord: [fp_num -> upto(2)]

  ord(x: fp_num): [fp_num -> upto(2)] =
      CASES x
        OF finite(finite1_var, finite2_var, finite3_var): 0,
           infinite(infinite1_var): 1,
           NaN(NaN1_var, NaN2_var): 2
        ENDCASES

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

  reduce_nat(finite?_fun: [[sign_rep, Exponent, digits] -> nat],
             infinite?_fun: [sign_rep -> nat],
             NaN?_fun: [[NaN_type, NaN_data] -> nat]):
        [fp_num -> nat] =
      LAMBDA (fp_num_adtvar: fp_num):
        LET red: [fp_num -> nat] =
              reduce_nat(finite?_fun, infinite?_fun, NaN?_fun)
          IN
          CASES fp_num_adtvar
            OF finite(finite1_var, finite2_var, finite3_var):
                 finite?_fun(finite1_var, finite2_var, finite3_var),
               infinite(infinite1_var): infinite?_fun(infinite1_var),
               NaN(NaN1_var, NaN2_var): NaN?_fun(NaN1_var, NaN2_var)
            ENDCASES;

  REDUCE_nat(finite?_fun: [[sign_rep, Exponent, digits, fp_num] -> nat],
             infinite?_fun: [[sign_rep, fp_num] -> nat],
             NaN?_fun: [[NaN_type, NaN_data, fp_num] -> nat]):
        [fp_num -> nat] =
      LAMBDA (fp_num_adtvar: fp_num):
        LET red: [fp_num -> nat] =
              REDUCE_nat(finite?_fun, infinite?_fun, NaN?_fun)
          IN
          CASES fp_num_adtvar
            OF finite(finite1_var, finite2_var, finite3_var):
                 finite?_fun(finite1_var, finite2_var, finite3_var,
                             fp_num_adtvar),
               infinite(infinite1_var):
                 infinite?_fun(infinite1_var, fp_num_adtvar),
               NaN(NaN1_var, NaN2_var):
                 NaN?_fun(NaN1_var, NaN2_var, fp_num_adtvar)
            ENDCASES;

  reduce_ordinal(finite?_fun: [[sign_rep, Exponent, digits] -> ordinal],
                 infinite?_fun: [sign_rep -> ordinal],
                 NaN?_fun: [[NaN_type, NaN_data] -> ordinal]):
        [fp_num -> ordinal] =
      LAMBDA (fp_num_adtvar: fp_num):
        LET red: [fp_num -> ordinal] =
              reduce_ordinal(finite?_fun, infinite?_fun, NaN?_fun)
          IN
          CASES fp_num_adtvar
            OF finite(finite1_var, finite2_var, finite3_var):
                 finite?_fun(finite1_var, finite2_var, finite3_var),
               infinite(infinite1_var): infinite?_fun(infinite1_var),
               NaN(NaN1_var, NaN2_var): NaN?_fun(NaN1_var, NaN2_var)
            ENDCASES;

  REDUCE_ordinal(finite?_fun:
                   [[sign_rep, Exponent, digits, fp_num] -> ordinal],
                 infinite?_fun: [[sign_rep, fp_num] -> ordinal],
                 NaN?_fun: [[NaN_type, NaN_data, fp_num] -> ordinal]):
        [fp_num -> ordinal] =
      LAMBDA (fp_num_adtvar: fp_num):
        LET red: [fp_num -> ordinal] =
              REDUCE_ordinal(finite?_fun, infinite?_fun, NaN?_fun)
          IN
          CASES fp_num_adtvar
            OF finite(finite1_var, finite2_var, finite3_var):
                 finite?_fun(finite1_var, finite2_var, finite3_var,
                             fp_num_adtvar),
               infinite(infinite1_var):
                 infinite?_fun(infinite1_var, fp_num_adtvar),
               NaN(NaN1_var, NaN2_var):
                 NaN?_fun(NaN1_var, NaN2_var, fp_num_adtvar)
            ENDCASES;

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

  % Subtype TCC generated (at line 45, column 25) for  (-n)
      % expected type  {i: int | b /= 0 OR i >= 0}
  value_digit_TCC1: OBLIGATION
    FORALL (d: digits, n: nat): n < p IMPLIES b /= 0 OR (-n) >= 0;

  % Subtype TCC generated (at line 48, column 27) for  Exp(fin)
      % expected type  {i: int | b /= 0 OR i >= 0}
  value_TCC1: OBLIGATION FORALL (fin: (finite?)): b /= 0 OR Exp(fin) >= 0;

  % Subtype TCC generated (at line 55, column 46) for  0
      % expected type  below(b)
  shift_left_TCC1: OBLIGATION
    FORALL ((d: digits), i: below(p)): (i + 1 = p) IMPLIES 0 < b;

  % Subtype TCC generated (at line 55, column 55) for  i + 1
      % expected type  below(p)
  shift_left_TCC2: OBLIGATION
    FORALL ((d: digits), i: below(p)): NOT (i + 1 = p) IMPLIES i + 1 < p;

  % Subtype TCC generated (at line 65, column 34) for  Exp(fin) - E_min
      % expected type  naturalnumber
  normalize_TCC1: OBLIGATION FORALL (fin: (finite?)): Exp(fin) - E_min >= 0;

  % Subtype TCC generated (at line 60, column 35) for  0
      % expected type  below(p)
  normalize_TCC2: OBLIGATION
    FORALL (fin: (finite?)): NOT Exp(fin) = E_min IMPLIES 0 < p;

  % Subtype TCC generated (at line 63, column 35) for  Exp(fin) - 1
      % expected type  Exponent
  normalize_TCC3: OBLIGATION
    FORALL (fin: (finite?)):
      NOT Exp(fin) = E_min AND NOT d(fin)(0) /= 0 IMPLIES
       E_min <= Exp(fin) - 1 & Exp(fin) - 1 <= E_max;

  % Termination TCC generated (at line 63, column 8) for
      % normalize(finite(sign(fin), Exp(fin) - 1, shift_left(d(fin))))
  normalize_TCC4: OBLIGATION
    FORALL (fin: (finite?)):
      NOT Exp(fin) = E_min AND NOT d(fin)(0) /= 0 IMPLIES
       Exp(fin) - 1 - E_min < Exp(fin) - E_min;

  % Subtype TCC generated (at line 78, column 27) for  0
      % expected type  below(p)
  subnormal?_TCC1: OBLIGATION
    FORALL (fp: fp_num):
      Exp(normalize(fp)) = E_min AND NOT zero?(fp) AND finite?(fp) IMPLIES
       0 < p;

  % Subtype TCC generated (at line 86, column 41) for  0
      % expected type  below(p)
  normal?_TCC1: OBLIGATION FORALL ((fp: fp_num)): finite?(fp) IMPLIES 0 < p;

  % Subtype TCC generated (at line 94, column 26) for  b - 1
      % expected type  below(b)
  max_significand_TCC1: OBLIGATION
    FORALL (i: below(p)): b - 1 >= 0 AND b - 1 < b;

  % Subtype TCC generated (at line 96, column 45) for  0
      % expected type  below(b)
  min_significand_TCC1: OBLIGATION
    FORALL (i: below(p)): i < p - 1 IMPLIES 0 < b;

  % Subtype TCC generated (at line 96, column 52) for  1
      % expected type  below(b)
  min_significand_TCC2: OBLIGATION
    FORALL (i: below(p)): NOT i < p - 1 IMPLIES 1 < b;

  % Subtype TCC generated (at line 97, column 41) for  0
      % expected type  below(b)
  d_zero_TCC1: OBLIGATION FORALL (i: below(p)): 0 < b;

  % Subtype TCC generated (at line 108, column 35) for  E_max
      % expected type  Exponent
  max_fp_pos_TCC1: OBLIGATION E_min <= E_max & E_max <= E_max;

  % Subtype TCC generated (at line 109, column 35) for  E_min
      % expected type  Exponent
  min_fp_pos_TCC1: OBLIGATION E_min <= E_min & E_min <= E_max;

  % Subtype TCC generated (at line 110, column 33) for
      % finite(pos, E_min, d_zero)
      % expected type  {fin | zero?(fin)}
  pos_zero_TCC1: OBLIGATION zero?(finite(pos, E_min, d_zero));

  % Subtype TCC generated (at line 114, column 34) for
      % finite(neg, E_min, d_zero)
      % expected type  {fin | zero?(fin)}
  neg_zero_TCC1: OBLIGATION zero?(finite(neg, E_min, d_zero));

  % Subtype TCC generated (at line 116, column 27) for  max_fp_pos
      % expected type  (finite?)
  max_pos_TCC1: OBLIGATION finite?(max_fp_pos);

  % Subtype TCC generated (at line 116, column 21) for  value(max_fp_pos)
      % expected type  posreal
  max_pos_TCC2: OBLIGATION value(max_fp_pos) >= 0 AND value(max_fp_pos) > 0;

  % Subtype TCC generated (at line 117, column 27) for  min_fp_pos
      % expected type  (finite?)
  min_pos_TCC1: OBLIGATION finite?(min_fp_pos);

  % Subtype TCC generated (at line 117, column 21) for  value(min_fp_pos)
      % expected type  posreal
  min_pos_TCC2: OBLIGATION value(min_fp_pos) >= 0 AND value(min_fp_pos) > 0;

  % Subtype TCC generated (at line 119, column 27) for  max_fp_neg
      % expected type  (finite?)
  max_neg_TCC1: OBLIGATION finite?(max_fp_neg);

  % Subtype TCC generated (at line 119, column 21) for  value(max_fp_neg)
      % expected type  negreal
  max_neg_TCC2: OBLIGATION value(max_fp_neg) <= 0 AND value(max_fp_neg) < 0;

  % Subtype TCC generated (at line 120, column 27) for  min_fp_neg
      % expected type  (finite?)
  min_neg_TCC1: OBLIGATION finite?(min_fp_neg);

  % Subtype TCC generated (at line 120, column 21) for  value(min_fp_neg)
      % expected type  negreal
  min_neg_TCC2: OBLIGATION value(min_fp_neg) <= 0 AND value(min_fp_neg) < 0;

  % Subtype TCC generated (at line 123, column 20) for  (E_max + 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  max_fp_correct_TCC1: OBLIGATION b /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 123, column 37) for  (E_max + 1 - p)
      % expected type  {i: int | b /= 0 OR i >= 0}
  max_fp_correct_TCC2: OBLIGATION b /= 0 OR (E_max + 1 - p) >= 0;

  % Subtype TCC generated (at line 126, column 30) for  (E_min + 1 - p)
      % expected type  {i: int | b /= 0 OR i >= 0}
  min_fp_correct_TCC1: OBLIGATION b /= 0 OR (E_min + 1 - p) >= 0;

  % Subtype TCC generated (at line 168, column 28) for  1 - s
      % expected type  sign_rep
  toggle_sign_TCC1: OBLIGATION
    FORALL (fp: fp_num, s: sign_rep, e: Exponent, d: digits):
      fp = finite(s, e, d) IMPLIES 1 - s >= 0 AND (1 - s = 0 OR 1 - s = 1);

  % Subtype TCC generated (at line 169, column 28) for  1 - s
      % expected type  sign_rep
  toggle_sign_TCC2: OBLIGATION
    FORALL (fp: fp_num, s: sign_rep):
      fp = infinite(s) IMPLIES 1 - s >= 0 AND (1 - s = 0 OR 1 - s = 1);

  % Subtype TCC generated (at line 177, column 28) for  toggle_sign(fin)
      % expected type  (finite?)
  value_toggle_TCC1: OBLIGATION
    FORALL (fin: (finite?)): finite?(toggle_sign(fin));

  % Subtype TCC generated (at line 198, column 56) for  (-j)
      % expected type  {i: int | b /= 0 OR i >= 0}
  value_digit_le_TCC1: OBLIGATION FORALL (j: nat): b /= 0 OR (-j) >= 0;

  % Subtype TCC generated (at line 202, column 21) for  0
      % expected type  below(p)
  Sum_d_lt1_TCC1: OBLIGATION 0 < p;

  % Subtype TCC generated (at line 221, column 14) for  E_min
      % expected type  {i: int | b /= 0 OR i >= 0}
  value_normal_TCC1: OBLIGATION
    FORALL (fin: (finite?)): normal?(fin) IMPLIES b /= 0 OR E_min >= 0;

  % Subtype TCC generated (at line 224, column 61) for  E_min
      % expected type  {i: int | b /= 0 OR i >= 0}
  value_subnormal_TCC1: OBLIGATION
    FORALL (fin: (finite?)):
      subnormal?(fin) AND min_pos <= abs(value(fin)) IMPLIES
       b /= 0 OR E_min >= 0;

  % Subtype TCC generated (at line 233, column 61) for  m
      % expected type  {i: int | b /= 0 OR i >= 0}
  scale_value_TCC1: OBLIGATION FORALL (m: nat): b /= 0 OR m >= 0;

  % Subtype TCC generated (at line 238, column 45) for  p - 1
      % expected type  nat
  scale_value_p_TCC1: OBLIGATION p - 1 >= 0;

  % Subtype TCC generated (at line 238, column 31) for
      % scale_value(d, p - 1)(n)
      % expected type  nat
  scale_value_p_TCC2: OBLIGATION
    FORALL (d: digits, n: nat):
      rational_pred(scale_value(d, p - 1)(n)) AND
       integer_pred(scale_value(d, p - 1)(n)) AND
        scale_value(d, p - 1)(n) >= 0;

  % Subtype TCC generated (at line 243, column 33) for  (i)
      % expected type  {i: int | b /= 0 OR i >= 0}
  scaled_Sum_i_TCC1: OBLIGATION FORALL (i: below(p)): b /= 0 OR i >= 0;

  % Subtype TCC generated (at line 252, column 23) for
      % Sum(i + 1, scale_value(d, i))
      % expected type  int
  mod_Sum_TCC1: OBLIGATION
    FORALL (d: digits, i: below(p)):
      rational_pred(Sum(i + 1, scale_value(d, i))) AND
       integer_pred(Sum(i + 1, scale_value(d, i)));


body:
  NaN_ops
    [b,p:above(1),
     E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY

    BEGIN

    IMPORTING IEEE_854_values[b,p,E_max,E_min],
              enumerated_type_defs
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Placeholders for defining results of operations on NaNs

    fp,fp1,fp2: var fp_num
    nan,nan1,nan2: var (NaN?)

    op: var fp_ops

    signal?(fp):bool = if NaN?(fp) then signal?(status(fp)) else false endif

  % mk_quiet takes an fp_num and coerces all NaNs into quiet NaNs.
  %  all numeric floating-point arguments are left unchanged
    mk_quiet(fp): fp_num = if NaN?(fp) then NaN(quiet,data(fp)) else fp endif

    mk_quiet_correct: lemma not signal?(fp) => mk_quiet(fp) = fp

    fp_quiet(op,fp1,(fp2| NaN?(fp1) OR NaN?(fp2))):{nan| nan=fp1 or nan=fp2}

    fp_signal(op, fp1,(fp2| NaN?(fp1) OR NaN?(fp2))): fp_num =
      IF trap_enabled?(invalid_operation) THEN invalid
      ELSE fp_quiet(op, mk_quiet(fp1), mk_quiet(fp2))
      ENDIF

    fp_nan(op, fp1, (fp2| NaN?(fp1) OR NaN?(fp2))): fp_num =
      IF signal?(fp1) OR signal?(fp2) THEN fp_signal(op, fp1, fp2)
      ELSE fp_quiet(op, fp1, fp2)
      ENDIF

    NaN_ops_correct: LEMMA
          NOT trap_enabled?(invalid_operation) & (NaN?(fp1) OR NaN?(fp2))
            => quiet?(status(fp_nan(op, fp1, fp2)))

    fp_nan_x(op, fp1, (fp2| NaN?(fp1) OR NaN?(fp2))): [fp_num,exception] =
      IF signal?(fp1) OR signal?(fp2) THEN 
         (fp_signal(op, fp1, fp2),invalid_operation)
      ELSE 
         (fp_quiet(op, fp1, fp2), no_exceptions)
      ENDIF  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    NaN_sqrt(nan): fp_num =
      if signal?(status(nan)) 
          & trap_enabled?(invalid_operation) then
         invalid
      else NaN(quiet,data(nan))
      endif
    

    END NaN_ops

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

  % Existence TCC generated (at line 26, column 2) for
      % fp_quiet(op, fp1,
      %          (fp2: fp_num[b, p, E_max, E_min] | NaN?(fp1) OR NaN?(fp2))):
      %       {nan | nan = fp1 OR nan = fp2}
  fp_quiet_TCC1: OBLIGATION
    EXISTS (x:
              [d:
                 [fp_ops, fp1: fp_num[b, p, E_max, E_min],
                  {fp2 |
                           NaN?[b, p, E_max, E_min](fp1) OR
                            NaN?[b, p, E_max, E_min](fp2)}] ->
                 {nan | nan = d`2 OR nan = d`3}]):
      TRUE;

  % Subtype TCC generated (at line 30, column 37) for  mk_quiet(fp2)
      % expected type  {fp2 | NaN?(mk_quiet(fp1)) OR NaN?(fp2)}
  fp_signal_TCC1: OBLIGATION
    FORALL (fp1: fp_num[b, p, E_max, E_min],
            (fp2: fp_num[b, p, E_max, E_min]
                 | NaN?[b, p, E_max, E_min](fp1) OR
                    NaN?[b, p, E_max, E_min](fp2))):
      NOT trap_enabled?(invalid_operation) IMPLIES
       NaN?[b, p, E_max, E_min](mk_quiet(fp1)) OR
        NaN?[b, p, E_max, E_min](mk_quiet(fp2));

  % Subtype TCC generated (at line 40, column 27) for  fp_nan(op, fp1, fp2)
      % expected type  (NaN?)
  NaN_ops_correct_TCC1: OBLIGATION
    FORALL (fp1, fp2: fp_num[b, p, E_max, E_min], op: fp_ops):
      (NaN?(fp1) OR NaN?(fp2)) AND NOT trap_enabled?(invalid_operation)
       IMPLIES NaN?[b, p, E_max, E_min](fp_nan(op, fp1, fp2));


body:
  infinity_arithmetic
    [b,p:above(1),
     E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY

    BEGIN

    IMPORTING IEEE_854_values[b,p,E_max,E_min],
              enumerated_type_defs

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Special functions for handling arithmetic on infinities
  %  These definitions return an undetermined NaN when the Invalid 
  %   exception should be raised.
  %
  %  The definitions come from constraints enumerated in sections
  %   6.1, 6.3, and 7.1 of IEEE-854
  %

    fp: var fp_num

    num,num1,num2: var {fp| finite?(fp) or infinite?(fp)}

  % Addition when at least one operand is an infinity
    fp_add_inf(num1, (num2: {num | infinite?(num1) OR infinite?(num)})): fp_num 
       =
      IF infinite?(num1) & infinite?(num2) THEN 
        IF (i_sign(num1) = i_sign(num2)) THEN num1
        ELSE invalid
        ENDIF
      ELSIF infinite?(num1) THEN num1
      ELSE num2
      ENDIF

  % Addition when at least one operand is an infinity with exceptions

    fp_add_inf_x(num1, (num2: {num | infinite?(num1) OR infinite?(num)})): 
      [fp_num, exception]
       =
      IF infinite?(num1) & infinite?(num2) THEN 
        IF (i_sign(num1) = i_sign(num2)) THEN (num1,no_exceptions)
        ELSE (invalid,invalid_operation)
        ENDIF
      ELSIF infinite?(num1) THEN (num1,no_exceptions)
      ELSE (num2,no_exceptions)
      ENDIF

  % Similarly for subtraction

    fp_sub_inf(num1, (num2: {num | infinite?(num1) OR infinite?(num)})): fp_num 
       =
      IF infinite?(num1) & infinite?(num2) THEN 
        IF (i_sign(num1) /= i_sign(num2)) THEN num1
        ELSE invalid
        ENDIF
      ELSIF infinite?(num1) THEN num1
      ELSE toggle_sign(num2)
      ENDIF

  % Similarly for subtraction with exceptions

    fp_sub_inf_x(num1, (num2: {num | infinite?(num1) OR infinite?(num)})): 
     [fp_num , exception]
       =
      IF infinite?(num1) & infinite?(num2) THEN 
        IF (i_sign(num1) /= i_sign(num2)) THEN (num1, no_exceptions)
        ELSE (invalid, invalid_operation)
        ENDIF
      ELSIF infinite?(num1) THEN (num1, no_exceptions)
      ELSE (toggle_sign(num2), no_exceptions)
      ENDIF

  % Alternate definition for fp_sub_inf
    fp_sub_inf_def: lemma
     forall num1,(num2:{num|infinite?(num1) OR infinite?(num)}):
      fp_sub_inf(num1,num2) = fp_add_inf(num1,toggle_sign(num2));

  % xor function defined on sign_rep to determine correct sign for mult/div
    xor(s1,s2:sign_rep): sign_rep = if s1=s2 then 0 else 1 endif

  % Determine correct sign for multiplication and division
  %  this definition is complicated by a bug in the adt mechanism
  %  PVS does not currently allow use of the same accessor for 
  %  different constructors. 
    mult_sign(num1,num2):sign_rep =
      if infinite?(num1) then
         if infinite?(num2) then
            xor(i_sign(num1),i_sign(num2))
         else
            xor(i_sign(num1),sign(num2))
         endif
      elsif infinite?(num2) then
            xor(sign(num1),i_sign(num2))
      else
            xor(sign(num1),sign(num2))
      endif
            

  % Multiplication of infinity
  %  The use of mult_sign may be replaced by xor(sign(num1),sign(num2)) 
  %  as soon as the accessor bug is fixed.
    fp_mul_inf(num1, (num2: {num | infinite?(num1) OR infinite?(num)})): fp_num 
       =
      If zero?(num1) or zero?(num2) then invalid
      else infinite(mult_sign(num1,num2))
      endif 


  % Division with infinities
    fp_div_inf(num1, (num2: {num | infinite?(num1) OR infinite?(num)})): fp_num 
       =
      IF infinite?(num1) & infinite?(num2) THEN invalid
      ELSIF infinite?(num1) THEN infinite(mult_sign(num1,num2))
      ELSE finite(mult_sign(num1,num2),E_min,d_zero)
      ENDIF   


  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    

    END infinity_arithmetic

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

  % Subtype TCC generated (at line 76, column 44) for  toggle_sign(num2)
      % expected type  {num | infinite?(num1) OR infinite?(num)}
  fp_sub_inf_def_TCC1: OBLIGATION
    FORALL (num1,
            num2:
              {num |
                       infinite?[b, p, E_max, E_min](num1) OR
                        infinite?[b, p, E_max, E_min](num)}):
      (finite?[b, p, E_max, E_min](toggle_sign[b, p, E_max, E_min](num2)) OR
        infinite?[b, p, E_max, E_min](toggle_sign[b, p, E_max, E_min](num2)))
       AND
       (infinite?[b, p, E_max, E_min](num1) OR
         infinite?[b, p, E_max, E_min]
             (toggle_sign[b, p, E_max, E_min](num2)));

  % Subtype TCC generated (at line 90, column 32) for  num2
      % expected type  (finite?[b, p, E_max, E_min])
  mult_sign_TCC1: OBLIGATION
    FORALL (num1:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)},
            num2:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)}):
      NOT infinite?(num2) AND infinite?(num1) IMPLIES
       finite?[b, p, E_max, E_min](num2);

  % Subtype TCC generated (at line 93, column 19) for  num1
      % expected type  (finite?[b, p, E_max, E_min])
  mult_sign_TCC2: OBLIGATION
    FORALL (num1:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)},
            num2:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)}):
      infinite?(num2) AND NOT infinite?(num1) IMPLIES
       finite?[b, p, E_max, E_min](num1);

  % Subtype TCC generated (at line 95, column 19) for  num1
      % expected type  (finite?[b, p, E_max, E_min])
  mult_sign_TCC3: OBLIGATION
    FORALL (num1:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)},
            num2:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)}):
      NOT infinite?(num2) AND NOT infinite?(num1) IMPLIES
       finite?[b, p, E_max, E_min](num1);

  % Subtype TCC generated (at line 95, column 30) for  num2
      % expected type  (finite?[b, p, E_max, E_min])
  mult_sign_TCC4: OBLIGATION
    FORALL (num1:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)},
            num2:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)}):
      NOT infinite?(num2) AND NOT infinite?(num1) IMPLIES
       finite?[b, p, E_max, E_min](num2);

  % Subtype TCC generated (at line 114, column 37) for  E_min
      % expected type  Exponent[b, p, E_max, E_min]
  fp_div_inf_TCC1: OBLIGATION
    FORALL (num1:
              {fp |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)},
            (num2:
               {num |
                        infinite?[b, p, E_max, E_min](num1) OR
                         infinite?[b, p, E_max, E_min](num)})):
      NOT infinite?(num1) AND NOT (infinite?(num1) & infinite?(num2)) IMPLIES
       E_min <= E_min & E_min <= E_max;


body:
  comparison1 
    [b,p:above(1),
     E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY

    BEGIN

    IMPORTING IEEE_854_values[b,p,E_max,E_min]

    num,num1,num2: var {fp:fp_num| finite?(fp) or infinite?(fp)}

  % extend value function so that infinities can be compared to finite
  % numbers
    n_value(num): real =
      IF infinite?(num) THEN (-1) ^ i_sign(num) * b ^ (E_max + 1)
      ELSE value(num)
      ENDIF
    

  % From section 5.7 of IEEE-854:
  %   ``Four mutually exclusive relations are possible: "less than,"
  %  "equal," "greater than," and "unordered."  The last case arises only
  %  when at least one operand is a NaN.'' ...

  %  ``The result of a comparison shall be delivered in one of two ways at
  %  the implementor's option: either as a condition code identifying one
  %  of the four relations listed above, or as a true/false response to a
  %  predicate that names the specific comparison desired.''

  % fp_compare, below, defines the first option:

    comparison_code: type = {gt, lt, eq, un}

    fp_compare((fp1, fp2: fp_num)): comparison_code =
      IF NaN?(fp1) OR NaN?(fp2) THEN un
      ELSIF n_value(fp1) > n_value(fp2) THEN gt
      ELSIF n_value(fp1) < n_value(fp2) THEN lt
      ELSE eq
      ENDIF

    fp,fp1,fp2: var fp_num

    posinf_ge: LEMMA
          gt?(fp_compare(infinite(pos), num))
            OR eq?(fp_compare(infinite(pos), num))

    NaN_unordered: LEMMA 
        NaN?(fp1) OR NaN?(fp2) => un?(fp_compare(fp1, fp2))

  % option 2, minimal set of predicates is {eq, ne, gt, ge, lt, le} also
  % should include un.  These predicates are defined below the level
  % where invalid will be signalled.

  % The follwing predicates are from table 3, page 12 of IEEE-854.  They
  % do not include the signalling of the invalid exception.  That test
  % may be applied prior to invoking these predicates.

  % shall include
    eq?(fp1,fp2) :bool = eq?(fp_compare(fp1,fp2))
    ne?(fp1,fp2) :bool = not eq?(fp_compare(fp1,fp2))
    gt?(fp1,fp2) :bool = gt?(fp_compare(fp1,fp2))
    ge?(fp1,fp2) :bool = gt?(fp_compare(fp1,fp2)) or eq?(fp_compare(fp1,fp2))
    lt?(fp1,fp2) :bool = lt?(fp_compare(fp1,fp2))
    le?(fp1,fp2) :bool = lt?(fp_compare(fp1,fp2)) or eq?(fp_compare(fp1,fp2))

  % should include
    un?(fp1,fp2) :bool = un?(fp_compare(fp1,fp2))

  % other
    lg?(fp1,fp2) :bool = gt?(fp_compare(fp1,fp2)) or lt?(fp_compare(fp1,fp2))
    leg?(fp1,fp2):bool = not un?(fp_compare(fp1,fp2))
    ug?(fp1,fp2) :bool = gt?(fp_compare(fp1,fp2)) or un?(fp_compare(fp1,fp2))
    uge?(fp1,fp2):bool = not lt?(fp_compare(fp1,fp2))
    ul?(fp1,fp2) :bool = lt?(fp_compare(fp1,fp2)) or un?(fp_compare(fp1,fp2))
    ule?(fp1,fp2):bool = not gt?(fp_compare(fp1,fp2))
    ue?(fp1,fp2) :bool = eq?(fp_compare(fp1,fp2)) or un?(fp_compare(fp1,fp2))

    eq_def: lemma  eq?(num1,num2) <=> n_value(num1) = n_value(num2)

    ne_def: lemma  ne?(num1,num2) <=> n_value(num1) /= n_value(num2)

    gt_def: lemma  gt?(num1,num2) <=> n_value(num1) > n_value(num2)

    ge_def: lemma  ge?(num1,num2) <=> n_value(num1) >= n_value(num2)

    lt_def: lemma  lt?(num1,num2) <=> n_value(num1) < n_value(num2)

    le_def: lemma  le?(num1,num2) <=> n_value(num1) <= n_value(num2)

    un_def: lemma  un?(fp1,fp2)   <=> (NaN?(fp1) or NaN?(fp2))

    END comparison1

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

  comparison_code_ord_defaxiom: AXIOM
    comparison_code_ord(gt) = 0 AND
     comparison_code_ord(lt) = 1 AND
      comparison_code_ord(eq) = 2 AND comparison_code_ord(un) = 3;

  comparison_code_inclusive: AXIOM
    FORALL (comparison_code_var: comparison_code):
      gt?(comparison_code_var) OR
       lt?(comparison_code_var) OR
        eq?(comparison_code_var) OR un?(comparison_code_var);

  comparison_code_induction: AXIOM
    FORALL (p: [comparison_code -> boolean]):
      p(gt) AND p(lt) AND p(eq) AND p(un) IMPLIES
       (FORALL (comparison_code_var: comparison_code):
          p(comparison_code_var));

  comparison_code_well_founded: AXIOM
    strict_well_founded?[comparison_code](<<);

  comparison_code: TYPE

  gt?: [comparison_code -> boolean]

  lt?: [comparison_code -> boolean]

  eq?: [comparison_code -> boolean]

  un?: [comparison_code -> boolean]

  comparison_code_ord: [comparison_code -> upto(3)]

  ord(x: comparison_code): [comparison_code -> upto(3)] =
      CASES x OF gt: 0, lt: 1, eq: 2, un: 3 ENDCASES

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

  gt: (gt?)

  lt: (lt?)

  eq: (eq?)

  un: (un?)

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

  % Subtype TCC generated (at line 15, column 53) for  (E_max + 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  n_value_TCC1: OBLIGATION
    FORALL (num:
              {fp: fp_num[b, p, E_max, E_min] |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)}):
      infinite?(num) IMPLIES b /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 16, column 15) for  num
      % expected type  (finite?[b, p, E_max, E_min])
  n_value_TCC2: OBLIGATION
    FORALL (num:
              {fp: fp_num[b, p, E_max, E_min] |
                       finite?[b, p, E_max, E_min](fp) OR
                        infinite?[b, p, E_max, E_min](fp)}):
      NOT infinite?(num) IMPLIES finite?[b, p, E_max, E_min](num);

  % Subtype TCC generated (at line 36, column 18) for  fp1
      % expected type  {fp: fp_num | finite?(fp) OR infinite?(fp)}
  fp_compare_TCC1: OBLIGATION
    FORALL ((fp1, fp2: fp_num[b, p, E_max, E_min])):
      NOT NaN?(fp1) AND NOT NaN?(fp2) IMPLIES
       finite?[b, p, E_max, E_min](fp1) OR infinite?[b, p, E_max, E_min](fp1);

  % Subtype TCC generated (at line 36, column 33) for  fp2
      % expected type  {fp: fp_num | finite?(fp) OR infinite?(fp)}
  fp_compare_TCC2: OBLIGATION
    FORALL ((fp1, fp2: fp_num[b, p, E_max, E_min])):
      NOT NaN?(fp1) AND NOT NaN?(fp2) IMPLIES
       finite?[b, p, E_max, E_min](fp2) OR infinite?[b, p, E_max, E_min](fp2);


body:
  round: THEORY
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Defines type:
  %   rounding_mode: type = {to_nearest,to_zero,to_pos,to_neg}
  %
  % Defines functions:
  %
  %   round: [[real,rounding_mode] -> integer]
  %
  %   Rounds a real number to the nearest integer in accordance 
  %   with the rounding mode (as specified in IEEE-854).
  %   The function round can be used in two parts of the IEEE-854
  %   floating point standard.
  %    1.)  Round floating point to integral value (section 5.5)
  %         or for converting a floating point to integer (5.4).
  %    2.)  By giving function `round' an appropriately scaled 
  %         argument, this function can be used in the process 
  %         of converting a real number to a floating point 
  %         representation.
  %
  %   round_to_even:[real -> integer]
  %
  %   Auxilliary function used in definition of round.  Selects the 
  %   integer nearest in value to the real argument.      
  %   If the real number is exactly halfway between two integers,
  %   this function selects the nearest even integer.
  %   Can also be used:
  %    --   As an auxilliary function in the definition of
  %         the remainder function (section 5.1).  For y/=0,
  %         x REM y =def= x - y*n, where n = round_to_even(x/y).
  %
  %
  % Author:
  %  Paul S. Miner                | email: p.s.miner@larc.nasa.gov
  %  1 South Wright St. / MS 130  |   fax: (757) 864-4234
  %  NASA Langley Research Center | phone: (757) 864-6201
  %  Hampton, Virginia 23681      |
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
  %  Requires library `floor'

    BEGIN 

    importing enumerated_type_defs

  %  rounding_mode:type = {to_nearest,to_zero,to_pos,to_neg}
    mode: var rounding_mode

    r: VAR real
    
    round_to_even(r): integer =
      IF r - floor(r) < ceiling(r) - r THEN floor(r)
      ELSIF ceiling(r) - r < r - floor(r) THEN ceiling(r)
      ELSIF floor(r) = ceiling(r) THEN floor(r)
      ELSE 2 * floor(ceiling(r) / 2)
      ENDIF
    
    round_to_even0: lemma round_to_even(0)=0

    round_to_even1: LEMMA abs(r - round_to_even(r)) <= 1 / 2
    
    round_to_even2: LEMMA
          abs(r - round_to_even(r)) = 1 / 2 => integer?(round_to_even(r) / 2)
    
    round(r,mode): integer =
      CASES mode of
        to_nearest: round_to_even(r),
        to_zero:    sgn(r) * floor(abs(r)),
        to_pos:     ceiling(r),
        to_neg:     floor(r)
      ENDCASES
      
    round1: LEMMA abs(r-round(r,mode))<1 

    i:var int

    round_int: LEMMA  round(i,mode)=i

    END round


body:
  fp_round_aux[b,p:above(1)]: THEORY

    BEGIN
    
    importing round,
  %%%%%%%%%%%%%%%%% ajout S. Boldo
              %% ints@mod_,
  %%%%%%%%%%%%%%%%% fin ajout
              enumerated_type_defs

    r: var real
    x: var posreal

    sign_of(r:real): sign_rep = IF r < 0 THEN neg ELSE pos ENDIF

    Exp_of(x:posreal): {i:int| b^i<= x & x < b^(i+1)}

    Exp_of_correct: lemma 
        1 <= x*b^(-Exp_of(x)) & x*b^(-Exp_of(x)) < b

    norm_fp_range: type = {x:posreal | 1 <= x & x < b}

    n1: var norm_fp_range

    z: var nzreal

    E(z):integer = Exp_of(abs(z))

    significand(z):norm_fp_range = abs(z)*b^(-Exp_of(abs(z)))

    real_components: lemma
      z = sgn(z)* b^E(z) * significand(z)    

    abs_real_components: LEMMA
      abs(z) = b^E(z)*significand(z)

    i,j: var integer

    Exp_of_unique: LEMMA
      b^i <= x & x < b^(i+1) & b^j<=x & x<b^(j+1) => i=j

    posreal_exponent: lemma
      x = b^i *n1 => E(x) = i

    real_exponent: lemma
      z = sgn(z)*b^i * n1 => E(z) = i

    scale(x:posreal):{i:int|b^(i+p-1)<=x & x < b^(i+p)} = Exp_of(x)-(p-1)

    scale_correct: lemma b^(p-1)<=x/b^scale(x) & x/b^scale(x)< b^p

    round_scaled(r:nzreal,mode:rounding_mode): real =
      b^(scale(abs(r)))*round( b^(-scale(abs(r)))*r,mode)

    E1: var integer
    px: var posreal
    nnx: var nonneg_real 

    truncate(E1,nnx): [below(p)->below(b)] = 
        (lambda (i:below(p)): mod(floor(b^(i-E1)*nnx),b))

    truncate_shift: LEMMA
      truncate(i,b^j*px) = truncate(i-j,px)

    Exp_of_shift: LEMMA
      Exp_of(b^j*px) = j + Exp_of(px)

    scale_shift: LEMMA
      scale(b^j*px) = j + scale(px)

    END fp_round_aux

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

  % Subtype TCC generated (at line 16, column 31) for  i
      % expected type  {i: int | b /= 0 OR i >= 0}
  Exp_of_TCC1: OBLIGATION FORALL (i: int): b /= 0 OR i >= 0;

  % Subtype TCC generated (at line 16, column 46) for  (i + 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  Exp_of_TCC2: OBLIGATION
    FORALL (x: posreal, i: int): b ^ i <= x IMPLIES b /= 0 OR (i + 1) >= 0;

  % Existence TCC generated (at line 16, column 2) for
      % Exp_of(x: posreal): {i: int | b ^ i <= x & x < b ^ (i + 1)}
  Exp_of_TCC3: OBLIGATION
    EXISTS (x1: [x: posreal -> {i: int | b ^ i <= x & x < b ^ (1 + i)}]):
      TRUE;

  % Subtype TCC generated (at line 19, column 16) for  (-Exp_of(x))
      % expected type  {i: int | b /= 0 OR i >= 0}
  Exp_of_correct_TCC1: OBLIGATION
    FORALL (x: posreal): b /= 0 OR (-Exp_of(x)) >= 0;

  % Subtype TCC generated (at line 29, column 43) for  (-Exp_of(abs(z)))
      % expected type  {i: int | b /= 0 OR i >= 0}
  significand_TCC1: OBLIGATION
    FORALL (z: nzreal): b /= 0 OR (-Exp_of(abs(z))) >= 0;

  % Subtype TCC generated (at line 29, column 33) for
      % abs(z) * b ^ (-Exp_of(abs(z)))
      % expected type  norm_fp_range
  significand_TCC2: OBLIGATION
    FORALL (z: nzreal):
      1 <= abs(z) * b ^ (-Exp_of(abs(z))) &
       abs(z) * b ^ (-Exp_of(abs(z))) < b;

  % Subtype TCC generated (at line 32, column 18) for  E(z)
      % expected type  {i: int | b /= 0 OR i >= 0}
  real_components_TCC1: OBLIGATION FORALL (z: nzreal): b /= 0 OR E(z) >= 0;

  % Subtype TCC generated (at line 40, column 31) for  j
      % expected type  {i: int | b /= 0 OR i >= 0}
  Exp_of_unique_TCC1: OBLIGATION
    FORALL (i, j: integer, x: posreal):
      b ^ i <= x AND x < b ^ (i + 1) IMPLIES b /= 0 OR j >= 0;

  % Subtype TCC generated (at line 40, column 43) for  (j + 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  Exp_of_unique_TCC2: OBLIGATION
    FORALL (i, j: integer, x: posreal):
      b ^ i <= x AND x < b ^ (i + 1) AND b ^ j <= x IMPLIES
       b /= 0 OR (j + 1) >= 0;

  % Subtype TCC generated (at line 48, column 29) for  (i + p - 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  scale_TCC1: OBLIGATION FORALL (i: int): b /= 0 OR (i + p - 1) >= 0;

  % Subtype TCC generated (at line 48, column 48) for  (i + p)
      % expected type  {i: int | b /= 0 OR i >= 0}
  scale_TCC2: OBLIGATION
    FORALL (x: posreal, i: int):
      b ^ (i + p - 1) <= x IMPLIES b /= 0 OR (i + p) >= 0;

  % Subtype TCC generated (at line 48, column 56) for  Exp_of(x) - (p - 1)
      % expected type  {i: int | b ^ (i - 1 + p) <= x & x < b ^ (i + p)}
  scale_TCC3: OBLIGATION
    FORALL (x: posreal):
      b ^ (Exp_of(x) - (p - 1) - 1 + p) <= x &
       x < b ^ (Exp_of(x) - (p - 1) + p);

  % Subtype TCC generated (at line 50, column 26) for  (p - 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  scale_correct_TCC1: OBLIGATION b /= 0 OR (p - 1) >= 0;

  % Subtype TCC generated (at line 50, column 36) for  scale(x)
      % expected type  {i: int | b /= 0 OR i >= 0}
  scale_correct_TCC2: OBLIGATION FORALL (x: posreal): b /= 0 OR scale(x) >= 0;

  % Subtype TCC generated (at line 50, column 63) for  p
      % expected type  {i: int | b /= 0 OR i >= 0}
  scale_correct_TCC3: OBLIGATION
    FORALL (x: posreal):
      b ^ (p - 1) <= x / b ^ scale(x) IMPLIES b /= 0 OR p >= 0;

  % Subtype TCC generated (at line 53, column 7) for  (scale(abs(r)))
      % expected type  {i: int | b /= 0 OR i >= 0}
  round_scaled_TCC1: OBLIGATION
    FORALL (r: nzreal): b /= 0 OR (scale(abs(r))) >= 0;

  % Subtype TCC generated (at line 53, column 32) for  (-scale(abs(r)))
      % expected type  {i: int | b /= 0 OR i >= 0}
  round_scaled_TCC2: OBLIGATION
    FORALL (r: nzreal): b /= 0 OR (-scale(abs(r))) >= 0;

  % Subtype TCC generated (at line 60, column 41) for  (i - E1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  truncate_TCC1: OBLIGATION
    FORALL (E1: integer, i: below(p)): b /= 0 OR (i - E1) >= 0;


body:
  over_under
    [b,p:above(1),
     alpha,E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY


    BEGIN

    IMPORTING IEEE_854_values[b,p,E_max,E_min], 
              fp_round_aux[b,p],
              enumerated_type_defs,
              round

    over_under?(r:real): bool = (r/=0 & (abs(r)>max_pos or abs(r)<b^E_min))

  % A real number that real_to_fp maps to infinity
    infinity: real = b^(E_max+1)

    trap_over((r1:nzreal), (r2: real), (mode: rounding_mode)): real =
      IF trap_enabled?(overflow) THEN round_scaled(r1 * b ^ (-alpha), mode)
      ELSE r2
      ENDIF

    overflow((r: nzreal | abs(r) > max_pos), (mode: rounding_mode)):
        [real, exception] =
      CASES mode OF
        to_nearest:
            IF abs(r)
                  >= b ^ (E_max + 1)
                       - (1 / 2) * b ^ (E_max + 1 - p)
              THEN (trap_over(r, (sgn(r) * infinity), mode),overflow)
            ELSE (sgn(r) * max_pos, inexact)
            ENDIF,
        to_zero:
            IF abs(r) >= b ^ (E_max + 1)
              THEN (trap_over(r, (sgn(r) * max_pos), mode),overflow)
            ELSE (sgn(r) * max_pos, inexact)
            ENDIF,
        to_pos:
            IF r > max_pos THEN (trap_over(r, infinity, mode),overflow)
            ELSIF r <= -b ^ (E_max + 1)
              THEN (trap_over(r, max_neg, mode),overflow)
            ELSE (max_neg, inexact)
            ENDIF,
        to_neg:
            IF r < max_neg THEN (trap_over(r, -infinity, mode),overflow)
            ELSIF r >= b ^ (E_max + 1)
              THEN (trap_over(r, max_pos, mode),overflow)
            ELSE (max_pos, inexact)
            ENDIF
        ENDCASES


    tiny_flag: bool % = true for tininess detected after rounding
    inaccurate_flag: bool % = true for inaccurate detected using first option

    exact_underflow((r:nzreal|abs(r)<b^E_min),mode:rounding_mode):bool =
         (r*b^alpha=round_scaled(r*b^alpha,mode))
    
    %implicitly already have tininess detected before rounding
    tiny?((r: nzreal | abs(r) < b ^ E_min), (mode: rounding_mode)): bool =
      IF tiny_flag THEN abs(round_scaled(r, mode)) < b ^ E_min ELSE TRUE ENDIF

    round_under((r: nzreal | abs(r) < b ^ E_min), (mode: rounding_mode)): real
      = b^(E_min - (p - 1))*round(b^(-(E_min - (p - 1)))*r,mode)

    mode: var rounding_mode
   
    round_under_correct: LEMMA
          round_under(min_pos,mode) = min_pos

    fin: var (finite?)

    round_under_value: lemma subnormal?(fin) =>
                   round_under(value(fin),mode) = value(fin)

    r:var nzreal

    round_under_error: LEMMA
          abs(r) < b ^ E_min
            => abs(r - round_under(r, mode)) < b ^ (E_min - (p - 1))

    round_under_near: LEMMA
          abs(r) < b ^ E_min
            => abs(r - round_under(r, to_nearest)) <= b ^ (E_min - (p - 1)) / 2

    round_under_pos: lemma abs(r)<b^E_min => round_under(r,to_pos)>=r

    round_under_neg: lemma abs(r)<b^E_min => round_under(r,to_neg)<=r

    round_under_zero: lemma abs(r)<b^E_min => abs(round_under(r,to_zero))<=abs(r)


    inaccurate?((r: nzreal | abs(r) < b ^ E_min), (mode: rounding_mode)): bool =
      IF inaccurate_flag THEN (round_scaled(r,mode)/=round_under(r,mode))
      ELSE (r/=round_under(r,mode))
      ENDIF

    underflow((r: nzreal | abs(r) < b ^ E_min), (mode: rounding_mode)):
        [real, exception] =
      IF tiny?(r, mode)
        THEN IF trap_enabled?(underflow(FALSE))
          THEN (round_scaled(r * b ^ alpha, mode),
                underflow(exact_underflow(r, mode)))
        ELSIF inaccurate?(r, mode) THEN (round_under(r, mode), underflow(TRUE))
        ELSE (round_under(r, mode),
              IF r = round_under(r, mode) THEN no_exceptions
              ELSE inexact
              ENDIF)
        ENDIF
      ELSE (round_under(r, mode), inexact)
      ENDIF
    
    END over_under

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

  % Subtype TCC generated (at line 14, column 66) for  E_min
      % expected type  {i: int | b /= 0 OR i >= 0}
  over_under?_TCC1: OBLIGATION
    FORALL (r: real):
      NOT abs(r) > max_pos AND r /= 0 IMPLIES b /= 0 OR E_min >= 0;

  % Subtype TCC generated (at line 17, column 22) for  (E_max + 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  infinity_TCC1: OBLIGATION b /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 20, column 59) for  (-alpha)
      % expected type  {i: int | b /= 0 OR i >= 0}
  trap_over_TCC1: OBLIGATION
    trap_enabled?(overflow) IMPLIES b /= 0 OR (-alpha) >= 0;

  % Subtype TCC generated (at line 30, column 38) for  (E_max + 1 - p)
      % expected type  {i: int | b /= 0 OR i >= 0}
  overflow_TCC1: OBLIGATION
    FORALL ((r: nzreal | abs(r) > max_pos[b, p, E_max, E_min]),
            (mode: rounding_mode)):
      mode = to_nearest IMPLIES b /= 0 OR (E_max + 1 - p) >= 0;

  % Subtype TCC generated (at line 57, column 37) for  E_min
      % expected type  {i: int | b /= 0 OR i >= 0}
  exact_underflow_TCC1: OBLIGATION b /= 0 OR E_min >= 0;

  % Subtype TCC generated (at line 58, column 12) for  alpha
      % expected type  {i: int | b /= 0 OR i >= 0}
  exact_underflow_TCC2: OBLIGATION
    FORALL ((r: nzreal | abs(r) < b ^ E_min)): b /= 0 OR alpha >= 0;

  % Subtype TCC generated (at line 65, column 9) for  (E_min - (p - 1))
      % expected type  {i: int | b /= 0 OR i >= 0}
  round_under_TCC1: OBLIGATION
    FORALL ((r: nzreal | abs(r) < b ^ E_min)):
      b /= 0 OR (E_min - (p - 1)) >= 0;

  % Subtype TCC generated (at line 65, column 35) for  (-(E_min - (p - 1)))
      % expected type  {i: int | b /= 0 OR i >= 0}
  round_under_TCC2: OBLIGATION
    FORALL ((r: nzreal | abs(r) < b ^ E_min)):
      b /= 0 OR (-(E_min - (p - 1))) >= 0;

  % Subtype TCC generated (at line 70, column 20) for  min_pos
      % expected type  {r: nzreal | abs(r) < b ^ E_min}
  round_under_correct_TCC1: OBLIGATION
    abs(min_pos[b, p, E_max, E_min]) < b ^ E_min;

  % Subtype TCC generated (at line 75, column 29) for  value(fin)
      % expected type  {r: nzreal | abs(r) < b ^ E_min}
  round_under_value_TCC1: OBLIGATION
    FORALL (fin: (finite?)):
      subnormal?(fin) IMPLIES
       value[b, p, E_max, E_min](fin) /= 0 AND
        abs(value[b, p, E_max, E_min](fin)) < b ^ E_min;

  % Subtype TCC generated (at line 81, column 50) for  (E_min - (p - 1))
      % expected type  {i: int | b /= 0 OR i >= 0}
  round_under_error_TCC1: OBLIGATION
    FORALL (r: nzreal):
      abs(r) < b ^ E_min IMPLIES b /= 0 OR (E_min - (p - 1)) >= 0;


body:
  real_to_fp
    [b,p:above(1),
     alpha,E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY

    BEGIN

    IMPORTING IEEE_854_values[b,p,E_max,E_min], 
              over_under[b,p,alpha,E_max,E_min],
              fp_round_aux[b,p],
              round

    r: var real
    mode: var rounding_mode
    op: var fp_ops
    fin, fin1, fin2: var (finite?)

    px: var posreal
    E: var integer

    JUDGEMENT truncate has_type [integer,nonneg_real -> digits]

    truncate_zero: lemma truncate(E,0)=d_zero

    digits_of_finite: lemma truncate(Exp(fin),abs(value(fin))) = d(fin)

    real_to_fp(r): fp_num =
      IF abs(r) >= b^(E_max+1) THEN 
         infinite(sign_of(r))
      ELSIF abs(r) < b^E_min THEN 
         finite(sign_of(r), E_min, truncate(E_min, abs(r)))
      ELSE 
         finite(sign_of(r), Exp_of(abs(r)), truncate(Exp_of(abs(r)), abs(r)))
      ENDIF    

    real_to_fp_x(r:real,e:exception): [fp_num,exception] = (real_to_fp(r),e)

    real_to_fp_zero: lemma real_to_fp(0) = pos_zero

    sign_of_value: lemma not zero?(fin) =>(sign_of(value(fin))= sign(fin))

    Exp_of_value_normal: LEMMA
           normal?(fin)
            => Exp_of(abs(value(fin))) = Exp(normalize(fin))

    real_to_fp_normal: LEMMA 
  	        normal?(fin) 
            => real_to_fp(value(fin)) = normalize(fin)

    real_to_fp_subnormal: LEMMA 
          subnormal?(fin) 
            => real_to_fp(value(fin)) = normalize(fin)

    real_to_fp_inverts_value: LEMMA 
         not zero?(fin) => real_to_fp(value(fin)) = normalize(fin)

    round_exceptions_x(x:(over_under?),mode:rounding_mode): [real,exception] =
      IF abs(x)>max_pos THEN 
              overflow(x,mode)
         ELSE underflow(x,mode)
         ENDIF

    round_exceptions(r:(over_under?),mode): real 
        = proj_1(round_exceptions_x(r,mode))

    fp_round(r, mode): real =
      IF r = 0 THEN 0
      ELSIF over_under?(r) then
        round_exceptions(r,mode)
      ELSE round_scaled(r,mode)
      ENDIF

    is_exact?(r:nzreal,mode):exception =
      IF round_scaled(r,mode) = r then no_exceptions ELSE inexact ENDIF
    
    fp_round_x(r, mode): [real,exception] =
      IF r = 0 THEN (0,no_exceptions)
      ELSIF over_under?(r) then
        round_exceptions_x(r,mode)
      ELSE (round_scaled(r,mode),is_exact?(r,mode))
      ENDIF

    round_value: lemma not over_under?(value(fin)) =>
                   fp_round(value(fin),mode) = value(fin)

    round_value2: lemma not trap_enabled?(underflow(FALSE)) =>
                   fp_round(value(fin),mode) = value(fin)

    round_0: lemma fp_round(0,mode)=0

    round_value3: lemma not trap_enabled?(underflow(FALSE)) =>
                   not zero?(fin) =>
                   real_to_fp(fp_round(value(fin),mode)) = normalize(fin)

    round_error: lemma r/=0 & not over_under?(r)
              => abs(r-fp_round(r,mode))<b^(Exp_of(abs(r))-(p-1))

    round_near: LEMMA
          r /= 0 & not over_under?(r)
            => abs(r - fp_round(r, to_nearest))
                 <= b ^ (Exp_of(abs(r)) - (p - 1)) / 2

    round_pos: lemma not over_under?(r) => fp_round(r,to_pos)>=r

    round_neg: lemma not over_under?(r) => fp_round(r,to_neg)<=r

    round_zero: lemma not over_under?(r) => abs(fp_round(r,to_zero))<=abs(r)
    
    END real_to_fp

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

  % Subtype TCC generated (at line 28, column 20) for  (E_max + 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  real_to_fp_TCC1: OBLIGATION b /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 30, column 21) for  E_min
      % expected type  {i: int | b /= 0 OR i >= 0}
  real_to_fp_TCC2: OBLIGATION
    FORALL (r: real):
      NOT abs(r) >= b ^ (E_max + 1) IMPLIES b /= 0 OR E_min >= 0;

  % Subtype TCC generated (at line 31, column 26) for  E_min
      % expected type  Exponent[b, p, E_max, E_min]
  real_to_fp_TCC3: OBLIGATION
    FORALL (r: real):
      abs(r) < b ^ E_min AND NOT abs(r) >= b ^ (E_max + 1) IMPLIES
       E_min <= E_min & E_min <= E_max;

  % Subtype TCC generated (at line 33, column 33) for  abs(r)
      % expected type  x: posreal
  real_to_fp_TCC4: OBLIGATION
    FORALL (r: real):
      NOT abs(r) < b ^ E_min AND NOT abs(r) >= b ^ (E_max + 1) IMPLIES
       abs(r) > 0;

  % Subtype TCC generated (at line 33, column 26) for  Exp_of(abs(r))
      % expected type  Exponent[b, p, E_max, E_min]
  real_to_fp_TCC5: OBLIGATION
    FORALL (r: real):
      NOT abs(r) < b ^ E_min AND NOT abs(r) >= b ^ (E_max + 1) IMPLIES
       E_min <= Exp_of[b, p](abs(r)) & Exp_of[b, p](abs(r)) <= E_max;

  % Subtype TCC generated (at line 44, column 20) for  abs(value(fin))
      % expected type  x: posreal
  Exp_of_value_normal_TCC1: OBLIGATION
    FORALL (fin: (finite?)):
      normal?(fin) IMPLIES abs(value[b, p, E_max, E_min](fin)) > 0;

  % Subtype TCC generated (at line 59, column 21) for  x
      % expected type  {r: nzreal | abs(r) > max_pos}
  round_exceptions_x_TCC1: OBLIGATION
    FORALL (x: (over_under?[b, p, alpha, E_max, E_min])):
      abs(x) > max_pos IMPLIES x /= 0;

  % Subtype TCC generated (at line 60, column 22) for  x
      % expected type  {r: nzreal | abs(r) < b ^ E_min}
  round_exceptions_x_TCC2: OBLIGATION
    FORALL (x: (over_under?[b, p, alpha, E_max, E_min])):
      NOT abs(x) > max_pos IMPLIES x /= 0 AND abs(x) < b ^ E_min;

  % Subtype TCC generated (at line 70, column 22) for  r
      % expected type  nzreal
  fp_round_TCC1: OBLIGATION
    FORALL (r: real): NOT over_under?(r) AND NOT r = 0 IMPLIES r /= 0;

  % Subtype TCC generated (at line 96, column 49) for  abs(r)
      % expected type  x: posreal
  round_error_TCC1: OBLIGATION
    FORALL (r: real): NOT over_under?(r) AND r /= 0 IMPLIES abs(r) > 0;

  % Subtype TCC generated (at line 96, column 42) for
      % (Exp_of(abs(r)) - (p - 1))
      % expected type  {i: int | b /= 0 OR i >= 0}
  round_error_TCC2: OBLIGATION
    FORALL (r: real):
      NOT over_under?(r) AND r /= 0 IMPLIES
       b /= 0 OR (Exp_of[b, p](abs(r)) - (p - 1)) >= 0;


body:
  arithmetic_ops
    [b,p:above(1),
     alpha,E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY

    BEGIN

    IMPORTING IEEE_854_values[b,p,E_max,E_min],
              real_to_fp[b,p,alpha,E_max,E_min],
              enumerated_type_defs

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % fp_op provides a template for defining a floating point operation
  %  for the case when both arguments are finites.    

    fin,fin1,fin2: var (finite?)
    op: var fp_ops
    mode: var rounding_mode

    apply(op,fin1,(fin2:{fin| div?(op) => not zero?(fin)})): real =
      cases op of
        add:  value(fin1) + value(fin2),
        sub:  value(fin1) - value(fin2),
        mult: value(fin1) * value(fin2),
        div:  value(fin1) / value(fin2)
      endcases

    signed_zero(op, fin1, fin2, mode): {fin | zero?(fin)} =
      CASES op OF
        add:
            IF zero?(fin1)
                  & zero?(fin2) & sign(fin1) = sign(fin2) THEN fin1
            ELSIF to_neg?(mode) THEN neg_zero
            ELSE pos_zero
            ENDIF,
        sub:
            IF zero?(fin1)
                  & zero?(fin2) & sign(fin1) /= sign(fin2) THEN fin1
            ELSIF to_neg?(mode) THEN neg_zero
            ELSE pos_zero
            ENDIF,
        mult:
            IF sign(fin1) = sign(fin2) THEN pos_zero
            ELSE neg_zero
            ENDIF,
        div:
            IF sign(fin1) = sign(fin2) THEN pos_zero
            ELSE neg_zero
            ENDIF
        ENDCASES  

    fp_op(op, fin1, (fin2: {fin | div?(op) => NOT zero?(fin)}), mode): fp_num =
      LET r = fp_round(apply(op, fin1, fin2), mode)
        IN IF r = 0 THEN signed_zero(op, fin1, fin2, mode)
          ELSE real_to_fp(r)
          ENDIF

    fp_op_x(op,fin1,(fin2:{fin| div?(op) => not zero?(fin)}),mode): 
      [fp_num, exception]
             = 
      LET rp = fp_round_x(apply(op, fin1, fin2), mode)
        IN IF proj_1(rp) = 0 THEN (signed_zero(op, fin1, fin2, mode),proj_2(rp))
          ELSE real_to_fp_x(rp)
          ENDIF

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



    END arithmetic_ops

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

  % Subtype TCC generated (at line 25, column 26) for  value(fin2)
      % expected type  nznum
  apply_TCC1: OBLIGATION
    FORALL (op: fp_ops, fin1: (finite?[b, p, E_max, E_min]),
            (fin2: {fin | div?(op) => NOT zero?[b, p, E_max, E_min](fin)})):
      op = div IMPLIES value[b, p, E_max, E_min](fin2) /= 0;


body:
  IEEE_854_fp_int
    [b,p:above(1),
     alpha,E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY


    BEGIN

    importing IEEE_854_values[b,p,E_max,E_min],
              real_to_fp[b,p,alpha,E_max,E_min],
              round

    fin, fin1: var (finite?)

    mode: var rounding_mode

    fp_to_int(fin,mode):integer = round(value(fin),mode)

    fp_to_int_fp(fin,mode): fp_num = 
         real_to_fp(round(value(fin),mode))


  %  large_value: lemma  
  %      abs(value(fin)) >= b^p => integer?(value(fin))
  %
  %  fp_to_int_fp_finite: lemma
  %       E_max>p => finite?(real_to_fp(round(value(fin),mode)))

    END IEEE_854_fp_int


body:
  IEEE_854_remainder
    [b,p:above(1),
     alpha,E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY

    BEGIN

    IMPORTING IEEE_854_values[b,p,E_max,E_min],
              real_to_fp[b,p,alpha,E_max,E_min],
              round

    fin, fin1, fin2: var (finite?)

    REM(fin1, (fin2:{fin|not zero?(fin)})): fp_num =
       let x = value(fin1),
           y = value(fin2) in
       if (x - y * round_to_even(x/y)) = 0
          then finite(sign(fin1),E_min,d_zero)
          else real_to_fp(x - y * round_to_even(x/y))
       endif

    END IEEE_854_remainder

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

  % Subtype TCC generated (at line 17, column 33) for  y
      % expected type  nznum
  REM_TCC1: OBLIGATION
    FORALL (fin1: (finite?[b, p, E_max, E_min]),
            (fin2: {fin | NOT zero?[b, p, E_max, E_min](fin)}), x: real):
      x = value(fin1) IMPLIES
       (FORALL (y: real): y = value(fin2) IMPLIES y /= 0);

  % Subtype TCC generated (at line 18, column 31) for  E_min
      % expected type  Exponent[b, p, E_max, E_min]
  REM_TCC2: OBLIGATION
    FORALL (fin1: (finite?[b, p, E_max, E_min]),
            (fin2: {fin | NOT zero?[b, p, E_max, E_min](fin)}), x: real):
      x = value(fin1) IMPLIES
       (FORALL (y: real):
          (x - y * round_to_even(x / y)) = 0 AND y = value(fin2) IMPLIES
           E_min <= E_min & E_min <= E_max);


body:
  IEEE_854_defs 
    [b,p:above(1),
     alpha,E_max:integer, 
     E_min:{i:integer|E_max>i}]: THEORY

    BEGIN

    IMPORTING IEEE_854_values[b,p,E_max,E_min],
              IEEE_854_remainder[b,p,alpha,E_max,E_min],
              IEEE_854_fp_int[b,p,alpha,E_max,E_min],
              arithmetic_ops[b,p,alpha,E_max,E_min],
              comparison1[b,p,E_max,E_min],
              infinity_arithmetic[b,p,E_max,E_min],
              NaN_ops[b,p,E_max,E_min],
              enumerated_type_defs

    IMPORTING reals@sqrt

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % basic instruction schemata, ignoring exceptions for now
  %  These functions are listed in section 5.1 of IEEE-854

    fp,fp1,fp2: var fp_num
    mode: var rounding_mode

  % Addition operator
    fp_add(fp1, fp2, mode): fp_num =
      IF finite?(fp1) & finite?(fp2)
        THEN fp_op(add, fp1, fp2, mode)
      ELSIF NaN?(fp1) OR NaN?(fp2) THEN fp_nan(add, fp1, fp2)
      ELSE fp_add_inf(fp1, fp2)
      ENDIF

  % Addition operator with exceptions
    fp_add_x(fp1, fp2, mode): [fp_num, exception] =
      IF finite?(fp1) & finite?(fp2)
        THEN fp_op_x(add, fp1, fp2, mode)
      ELSIF NaN?(fp1) OR NaN?(fp2) THEN fp_nan_x(add, fp1, fp2)
      ELSE fp_add_inf_x(fp1, fp2)
      ENDIF

    fp_add_x_correct: lemma fp_add(fp1,fp2,mode) = proj_1(fp_add_x(fp1,fp2,mode))

  % Subtraction Operator
    fp_sub(fp1, fp2, mode): fp_num =
      IF finite?(fp1) & finite?(fp2)
        THEN fp_op(sub, fp1, fp2, mode)
      ELSIF NaN?(fp1) OR NaN?(fp2) THEN fp_nan(sub, fp1, fp2)
      ELSE fp_sub_inf(fp1, fp2)
      ENDIF

  % Subtraction Operator with exceptions
    fp_sub_x(fp1, fp2, mode): [fp_num, exception] =
      IF finite?(fp1) & finite?(fp2)
        THEN fp_op_x(sub, fp1, fp2, mode)
      ELSIF NaN?(fp1) OR NaN?(fp2) THEN fp_nan_x(sub, fp1, fp2)
      ELSE fp_sub_inf_x(fp1, fp2)
      ENDIF

  % Excluding NaN operands, we should be able to prove a - b = a + (-b)
  %  independent of the rounding mode  
    fsub_alt_def: LEMMA
          NOT (NaN?(fp1) OR NaN?(fp2))
            => fp_sub(fp1, fp2, mode) = fp_add(fp1, toggle_sign(fp2), mode)

  % Multiplication
    fp_mul(fp1, fp2, mode): fp_num =
      IF finite?(fp1) & finite?(fp2)
        THEN fp_op(mult, fp1, fp2, mode)
      ELSIF NaN?(fp1) OR NaN?(fp2) THEN fp_nan(mult, fp1, fp2)
      ELSE fp_mul_inf(fp1, fp2)
      ENDIF
    
  % Division
    fp_div(fp1, fp2, mode): fp_num =
      IF finite?(fp1) & finite?(fp2)
        THEN IF zero?(fp2)
          THEN IF zero?(fp1)
            THEN invalid
          ELSE infinite(mult_sign(fp1, fp2))
          ENDIF
        ELSE fp_op(div, fp1, fp2, mode)
        ENDIF
      ELSIF NaN?(fp1) OR NaN?(fp2) THEN fp_nan(div, fp1, fp2)
      ELSE fp_div_inf(fp1, fp2)
      ENDIF

  % Remainder (independent of rounding mode)
    fp_rem(fp1, fp2): fp_num =
      IF finite?(fp1) & finite?(fp2)
        THEN IF zero?(fp2)
          THEN invalid
        ELSE REM(fp1, fp2)
        ENDIF
      ELSIF NaN?(fp1) OR NaN?(fp2) THEN fp_nan(div, fp1, fp2)
      ELSIF infinite?(fp1) THEN invalid
      ELSE fp1
      ENDIF

  % Square root

    fp_sqrt(fp, mode): fp_num =
      IF NaN?(fp) THEN NaN_sqrt(fp)
      ELSIF zero?(fp) THEN fp
      ELSIF finite?(fp)
        THEN IF sign(fp) = pos
          THEN real_to_fp(fp_round(sqrt(value(fp)), mode))
        ELSE invalid
        ENDIF
      ELSIF i_sign(fp) = pos THEN fp
      ELSE invalid
      ENDIF

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  %% bug test spec, won't typecheck, 
  %% cannot determine full theory instance
  %  fp_id(fp):fp_num =
  %    cases fp of
  %      finite(s,e,d): fp,
  %      infinite(s): fp,
  %      NaN(sig,data):fp
  %    endcases
    
    END IEEE_854_defs

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

  % Subtype TCC generated (at line 31, column 20) for  fp1
      % expected type  {fp | finite?(fp) OR infinite?(fp)}
  fp_add_TCC1: OBLIGATION
    FORALL (fp1: fp_num[b, p, E_max, E_min],
            fp2: fp_num[b, p, E_max, E_min]):
      NOT NaN?(fp1) AND NOT NaN?(fp2) AND NOT (finite?(fp1) & finite?(fp2))
       IMPLIES
       finite?[b, p, E_max, E_min](fp1) OR infinite?[b, p, E_max, E_min](fp1);

  % Subtype TCC generated (at line 31, column 25) for  fp2
      % expected type  {num | infinite?(fp1) OR infinite?(num)}
  fp_add_TCC2: OBLIGATION
    FORALL (fp1: fp_num[b, p, E_max, E_min],
            fp2: fp_num[b, p, E_max, E_min]):
      NOT NaN?(fp1) AND NOT NaN?(fp2) AND NOT (finite?(fp1) & finite?(fp2))
       IMPLIES
       (finite?[b, p, E_max, E_min](fp2) OR
         infinite?[b, p, E_max, E_min](fp2))
        AND
        (infinite?[b, p, E_max, E_min](fp1) OR
          infinite?[b, p, E_max, E_min](fp2));

  % Subtype TCC generated (at line 80, column 32) for  fp1
      % expected type  {fp | finite?(fp) OR infinite?(fp)}
  fp_div_TCC1: OBLIGATION
    FORALL (fp1: fp_num[b, p, E_max, E_min],
            fp2: fp_num[b, p, E_max, E_min]):
      NOT zero?(fp1) AND zero?(fp2) AND finite?(fp1) AND finite?(fp2) IMPLIES
       finite?[b, p, E_max, E_min](fp1) OR infinite?[b, p, E_max, E_min](fp1);

  % Subtype TCC generated (at line 80, column 37) for  fp2
      % expected type  {fp | finite?(fp) OR infinite?(fp)}
  fp_div_TCC2: OBLIGATION
    FORALL (fp1: fp_num[b, p, E_max, E_min],
            fp2: fp_num[b, p, E_max, E_min]):
      NOT zero?(fp1) AND zero?(fp2) AND finite?(fp1) AND finite?(fp2) IMPLIES
       finite?[b, p, E_max, E_min](fp2) OR infinite?[b, p, E_max, E_min](fp2);

  % Subtype TCC generated (at line 107, column 38) for  value(fp)
      % expected type  nnx: nonneg_real
  fp_sqrt_TCC1: OBLIGATION
    FORALL (fp: fp_num[b, p, E_max, E_min]):
      sign(fp) = pos AND finite?(fp) AND NOT zero?(fp) AND NOT NaN?(fp)
       IMPLIES value[b, p, E_max, E_min](fp) >= 0;

  % Subtype TCC generated (at line 110, column 17) for  fp
      % expected type  (infinite?[b, p, E_max, E_min])
  fp_sqrt_TCC2: OBLIGATION
    FORALL (fp: fp_num[b, p, E_max, E_min]):
      NOT finite?(fp) AND NOT zero?(fp) AND NOT NaN?(fp) IMPLIES
       infinite?[b, p, E_max, E_min](fp);


body:
  IEEE_854 [b,p:above(1),alpha,E_max,E_min:integer]: THEORY
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  This theory defines the representation and basic operations for 
  %    arbitrary precision IEEE-854 floating point numbers.  It also 
  %    introduces the required assumption for arbitrary precision
  %    IEEE-854 floating point numbers.
  %
  %  Example use:
  %
  %   To define IEEE-754 single-precision operations use the following
  %     importing:
  %   
  %     IMPORTING IEEE_854[2,24,192,127,-126]
  %
  %  Author: 
  %  Paul S. Miner                | email: p.s.miner@larc.nasa.gov
  %  1 South Wright St. / MS 130  |   fax: (757) 864-4234
  %  NASA Langley Research Center | phone: (757) 864-6201
  %  Hampton, Virginia 23681      |
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    BEGIN

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  Representation assumptions (from section 3.1 of IEEE-854)
    ASSUMING

      Base_values: ASSUMPTION b=2 or b=10

      Exponent_range: ASSUMPTION (E_max - E_min)/p > 5 %10 % may be 5

      Significand_size: ASSUMPTION b^(p-1)>=10^5 

  %  Uncomment the following, if you wish to include the suggestion
  %   about exponent balance .

      E_balance: ASSUMPTION
          IF b < 4 THEN E_max + E_min = 1 ELSE E_max + E_min = 0 ENDIF

  % Although not mentioned explicitly as a parameter.  We need the following 
  % value for adjusting the exponent of overflow and underflow results when the 
  % corresponing traps are enabled.

  % Section 7.3 of IEEE-854 states: `` The exponent adjustment $\alpha$
  % for a precision shall be chosen to be approximately 
  % $3\times(\Emax - \Emin)/4$ for that precision and should be
  % divisible by twelve.''

      Exponent_Adjustment: ASSUMPTION
           abs(alpha - (3 * (E_max - E_min) / 4)) <= 6 
            & integer?(alpha / 12) 

    ENDASSUMING
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Assumption about balanced exponents as given in standard
  %  (comment out if you do not desire this constraint)

    Exponent_balance: LEMMA b^(E_max+E_min) <4 & 4<=b^(E_max+E_min+1)
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  A useful consequence of the assumptions

    E_max_gt_E_min: lemma E_max > E_min

    AUTO_REWRITE+ E_max_gt_E_min

  % An illustrative example for HUG95 paper
    HUG_example: lemma 5*p < E_max-E_min  => E_min < E_max

  % Simple examples showing how importing tccs may be automatically proven
    ex754_2:lemma (127 - (-126))/24 > 5

    ex754_3: lemma 2^23 >=10^5

  % Some beneficial consequences of assumption E_balance
  %  (These cannot be proven without E_balance)

    E_min_neg: lemma E_min<0

    E_max_pos: lemma E_max>0

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    Importing IEEE_854_defs[b,p,alpha,E_max,E_min]

    

    END IEEE_854

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

  % Subtype TCC generated (at line 60, column 29) for  (E_max + E_min)
      % expected type  {i: int | b /= 0 OR i >= 0}
  Exponent_balance_TCC1: OBLIGATION b /= 0 OR (E_max + E_min) >= 0;

  % Subtype TCC generated (at line 60, column 53) for  (E_max + E_min + 1)
      % expected type  {i: int | b /= 0 OR i >= 0}
  Exponent_balance_TCC2: OBLIGATION
    b ^ (E_max + E_min) < 4 IMPLIES b /= 0 OR (E_max + E_min + 1) >= 0;

  % Subtype TCC generated (at line 87, column 42) for  E_min
      % expected type  {i: integer | E_max > i}
  IMP_IEEE_854_defs_TCC1: OBLIGATION E_max > E_min;


body:
  IEEE_link[radix, p: above(1), alpha, E_max, E_min: integer]: THEORY
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  This theory defines the equivalence between IEEE floats and
  %  bounded floats and of their respective rounding functions. 
  %  Author: 
  %  Sylvie Boldo (ENS-Lyon)
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   BEGIN
    ASSUMING
     Base_values: ASSUMPTION radix = 2 OR radix = 10
     Exponent_range: ASSUMPTION (E_max - E_min) / p > 5
     Significand_size: ASSUMPTION radix ^ (p - 1) >= 10 ^ 5
     E_balance: ASSUMPTION
       IF radix < 4 THEN E_max + E_min = 1 ELSE E_max + E_min = 0 ENDIF
     Exponent_Adjustment: ASSUMPTION
       abs(alpha - (3 * (E_max - E_min) / 4)) <= 6 & integer?(alpha / 12)
    ENDASSUMING

    IMPORTING ints@mod_lems
    IMPORTING IEEE_854[radix, p, alpha, E_max, E_min], float[radix]

    ieee,ieee2 : VAR (finite?)
    f          : VAR float
    r,z1,z2    : VAR real
    mode       : VAR rounding_mode

    b: Format = (# Prec := p, dExp := -E_min + p - 1 #)

    IEEE_to_float(ieee): {x: (Fbounded?(b)) | 
      value(ieee) = FtoR(x):: real AND abs(FtoR(x)) < radix^(E_max+1)} =
        (# Fnum
             := (-1) ^ sign(ieee) * radix ^ (p - 1) *
                 Sum(p, value_digit(d(ieee))),
           Fexp := Exp(ieee) + 1 - p #)

    float_to_IEEE(f: (Fcanonic?(b)) | abs(FtoR(f)) < radix^(E_max+1)):
          {x: (finite?) | FtoR(f) = value(x)} =
        finite(sign_of(Fnum(f)), Fexp(f) + p - 1,
               (LAMBDA (i: below(p)):
                  mod(floor(radix ^ (i+1-p) * abs(Fnum(f))), radix)))


  value_nonzero_bis: lemma Fbounded?(b)(f) => abs(FtoR(f)) < radix^(E_max+1)
     => not FtoR(f)=0 => min_pos <= abs(FtoR(f)) & abs(FtoR(f)) <= max_pos

  Sterbenz_bis : lemma
     value(ieee)/2 <= value(ieee2) =>  value(ieee2) <= 2*value(ieee) 
       =>  (exists (s:(finite?)): value(s)=value(ieee2)-value(ieee))


  Roundings_eq_pos: lemma
    NOT trap_enabled?(underflow(FALSE)) =>
     0 <= r =>
      abs(r) < radix ^ (E_max + 1) =>
       fp_round(r, to_neg) = FtoR[radix](RND_Min(b)(r))

  Roundings_eq_neg: lemma
    NOT trap_enabled?(underflow(FALSE)) =>
      0 < r =>
      abs(r) <= max_pos =>
       fp_round(r, to_pos) = FtoR[radix](RND_Max(b)(r))

  fp_round_opp_aux: lemma NOT r=0 => round_scaled(r, to_neg)=-round_scaled(-r, to_pos)

  fp_round_opp: lemma NOT r=0 => fp_round(r, to_neg)=-fp_round(-r, to_pos);


  RND_EClosest2: lemma FtoR(RND_EClosest(b)(r))= 
    FtoR(if    r-FtoR(RND_Min(b)(r)) < FtoR(RND_Max(b)(r))-r then RND_Min(b)(r)
    elsif FtoR(RND_Max(b)(r))-r < r-FtoR(RND_Min(b)(r)) then RND_Max(b)(r)
    elsif FtoR(RND_Min(b)(r))=FtoR(RND_Max(b)(r))::real then RND_Min(b)(r)
    else  (# Fnum:= 2 * floor(ceiling(r*radix^(-Fexp(RND_aux(b)(abs(r))))) / 2), 
             Fexp:= Fexp(RND_aux(b)(abs(r))) #)
   endif)::real

  Roundings_eq_1: lemma
    NOT trap_enabled?(underflow(FALSE)) =>
       max_neg <= r => r < radix ^ (E_max + 1) =>
       fp_round(r, to_neg) = FtoR[radix](RND_Min(b)(r))

  Roundings_eq_2: lemma
    NOT trap_enabled?(underflow(FALSE)) =>
      - radix ^ (E_max + 1) < r => r <= max_pos =>
       fp_round(r, to_pos) = FtoR[radix](RND_Max(b)(r))

  Roundings_eq_3: lemma
    NOT trap_enabled?(underflow(FALSE)) =>
      abs(r) < radix ^ (E_max + 1) - (1 / 2) * radix ^ (E_max + 1 - p) => 
        fp_round(r, to_nearest) = FtoR[radix](RND_EClosest(b)(r))

  Roundings_eq_4: lemma
    NOT trap_enabled?(underflow(FALSE)) =>
      abs(r) < radix ^ (E_max + 1) =>
        fp_round(r, to_zero) = if 0 <= r then FtoR[radix](RND_Min(b)(r))
                                         else FtoR[radix](RND_Max(b)(r))
                                         endif

  RoundedModeNonDecreasing_bis : lemma
     NOT trap_enabled?(underflow(FALSE)) =>
     z1 <= z2 => abs(z1) <= max_pos => abs(z2) <= max_pos =>
         fp_round(z1, mode) <= fp_round(z2, mode)



   END IEEE_link

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

  % Assuming TCC generated (at line 20, column 12) for
      % IEEE_854[radix, p, alpha, E_max, E_min]
      % generated from assumption IEEE_854.Base_values
  IMP_IEEE_854_TCC1: OBLIGATION radix = 2 OR radix = 10;

  % Assuming TCC generated (at line 20, column 12) for
      % IEEE_854[radix, p, alpha, E_max, E_min]
      % generated from assumption IEEE_854.Exponent_range
  IMP_IEEE_854_TCC2: OBLIGATION (E_max - E_min) / p > 5;

  % Assuming TCC generated (at line 20, column 12) for
      % IEEE_854[radix, p, alpha, E_max, E_min]
      % generated from assumption IEEE_854.Significand_size
  IMP_IEEE_854_TCC3: OBLIGATION radix ^ (p - 1) >= 10 ^ 5;

  % Assuming TCC generated (at line 20, column 12) for
      % IEEE_854[radix, p, alpha, E_max, E_min]
      % generated from assumption IEEE_854.E_balance
  IMP_IEEE_854_TCC4: OBLIGATION
    IF radix < 4 THEN E_max + E_min = 1 ELSE E_max + E_min = 0 ENDIF;

  % Assuming TCC generated (at line 20, column 12) for
      % IEEE_854[radix, p, alpha, E_max, E_min]
      % generated from assumption IEEE_854.Exponent_Adjustment
  IMP_IEEE_854_TCC5: OBLIGATION
    abs(alpha - (3 * (E_max - E_min) / 4)) <= 6 & integer?(alpha / 12);

  % Subtype TCC generated (at line 27, column 36) for  -E_min + p - 1
      % expected type  nat
  b_TCC1: OBLIGATION -E_min + p - 1 >= 0;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  IEEE_to_float_TCC1: OBLIGATION
    FORALL (x: (Fbounded?[radix](b))): E_max > E_min;

  % Subtype TCC generated (at line 30, column 59) for  (E_max + 1)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  IEEE_to_float_TCC2: OBLIGATION
    FORALL (ieee, x: (Fbounded?[radix](b))):
      value(ieee) = FtoR(x) IMPLIES radix /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  IEEE_to_float_TCC3: OBLIGATION
    FORALL (ieee: (finite?[radix, p, E_max, E_min])): E_max > E_min;

  % Subtype TCC generated (at line 32, column 14) for
      % (-1) ^ sign(ieee) * radix ^ (p - 1) * Sum(p, value_digit(d(ieee)))
      % expected type  int
  IEEE_to_float_TCC4: OBLIGATION
    FORALL (ieee: (finite?[radix, p, E_max, E_min])):
      rational_pred((-1) ^ sign[radix, p, E_max, E_min](ieee) *
                     radix ^ (p - 1)
                     *
                     Sum(p,
                         value_digit[radix, p, E_max, E_min]
                             (d[radix, p, E_max, E_min](ieee))))
       AND
       integer_pred((-1) ^ sign[radix, p, E_max, E_min](ieee) *
                     radix ^ (p - 1)
                     *
                     Sum(p,
                         value_digit[radix, p, E_max, E_min]
                             (d[radix, p, E_max, E_min](ieee))));

  % Subtype TCC generated (at line 31, column 6) for
      % (# Fnum
      %      := (-1) ^ sign(ieee) * radix ^ (p - 1) *
      %          Sum(p, value_digit(d(ieee))),
      %    Fexp := Exp(ieee) + 1 - p #)
      % expected type  {x: (Fbounded?(b)) |
                     %          value(ieee) = FtoR(x) AND
                     %           abs(FtoR(x)) < radix ^ (1 + E_max)}
  IEEE_to_float_TCC5: OBLIGATION
    FORALL (ieee: (finite?[radix, p, E_max, E_min])):
      Fbounded?[radix]
          (b)
          ((# Fnum
                := (-1) ^ sign[radix, p, E_max, E_min](ieee) *
                    radix ^ (p - 1)
                    *
                    Sum(p,
                        value_digit[radix, p, E_max, E_min]
                            (d[radix, p, E_max, E_min](ieee))),
              Fexp := Exp[radix, p, E_max, E_min](ieee) + 1 - p #))
       AND
       value[radix, p, E_max, E_min](ieee) =
        FtoR[radix]
            ((# Fnum
                  := (-1) ^ sign[radix, p, E_max, E_min](ieee) *
                      radix ^ (p - 1)
                      *
                      Sum(p,
                          value_digit[radix, p, E_max, E_min]
                              (d[radix, p, E_max, E_min](ieee))),
                Fexp := Exp[radix, p, E_max, E_min](ieee) + 1 - p #))
        AND
        abs(FtoR[radix]
                ((# Fnum
                      := (-1) ^ sign[radix, p, E_max, E_min](ieee) *
                          radix ^ (p - 1)
                          *
                          Sum(p,
                              value_digit[radix, p, E_max, E_min]
                                  (d[radix, p, E_max, E_min](ieee))),
                    Fexp := Exp[radix, p, E_max, E_min](ieee) + 1 - p #)))
         < radix ^ (1 + E_max);

  % Subtype TCC generated (at line 36, column 58) for  (E_max + 1)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  float_to_IEEE_TCC1: OBLIGATION
    FORALL (f: (Fcanonic?[radix](b))): radix /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 38, column 31) for  Fexp(f) + p - 1
      % expected type  Exponent[radix, p, E_max, E_min]
  float_to_IEEE_TCC2: OBLIGATION
    FORALL (f: (Fcanonic?[radix](b))
                | abs(FtoR[radix](f)) < radix ^ (E_max + 1)):
      E_min <= Fexp(f) + p - 1 & Fexp(f) + p - 1 <= E_max;

  % Subtype TCC generated (at line 40, column 35) for  (i + 1 - p)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  float_to_IEEE_TCC3: OBLIGATION
    FORALL (f: (Fcanonic?[radix](b))
                | abs(FtoR[radix](f)) < radix ^ (E_max + 1),
            i: below(p)):
      radix /= 0 OR (i + 1 - p) >= 0;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  float_to_IEEE_TCC4: OBLIGATION
    FORALL (f: (Fcanonic?[radix](b))
                | abs(FtoR[radix](f)) < radix ^ (E_max + 1)):
      E_max > E_min;

  % Subtype TCC generated (at line 38, column 6) for
      % finite(sign_of(Fnum(f)), Fexp(f) + p - 1,
      %        (LAMBDA (i: below(p)):
      %           mod(floor(radix ^ (i + 1 - p) * abs(Fnum(f))), radix)))
      % expected type  {x: (finite?) | FtoR(f) = value(x)}
  float_to_IEEE_TCC5: OBLIGATION
    FORALL (f: (Fcanonic?[radix](b))
                | abs(FtoR[radix](f)) < radix ^ (E_max + 1)):
      FtoR[radix](f) =
       value[radix, p, E_max, E_min]
           (finite[radix, p, E_max, E_min]
                (sign_of[radix, p](Fnum(f)), Fexp(f) + p - 1,
                 LAMBDA (i: below(p)):
                   mod(floor(radix ^ (i + 1 - p) * abs(Fnum(f))), radix)));

  % Subtype TCC generated (at line 43, column 66) for  (E_max + 1)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  value_nonzero_bis_TCC1: OBLIGATION
    FORALL (f: float[radix]):
      Fbounded?(b)(f) IMPLIES radix /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  value_nonzero_bis_TCC2: OBLIGATION
    FORALL (f: float[radix]):
      Fbounded?(b)(f) AND
       abs(FtoR(f)) < radix ^ (E_max + 1) AND NOT FtoR(f) = 0
       IMPLIES E_max > E_min;

  % Subtype TCC generated (at line 54, column 22) for  (E_max + 1)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Roundings_eq_pos_TCC1: OBLIGATION
    FORALL (r: real):
      NOT trap_enabled?(underflow(FALSE)) AND 0 <= r IMPLIES
       radix /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  Roundings_eq_pos_TCC2: OBLIGATION
    FORALL (r: real):
      NOT trap_enabled?(underflow(FALSE)) AND
       0 <= r AND abs(r) < radix ^ (E_max + 1)
       IMPLIES E_max > E_min;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  Roundings_eq_neg_TCC1: OBLIGATION
    FORALL (r: real):
      NOT trap_enabled?(underflow(FALSE)) AND 0 < r IMPLIES E_max > E_min;

  % Subtype TCC generated (at line 63, column 48) for  r
      % expected type  nzreal
  fp_round_opp_aux_TCC1: OBLIGATION
    FORALL (r: real): NOT r = 0 IMPLIES r /= 0;

  % Subtype TCC generated (at line 63, column 73) for  -r
      % expected type  nzreal
  fp_round_opp_aux_TCC2: OBLIGATION
    FORALL (r: real): NOT r = 0 IMPLIES -r /= 0;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  fp_round_opp_TCC1: OBLIGATION
    FORALL (r: real): NOT r = 0 IMPLIES E_max > E_min;

  % Subtype TCC generated (at line 72, column 45) for
      % (-Fexp(RND_aux(b)(abs(r))))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  RND_EClosest2_TCC1: OBLIGATION
    FORALL (r: real):
      NOT r - FtoR(RND_Min(b)(r)) < FtoR(RND_Max(b)(r)) - r AND
       NOT FtoR(RND_Max(b)(r)) - r < r - FtoR(RND_Min(b)(r)) AND
        NOT FtoR(RND_Min(b)(r)) = FtoR(RND_Max(b)(r)):: real
       IMPLIES radix /= 0 OR (-Fexp(RND_aux[radix](b)(abs(r)))) >= 0;

  % Subtype TCC generated (at line 78, column 34) for  (E_max + 1)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Roundings_eq_1_TCC1: OBLIGATION
    FORALL (r: real):
      NOT trap_enabled?(underflow(FALSE)) AND max_neg <= r IMPLIES
       radix /= 0 OR (E_max + 1) >= 0;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  Roundings_eq_1_TCC2: OBLIGATION
    FORALL (r: real):
      NOT trap_enabled?(underflow(FALSE)) AND
       max_neg <= r AND r < radix ^ (E_max + 1)
       IMPLIES E_max > E_min;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  Roundings_eq_2_TCC1: OBLIGATION
    FORALL (r: real):
      NOT trap_enabled?(underflow(FALSE)) AND -radix ^ (E_max + 1) < r
       IMPLIES E_max > E_min;

  % Subtype TCC generated (at line 88, column 54) for  (E_max + 1 - p)
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Roundings_eq_3_TCC1: OBLIGATION
    NOT trap_enabled?(underflow(FALSE)) IMPLIES
     radix /= 0 OR (E_max + 1 - p) >= 0;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  Roundings_eq_3_TCC2: OBLIGATION
    FORALL (r: real):
      NOT trap_enabled?(underflow(FALSE)) AND
       abs(r) < radix ^ (E_max + 1) - (1 / 2) * radix ^ (E_max + 1 - p)
       IMPLIES E_max > E_min;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  Roundings_eq_4_TCC1: OBLIGATION
    FORALL (r: real):
      NOT trap_enabled?(underflow(FALSE)) AND abs(r) < radix ^ (E_max + 1)
       IMPLIES E_max > E_min;

  % Subtype TCC generated (at line 20, column 45) for  E_min
      % expected type  {i: integer | E_max > i}
  RoundedModeNonDecreasing_bis_TCC1: OBLIGATION
    FORALL (z1, z2: real):
      NOT trap_enabled?(underflow(FALSE)) AND z1 <= z2 IMPLIES E_max > E_min;


body:
  axpy[radix:above(1), (IMPORTING float[radix]) b:Format]: THEORY
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  This theory defines a faithful computation of  a*x + y, where
  %  a,x, and y are floating point numbers.
  %  Author: 
  %  Sylvie Boldo (ENS-Lyon)
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  BEGIN


  FcanonicBounded2: JUDGEMENT {x:float | Fcanonic?(b)(x)} SUBTYPE_OF {x:float | Fbounded?(b)(x)}


  MinOrMax?(r:real,f:(Fbounded?(b))):bool=isMin?(b)(r,f) OR isMax?(b)(r,f)
  Fless(f:float):float= if    0 < FtoR(f) then Fpred(b)(f) 
  		      elsif FtoR(f) < 0 then Fsucc(b)(f)
                        else  f endif

  % Variables and lemmas

  f,p,q       : VAR float
  a,x,y,t,u   : VAR {x:float | Fcanonic?(b)(x)}
  a1,x1,y1,z  : VAR real
  n           : VAR nat

  % MinOrMax properties
  MinOrMax_Rlt : lemma Fbounded?(b)(f) => MinOrMax?(z,f) => abs(FtoR(f)-z) < Fulp(b)(f)

  MinOrMax_Fopp : lemma Fbounded?(b)(f) =>MinOrMax?(z,f) => MinOrMax?(-z,Fopp(f))

  MinOrMax1 : lemma Fcanonic?(b)(f) => 0 < FtoR(f) 
       => abs(FtoR(f)-z) < Fulp(b)(Fpred(b)(f)) => MinOrMax?(z,f)

  MinOrMax2 : lemma Fcanonic?(b)(f) => 0 < FtoR(f) 
       => abs(FtoR(f)-z) < Fulp(b)(f) => FtoR(f) <= z => MinOrMax?(z,f)

  MinOrMax3 : lemma Fcanonic?(b)(f) => 0 = FtoR(f) 
       => abs(FtoR(f)-z) < Fulp(b)(f) => MinOrMax?(z,f)

  % Links between a real and its rounding
  RoundLe : lemma Fcanonic?(b)(f) => NOT FtoR(f)=0 => Closest?(b)(z,f)
       => abs(FtoR(f)) <= abs(z)/(1-1/(2*abs(Fnum(f))))

  RoundGe : lemma Fcanonic?(b)(f) => NOT FtoR(f)=0 => Closest?(b)(z,f)
       =>  abs(z)/(1+1/(2*abs(Fnum(f)))) <= abs(FtoR(f))

  % Various lemmas
  ExactSum_Near : lemma
    Fbounded?(b)(p) => Fbounded?(b)(q) => Fbounded?(b)(f) => Closest?(b)(FtoR(p)+FtoR(q),f)
      => abs(FtoR(f)-(FtoR(p)+FtoR(q))) < radix^(-dExp(b)) => FtoR(f)=FtoR(p)+FtoR(q)

  Normal_iff : lemma
    Fcanonic?(b)(f) =>
      (Fnormal?(b)(f) IFF radix^(Prec(b)-1-dExp(b)) <= abs(FtoR(f)))


  % Let us go !
  Axpy_aux1 : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
     => abs(FtoR(t)-FtoR(a)*FtoR(x))          <=  Fulp(b)(Fpred(b)(u))/4 
     => abs(y1-FtoR(y)+a1*x1-FtoR(a)*FtoR(x)) <   Fulp(b)(Fpred(b)(u))/4
     => MinOrMax?(y1+a1*x1,u)


  Axpy_aux1_aux1 : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    => Fnormal?(b)(t) => radix*abs(FtoR(t)) <= FtoR(Fpred(b)(u))
    => abs(FtoR(t)-FtoR(a)*FtoR(x))  <=  Fulp(b)(Fpred(b)(u))/4 

  Axpy_aux1_aux2 : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    => Fsubnormal?(b)(t) => 1-dExp(b) <= Fexp(Fpred(b)(u))
    => abs(FtoR(t)-FtoR(a)*FtoR(x)) <=  Fulp(b)(Fpred(b)(u))/4 

  Axpy_aux2 : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    => Fsubnormal?(b)(t) => FtoR(u)=FtoR(t)+FtoR(y)
    => abs(y1-FtoR(y)+a1*x1-FtoR(a)*FtoR(x)) < Fulp(b)(Fpred(b)(u))/4
    => MinOrMax?(y1+a1*x1,u)


  Axpy_aux3 : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    => Fsubnormal?(b)(t) 
    => -dExp(b) = Fexp(Fpred(b)(u)) =>  1-dExp(b) <= Fexp(u)
    => abs(y1-FtoR(y)+a1*x1-FtoR(a)*FtoR(x)) < Fulp(b)(Fpred(b)(u))/4
    => MinOrMax?(y1+a1*x1,u)


  AxpyPos : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    => (Fnormal?(b)(t) => radix*abs(FtoR(t)) <= FtoR(Fpred(b)(u)))
    => abs(y1-FtoR(y)+a1*x1-FtoR(a)*FtoR(x)) < Fulp(b)(Fpred(b)(u))/4
    => MinOrMax?(y1+a1*x1,u)


  Axpy_opt_aux1_aux1 : lemma Fnormal?(b)(t) => Fnormal?(b)(u) => 0 < FtoR(u) 
      => Prec(b) >= 3 => 
     (1+radix*(1+1/(2*abs(Fnum(u))))*(1+1/abs(Fnum(Fpred(b)(u)))))/(1-1/(2*abs(Fnum(t))))
        <= 1+radix+radix^(4-Prec(b))

  Axpy_opt_aux1 : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    =>  Prec(b) >= 3 => Fnormal?(b)(t) 
    => (radix+1+radix^(4-Prec(b)))*abs(FtoR(a)*FtoR(x)) <= abs(FtoR(y))
    =>  radix*abs(FtoR(t)) <= FtoR(Fpred(b)(u))

  Axpy_opt_aux2 : lemma  Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    =>  Prec(b) >= 6 =>  Fnormal?(b)(t) 
    => (radix+1+radix^(4-Prec(b)))*abs(FtoR(a)*FtoR(x)) <= abs(FtoR(y))
    =>  abs(FtoR(y))*radix^(1-Prec(b))/(radix+1) < Fulp(b)(Fpred(b)(u))

  Axpy_opt_aux3 : lemma  Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    =>  Prec(b) >= 3  =>  Fsubnormal?(b)(t) 
    => (radix+1+radix^(4-Prec(b)))*abs(FtoR(a)*FtoR(x)) <= abs(FtoR(y))
    =>  abs(FtoR(y))*radix^(1-Prec(b))/(radix+radix/2) <= Fulp(b)(Fpred(b)(u))


  Axpy_optPos : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 < FtoR(u)
    => Prec(b) >= 6 
    => (radix+1+radix^(4-Prec(b)))*abs(FtoR(a)*FtoR(x)) <= abs(FtoR(y))
    => abs(y1-FtoR(y)+a1*x1-FtoR(a)*FtoR(x)) < abs(FtoR(y))*radix^(1-Prec(b))/(6*radix)
    => MinOrMax?(y1+a1*x1,u)


  Axpy_optZero : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u) => 0 = FtoR(u)
    => (radix+1+radix^(4-Prec(b)))*abs(FtoR(a)*FtoR(x)) <= abs(FtoR(y))
    => abs(y1-FtoR(y)+a1*x1-FtoR(a)*FtoR(x)) < abs(FtoR(y))*radix^(1-Prec(b))/(6*radix)
    => MinOrMax?(y1+a1*x1,u)

  Axpy_opt : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u)
    => Prec(b) >= 6
    => (radix+1+radix^(4-Prec(b)))*abs(FtoR(a)*FtoR(x)) <= abs(FtoR(y))
    => abs(y1-FtoR(y)+a1*x1-FtoR(a)*FtoR(x)) < abs(FtoR(y))*radix^(1-Prec(b))/(6*radix)
    => MinOrMax?(y1+a1*x1,u)

  Axpy_simpl : lemma Closest?(b)(FtoR(a)*FtoR(x),t) => Closest?(b)(FtoR(t)+FtoR(y),u)
    => Prec(b) >= 24 => radix=2 
    => (3+1/100000)*abs(FtoR(a)*FtoR(x)) <= abs(FtoR(y))
    => abs(y1-FtoR(y)+a1*x1-FtoR(a)*FtoR(x)) < abs(FtoR(y))*2^(1-Prec(b))/12
    => MinOrMax?(y1+a1*x1,u)

  END axpy

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

  % Judgement subtype TCC generated (at line 11, column 28) for  x1
      % expected type  {x: float | Fbounded?(b)(x)}
  FcanonicBounded2: OBLIGATION
    FORALL (x1: {x: float | Fcanonic?(b)(x)}): Fbounded?[radix](b)(x1);

  % Subtype TCC generated (at line 29, column 71) for  Fopp(f)
      % expected type  (Fbounded?(b))
  MinOrMax_Fopp_TCC1: OBLIGATION
    FORALL (f: float[radix], z: real):
      Fbounded?(b)(f) AND MinOrMax?(z, f) IMPLIES
       Fbounded?[radix](b)(Fopp[radix](f));

  % Subtype TCC generated (at line 32, column 33) for  Fpred(b)(f)
      % expected type  (Fbounded?(b))
  MinOrMax1_TCC1: OBLIGATION
    FORALL (f: float[radix]):
      Fcanonic?(b)(f) AND 0 < FtoR(f) IMPLIES
       Fbounded?[radix](b)(Fpred[radix](b)(f));

  % Subtype TCC generated (at line 32, column 61) for  f
      % expected type  (Fbounded?(b))
  MinOrMax1_TCC2: OBLIGATION
    FORALL (f: float[radix], z: real):
      Fcanonic?(b)(f) AND
       0 < FtoR(f) AND abs(FtoR(f) - z) < Fulp(b)(Fpred(b)(f))
       IMPLIES Fbounded?[radix](b)(f);

  % Subtype TCC generated (at line 35, column 33) for  f
      % expected type  (Fbounded?(b))
  MinOrMax2_TCC1: OBLIGATION
    FORALL (f: float[radix]):
      Fcanonic?(b)(f) AND 0 < FtoR(f) IMPLIES Fbounded?[radix](b)(f);

  % Subtype TCC generated (at line 38, column 33) for  f
      % expected type  (Fbounded?(b))
  MinOrMax3_TCC1: OBLIGATION
    FORALL (f: float[radix]):
      Fcanonic?(b)(f) AND 0 = FtoR(f) IMPLIES Fbounded?[radix](b)(f);

  % Subtype TCC generated (at line 41, column 66) for  f
      % expected type  (Fbounded?(b))
  RoundLe_TCC1: OBLIGATION
    FORALL (f: float[radix]):
      Fcanonic?(b)(f) AND NOT FtoR(f) = 0 IMPLIES Fbounded?[radix](b)(f);

  % Subtype TCC generated (at line 42, column 37) for  (2 * abs(Fnum(f)))
      % expected type  nznum
  RoundLe_TCC2: OBLIGATION
    FORALL (f: float[radix], z: real):
      Fcanonic?(b)(f) AND NOT FtoR(f) = 0 AND Closest?(b)(z, f) IMPLIES
       (2 * abs(Fnum(f))) /= 0;

  % Subtype TCC generated (at line 42, column 32) for
      % (1 - 1 / (2 * abs(Fnum(f))))
      % expected type  nznum
  RoundLe_TCC3: OBLIGATION
    FORALL (f: float[radix], z: real):
      Fcanonic?(b)(f) AND NOT FtoR(f) = 0 AND Closest?(b)(z, f) IMPLIES
       (1 - 1 / (2 * abs(Fnum(f)))) /= 0;

  % Subtype TCC generated (at line 45, column 17) for
      % (1 + 1 / (2 * abs(Fnum(f))))
      % expected type  nznum
  RoundGe_TCC1: OBLIGATION
    FORALL (f: float[radix], z: real):
      Fcanonic?(b)(f) AND NOT FtoR(f) = 0 AND Closest?(b)(z, f) IMPLIES
       (1 + 1 / (2 * abs(Fnum(f)))) /= 0;

  % Subtype TCC generated (at line 50, column 47) for  (-dExp(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  ExactSum_Near_TCC1: OBLIGATION
    FORALL (f, p, q: float[radix]):
      Fbounded?(b)(p) AND
       Fbounded?(b)(q) AND
        Fbounded?(b)(f) AND Closest?(b)(FtoR(p) + FtoR(q), f)
       IMPLIES radix /= 0 OR (-dExp(b)) >= 0;

  % Subtype TCC generated (at line 54, column 31) for  (Prec(b) - 1 - dExp(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Normal_iff_TCC1: OBLIGATION
    FORALL (f: float[radix]):
      Fcanonic?(b)(f) IMPLIES radix /= 0 OR (Prec(b) - 1 - dExp(b)) >= 0;

  % Subtype TCC generated (at line 59, column 56) for  Fpred(b)(u)
      % expected type  (Fbounded?(b))
  Axpy_aux1_TCC1: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
      Closest?(b)(FtoR(a) * FtoR(x), t) AND
       Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 < FtoR(u)
       IMPLIES Fbounded?[radix](b)(Fpred[radix](b)(u));

  % Subtype TCC generated (at line 93, column 18) for  (2 * abs(Fnum(u)))
      % expected type  nznum
  Axpy_opt_aux1_aux1_TCC1: OBLIGATION
    FORALL (t, u: {x: float | Fcanonic?(b)(x)}):
      Fnormal?(b)(t) AND Fnormal?(b)(u) AND 0 < FtoR(u) AND Prec(b) >= 3
       IMPLIES (2 * abs(Fnum(u))) /= 0;

  % Subtype TCC generated (at line 93, column 40) for  abs(Fnum(Fpred(b)(u)))
      % expected type  nznum
  Axpy_opt_aux1_aux1_TCC2: OBLIGATION
    FORALL (t, u: {x: float | Fcanonic?(b)(x)}):
      Fnormal?(b)(t) AND Fnormal?(b)(u) AND 0 < FtoR(u) AND Prec(b) >= 3
       IMPLIES abs(Fnum(Fpred[radix](b)(u))) /= 0;

  % Subtype TCC generated (at line 93, column 71) for  (2 * abs(Fnum(t)))
      % expected type  nznum
  Axpy_opt_aux1_aux1_TCC3: OBLIGATION
    FORALL (t, u: {x: float | Fcanonic?(b)(x)}):
      Fnormal?(b)(t) AND Fnormal?(b)(u) AND 0 < FtoR(u) AND Prec(b) >= 3
       IMPLIES (2 * abs(Fnum(t))) /= 0;

  % Subtype TCC generated (at line 93, column 66) for
      % (1 - 1 / (2 * abs(Fnum(t))))
      % expected type  nznum
  Axpy_opt_aux1_aux1_TCC4: OBLIGATION
    FORALL (t, u: {x: float | Fcanonic?(b)(x)}):
      Fnormal?(b)(t) AND Fnormal?(b)(u) AND 0 < FtoR(u) AND Prec(b) >= 3
       IMPLIES (1 - 1 / (2 * abs(Fnum(t)))) /= 0;

  % Subtype TCC generated (at line 94, column 24) for  (4 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_opt_aux1_aux1_TCC5: OBLIGATION
    FORALL (t, u: {x: float | Fcanonic?(b)(x)}):
      Fnormal?(b)(t) AND Fnormal?(b)(u) AND 0 < FtoR(u) AND Prec(b) >= 3
       IMPLIES radix /= 0 OR (4 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 98, column 21) for  (4 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_opt_aux1_TCC1: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
           Closest?(b)(FtoR(a) * FtoR(x), t)
       AND Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 < FtoR(u) AND Prec(b) >= 3
       AND Fnormal?(b)(t)
       IMPLIES radix /= 0 OR (4 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 103, column 21) for  (4 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_opt_aux2_TCC1: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
           Closest?(b)(FtoR(a) * FtoR(x), t)
       AND Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 < FtoR(u) AND Prec(b) >= 6
       AND Fnormal?(b)(t)
       IMPLIES radix /= 0 OR (4 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 104, column 26) for  (1 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_opt_aux2_TCC2: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
           Closest?(b)(FtoR(a) * FtoR(x), t)
       AND Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 < FtoR(u) AND Prec(b) >= 6
       AND Fnormal?(b)(t)
       AND (radix + 1 + radix ^ (4 - Prec(b))) * abs(FtoR(a) * FtoR(x)) <=
            abs(FtoR(y))
       IMPLIES radix /= 0 OR (1 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 108, column 21) for  (4 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_opt_aux3_TCC1: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
           Closest?(b)(FtoR(a) * FtoR(x), t)
       AND Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 < FtoR(u) AND Prec(b) >= 3
       AND Fsubnormal?(b)(t)
       IMPLIES radix /= 0 OR (4 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 109, column 26) for  (1 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_opt_aux3_TCC2: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
           Closest?(b)(FtoR(a) * FtoR(x), t)
       AND Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 < FtoR(u) AND Prec(b) >= 3
       AND Fsubnormal?(b)(t)
       AND (radix + 1 + radix ^ (4 - Prec(b))) * abs(FtoR(a) * FtoR(x)) <=
            abs(FtoR(y))
       IMPLIES radix /= 0 OR (1 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 114, column 21) for  (4 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_optPos_TCC1: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
      Closest?(b)(FtoR(a) * FtoR(x), t) AND
       Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 < FtoR(u) AND Prec(b) >= 6
       IMPLIES radix /= 0 OR (4 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 115, column 65) for  (1 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_optPos_TCC2: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
           Closest?(b)(FtoR(a) * FtoR(x), t)
       AND Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 < FtoR(u) AND Prec(b) >= 6
       AND (radix + 1 + radix ^ (4 - Prec(b))) * abs(FtoR(a) * FtoR(x)) <=
            abs(FtoR(y))
       IMPLIES radix /= 0 OR (1 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 120, column 21) for  (4 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_optZero_TCC1: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
      Closest?(b)(FtoR(a) * FtoR(x), t) AND
       Closest?(b)(FtoR(t) + FtoR(y), u) AND 0 = FtoR(u)
       IMPLIES radix /= 0 OR (4 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 121, column 65) for  (1 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_optZero_TCC2: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
      Closest?(b)(FtoR(a) * FtoR(x), t) AND
       Closest?(b)(FtoR(t) + FtoR(y), u) AND
        0 = FtoR(u) AND
         (radix + 1 + radix ^ (4 - Prec(b))) * abs(FtoR(a) * FtoR(x)) <=
          abs(FtoR(y))
       IMPLIES radix /= 0 OR (1 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 126, column 21) for  (4 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_opt_TCC1: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
      Closest?(b)(FtoR(a) * FtoR(x), t) AND
       Closest?(b)(FtoR(t) + FtoR(y), u) AND Prec(b) >= 6
       IMPLIES radix /= 0 OR (4 - Prec(b)) >= 0;

  % Subtype TCC generated (at line 127, column 65) for  (1 - Prec(b))
      % expected type  {i: int | radix /= 0 OR i >= 0}
  Axpy_opt_TCC2: OBLIGATION
    FORALL (a, t, u, x, y: {x: float | Fcanonic?(b)(x)}):
      Closest?(b)(FtoR(a) * FtoR(x), t) AND
       Closest?(b)(FtoR(t) + FtoR(y), u) AND
        Prec(b) >= 6 AND
         (radix + 1 + radix ^ (4 - Prec(b))) * abs(FtoR(a) * FtoR(x)) <=
          abs(FtoR(y))
       IMPLIES radix /= 0 OR (1 - Prec(b)) >= 0;


body:
  %------------------------------------------------------------------------------
  %
  % Graph Theory
  %
  %  Authors:
  %
  %      Jon Sjogren       AFOSR
  %      Ricky W. Butler   NASA Langley
  %
  %  Version 2.1           UPDATED to PVS 2.2: 11/17/98
  %  Version 2.2           cycle_deg, tree_paths extended  12/20/04 
  %  Version 2.3           matroids and mappings added     7/19/2005 
  %  Version 2.4           Jon Sjogren has generalized Menger's theorem
  %                        for k independent paths (not just 2)           7/12/2007
  %                        See k_menger.pvs and menger.pvs
  %
  %
  %  Maintained by:
  %
  %     Rick Butler        NASA Langley Research Center   
  %                        R.W.Butler@larc.nasa.gov
  %
  %  abstract_min          -- abstract definition of min
  %  abstract_max          -- abstract definition of max
  %  circuit_deg           -- degree of circuits
  %  circuits              -- theory of circuits
  %  cycle_deg             -- theorem about degree and existence of cycle
  %  doubletons            -- theory of doubletons used for definition of edge
  %  graphs                -- fundamental definition of a graph
  %  graph_complected      -- unusual definition of connected graph
  %  graph_conn_defs       -- defs of piece, path, and structural connectedness
  %  graph_conn_piece      -- structural connected ==> piece connected
  %  graph_connected       -- all connected defs are equivalent
  %  graph_path_conn       -- path connected ==> structural connected
  %  graph_piece_path      -- piece connected ==> path connected
  %  graph_deg             -- definition of degree
  %  graph_deg_sum         -- theorem relating vertex degree and number of edges
  %  graph_inductions      -- vertex and edge inductions for graphs
  %  graph_ops             -- delete vertex and delete edge operations
  %  ind_paths             -- definition of independent paths
  %  max_subgraphs         -- maximal subgraphs with specified property
  %  max_subtrees          -- maximal subtrees with specified property
  %  min_walk_reduced      -- theorem that minimum walk is reduced
  %  min_walks             -- minimum walk satisfying a property
  %  path_lems             -- some useful lemmas about paths
  %  path_ops              -- deleting vertex and edge operations
  %  paths                 -- fundamental definition and properties about paths
  %  ramsey_new            -- Ramsey's theorem
  %  reduce_walks          -- operation to reduce a walk
  %  sep_set_lems          -- properties of separating sets
  %  sep_sets              -- definition of separating sets
  %  subgraphs             -- generation of subgraphs from vertex sets
  %  subgraphs_from_walk   -- generation of subgraphs from walks
  %  subtrees              -- subtrees of a graph
  %  tree_circ             -- theorem that tree has no circuits
  %  tree_paths            -- theorem that tree has only one path between vertices
  %  trees                 -- fundamental definition of trees
  %  walk_inductions       -- induction on length of a walk
  %  walks                 -- fundamental definition and properties of walks
  %  NEW   
  %    k_menger, 
  %    complem, 
  %    graph_pair, 
  %    mappings
  %    menger              -- menger's theorem now fully general (by Jon Sjogren 2007)
  % 
  %  The FOLLOWING theories are now obsolete:
  %              
  %    old_menger             
  %    h_menger              -- hard menger 
  %    meng_scaff            -- scaffolding for hard menger proof
  %    meng_scaff_defs       -- scaffolding for hard menger proof
  %    meng_scaff_prelude    -- scaffolding for hard menger proof
  %-------------------------------------------------------------------------------
  top: THEORY

  BEGIN

     IMPORTING graphs, 
               graph_deg, 
               graph_deg_sum,  
               walks,
               paths, 
               path_ops,
               path_lems, 
               path_circ,
               circuits, 
               subgraphs, 
               subgraphs_from_walk, 
               graph_ops,
               graph_from_edges,
               max_subgraphs,
               max_subtrees,
               trees,
               tree_circ, 
               subtrees, 
               graph_connected, 
               graph_inductions, 
               walk_inductions,
               ramsey_new,
               min_walk_reduced,  
               reduce_walks,
               menger, 
               tree_paths,         
               circuit_deg,  
  	     cycle_deg,          


  	     abstract_min      ,
  	     abstract_max      ,
  	     doubletons        ,
  	     graph_complected  ,
  	     graph_conn_defs   ,
  	     graph_conn_piece  ,
  	     graph_connected   ,
  	     graph_path_conn   ,
  	     graph_piece_path  ,
  	     graph_inductions  ,
  	     ind_paths         ,
               old_menger        ,  %% obsolete
  	     h_menger          ,  %% obsolete
  	     meng_scaff        ,  %% obsolete
  	     meng_scaff_defs   ,  %% obsolete
  	     meng_scaff_prelude,  %% obsolete
  	     menger            ,
  	     min_walks         ,
  	     sep_set_lems      ,
  	     sep_sets          ,           
  		complem,
  		k_menger,
   	     mantel,              %% Mantel's Theorem (A. Dutle)
               graph_pair,
  	     mappings,
               matroids             %% experimental

  END top


body:
  matroids[T: TYPE]: THEORY
  %------------------------------------------------------------------------------
  %
  % Experimental Theory
  %
  % Author: Jon Sjogren, Rick Butler
  %
  %------------------------------------------------------------------------------

  BEGIN

   IMPORTING  finite_sets@finite_sets_eq[T,T]

    pre_matroid: TYPE = [# elem: finite_set[T],
                           indep: [finite_set[T] -> bool]  #]

    indep_in_elem(M: pre_matroid): bool = (FORALL (A:finite_set[T]): 
                                           indep(M)(A) IMPLIES subset?(A,elem(M)))

    indep_subset(M: pre_matroid): bool = (FORALL (A,B:finite_set[T]): 
                      indep(M)(A) and subset?(B,A) IMPLIES indep(M)(B))

    indep_card(M: pre_matroid): bool = (FORALL (A,B:finite_set[T]):
               indep(M)(A) AND indep(M)(B) AND card(A) < card(B)
                   IMPLIES (Exists (x: T): elem(M)(x) AND A(x) AND NOT B(x)
                                           AND indep(M)(add(x,B))))
   
    Matroid: TYPE = {M: pre_matroid | indep_in_elem(M) AND
                                      indep_subset(M) AND 
                                      indep_card(M)}

    x,y: VAR T

    single(x): finite_set[T] = {t: T | t = x}

    double(x,y): finite_set[T] = {t: T | t = x OR t = y}

    simple?(M: Matroid): bool = (FORALL x: elem(M)(x) IMPLIES
                                           (indep(M)(single(x)) AND 
                                            (FORALL y: x /=y IMPLIES 
                                                    indep(M)(double(x,y)))))
                                 
    Simple_matroid: TYPE = {M: Matroid | simple?(M)}

    A,B: VAR finite_set[T]
    Subsets(A): TYPE = {B: finite_set[T] | subset?(B,A)}

    M1,M2: VAR Matroid

    extend(M1,M2,(f:[(elem(M1)) -> (elem(M2))])):
                            [Subsets(elem(M1)) -> finite_set[T]] =
             (LAMBDA (A: Subsets(elem(M1))): {t: T | (EXISTS (a: (A)): f(a) = t)})

    isomorph(M1,M2): TYPE = {f: [(elem(M1)) -> (elem(M2))] | 
                           bijective?(f) AND
                           (FORALL (A: Subsets(elem(M1))): indep(M1)(A) IFF
                                                indep(M2)(extend(M1,M2,f)(A)))}


  % A circuit is a non-independent set such that when you remove any element,
  % it becomes independent.

    circuit?(M: Matroid, A: finite_set[T]): bool = subset?(A,elem(M))
                                                   AND NOT indep(M)(A) AND 
                                                   (FORALL (x: (elem(M))): A(x) 
                                                      IMPLIES indep(M)(remove(x,A)))

    M: VAR Matroid

    circuit_test: LEMMA circuit?(M,A) IMPLIES (subset?(A,elem(M)) AND
                        NOT indep(M)(A) AND (subset?(B,A) and B /= A 
                    IMPLIES indep(M)(B)))

  circuit_test2: LEMMA  (subset?(A,elem(M)) AND
                        NOT indep(M)(A) AND 
                        FORALL B: (subset?(B,A) AND B /= A IMPLIES indep(M)(B))) 
                           IMPLIES circuit?(M,A)



  End matroids

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

  % Subtype TCC generated (at line 34, column 29) for  {t: T | t = x}
      % expected type  finite_set[T]
  single_TCC1: OBLIGATION FORALL (x: T): is_finite[T]({t: T | t = x});

  % Subtype TCC generated (at line 36, column 31) for  {t: T | t = x OR t = y}
      % expected type  finite_set[T]
  double_TCC1: OBLIGATION
    FORALL (x: T, y: T): is_finite[T]({t: T | t = x OR t = y});

  % Subtype TCC generated (at line 52, column 71) for  a
      % expected type  (elem(M1))
  extend_TCC1: OBLIGATION
    FORALL (M1: Matroid, M2: Matroid, (f: [(elem(M1)) -> (elem(M2))]),
            A: Subsets(elem(M1)), t: T, a: (A)):
      elem(M1)(a);

  % Subtype TCC generated (at line 52, column 43) for
      % {t: T | (EXISTS (a: (A)): f(a) = t)}
      % expected type  finite_set[T]
  extend_TCC2: OBLIGATION
    FORALL (M1: Matroid, M2: Matroid, (f: [(elem(M1)) -> (elem(M2))]),
            A: Subsets(elem(M1))):
      is_finite[T]({t: T | EXISTS (a: (A)): f(a) = t});


body:
  doubletons[T: TYPE]: THEORY

  BEGIN

     x,y,z: VAR T

     dbl(x,y): set[T] = {t: T | t = x OR t = y}

     S: VAR set[T]

     doubleton?(S): bool = (EXISTS x,y: x /= y AND S = dbl(x,y))

     doubleton: TYPE = {S | EXISTS x,y: x /= y AND S = dbl(x,y)}

     Dbl: TYPE = doubleton

     dbl_comm: LEMMA dbl(x,y) = dbl(y,x)

     D: VAR doubleton

     doubleton_irreflexive  : LEMMA NOT doubleton?(dbl(x,x))

     doubleton_nonempty     : LEMMA nonempty?(D)

     doubleton_rest_nonempty: LEMMA nonempty?(rest(D))

     dbl_choose             : LEMMA choose(dbl(x,y)) = x or choose(dbl(x,y)) = y

     dbl_rest_choose        : LEMMA x /= y IMPLIES
                                    (choose(dbl(x,y)) /= choose(rest(dbl(x,y)))) AND 
                                    (choose(rest(dbl(x,y))) = x 
                                        OR choose(rest(dbl(x,y))) = y)

     dbl_to_pair(D) : {(x,y) | D = dbl(x,y)}

     dbl_def        : LEMMA dbl(PROJ_1(dbl_to_pair(D)), PROJ_2(dbl_to_pair(D))) = D

     dbl_in         : LEMMA D = dbl(x,y) IMPLIES D(x) AND D(y)
     
     dbl_not_in     : LEMMA D = dbl(x,y) AND z /= x AND z /= y IMPLIES NOT D(z)

     dbl_to_pair_lem        : LEMMA x /= y IMPLIES
                                     dbl_to_pair(dbl(x,y)) = (x,y) OR
                                     dbl_to_pair(dbl(x,y)) = (y,x) 

     dbl_to_pair_inverse_l  : LEMMA dbl(dbl_to_pair(D)) = D

     dbl_proj               : LEMMA D(PROJ_1(dbl_to_pair(D))) AND
                                    D(PROJ_2(dbl_to_pair(D)))
     v: VAR T
     proj_dbl: LEMMA (PROJ_1(dbl_to_pair(D)) = v OR PROJ_2(dbl_to_pair(D)) = v)
                      IMPLIES D(v)

     dbl_eq: LEMMA dbl(x,y) = dbl(v,z) IMPLIES
                          (x = v AND y = z) OR (x = z AND y = v)

     finite_dbl: LEMMA is_finite(dbl(x,y))

     e: VAR doubleton
     finite_doubleton: LEMMA is_finite(e)

     card_dbl: LEMMA x /= y IMPLIES card(dbl(x,y)) = 2

     JUDGEMENT dbl(x,y) HAS_TYPE finite_set[T]



     AUTO_REWRITE+ doubleton_irreflexive   % NOT doubleton?(dbl(x,x))
     AUTO_REWRITE+ doubleton_nonempty      % nonempty?(D)  
     AUTO_REWRITE+ dbl_def                 % dbl(PROJ_1(dbl_to_pair(D)), 
                                           %     PROJ_2(dbl_to_pair(D))) = D

     AUTO_REWRITE+ dbl_to_pair_inverse_l   % dbl(dbl_to_pair(D)) = D
     AUTO_REWRITE+ dbl_proj                

     AUTO_REWRITE+ finite_dbl
     AUTO_REWRITE+ finite_doubleton

  %  ------------- The following two cause wierd PVS bug -------

     AUTO_REWRITE+ dbl_in                  % D = dbl(x,y) IMPLIES D(x) AND D(y)
     AUTO_REWRITE+ dbl_not_in              % D = dbl(x,y) AND z /= x AND z /= y 





    rev(fs: finseq[T]): finseq[T] = (# length := length(fs),
                                    seq := (LAMBDA (i: below(length(fs))): seq(fs)(length(fs)-1-i))
                               #)
    


  END doubletons

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

  % Subtype TCC generated (at line 27, column 41) for  dbl(x, y)
      % expected type  p: (nonempty?[T])
  dbl_choose_TCC1: OBLIGATION FORALL (x, y: T): nonempty?[T](dbl(x, y));

  % Subtype TCC generated (at line 30, column 62) for  rest(dbl(x, y))
      % expected type  p: (nonempty?[T])
  dbl_rest_choose_TCC1: OBLIGATION
    FORALL (x, y: T): x /= y IMPLIES nonempty?[T](rest[T](dbl(x, y)));

  % Existence TCC generated (at line 34, column 3) for
      % dbl_to_pair(D): {x, y | D = dbl(x, y)}
  dbl_to_pair_TCC1: OBLIGATION
    EXISTS (x1: [D: doubleton -> {x, y | D = dbl(x, y)}]): TRUE;

  % Subtype TCC generated (at line 43, column 47) for  dbl(x, y)
      % expected type  D: doubleton
  dbl_to_pair_lem_TCC1: OBLIGATION
    FORALL (x, y: T):
      x /= y IMPLIES
       (EXISTS (x_1: T), (y_1: T): x_1 /= y_1 AND dbl(x, y) = dbl(x_1, y_1));

  % Subtype TCC generated (at line 62, column 39) for  dbl(x, y)
      % expected type  S: finite_set[T]
  card_dbl_TCC1: OBLIGATION
    FORALL (x, y: T): x /= y IMPLIES is_finite[T](dbl(x, y));

  % Judgement subtype TCC generated (at line 64, column 13) for  dbl(x, y)
      % expected type  finite_set[T]
  dbl_TCC1: OBLIGATION FORALL (x, y): is_finite[T](dbl(x, y));

  % Subtype TCC generated (at line 89, column 81) for  length(fs) - 1 - i
      % expected type  below[fs`length]
  rev_TCC1: OBLIGATION
    FORALL (fs: finseq[T], i: below(length(fs))):
      length(fs) - 1 - i >= 0 AND length(fs) - 1 - i < fs`length;


body:
  graphs[T: TYPE]: THEORY
  %-------------------------------------------------------------------------------
  %
  % Defines:
  %
  %      Graph[T] -- graph over domain T
  %      vert(G)  -- vertices of graph G
  %      edges(G) -- set of edges in a graph G
  %
  %  Authors:
  %
  %      Ricky W. Butler   NASA Langley
  %      Jon Sjogren       AFOSR
  %
  %  Version 1.0           Last modified 12/20/96
  %
  %  Maintained by:
  %
  %     Rick Butler        NASA Langley Research Center   
  %                        R.W.Butler@larc.nasa.gov
  %
  %  NOTE:
  %
  %-------------------------------------------------------------------------------
  BEGIN


    IMPORTING %finite_sets@finite_sets[T], 
              doubletons[T] 
              %finite_sets@finite_sets[doubleton[T]]

    R: VAR PRED[[T, T]]
    x,y,v: VAR T

    pregraph: TYPE = [# vert : finite_set[T],
                        edges: finite_set[doubleton[T]] #]

    graph: TYPE = {g: pregraph | (FORALL (e: doubleton[T]): edges(g)(e) IMPLIES
                                       (FORALL (x: T): e(x) IMPLIES vert(g)(x)))}
   
    e: VAR doubleton[T]
    G: var graph
   
    edg(x,(y:{y:T | y /= x})): doubleton[T] = dbl[T](x,y)

    edge?(G)(x,y): bool = x /= y AND edges(G)(dbl[T](x,y))

    edge?_comm : LEMMA edge?(G)(y, x) IMPLIES edge?(G)(x, y)

    edges_vert      : LEMMA e(x) AND edges(G)(e) IMPLIES
                               (EXISTS y: x /= y AND vert(G)(y) AND e(y))


    other_vert      : LEMMA e(v) AND edges(G)(e)
                           IMPLIES (EXISTS (u: T): u /= v AND vert(G)(u) 
                                                   AND e = dbl[T](u, v))

    edge_has_2_verts: LEMMA x /= v AND e(x) AND e(v)
                                     IMPLIES e = dbl(x,v)

  %To aid in discharging TCCs
   edges_vert_in: LEMMA e = dbl[T](x, y) AND edges(G)(e)
                         IMPLIES vert(G)(x) AND vert(G)(y)

   vert_in: LEMMA edge?(G)(x,y) IMPLIES vert(G)(x) AND vert(G)(y)


  % -------------- size of graphs --------------------

    size(G): nat = card[T](vert(G))

    empty?(G): bool = empty?(vert(G))

    singleton?(G): bool = (size(G) = 1)

    isolated?(G): bool = empty?(edges(G))

    empty?_rew          : LEMMA empty?(G) = (card(vert(G)) = 0)

    edges_of_empty      : LEMMA empty?(G) 
                                   IMPLIES edges(G) = emptyset[doubleton[T]]

    singleton_edges     : LEMMA singleton?(G) IMPLIES  empty?(edges(G))

    edge_in_card_gt_1   : LEMMA edges(G)(e) IMPLIES card(vert(G)) > 1

    not_singleton_2_vert: LEMMA NOT empty?(G) AND NOT singleton?(G) 
                                  IMPLIES (EXISTS (x,y: T): x /= y AND
                                       vert(G)(x) AND vert(G)(y))

    infgraph: TYPE = [# vert : set[T],
                        edges: set[doubleton[T]] #]


    graph?(g: infgraph): bool = is_finite[T](vert(g))
                                  AND is_finite[doubleton[T]](edges(g))
                                  AND (FORALL (e: doubleton[T]): edges(g)(e) 
                                       IMPLIES (FORALL x: e(x) IMPLIES vert(g)(x)))


    singleton_graph(v): (singleton?) = (# vert := singleton[T](v), 
                                         edges := emptyset[doubleton[T]] #)
    
    Graph: TYPE = {g: graph | nonempty?(vert(g))}


  END graphs

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

  % Subtype TCC generated (at line 44, column 44) for  dbl[T](x, y)
      % expected type  doubleton[T]
  edg_TCC1: OBLIGATION
    FORALL (x: T, (y: {y: T | y /= x})):
      EXISTS (x_1: T), (y_1: T):
        x_1 /= y_1 AND dbl[T](x, y) = dbl[T](x_1, y_1);

  % Subtype TCC generated (at line 46, column 44) for  dbl[T](x, y)
      % expected type  doubleton[T]
  edge?_TCC1: OBLIGATION
    FORALL (G: graph, x: T, y: T):
      x /= y IMPLIES
       (EXISTS (x_1: T), (y_1: T):
          x_1 /= y_1 AND dbl[T](x, y) = dbl[T](x_1, y_1));

  % Subtype TCC generated (at line 101, column 37) for
      % (# vert := singleton[T](v), edges := emptyset[doubleton[T]] #)
      % expected type  (singleton?)
  singleton_graph_TCC1: OBLIGATION
    FORALL (v: T):
      (FORALL (e: doubleton[T]):
         emptyset[doubleton[T]](e) IMPLIES
          (FORALL (x: T): e(x) IMPLIES singleton[T](v)(x)))
       AND
       singleton?((# vert := singleton[T](v),
                     edges := emptyset[doubleton[T]] #));


body:
  walks[T: TYPE]: THEORY

  BEGIN

     IMPORTING graphs[T], 
               finite_sets@finite_sets_eq

     G,GG: VAR graph[T]
     n: VAR nat
     
     non_null: TYPE = {M: list[T] | length(M)>0}

     L: VAR non_null
     fs: VAR finseq[T]
   
     x,u,v,u1,u2,v1,v2,v3: VAR T
     e: VAR doubleton[T]
     i,j: VAR nat

     prewalk: TYPE = {w: finseq[T] | length(w) > 0}

     s,ps,ww: VAR prewalk

     verts_in?(G,s): bool = (FORALL (i: below(length(s))): vert(G)(seq(s)(i)))
     
     Seq(G): TYPE = {w: prewalk | verts_in?(G,w)}

     walk?(G,ps): bool = verts_in?(G,ps) AND
                               (FORALL n: n < length(ps) - 1 IMPLIES
                                           edge?(G)(ps(n),ps(n+1)))

     Walk(G): TYPE = {w: prewalk | walk?(G,w)}

     list2prewalk(L: non_null): prewalk =
            (# length := length(L),
               seq := (LAMBDA (x: below[length(L)]): nth(L, x)) #)

     from?(ps,u,v): bool = seq(ps)(0) = u AND seq(ps)(length(ps) - 1) = v

     walk_from?(G,ps,u,v): bool =
  	          seq(ps)(0) = u AND seq(ps)(length(ps) - 1) = v AND walk?(G,ps)

     Walk_from(G,u,v): TYPE = {w: prewalk | walk_from?(G,w,u,v)}


     verts_of(ww: prewalk): finite_set[T] = 
                 {t: T | (EXISTS (i: below(length(ww))): ww(i) = t)}

     edges_of(ww): finite_set[doubleton[T]] = {e: doubleton[T] |
                             EXISTS (i: below(length(ww)-1)): e = dbl(ww(i),ww(i+1))}


     pre_circuit?(G: graph[T], w: prewalk): bool = walk?(G,w) AND 
                                                   w(0) = w(length(w)-1)

  %  ----------------------- Properties -----------------------

     verts_in?_concat: LEMMA FORALL (s1,s2: Seq(G)): verts_in?(G,s1 o s2)

     verts_in?_caret : LEMMA FORALL (j: below(length(ps))): i <= j IMPLIES
                                     verts_in?(G,ps) IMPLIES verts_in?(G,ps^(i,j))

    
     vert_seq_lem    : LEMMA FORALL (w: Seq(G)): n < length(w) IMPLIES vert(G)(w(n))

     verts_of_subset : LEMMA FORALL (w: Seq(G)):
                                     subset?(verts_of(w),vert(G))


     edges_of_subset : LEMMA walk?(G,ww) IMPLIES subset?(edges_of(ww),edges(G))

     walk_verts_in   : LEMMA walk?(G,ps) IMPLIES verts_in?(G,ps)


     walk_from_vert  : LEMMA FORALL (w: prewalk,v1,v2:T):
                               walk_from?(G,w,v1,v2) IMPLIES
                                  vert(G)(v1) AND vert(G)(v2)

     walk_edge_in    : LEMMA walk?(G,ww) AND 
                             subset?(edges_of(ww),edges(GG)) AND
                             subset?(verts_of(ww),vert(GG))
                           IMPLIES walk?(GG,ww)
    
  %  ----------- operations and constructors for walks --------------------

     gen_seq1(G, (u: (vert(G)))): Seq(G) = 
                          (# length := 1, seq := (LAMBDA (i: below(1)): u) #)

     gen_seq2(G, (u,v: (vert(G)))): Seq(G) = 
                    (# length := 2,
                       seq := (LAMBDA (i: below(2)):
                                        IF i = 0 THEN u ELSE v ENDIF) #)
     
     Longprewalk: TYPE = {ps: prewalk | length(ps) >= 2}
     
     trunc1(p: Longprewalk ): prewalk = p^(0,length(p)-2)

     add1(ww,x): prewalk = (# length := length(ww) + 1,
                             seq := (LAMBDA (ii: below(length(ww) + 1)):
                                      IF ii < length(ww) THEN seq(ww)(ii) ELSE x ENDIF)
                           #)


     gen_seq1_is_walk: LEMMA vert(G)(x) IMPLIES walk?(G,gen_seq1(G,x))

     edge_to_walk    : LEMMA u /= v AND edges(G)(edg[T](u, v)) IMPLIES
                               walk?(G,gen_seq2(G,u,v))


     walk?_rev       : LEMMA walk?(G,ps) IMPLIES walk?(G,rev(ps))

     

     w1,w2: VAR prewalk
     walk?_reverse   : LEMMA walk_from?(G,w1,v1,v2) IMPLIES
                               (EXISTS (w: Walk(G)): walk_from?(G,w,v2,v1))

     walk?_caret     : LEMMA i <= j AND j < length(ps) AND walk?(G,ps) 
                                 IMPLIES walk?(G,ps^(i,j))



     l_trunc1        : LEMMA length(ww) > 1 IMPLIES length(trunc1(ww)) = length(ww)-1

     
     walk?_add1      : LEMMA walk?(G,ww) AND vert(G)(x)
                             AND edge?(G)(seq(ww)(length(ww)-1),x)
                             IMPLIES walk?(G,add1(ww,x))                      


     walk_concat_edge: LEMMA walk_from?(G, w1, u1, v1) AND
           		           walk_from?(G, w2, u2, v2) AND
                                edge?(G)(v1,u2)
           		        IMPLIES
           		            walk_from?(G, w1 o w2,u1,v2)

     walk_concat: LEMMA length(w1) > 1 AND
        		      walk_from?(G, w1, u1, v) AND
        		      walk_from?(G, w2, u2, v)
        		 IMPLIES
        		     walk_from?(G, w1 ^ (0, length(w1) - 2) o rev(w2),u1,u2)

     walk?_cut  : LEMMA FORALL (i,j: below(length(ps))): i < j AND
                                    seq(ps)(i) = seq(ps)(j) AND
                                    walk_from?(G, ps, u, v)
                                 IMPLIES
                                    walk_from?(G, ps^(0,i) o ps^(j+1,length(ps)-1),u,v)

     yt: VAR T
     p1,p2: VAR prewalk
     walk_merge: LEMMA walk_from?(G, p1, v, yt) AND
        	             walk_from?(G, p2, u, yt)
                             IMPLIES
        	                (EXISTS (p: prewalk): walk_from?(G, p, u, v))

  END walks

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

  % Subtype TCC generated (at line 31, column 53) for  n
      % expected type  below[length(ps)]
  walk?_TCC1: OBLIGATION
    FORALL (G: graph[T], ps: prewalk):
      verts_in?(G, ps) IMPLIES
       (FORALL (n): n < length(ps) - 1 IMPLIES n < length(ps));

  % Subtype TCC generated (at line 31, column 59) for  n + 1
      % expected type  below[length(ps)]
  walk?_TCC2: OBLIGATION
    FORALL (G: graph[T], ps: prewalk):
      verts_in?(G, ps) IMPLIES
       (FORALL (n): n < length(ps) - 1 IMPLIES n + 1 < length(ps));

  % Subtype TCC generated (at line 36, column 10) for
      % (# length := length(L),
      %    seq := (LAMBDA (x: below[length(L)]): nth(L, x)) #)
      % expected type  prewalk
  list2prewalk_TCC1: OBLIGATION FORALL (L: non_null): length[T](L) > 0;

  % Subtype TCC generated (at line 39, column 33) for  0
      % expected type  below[ps`length]
  from?_TCC1: OBLIGATION FORALL (ps: prewalk, u: T, v: T): 0 < ps`length;

  % Subtype TCC generated (at line 39, column 52) for  length(ps) - 1
      % expected type  below[ps`length]
  from?_TCC2: OBLIGATION
    FORALL (ps: prewalk, u: T, v: T):
      seq(ps)(0) = u IMPLIES
       length(ps) - 1 >= 0 AND length(ps) - 1 < ps`length;

  % Subtype TCC generated (at line 48, column 15) for
      % {t: T | (EXISTS (i: below(length(ww))): finseq_appl[T](ww)(i) = t)}
      % expected type  finite_set[T]
  verts_of_TCC1: OBLIGATION
    FORALL (ww: prewalk):
      is_finite[T]
          ({t: T |
              (EXISTS (i: below(length(ww))): finseq_appl[T](ww)(i) = t)});

  % Subtype TCC generated (at line 51, column 71) for  i
      % expected type  below[length(ww)]
  edges_of_TCC1: OBLIGATION
    FORALL (ww: prewalk, e: doubleton[T], i: below(length(ww) - 1)):
      i < length(ww);

  % Subtype TCC generated (at line 51, column 77) for  i + 1
      % expected type  below[length(ww)]
  edges_of_TCC2: OBLIGATION
    FORALL (ww: prewalk, e: doubleton[T], i: below(length(ww) - 1)):
      i + 1 < length(ww);

  % Subtype TCC generated (at line 50, column 44) for
      % {e: doubleton[T] |
      %    EXISTS (i: below(length(ww) - 1)):
      %      e = dbl(finseq_appl[T](ww)(i), finseq_appl[T](ww)(i + 1))}
      % expected type  finite_set[doubleton[T]]
  edges_of_TCC3: OBLIGATION
    FORALL (ww: prewalk):
      is_finite[doubleton[T]]
          ({e: doubleton[T] |
              EXISTS (i: below(length(ww) - 1)):
                e =
                 dbl[T](finseq_appl[T](ww)(i), finseq_appl[T](ww)(i + 1))});

  % Subtype TCC generated (at line 55, column 51) for  0
      % expected type  below[length(w)]
  pre_circuit?_TCC1: OBLIGATION
    FORALL (G: graph[T], w: prewalk): walk?(G, w) IMPLIES 0 < length(w);

  % Subtype TCC generated (at line 55, column 58) for  length(w) - 1
      % expected type  below[length(w)]
  pre_circuit?_TCC2: OBLIGATION
    FORALL (G: graph[T], w: prewalk):
      walk?(G, w) IMPLIES length(w) - 1 >= 0 AND length(w) - 1 < length(w);

  % Subtype TCC generated (at line 59, column 63) for  s1 o s2
      % expected type  prewalk
  verts_in?_concat_TCC1: OBLIGATION
    FORALL (G: graph[T], s1, s2: Seq(G)): length(o[T](s1, s2)) > 0;

  % Subtype TCC generated (at line 62, column 71) for  ps ^ (i, j)
      % expected type  prewalk
  verts_in?_caret_TCC1: OBLIGATION
    FORALL (G: graph[T], i: nat, ps: prewalk, j: below(length(ps))):
      verts_in?(G, ps) AND i <= j IMPLIES length(^[T](ps, (i, j))) > 0;

  % Subtype TCC generated (at line 88, column 24) for
      % (# length := 1, seq := (LAMBDA (i: below(1)): u) #)
      % expected type  Seq(G)
  gen_seq1_TCC1: OBLIGATION
    FORALL (G: graph[T], (u: (vert(G)))):
      1 > 0 AND
       verts_in?(G, (# length := 1, seq := LAMBDA (i: below(1)): u #));

  % Subtype TCC generated (at line 91, column 18) for
      % (# length := 2,
      %    seq := (LAMBDA (i: below(2)): IF i = 0 THEN u ELSE v ENDIF) #)
      % expected type  Seq(G)
  gen_seq2_TCC1: OBLIGATION
    FORALL (G: graph[T], (u, v: (vert(G)))):
      2 > 0 AND
       verts_in?(G,
                 (# length := 2,
                    seq
                      := LAMBDA (i: below(2)):
                           IF i = 0 THEN u ELSE v ENDIF #));

  % Subtype TCC generated (at line 97, column 43) for  length(p) - 2
      % expected type  nat
  trunc1_TCC1: OBLIGATION FORALL (p: Longprewalk): length(p) - 2 >= 0;

  % Subtype TCC generated (at line 97, column 38) for  p ^ (0, length(p) - 2)
      % expected type  prewalk
  trunc1_TCC2: OBLIGATION
    FORALL (p: Longprewalk): length(^[T](p, (0, length(p) - 2))) > 0;

  % Subtype TCC generated (at line 99, column 25) for
      % (# length := length(ww) + 1,
      %    seq
      %      := (LAMBDA (ii: below(length(ww) + 1)):
      %            IF ii < length(ww) THEN seq(ww)(ii) ELSE x ENDIF) #)
      % expected type  prewalk
  add1_TCC1: OBLIGATION FORALL (ww: prewalk, x: T): length(ww) + 1 > 0;

  % Subtype TCC generated (at line 107, column 57) for  v
      % expected type  {y: T | y /= u}
  edge_to_walk_TCC1: OBLIGATION FORALL (u, v: T): u /= v IMPLIES v /= u;

  % Subtype TCC generated (at line 108, column 48) for  u
      % expected type  (vert(G))
  edge_to_walk_TCC2: OBLIGATION
    FORALL (G: graph[T], u, v: T):
      edges(G)(edg[T](u, v)) AND u /= v IMPLIES vert(G)(u);

  % Subtype TCC generated (at line 108, column 50) for  v
      % expected type  (vert(G))
  edge_to_walk_TCC3: OBLIGATION
    FORALL (G: graph[T], u, v: T):
      edges(G)(edg[T](u, v)) AND u /= v IMPLIES vert(G)(v);

  % Subtype TCC generated (at line 111, column 55) for  rev(ps)
      % expected type  prewalk
  walk?_rev_TCC1: OBLIGATION
    FORALL (G: graph[T], ps: prewalk):
      walk?(G, ps) IMPLIES length(rev[T](ps)) > 0;

  % Subtype TCC generated (at line 120, column 47) for  ps ^ (i, j)
      % expected type  prewalk
  walk?_caret_TCC1: OBLIGATION
    FORALL (G: graph[T], i, j: nat, ps: prewalk):
      walk?(G, ps) AND j < length(ps) AND i <= j IMPLIES
       length(^[T](ps, (i, j))) > 0;

  % Subtype TCC generated (at line 124, column 64) for  ww
      % expected type  Longprewalk
  l_trunc1_TCC1: OBLIGATION
    FORALL (ww: prewalk): length(ww) > 1 IMPLIES length(ww) >= 2;

  % Subtype TCC generated (at line 136, column 37) for  w1 o w2
      % expected type  prewalk
  walk_concat_edge_TCC1: OBLIGATION
    FORALL (G: graph[T], u1, u2, v1, v2: T, w1, w2: prewalk):
      edge?(G)(v1, u2) AND
       walk_from?(G, w2, u2, v2) AND walk_from?(G, w1, u1, v1)
       IMPLIES length(o[T](w1, w2)) > 0;

  % Subtype TCC generated (at line 142, column 36) for  length(w1) - 2
      % expected type  nat
  walk_concat_TCC1: OBLIGATION
    FORALL (G: graph[T], u1, u2, v: T, w1, w2: prewalk):
      walk_from?(G, w2, u2, v) AND
       walk_from?(G, w1, u1, v) AND length(w1) > 1
       IMPLIES length(w1) - 2 >= 0;

  % Subtype TCC generated (at line 142, column 27) for
      % w1 ^ (0, length(w1) - 2) o rev(w2)
      % expected type  prewalk
  walk_concat_TCC2: OBLIGATION
    FORALL (G: graph[T], u1, u2, v: T, w1, w2: prewalk):
      walk_from?(G, w2, u2, v) AND
       walk_from?(G, w1, u1, v) AND length(w1) > 1
       IMPLIES length(o[T](^[T](w1, (0, length(w1) - 2)), rev[T](w2))) > 0;

  % Subtype TCC generated (at line 148, column 67) for  length(ps) - 1
      % expected type  nat
  walk?_cut_TCC1: OBLIGATION
    FORALL (G: graph[T], ps: prewalk, u, v: T, i, j: below(length(ps))):
      i < j AND seq(ps)(i) = seq(ps)(j) AND walk_from?(G, ps, u, v) IMPLIES
       length(ps) - 1 >= 0;

  % Subtype TCC generated (at line 148, column 48) for
      % ps ^ (0, i) o ps ^ (j + 1, length(ps) - 1)
      % expected type  prewalk
  walk?_cut_TCC2: OBLIGATION
    FORALL (G: graph[T], ps: prewalk, u, v: T, i, j: below(length(ps))):
      i < j AND seq(ps)(i) = seq(ps)(j) AND walk_from?(G, ps, u, v) IMPLIES
       length(o[T](^[T](ps, (0, i)), ^[T](ps, (j + 1, length(ps) - 1)))) > 0;


body:
  paths[T: TYPE]: THEORY

  BEGIN

     IMPORTING graphs[T], walks[T] 

     G: VAR graph[T]
     x,y,s,t: VAR T
     i,j: VAR nat
     p,ps: VAR prewalk

     path?(G,ps): bool = walk?(G,ps) AND (FORALL (i,j: below(length(ps))):
                                            i /= j IMPLIES ps(i) /= ps(j))

     Path(G): TYPE = {p: prewalk | path?(G,p)}

     path_from?(G,ps,s,t): bool = path?(G,ps) AND from?(ps,s,t)

     Path_from(G,s,t): TYPE = {p: prewalk | path_from?(G,p,s,t)}

     endpoint?(i: nat, w: prewalk): bool = (i = 0) OR (i = length(w)-1)

     path_verts(G,(x:T)): set[T] = {v: T | EXISTS (w: prewalk): walk_from?(G,w,x,v)}


     path?_verts     : LEMMA path?(G,ps) IMPLIES verts_in?(G,ps)

     path_from_l     : LEMMA path_from?(G,ps,s,t) AND s /= t IMPLIES length(ps) >= 2

     path_from_in    : LEMMA path_from?(G, ps, s, t) IMPLIES 
                            vert(G)(s) AND vert(G)(t)


     path?_caret     : LEMMA i <= j AND j < length(ps) AND path?(G,ps) 
                              IMPLIES path?(G,ps^(i,j))

     path_from?_caret: LEMMA  i <= j AND j < length(ps) AND path_from?(G, ps, s, t)
                           IMPLIES path_from?(G, ps^(i, j),seq(ps)(i),seq(ps)(j))

     path?_rev       : LEMMA path?(G,ps) IMPLIES path?(G,rev(ps))


     path?_gen_seq2  : LEMMA vert(G)(x) AND vert(G)(y) AND
                              edge?(G)(x,y) IMPLIES path?(G,gen_seq2(G,x,y))

     path?_add1      : LEMMA path?(G,p) AND vert(G)(x)
                              AND edge?(G)(seq(p)(length(p)-1),x)
                              AND NOT verts_of(p)(x)
                              IMPLIES path?(G,add1(p,x))                      

     path?_trunc1      : LEMMA path?(G,p) AND length(p) > 1 IMPLIES
                              path_from?(G,trunc1(p),seq(p)(0),seq(p)(length(p)-2)) 


  END paths

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

  % Subtype TCC generated (at line 35, column 44) for  ps ^ (i, j)
      % expected type  prewalk[T]
  path?_caret_TCC1: OBLIGATION
    FORALL (G: graph[T], i, j: nat, ps: prewalk[T]):
      path?(G, ps) AND j < length(ps) AND i <= j IMPLIES
       length(^[T](ps, (i, j))) > 0;

  % Subtype TCC generated (at line 38, column 47) for  ps ^ (i, j)
      % expected type  prewalk[T]
  path_from?_caret_TCC1: OBLIGATION
    FORALL (G: graph[T], i, j: nat, ps: prewalk[T], s, t: T):
      path_from?(G, ps, s, t) AND j < length(ps) AND i <= j IMPLIES
       length(^[T](ps, (i, j))) > 0;

  % Subtype TCC generated (at line 38, column 65) for  i
      % expected type  below[ps`length]
  path_from?_caret_TCC2: OBLIGATION
    FORALL (G: graph[T], i, j: nat, ps: prewalk[T], s, t: T):
      path_from?(G, ps, s, t) AND j < length(ps) AND i <= j IMPLIES
       i < ps`length;

  % Subtype TCC generated (at line 40, column 55) for  rev(ps)
      % expected type  prewalk[T]
  path?_rev_TCC1: OBLIGATION
    FORALL (G: graph[T], ps: prewalk[T]):
      path?(G, ps) IMPLIES length(rev[T](ps)) > 0;

  % Subtype TCC generated (at line 47, column 48) for  length(p) - 1
      % expected type  below[p`length]
  path?_add1_TCC1: OBLIGATION
    FORALL (G: graph[T], p: prewalk[T], x: T):
      path?(G, p) AND vert(G)(x) IMPLIES
       length(p) - 1 >= 0 AND length(p) - 1 < p`length;

  % Subtype TCC generated (at line 52, column 48) for  p
      % expected type  Longprewalk[T]
  path?_trunc1_TCC1: OBLIGATION
    FORALL (G: graph[T], p: prewalk[T]):
      length(p) > 1 AND path?(G, p) IMPLIES length(p) >= 2;

  % Subtype TCC generated (at line 52, column 58) for  0
      % expected type  below[p`length]
  path?_trunc1_TCC2: OBLIGATION
    FORALL (G: graph[T], p: prewalk[T]):
      length(p) > 1 AND path?(G, p) IMPLIES 0 < p`length;

  % Subtype TCC generated (at line 52, column 68) for  length(p) - 2
      % expected type  below[p`length]
  path?_trunc1_TCC3: OBLIGATION
    FORALL (G: graph[T], p: prewalk[T]):
      length(p) > 1 AND path?(G, p) IMPLIES
       length(p) - 2 >= 0 AND length(p) - 2 < p`length;


body:
  path_lems[T: TYPE]: THEORY

  BEGIN

     IMPORTING paths[T]

     IMPORTING graphs, finite_sets@finite_sets_card_eq, 
               structures@seq_pigeon

     GF: VAR Graph[T]

     Pigeon_hole: THEOREM FORALL (w: Walk(GF)): length(w) > card(vert(GF)) IMPLIES 
                    (EXISTS (i,j: below(length(w))): i /= j AND w(i) = w(j))
     

  END path_lems


body:
  subgraphs[T: TYPE]: THEORY

  BEGIN

     IMPORTING graphs[T]

     V: VAR set[T]
     G,G1,G2,SS: VAR graph[T]
     i: VAR T
     e: VAR doubleton[T]

     subgraph?(G1,G2): bool = subset?(vert(G1),vert(G2)) AND
                              subset?(edges(G1),edges(G2))

     equal?(G1,G2): bool = subgraph?(G1,G2) AND subgraph?(G2,G1)

     Subgraph(G): TYPE = {S: graph[T] | subgraph?(S,G)}

     finite_vert_subset: LEMMA is_finite(LAMBDA (i:T): vert(G)(i) AND V(i))


     subgraph(G, V): Subgraph(G) =
         (G WITH [vert :=  {i | vert(G)(i) AND V(i)},
                  edges := {e | edges(G)(e) AND 
                                (FORALL (x: T): e(x) IMPLIES V(x))}])

     subgraph_vert_sub: LEMMA subset?(V,vert(G)) IMPLIES
                                          vert(subgraph(G,V)) = V

     subgraph_lem     : LEMMA subgraph?(subgraph(G,V),G)

     subgraph_smaller: LEMMA subgraph?(SS, G) IMPLIES
     	                     size(SS) <= size(G)

  END subgraphs

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

  % Subtype TCC generated (at line 24, column 25) for
      % {e | edges(G)(e) AND (FORALL (x: T): e(x) IMPLIES V(x))}
      % expected type  finite_set[doubleton[T]]
  subgraph_TCC1: OBLIGATION
    FORALL (G: graph[T], V: set[T]):
      is_finite[doubleton[T]]
          ({e | edges(G)(e) AND (FORALL (x: T): e(x) IMPLIES V(x))});

  % Subtype TCC generated (at line 23, column 25) for
      % {i | vert(G)(i) AND V(i)}
      % expected type  finite_set[T]
  subgraph_TCC2: OBLIGATION
    FORALL (G: graph[T], V: set[T]): is_finite[T]({i | vert(G)(i) AND V(i)});

  % Subtype TCC generated (at line 23, column 8) for
      % (G
      %    WITH [vert := {i | vert(G)(i) AND V(i)},
      %          edges
      %            := {e |
      %                  edges(G)(e) AND (FORALL (x: T): e(x) IMPLIES V(x))}])
      % expected type  Subgraph(G)
  subgraph_TCC3: OBLIGATION
    FORALL (G: graph[T], V: set[T]):
      (FORALL (e_1: doubleton[T]):
         (edges(G)(e_1) AND (FORALL (x: T): e_1(x) IMPLIES V(x))) IMPLIES
          (FORALL (x_1: T): e_1(x_1) IMPLIES vert(G)(x_1) AND V(x_1)))
       AND
       subgraph?((G
                    WITH [vert := {i | vert(G)(i) AND V(i)},
                          edges
                            := {e |
                                  edges(G)(e) AND
                                   (FORALL (x: T): e(x) IMPLIES V(x))}]),
                 G);


body:
  %------------------------------------------------------------------------
  % 
  %  Operations on a graph
  %  ------------------------------------------------
  %
  %      Author: Ricky W. Butler   NASA Langley Research Center
  %
  %  Defines:
  %
  %      union(G1,G2)      -- creates graph that is a union of G1 and G2  
  %
  %      del_vert(G,v)     -- removes a vertex and all adjacent edges from a graph
  %
  %      del_edge(e,G)     --  creates subgraph with edge e removed
  %   
  %      num_edges(G): nat --  number of edges in a graph
  %
  %------------------------------------------------------------------------
  graph_ops[T: TYPE]: THEORY

  BEGIN

     IMPORTING graphs[T]

     G, G1, G2: VAR graph[T]
     t1,t2: VAR T
     x,v: VAR T
     e,e2: VAR doubleton[T]

     union(G1,G2): graph[T] = (# vert := union(vert(G1),vert(G2)),
                                 edges := union(edges(G1),edges(G2)) #)
   
     del_vert(G: graph[T], v: T): graph[T] = 
                          (# vert := remove[T](v,vert(G)),
                             edges := {e | edges(G)(e) AND NOT e(v)} #)
                              
     del_edge(G,e): graph[T] = G WITH [edges := remove(e,edges(G))]

     num_edges(G): nat = card(edges(G))

     adjacent(G, (x:T)): finite_set[T] = {y: T| vert(G)(y) AND edge?(G)(x,y)}

  %  --------------------- del_vert(G,v) lemmas ----------------

     del_vert_still_in   : LEMMA FORALL (x: (vert(G))):
                                       x /= v IMPLIES vert(del_vert(G, v))(x)

     size_del_vert       : LEMMA FORALL (v: (vert(G))):
                                     size(del_vert(G,v)) = size(G) - 1

     del_vert_le         : LEMMA size(del_vert(G,v)) <= size(G) 

     del_vert_ge         : LEMMA size(del_vert(G,v)) >= size(G) - 1

     edge_in_del_vert    : LEMMA (edges(G)(e) AND NOT e(v)) IMPLIES
                                   edges(del_vert(G,v))(e)
     
     edges_del_vert      : LEMMA edges(del_vert(G,v))(e) IMPLIES
                                         edges(G)(e)

     del_vert_comm       : LEMMA del_vert(del_vert(G, x), v) =
                                      del_vert(del_vert(G, v), x)

     del_vert_empty?     : LEMMA FORALL (v: (vert(G))): 
                                    empty?(vert(del_vert(G, v))) IMPLIES
                                        singleton?(G)



  %  ---------- del_edge(G,e) ----------------------------------

     del_edge_lem       : LEMMA NOT member(e,edges(del_edge(G,e)))
    
     del_edge_lem2      : LEMMA edges(del_edge(G,e))(e2)
                      		    IMPLIES edges(G)(e2)
    
     del_edge_lem3      : LEMMA edges(G)(e2) AND e2 /= e IMPLIES
                      		    edges(del_edge(G,e))(e2) 
    
     del_edge_lem5      : LEMMA NOT edges(G)(e) IMPLIES del_edge(G, e) = G

     vert_del_edge      : LEMMA vert(del_edge(G,e)) = vert(G)
    
     del_edge_num       : LEMMA num_edges(del_edge(G,e)) = num_edges(G) 
                                         - IF edges(G)(e) THEN 1 ELSE 0 ENDIF

     del_edge_singleton : LEMMA singleton?(del_edge(G,e)) IMPLIES singleton?(G)


     del_vert_edge_comm : LEMMA del_vert(del_edge(G, e), v) = 
                                 del_edge(del_vert(G, v), e)

     del_vert_edge      : LEMMA e(v) IMPLIES
                                 del_vert(del_edge(G,e),v) = del_vert(G,v)


  END graph_ops

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

  % Subtype TCC generated (at line 30, column 28) for
      % (# vert := union(vert(G1), vert(G2)),
      %    edges := union(edges(G1), edges(G2)) #)
      % expected type  graph[T]
  union_TCC1: OBLIGATION
    FORALL (G1: graph[T], G2: graph[T]):
      FORALL (e: doubleton[T]):
        union[doubleton[T]](edges(G1), edges(G2))(e) IMPLIES
         (FORALL (x: T): e(x) IMPLIES union[T](vert(G1), vert(G2))(x));

  % Subtype TCC generated (at line 35, column 36) for
      % {e | edges(G)(e) AND NOT e(v)}
      % expected type  finite_set[doubleton[T]]
  del_vert_TCC1: OBLIGATION
    FORALL (G: graph[T], v: T):
      is_finite[doubleton[T]]({e | edges(G)(e) AND NOT e(v)});

  % Subtype TCC generated (at line 34, column 24) for
      % (# vert := remove[T](v, vert(G)),
      %    edges := {e | edges(G)(e) AND NOT e(v)} #)
      % expected type  graph[T]
  del_vert_TCC2: OBLIGATION
    FORALL (G: graph[T], v: T):
      FORALL (e_1: doubleton[T]):
        edges(G)(e_1) AND NOT e_1(v) IMPLIES
         (FORALL (x: T): e_1(x) IMPLIES remove[T](v, vert(G))(x));

  % Subtype TCC generated (at line 37, column 29) for
      % G WITH [edges := remove(e, edges(G))]
      % expected type  graph[T]
  del_edge_TCC1: OBLIGATION
    FORALL (G: graph[T], e: doubleton[T]):
      FORALL (e_1: doubleton[T]):
        remove[doubleton[T]](e, edges(G))(e_1) IMPLIES
         (FORALL (x_1: T): e_1(x_1) IMPLIES G`vert(x_1));

  % Subtype TCC generated (at line 41, column 39) for
      % {y: T | vert(G)(y) AND edge?(G)(x, y)}
      % expected type  finite_set[T]
  adjacent_TCC1: OBLIGATION
    FORALL (G: graph[T], (x: T)):
      is_finite[T]({y: T | vert(G)(y) AND edge?[T](G)(x, y)});


body:
  graph_deg[T: TYPE]: THEORY
  %------------------------------------------------------------------------
  % 
  %  Defines degree of a vertex
  %  ------------------------------------------------
  %
  %      Author: Ricky W. Butler   NASA Langley Research Center
  %
  %  Defines:
  %
  %    incident_edges(v,G) -- returns set of edges attached to vertex v
  %
  %    deg(v,G)          -- number of edges attached to vertex v    
  %
  %------------------------------------------------------------------------

  BEGIN

     IMPORTING graphs[T], graph_ops[T]

     v: VAR T
     G,GS: VAR graph[T]

     incident_edges(v,G)  : finite_set[doubleton[T]] 
                                = {e: doubleton[T] | edges(G)(e) AND e(v)}

     incident_edges_subset: LEMMA subset?(incident_edges(v,G),edges(G))

     deg(v,G): nat = card(incident_edges(v,G))

     P : VAR pred[graph[T]]
     n : VAR nat
     e: VAR doubleton[T]
     x,y: VAR T

     incident_edges_emptyset: LEMMA edges(G) = emptyset[doubleton[T]] IMPLIES
                                      incident_edges(v,G) = emptyset[doubleton[T]]


     deg_del_edge    : LEMMA e = dbl(x,y) AND edges(G)(e) IMPLIES  
                               deg(y, G) = deg(y, del_edge(G, e)) + 1

     deg_del_edge2   : LEMMA e(y) AND edges(G)(e) IMPLIES  
                               deg(y, G) = deg(y, del_edge(G, e)) + 1


     deg_del_edge3   : LEMMA NOT e(y)  IMPLIES  
                                deg(y, G) = deg(y, del_edge(G, e))

     deg_del_edge_ge : LEMMA deg(y, G) >= deg(y, del_edge(G, e))


     deg_del_edge_le : LEMMA deg(y, G) - 1 <= deg(y, del_edge(G, e))

     deg_edge_exists       : LEMMA deg(v,G) > 0 IMPLIES
                               (EXISTS e: e(v) AND edges(G)(e))
        
     deg_to_card     : LEMMA deg(v,G) > 0 IMPLIES size(G) >= 2

     del_vert_deg_0  : LEMMA deg(v,G) = 0 IMPLIES 
                                 edges(del_vert(G,v)) = edges(G)

     deg_del_vert: LEMMA x /= v AND edges(G)(dbl[T](x, v))  
                                  IMPLIES deg(v, del_vert(G, x)) = 
                                             deg(v, G) - 1

     del_vert_not_incident: LEMMA x /= v AND NOT edges(G)(dbl[T](x, v)) IMPLIES
                                         deg(x, del_vert(G, v)) = deg(x, G)

     singleton_deg: LEMMA singleton?(G) IMPLIES deg(v, G) = 0

     deg_1_sing   : LEMMA deg(v, G) = 1 IMPLIES 
                             (EXISTS e: incident_edges(v, G) = singleton(e) AND
                                        e(v) AND edges(G)(e))


   
  END graph_deg

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

  % Subtype TCC generated (at line 25, column 32) for
      % {e: doubleton[T] | edges(G)(e) AND e(v)}
      % expected type  finite_set[doubleton[T]]
  incident_edges_TCC1: OBLIGATION
    FORALL (v: T, G: graph[T]):
      is_finite[doubleton[T]]({e: doubleton[T] | edges(G)(e) AND e(v)});

  % Subtype TCC generated (at line 63, column 43) for  dbl[T](x, v)
      % expected type  doubleton[T]
  deg_del_vert_TCC1: OBLIGATION
    FORALL (v, x: T):
      x /= v IMPLIES
       (EXISTS (x_1: T), (y: T): x_1 /= y AND dbl[T](x, v) = dbl[T](x_1, y));


body:
  graph_deg_sum[T: TYPE]: THEORY
  BEGIN

     IMPORTING graph_deg[T],    %  fslib@finite_sets_sum_real[T]
               finite_sets@finite_sets_sum_real[T]

     v: VAR T
     G,GS: VAR graph[T]
     x,y: VAR T
     V_reduced: VAR set[T]
     P : VAR pred[graph[T]]
     n : VAR nat
     e: VAR doubleton[T]
     S: VAR finite_set[T]
     f: VAR [T -> real]
     B: VAR real

     deg_lem0: LEMMA num_edges(G) = 0 IMPLIES 
                        sum(vert(G), (LAMBDA (v: T): deg(v, G))) = 0

     deg_lem2: LEMMA remove(x, remove(y, vert(G))) = V_reduced AND
                      e = dbl[T](x, y) AND nonempty?(edges(G)) AND 
                      choose(edges(G)) = e IMPLIES  
                        sum(V_reduced, (LAMBDA (v:T): deg(v,G)))
                        = sum(V_reduced,(LAMBDA (v:T): deg(v,del_edge(G,e))))
    
     edge_induction : LEMMA
       (FORALL G : P(G)) IFF (FORALL n, G: num_edges(G) = n IMPLIES P(G)) 


     deg_thm: THEOREM sum(vert(G), (LAMBDA (v: T): deg(v,G))) =
                             2 * num_edges(G)          


     IMPORTING subgraphs[T]

     subgraph_deg : THEOREM subgraph?(GS,G) AND vert(G)(v) IMPLIES 
                                 deg(v,GS) <= deg(v,G)


     sum_gt_bound : THEOREM (FORALL (t: (S)): f(t) >= B) 
                               IMPLIES sum(S,f) >= B*card(S)

     deg_gt_one   : THEOREM (FORALL (v:(vert(G))): deg(v,G) > 1) 
                                       IMPLIES num_edges(G)>=size(G)

   
  END graph_deg_sum

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

  % Subtype TCC generated (at line 24, column 26) for  V_reduced
      % expected type  finite_set[T]
  deg_lem2_TCC1: OBLIGATION
    FORALL (G: graph[T], V_reduced: set[T], e: doubleton[T], x, y: T):
      choose(edges(G)) = e AND
       nonempty?(edges(G)) AND
        e = dbl[T](x, y) AND remove(x, remove(y, vert(G))) = V_reduced
       IMPLIES is_finite[T](V_reduced);


body:
  subgraph_paths[T: TYPE]: THEORY
  BEGIN

     IMPORTING paths[T], subgraphs[T]

     G,HH: VAR graph[T]
     w1,w2,v,s,t,z: VAR T
     e: VAR doubleton[T]
     V: VAR finite_set[T]
     p: VAR prewalk


     walk?_subgraph  : LEMMA subgraph?(HH,G) AND walk?(HH, p)
                                 IMPLIES walk?(G, p)

     path?_subgraph  : LEMMA subgraph?(HH,G) AND path?(HH, p)
                                    IMPLIES path?(G, p)

  END subgraph_paths


body:
  abstract_min[T: TYPE, size: [T -> nat], P: pred[T]]: THEORY
  %------------------------------------------------------------------------------
  %
  %  The need for a function that returns the smallest object that
  %  satisfies a particular predicate arises in many contexts.  Thus it is
  %  useful to develop an "abstract" min theory that can be instantiated in
  %  multiple ways to provide different min functions.  Such a theory must
  %  be parameterized by
  %
  %    -------------------------------------------------------------------------
  %    | T: TYPE          | the base type over which min is defined            |
  %    | size:[T -> nat]  | the size function by which objects are compared    |
  %    | P: pred[T]       | the property that the min function must satisfy    |
  %    -------------------------------------------------------------------------
  %
  %  Author:
  %
  %      Ricky W. Butler   NASA Langley
  %
  %  Version 2.0           Last modified 10/21/97
  %
  %  Maintained by:
  %
  %     Rick Butler        NASA Langley Research Center   
  %                        R.W.Butler@larc.nasa.gov
  %
  %------------------------------------------------------------------------------
  BEGIN

     ASSUMING

     T_ne: ASSUMPTION EXISTS (t: T): P(t)

     ENDASSUMING

     IMPORTING min_nat

     n: VAR nat
     S,SS: VAR T

     is_one(n): bool = (EXISTS (S: T): P(S) AND size(S) = n)

     prep0: LEMMA nonempty?({n: nat | is_one(n)})

     min_f: nat = min({n: nat | is_one(n)})

     prep1: LEMMA nonempty?({S: T | size(S) = min_f AND P(S)})

     minimal?(S): bool = P(S) AND 
                         (FORALL (SS: T): P(SS) IMPLIES size(S) <= size(SS))

     min: {S: T | minimal?(S)} 


     min_def: LEMMA minimal?(min)

     min_in : LEMMA P(min) 

     min_is_min: LEMMA P(SS) IMPLIES size(min) <= size(SS) 


  END abstract_min

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

  % Subtype TCC generated (at line 45, column 20) for  {n: nat | is_one(n)}
      % expected type  S: (nonempty?[nat])
  min_f_TCC1: OBLIGATION nonempty?[nat]({n: nat | is_one(n)});

  % Existence TCC generated (at line 52, column 3) for
      % min: {S: T | minimal?(S)}
  min_TCC1: OBLIGATION EXISTS (x: {S: T | minimal?(S)}): TRUE;


body:
  cycles[T: TYPE]: THEORY

  BEGIN

     IMPORTING paths[T]

     G: VAR graph[T]


     cycle?(G: graph[T], (w: Seq(G))): bool = pre_circuit?(G,w) AND length(w) > 1 AND 
                            w(1) /= w(length(w)-2) AND
                            (FORALL (i,j: below(length(w))):
                               w(i) = w(j) IMPLIES (i = j OR 
                                           (endpoint?(i,w) AND endpoint?(j,w)))) 

     cycle_l_gt_3: LEMMA (FORALL (w: Seq(G)): cycle?(G,w) IMPLIES length(w) > 3)



     cycle_has_path: LEMMA FORALL (w: Seq(G)): cycle?(G,w) IMPLIES
                              (EXISTS (j: below(length(w))): path?(G,w^(0,j)))


  %% -- the term "w(1) /= w(length(w)-2)" rules out length(w) = 2 AND length(w) = 3 --
     

     cycle_gt3: LEMMA FORALL (w: Seq(G)):  cycle?(G,w) IMPLIES length(w) > 3

     cycle_def: LEMMA FORALL (w: Seq(G)): cycle?(G,w) IFF
                            pre_circuit?(G,w) AND length(w) > 3 AND 
                            (FORALL (i,j: below(length(w))):
                               w(i) = w(j) IMPLIES (i = j OR 
                                           (endpoint?(i,w) AND endpoint?(j,w))))
                         



  END cycles

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

  % Subtype TCC generated (at line 11, column 28) for  1
      % expected type  below[length(w)]
  cycle?_TCC1: OBLIGATION
    FORALL (G: graph[T], (w: Seq[T](G))):
      length(w) > 1 AND pre_circuit?(G, w) IMPLIES 1 < length(w);

  % Subtype TCC generated (at line 11, column 36) for  length(w) - 2
      % expected type  below[length(w)]
  cycle?_TCC2: OBLIGATION
    FORALL (G: graph[T], (w: Seq[T](G))):
      length(w) > 1 AND pre_circuit?(G, w) IMPLIES
       length(w) - 2 >= 0 AND length(w) - 2 < length(w);

  % Subtype TCC generated (at line 21, column 67) for  w ^ (0, j)
      % expected type  prewalk[T]
  cycle_has_path_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Seq[T](G)):
      cycle?(G, w) IMPLIES
       (FORALL (j: below(length(w))): length(^[T](w, (0, j))) > 0);


body:
  circuits[T: TYPE]: THEORY
  %
  %  A circuit is a pre_circuit with no small loops (i.e. reduced)
  %
  %     pre_circuit?(G: graph[T], w: prewalk): bool = walk?(G,w) AND 
  %                                                   w(0) = w(length(w)-1)
  %
  %  NOTE: The extra term "w(1) /= w(length(w)-2)" in the definition of
  %        cyclically_reduced? handles the special case where
  %        w(0) is a small loop
  %
  %        removed "walk?(G,w)" from circuit? defn because it is in pre_circuit
  %
  BEGIN

     IMPORTING walks[T]

     G: VAR graph[T]


     reducible?(G: graph[T], w: Seq(G)): bool  = 
            (EXISTS (k: posnat): k < length(w) - 1 AND w(k-1) = w(k+1))

     reduced?(G: graph[T], w: Seq(G)): bool = NOT reducible?(G,w)

  %
  %   cyclically_reduced?(G: graph[T], w: Long_walk(G)): bool = 
  %         reduced?(G,w) AND
  %         (FORALL (j: below(length(w)-1)): reduced?(G,w^(j+1, length(w)-1) o w^(1,j))) 


     cyclically_reduced?(G: graph[T], w: Seq(G)): bool = length(w) > 2 AND
           reduced?(G,w) AND w(1) /= w(length(w)-2)

     circuit?(G:  graph[T], w: Seq(G)): bool = %% walk?(G,w) AND
                                               cyclically_reduced?(G,w) AND
                                               pre_circuit?(G,w) 

  END circuits

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

  % Subtype TCC generated (at line 22, column 55) for  k - 1
      % expected type  below[length(w)]
  reducible?_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Seq[T](G), k: posnat):
      k < length(w) - 1 IMPLIES k - 1 >= 0 AND k - 1 < length(w);

  % Subtype TCC generated (at line 22, column 64) for  k + 1
      % expected type  below[length(w)]
  reducible?_TCC2: OBLIGATION
    FORALL (G: graph[T], w: Seq[T](G), k: posnat):
      k < length(w) - 1 IMPLIES k + 1 < length(w);

  % Subtype TCC generated (at line 33, column 29) for  1
      % expected type  below[length(w)]
  cyclically_reduced?_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Seq[T](G)):
      reduced?(G, w) AND length(w) > 2 IMPLIES 1 < length(w);

  % Subtype TCC generated (at line 33, column 37) for  length(w) - 2
      % expected type  below[length(w)]
  cyclically_reduced?_TCC2: OBLIGATION
    FORALL (G: graph[T], w: Seq[T](G)):
      reduced?(G, w) AND length(w) > 2 IMPLIES
       length(w) - 2 >= 0 AND length(w) - 2 < length(w);


body:
  path_circ[T: TYPE]: THEORY

  BEGIN

   IMPORTING walks[T],circuits[T],paths[T]


    x,y,s,t,ss,tt: VAR T
    i: VAR nat
    G,GG: VAR graph[T]
    u,w,p,q: VAR prewalk

    path_reduc       : LEMMA FORALL (p: Path(G)) : reduced?(G,p)

    trunc_long       : LEMMA length(u)>= 2 AND length(w) >= 2 IMPLIES length(trunc1(u) o w) >= 1

    trunc_walk       : LEMMA length(u)>=2 AND walk?(G,u) IMPLIES walk?(G,trunc1(u))

    walks_concat_red : LEMMA walk?(G,u) AND walk?(G,w) AND
                             length(u) >=2 AND length(w) >=2 AND reduced?(G,u) AND 
                             reduced?(G,w) AND u(length(u)-1) = w(0) AND
                             u(length(u)-2) /= w(1) IMPLIES reduced?(G,trunc1(u) o w)

    index_rev        : LEMMA length(q)>=2 IMPLIES length(rev(q)) = length(q) AND 
                                             rev(q)(0) = q(length(q)-1) AND
                                             rev(q)(1) = q(length(q)-2)

    rev_rev          : LEMMA rev(rev(q))=q

    ind_rev_rev      : LEMMA length(q)>=2  IMPLIES rev(q)(length(q)-1) = q(0) AND 
                                              rev(q)(length(q)-2) = q(1)

    second_in_cat    : LEMMA s /= t AND from?(p,s,t) AND from?(q,s,t) IMPLIES 
                                 p(1) = (trunc1(p) o rev(q))(1)

    sec_from_last    : LEMMA s /= t AND from?(p,s,t) AND from?(q,s,t) IMPLIES 
                             q(1) = (trunc1(p) o rev(q))(length(trunc1(p) o rev(q))-2)

    prewalk_same     : LEMMA s=t AND length(p)=1 AND length(q)=1 AND from?(p,s,t) AND 
                             from?(q,s,t) IMPLIES p=q 


    compose_long     : LEMMA s /= t AND from?(p,s,t) AND from?(q,s,t) AND 
                             p(length(p)-2) /= q(length(q)-2) IMPLIES length(trunc1(p) o rev(q)) > 2 

    red_compos       : LEMMA s /= t AND path_from?(G,p,s,t) AND 
                             path_from?(G,q,s,t) AND p(length(p)-2) /= q(length(q)-2) 
                                IMPLIES reduced?(G,trunc1(p) o rev(q))

    cycl_red_compos  : LEMMA s /= t AND path_from?(G,p,s,t) AND 
                             path_from?(G,q,s,t) AND p(length(p)-2) /= q(length(q)-2) AND 
                             p(1) /= q(1) 
                                IMPLIES cyclically_reduced?(G,trunc1(p) o rev(q))

    walkers          : LEMMA finseq_appl(p)(0)=finseq_appl(q)(0) AND 
                             finseq_appl(p)(length(p)-1)=finseq_appl(q)(length(q)-1)
                           IMPLIES 
                             from?(p,finseq_appl(p)(0),finseq_appl(p)(length(p)-1)) AND 
                             from?(q,finseq_appl(p)(0),finseq_appl(p)(length(p)-1))

    path_one         : LEMMA s=t and path_from?(G,p,s,t) IMPLIES length(p)=1 OR circuit?(G,p)

    rev_eq           : LEMMA rev(p)=rev(q) IMPLIES p=q

    front_back       : LEMMA from?(p,s,t) AND from?(q,s,t) 
                              IMPLIES p(0)=q(0) AND  p(length(p)-1)=q(length(q)-1)

    walk_from_l      : LEMMA from?(p,s,t) AND s /= t IMPLIES length(p) >= 2

    plus_up          : LEMMA s /= t AND from?(p,s,t) AND from?(q,s,t)  IMPLIES 
    		            (trunc1(p) = trunc1(q) IMPLIES  p=q)


    two_walks        : LEMMA s /=t AND walk?(G,p) AND walk?(G,q) AND 
                             from?(p,s,t) AND from?(q,s,t) IMPLIES 
                                       pre_circuit?(G,trunc1(p) o rev(q))

    back_short       : LEMMA s /= t AND path_from?(G,p,s,t) AND 
                             path_from?(G,q,s,t) 
                          IMPLIES 
                             ( p(length(p)-2)=q(length(q)-2) AND p /= q IMPLIES  
                               (EXISTS (pp,qq: prewalk) : pp /= qq AND 
                                   path_from?(G,pp,s,p(length(p)-2)) AND 
                                   path_from?(G,qq,s,p(length(p)-2)) AND 
                                   length(pp)= length(p)-1 AND length(qq)=length(q)-1)
                             )

    from_rev         : LEMMA from?(p,s,t) IMPLIES from?(rev(p),t,s)

    front_short: LEMMA s /= t AND path_from?(G,p,s,t) AND path_from?(G,q,s,t)
                        IMPLIES 
                          ( p(1)=q(1) AND p /= q  IMPLIES  
                            (EXISTS (pp,qq: prewalk) :
                              pp /= qq AND path_from?(G,pp,t,p(1)) 
                              AND path_from?(G,qq,t,p(1))
                              AND length(pp)= length(p)-1 AND length(qq)=length(q)-1)
                          )

    add1_rev: LEMMA FORALL (w:Seq(G),x:(vert(G))): 
                     length(w)>1 AND x /= seq(w)(length(w)-1) 
                     IMPLIES add1(w,x)=trunc1(w) o rev(gen_seq2(G,x,seq(w)(length(w)-1)))
   

  END path_circ

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

  % Subtype TCC generated (at line 13, column 60) for  p
      % expected type  Seq[T](G)
  path_reduc_TCC1: OBLIGATION
    FORALL (G: graph[T], p: Path[T](G)): verts_in?[T](G, p);

  % Subtype TCC generated (at line 20, column 74) for  u
      % expected type  Seq[T](G)
  walks_concat_red_TCC1: OBLIGATION
    FORALL (G: graph[T], u, w: prewalk[T]):
      walk?(G, u) AND walk?(G, w) AND length(u) >= 2 AND length(w) >= 2
       IMPLIES verts_in?[T](G, u);

  % Subtype TCC generated (at line 21, column 38) for  w
      % expected type  Seq[T](G)
  walks_concat_red_TCC2: OBLIGATION
    FORALL (G: graph[T], u, w: prewalk[T]):
           walk?(G, u) AND walk?(G, w) AND length(u) >= 2 AND length(w) >= 2
       AND reduced?(G, u)
       IMPLIES verts_in?[T](G, w);

  % Subtype TCC generated (at line 21, column 47) for  length(u) - 1
      % expected type  below[length(u)]
  walks_concat_red_TCC3: OBLIGATION
    FORALL (G: graph[T], u, w: prewalk[T]):
           walk?(G, u) AND walk?(G, w) AND length(u) >= 2 AND length(w) >= 2
       AND reduced?(G, u) AND reduced?(G, w)
       IMPLIES length(u) - 1 >= 0 AND length(u) - 1 < length(u);

  % Subtype TCC generated (at line 21, column 64) for  0
      % expected type  below[length(w)]
  walks_concat_red_TCC4: OBLIGATION
    FORALL (G: graph[T], u, w: prewalk[T]):
           walk?(G, u) AND walk?(G, w) AND length(u) >= 2 AND length(w) >= 2
       AND reduced?(G, u) AND reduced?(G, w)
       IMPLIES 0 < length(w);

  % Subtype TCC generated (at line 22, column 29) for  length(u) - 2
      % expected type  below[length(u)]
  walks_concat_red_TCC5: OBLIGATION
    FORALL (G: graph[T], u, w: prewalk[T]):
           walk?(G, u) AND walk?(G, w) AND length(u) >= 2 AND length(w) >= 2
       AND reduced?(G, u) AND reduced?(G, w)
       AND finseq_appl[T](u)(length(u) - 1) = finseq_appl[T](w)(0)
       IMPLIES length(u) - 2 >= 0 AND length(u) - 2 < length(u);

  % Subtype TCC generated (at line 22, column 47) for  1
      % expected type  below[length(w)]
  walks_concat_red_TCC6: OBLIGATION
    FORALL (G: graph[T], u, w: prewalk[T]):
           walk?(G, u) AND walk?(G, w) AND length(u) >= 2 AND length(w) >= 2
       AND reduced?(G, u) AND reduced?(G, w)
       AND finseq_appl[T](u)(length(u) - 1) = finseq_appl[T](w)(0)
       IMPLIES 1 < length(w);

  % Subtype TCC generated (at line 22, column 69) for  trunc1(u) o w
      % expected type  Seq[T](G)
  walks_concat_red_TCC7: OBLIGATION
    FORALL (G: graph[T], u, w: prewalk[T]):
           finseq_appl[T](u)(length(u) - 2) /= finseq_appl[T](w)(1)
       AND finseq_appl[T](u)(length(u) - 1) = finseq_appl[T](w)(0)
       AND reduced?(G, w) AND reduced?(G, u) AND length(w) >= 2
       AND length(u) >= 2 AND walk?(G, w) AND walk?(G, u)
       IMPLIES
       length(o[T](trunc1[T](u), w)) > 0 AND
        verts_in?[T](G, o[T](trunc1[T](u), w));

  % Subtype TCC generated (at line 25, column 50) for  0
      % expected type  below[length(rev(q))]
  index_rev_TCC1: OBLIGATION
    FORALL (q: prewalk[T]):
      length(q) >= 2 AND length(rev(q)) = length(q) IMPLIES
       0 < length(rev[T](q));

  % Subtype TCC generated (at line 25, column 57) for  length(q) - 1
      % expected type  below[length(q)]
  index_rev_TCC2: OBLIGATION
    FORALL (q: prewalk[T]):
      length(q) >= 2 AND length(rev(q)) = length(q) IMPLIES
       length(q) - 1 >= 0 AND length(q) - 1 < length(q);

  % Subtype TCC generated (at line 26, column 50) for  1
      % expected type  below[length(rev(q))]
  index_rev_TCC3: OBLIGATION
    FORALL (q: prewalk[T]):
      length(q) >= 2 AND
       length(rev(q)) = length(q) AND
        finseq_appl(rev(q))(0) = finseq_appl[T](q)(length(q) - 1)
       IMPLIES 1 < length(rev[T](q));

  % Subtype TCC generated (at line 26, column 57) for  length(q) - 2
      % expected type  below[length(q)]
  index_rev_TCC4: OBLIGATION
    FORALL (q: prewalk[T]):
      length(q) >= 2 AND
       length(rev(q)) = length(q) AND
        finseq_appl(rev(q))(0) = finseq_appl[T](q)(length(q) - 1)
       IMPLIES length(q) - 2 >= 0 AND length(q) - 2 < length(q);

  % Subtype TCC generated (at line 30, column 56) for  length(q) - 1
      % expected type  below[length(rev(q))]
  ind_rev_rev_TCC1: OBLIGATION
    FORALL (q: prewalk[T]):
      length(q) >= 2 IMPLIES
       length(q) - 1 >= 0 AND length(q) - 1 < length(rev[T](q));

  % Subtype TCC generated (at line 30, column 73) for  0
      % expected type  below[length(q)]
  ind_rev_rev_TCC2: OBLIGATION
    FORALL (q: prewalk[T]): length(q) >= 2 IMPLIES 0 < length(q);

  % Subtype TCC generated (at line 31, column 51) for  length(q) - 2
      % expected type  below[length(rev(q))]
  ind_rev_rev_TCC3: OBLIGATION
    FORALL (q: prewalk[T]):
      length(q) >= 2 AND
       finseq_appl(rev(q))(length(q) - 1) = finseq_appl[T](q)(0)
       IMPLIES length(q) - 2 >= 0 AND length(q) - 2 < length(rev[T](q));

  % Subtype TCC generated (at line 31, column 68) for  1
      % expected type  below[length(q)]
  ind_rev_rev_TCC4: OBLIGATION
    FORALL (q: prewalk[T]):
      length(q) >= 2 AND
       finseq_appl(rev(q))(length(q) - 1) = finseq_appl[T](q)(0)
       IMPLIES 1 < length(q);

  % Subtype TCC generated (at line 34, column 33) for  1
      % expected type  below[length(p)]
  second_in_cat_TCC1: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      from?(q, s, t) AND from?(p, s, t) AND s /= t IMPLIES 1 < length(p);

  % Subtype TCC generated (at line 34, column 59) for  1
      % expected type  below[length((trunc1(p) o rev(q)))]
  second_in_cat_TCC2: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      from?(q, s, t) AND from?(p, s, t) AND s /= t IMPLIES
       1 < length((o[T](trunc1[T](p), rev[T](q))));

  % Subtype TCC generated (at line 34, column 46) for  p
      % expected type  Longprewalk[T]
  second_in_cat_TCC3: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      from?(q, s, t) AND from?(p, s, t) AND s /= t IMPLIES length(p) >= 2;

  % Subtype TCC generated (at line 37, column 29) for  1
      % expected type  below[length(q)]
  sec_from_last_TCC1: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      from?(q, s, t) AND from?(p, s, t) AND s /= t IMPLIES 1 < length(q);

  % Subtype TCC generated (at line 37, column 55) for
      % length(trunc1(p) o rev(q)) - 2
      % expected type  below[length((trunc1(p) o rev(q)))]
  sec_from_last_TCC2: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      from?(q, s, t) AND from?(p, s, t) AND s /= t IMPLIES
       length(o[T](trunc1[T](p), rev[T](q))) - 2 >= 0 AND
        length(o[T](trunc1[T](p), rev[T](q))) - 2 <
         length((o[T](trunc1[T](p), rev[T](q))));

  % Subtype TCC generated (at line 44, column 29) for  length(p) - 2
      % expected type  below[length(p)]
  compose_long_TCC1: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      s /= t AND from?(p, s, t) AND from?(q, s, t) IMPLIES
       length(p) - 2 >= 0 AND length(p) - 2 < length(p);

  % Subtype TCC generated (at line 44, column 47) for  length(q) - 2
      % expected type  below[length(q)]
  compose_long_TCC2: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      s /= t AND from?(p, s, t) AND from?(q, s, t) IMPLIES
       length(q) - 2 >= 0 AND length(q) - 2 < length(q);

  % Subtype TCC generated (at line 47, column 53) for  length(p) - 2
      % expected type  below[length(p)]
  red_compos_TCC1: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
      s /= t AND path_from?(G, p, s, t) AND path_from?(G, q, s, t) IMPLIES
       length(p) - 2 >= 0 AND length(p) - 2 < length(p);

  % Subtype TCC generated (at line 47, column 71) for  length(q) - 2
      % expected type  below[length(q)]
  red_compos_TCC2: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
      s /= t AND path_from?(G, p, s, t) AND path_from?(G, q, s, t) IMPLIES
       length(q) - 2 >= 0 AND length(q) - 2 < length(q);

  % Subtype TCC generated (at line 48, column 56) for  p
      % expected type  Longprewalk[T]
  red_compos_TCC3: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
      finseq_appl[T](p)(length(p) - 2) /= finseq_appl[T](q)(length(q) - 2)
       AND path_from?(G, q, s, t) AND path_from?(G, p, s, t) AND s /= t
       IMPLIES length(p) >= 2;

  % Subtype TCC generated (at line 48, column 49) for  trunc1(p) o rev(q)
      % expected type  Seq[T](G)
  red_compos_TCC4: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
      finseq_appl[T](p)(length(p) - 2) /= finseq_appl[T](q)(length(q) - 2)
       AND path_from?(G, q, s, t) AND path_from?(G, p, s, t) AND s /= t
       IMPLIES
       length(o[T](trunc1[T](p), rev[T](q))) > 0 AND
        verts_in?[T](G, o[T](trunc1[T](p), rev[T](q)));

  % Subtype TCC generated (at line 52, column 29) for  1
      % expected type  below[length(p)]
  cycl_red_compos_TCC1: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
      s /= t AND
       path_from?(G, p, s, t) AND
        path_from?(G, q, s, t) AND
         finseq_appl[T](p)(length(p) - 2) /= finseq_appl[T](q)(length(q) - 2)
       IMPLIES 1 < length(p);

  % Subtype TCC generated (at line 52, column 37) for  1
      % expected type  below[length(q)]
  cycl_red_compos_TCC2: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
      s /= t AND
       path_from?(G, p, s, t) AND
        path_from?(G, q, s, t) AND
         finseq_appl[T](p)(length(p) - 2) /= finseq_appl[T](q)(length(q) - 2)
       IMPLIES 1 < length(q);

  % Subtype TCC generated (at line 55, column 42) for  0
      % expected type  below[length(p)]
  walkers_TCC1: OBLIGATION FORALL (p: prewalk[T]): 0 < length(p);

  % Subtype TCC generated (at line 56, column 42) for  length(p) - 1
      % expected type  below[length(p)]
  walkers_TCC2: OBLIGATION
    FORALL (p, q: prewalk[T]):
      finseq_appl(p)(0) = finseq_appl(q)(0) IMPLIES
       length(p) - 1 >= 0 AND length(p) - 1 < length(p);

  % Subtype TCC generated (at line 56, column 70) for  length(q) - 1
      % expected type  below[length(q)]
  walkers_TCC3: OBLIGATION
    FORALL (p, q: prewalk[T]):
      finseq_appl(p)(0) = finseq_appl(q)(0) IMPLIES
       length(q) - 1 >= 0 AND length(q) - 1 < length(q);

  % Subtype TCC generated (at line 61, column 89) for  p
      % expected type  Seq[T](G)
  path_one_TCC1: OBLIGATION
    FORALL (G: graph[T], p: prewalk[T], s, t: T):
      path_from?(G, p, s, t) AND s = t AND NOT length(p) = 1 IMPLIES
       verts_in?[T](G, p);

  % Subtype TCC generated (at line 66, column 43) for  0
      % expected type  below[length(q)]
  front_back_TCC1: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      from?(q, s, t) AND from?(p, s, t) IMPLIES 0 < length(q);

  % Subtype TCC generated (at line 71, column 36) for  q
      % expected type  Longprewalk[T]
  plus_up_TCC1: OBLIGATION
    FORALL (p, q: prewalk[T], s, t: T):
      from?(q, s, t) AND from?(p, s, t) AND s /= t IMPLIES length(q) >= 2;

  % Subtype TCC generated (at line 76, column 52) for  trunc1(p) o rev(q)
      % expected type  prewalk[T]
  two_walks_TCC1: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
           from?(q, s, t) AND from?(p, s, t) AND walk?(G, q) AND walk?(G, p)
       AND s /= t
       IMPLIES length(o[T](trunc1[T](p), rev[T](q))) > 0;

  % Subtype TCC generated (at line 88, column 54) for  rev(p)
      % expected type  prewalk[T]
  from_rev_TCC1: OBLIGATION
    FORALL (p: prewalk[T], s, t: T):
      from?(p, s, t) IMPLIES length(rev[T](p)) > 0;

  % Subtype TCC generated (at line 92, column 28) for  1
      % expected type  below[length(p)]
  front_short_TCC1: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
      path_from?(G, q, s, t) AND path_from?(G, p, s, t) AND s /= t IMPLIES
       1 < length(p);

  % Subtype TCC generated (at line 92, column 33) for  1
      % expected type  below[length(q)]
  front_short_TCC2: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], s, t: T):
      path_from?(G, q, s, t) AND path_from?(G, p, s, t) AND s /= t IMPLIES
       1 < length(q);

  % Subtype TCC generated (at line 100, column 47) for  length(w) - 1
      % expected type  below[w`length]
  add1_rev_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Seq[T](G), x: (vert(G))):
      length(w) > 1 IMPLIES length(w) - 1 >= 0 AND length(w) - 1 < w`length;

  % Subtype TCC generated (at line 101, column 44) for  w
      % expected type  Longprewalk[T]
  add1_rev_TCC2: OBLIGATION
    FORALL (G: graph[T], w: Seq[T](G), x: (vert(G))):
      length(w) > 1 AND x /= seq(w)(length(w) - 1) IMPLIES length(w) >= 2;

  % Subtype TCC generated (at line 101, column 66) for  seq(w)(length(w) - 1)
      % expected type  (vert(G))
  add1_rev_TCC3: OBLIGATION
    FORALL (G: graph[T], w: Seq[T](G), x: (vert(G))):
      length(w) > 1 AND x /= seq(w)(length(w) - 1) IMPLIES
       vert(G)(seq(w)(length(w) - 1));


body:
  subgraphs_from_walk[T: TYPE]: THEORY

  BEGIN
     IMPORTING graphs[T], walks[T], subgraphs[T]
     
     G,GG: VAR graph[T]
     t,t1,t2,v: VAR T
     i: VAR nat
     e: VAR doubleton[T]

     G_from(G, (w: Walk(G))): Subgraph(G) = (# vert  := verts_of(w),
                                               edges := edges_of(w) #)


     G_from_vert     : LEMMA FORALL (w: Walk(G)): vert(G_from(G,w)) = verts_of(w)


     vert_G_from     : LEMMA FORALL (w: Walk(G), i: below(length(w))): 
                                        vert(G_from(G, w))(w(i))

     edge?_G_from    : LEMMA FORALL (w: Walk(G), i: below(length(w)-1)): 
                                        edge?(G_from(G, w))(w(i), w(i+1)) 

     edge?_G_from_rev: LEMMA FORALL (w: Walk(G), i: below(length(w)-1)): 
                                       edge?(G_from(G, w))(w(i+1), w(i))


     vert_G_from_not : LEMMA FORALL (w: Walk(G)): 
                         subset?(vert(G_from(G, w)), vert(GG)) AND
                         NOT  verts_of(w)(v)
                       IMPLIES
                          subset?(vert(G_from(G, w)), remove[T](v, vert(GG)))

     IMPORTING graph_ops[T]

     del_vert_subgraph: LEMMA FORALL (w: Walk(G), v: (vert(GG))): 
                                subgraph?(G_from(G, w), GG) AND
                                NOT verts_of(w)(v) IMPLIES
                                      subgraph?(G_from(G, w), del_vert(GG, v))
          
  END subgraphs_from_walk

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

  % Subtype TCC generated (at line 11, column 42) for
      % (# vert := verts_of(w), edges := edges_of(w) #)
      % expected type  Subgraph[T](G)
  G_from_TCC1: OBLIGATION
    FORALL (G: graph[T], (w: Walk[T](G))):
      (FORALL (e: doubleton[T]):
         edges_of[T](w)(e) IMPLIES
          (FORALL (x: T): e(x) IMPLIES verts_of[T](w)(x)))
       AND
       subgraph?[T]((# vert := verts_of[T](w), edges := edges_of[T](w) #), G);

  % Subtype TCC generated (at line 22, column 60) for  i
      % expected type  below[length(w)]
  edge?_G_from_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Walk[T](G), i: below(length(w) - 1)):
      i < length(w);

  % Subtype TCC generated (at line 22, column 66) for  i + 1
      % expected type  below[length(w)]
  edge?_G_from_TCC2: OBLIGATION
    FORALL (G: graph[T], w: Walk[T](G), i: below(length(w) - 1)):
      i + 1 < length(w);


body:
  circuit_deg[T: TYPE]: THEORY

  BEGIN

     IMPORTING graph_deg[T], circuits[T], subgraphs_from_walk[T]

     G: VAR graph[T]

     e_duo(e1,e2: doubleton[T]): finite_set[doubleton[T]] =
                     add[doubleton[T]](e1,singleton[doubleton[T]](e2))

     z: VAR T
     cir_deg_G: LEMMA (EXISTS (a,b: (vert(G))): vert(G)(z) AND
                            a /= b AND edge?(G)(a,z) AND edge?(G)(b,z) ) IMPLIES
                                deg(z,G) >= 2
     
     circuit_deg: LEMMA FORALL (w: Walk(G),i: below(length(w))): circuit?(G,w) 
                              IMPLIES deg(w(i),G_from(G,w)) >= 2

   
     circuit_subgraph_len_1: LEMMA FORALL (w: Walk(G)): circuit?(G,w) 
                                  IMPLIES card(vert(G_from(G,w))) > 1
   
  END circuit_deg

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

  % Subtype TCC generated (at line 17, column 74) for  w
      % expected type  Seq[T](G)
  circuit_deg_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Walk[T](G), i: below(length(w))):
      verts_in?[T](G, w);

  % Subtype TCC generated (at line 21, column 65) for  w
      % expected type  Seq[T](G)
  circuit_subgraph_len_1_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Walk[T](G)): verts_in?[T](G, w);


body:
  graph_inductions[T: TYPE]: THEORY

  BEGIN


    IMPORTING graphs[T]

    G,GG,GGG: VAR graph[T]
    P: VAR pred[graph[T]]
    n: VAR nat

    size_prep              : LEMMA (FORALL G : P(G)) IFF 
                                        (FORALL n, G : size(G) = n IMPLIES P(G)) 


    graph_induction_vert    : THEOREM (FORALL G:
                                  (FORALL GG: size(GG) < size(G) IMPLIES P(GG))
                                                  IMPLIES P(G))
                                    IMPLIES (FORALL G: P(G))


    graph_induction_vert_not: THEOREM (FORALL G: P(G)
                                 IMPLIES
                               (EXISTS GG: size(GG) < size(G) AND
                                              P(GG)))
                             IMPLIES (FORALL G: NOT P(G))

    IMPORTING graph_ops[T]

    num_edges_prep         : LEMMA (FORALL G : P(G)) IFF 
                                     (FORALL n, G : num_edges(G) = n IMPLIES P(G)) 

    graph_induction_edge   : THEOREM (FORALL G:
                            (FORALL GG: num_edges(GG) < num_edges(G) IMPLIES P(GG))
                                                  IMPLIES P(G))
                                    IMPLIES (FORALL G: P(G))


  END graph_inductions


body:
  trees[T: TYPE]: THEORY
  BEGIN

     IMPORTING graph_deg[T], graph_ops[T], subgraphs[T], graph_inductions[T]

     G,GP,C,GG: VAR graph[T]
     u,v: VAR T
     k,n,m: VAR nat

     tree?(G): RECURSIVE bool = card[T](vert(G)) = 1 OR
                           (EXISTS (v: (vert(G))): deg(v,G) = 1 AND 
                                    tree?(del_vert[T](G,v)))
               MEASURE size(G)
                               
     tree_nonempty: LEMMA tree?(G) IMPLIES NOT empty?(G)

     Tree: TYPE = {G: graph[T] | tree?(G)}


     tree_edge_card: LEMMA tree?(G) IMPLIES 
               size(G)= card[doubleton[T]](edges(G))+1

     tree_edge_k: LEMMA (FORALL G,v,k: tree?(G) AND size(G) = k+2 AND vert(G)(v)
  	               IMPLIES deg(v,G)>0 OR card[T](vert(G)) = 1) IMPLIES 
                              (FORALL G,v: tree?(G) AND vert(G)(v) 
                                IMPLIES deg(v,G)>0 OR card[T](vert(G)) = 1)

     tree_edge: LEMMA (FORALL G,v,k: tree?(G) AND size(G) = k+2 AND vert(G)(v)
  	                 IMPLIES deg(v,G)>0 OR card[T](vert(G)) = 1)

     tree_edge_all: LEMMA tree?(G) AND vert(G)(v) IMPLIES deg(v,G)>0 OR 
  	                  card[T](vert(G)) = 1 

     del_tree_k: LEMMA ( FORALL G,v,k: tree?(G) and size(G) = k+1 AND 
                         vert(G)(v) AND deg(v,G)=1 
                        IMPLIES tree?(del_vert(G,v))) 
                            IMPLIES (FORALL G,v: tree?(G) AND 
                                                 vert(G)(v) AND 
                                                 deg(v,G)=1 
                                         IMPLIES tree?(del_vert(G,v)))

    del_tree: LEMMA ( FORALL G,v,k: tree?(G) AND size(G) = k+1 AND 
                                    vert(G)(v) AND deg(v,G)=1 
                             IMPLIES tree?(del_vert(G,v)))


    del_tree_all: LEMMA tree?(G) AND vert(G)(v) AND deg(v,G)=1 IMPLIES
  	                     tree?(del_vert(G,v))



  END trees

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

  % Termination TCC generated (at line 12, column 34) for
      % tree?(del_vert[T](G, v))
  tree?_TCC1: OBLIGATION
    FORALL (G: graph[T]):
      NOT card[T](vert(G)) = 1 IMPLIES
       (FORALL (v: (vert(G))):
          deg(v, G) = 1 IMPLIES size[T](del_vert[T](G, v)) < size[T](G));


body:
  tree_circ[T: TYPE]: THEORY
  BEGIN

     IMPORTING trees[T], graphs[T], graph_deg[T], graph_ops[T],
               circuit_deg[T], subgraphs_from_walk[T]  

     G,GP,C,GG: VAR graph[T]

     GT: VAR Tree

     IMPORTING abstract_min

     exists_c_tree: LEMMA FORALL (w: Walk(GT)): 
                                EXISTS (t: Tree[T]): subgraph?(G_from(GT, w), t)

     c_tree(TR: Tree, C: Subgraph(TR)): Tree =
              min[Tree[T],(LAMBDA GT: size(GT)),
                           (LAMBDA GT: subgraph?(C,GT))]

     tree_containing_lem: LEMMA FORALL (w: Walk(GT)): 
           tree?(c_tree(GT,G_from(GT,w))) AND
           subgraph?(G_from(GT,w),c_tree(GT,G_from(GT,w))) AND
           (FORALL (GG: Tree): subgraph?(G_from(GT,w),GG) IMPLIES
                                   size(c_tree(GT,G_from(GT,w))) <= size(GG))

     tree_deg: LEMMA FORALL (w: Walk(GT), v: T): 
                   vert(c_tree(GT,G_from(GT,w)))(v) AND 
                   deg(v, G_from(GT,w)) >= 2
                       IMPLIES  deg(v, c_tree(GT,G_from(GT,w))) >= 2

     small_tree_lem: LEMMA FORALL (w: Walk(G)): tree?(G) =>
                                   size(G) <= 1 IMPLIES NOT circuit?(G,w)

     tree_no_circuits: THEOREM (FORALL (w: Walk(G)): tree?(G) =>
                                     NOT circuit?(G,w))


  END tree_circ

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

  % Assuming TCC generated (at line 17, column 12) for
      % min[Tree[T], (LAMBDA GT: size(GT)), (LAMBDA GT: subgraph?(C, GT))]
      % generated from assumption abstract_min.T_ne
  c_tree_TCC1: OBLIGATION
    FORALL (TR: Tree[T], C: Subgraph[T](TR)):
      EXISTS (t: Tree[T]): subgraph?[T](C, t);

  % Subtype TCC generated (at line 32, column 69) for  w
      % expected type  Seq[T](G)
  small_tree_lem_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Walk[T](G)):
      size(G) <= 1 AND tree?(G) IMPLIES verts_in?[T](G, w);

  % Subtype TCC generated (at line 35, column 50) for  w
      % expected type  Seq[T](G)
  tree_no_circuits_TCC1: OBLIGATION
    FORALL (G: graph[T], w: Walk[T](G)): tree?(G) IMPLIES verts_in?[T](G, w);


body:
  tree_paths[T: TYPE]: THEORY
  BEGIN

     IMPORTING tree_circ[T], paths[T], path_circ[T], circuits[T], cycles[T]

     u,v: VAR T
   
     m,n: VAR nat
     G: VAR graph[T]
     p,q: VAR prewalk

     dual_paths?(G,(p:Path(G)),(q:Path(G))):bool = p /= q AND p(0)=q(0)
      AND p(length(p)-1)=q(length(q)-1)

     Dual_paths(G):TYPE = {((p:Path(G)),(q:Path(G))) | dual_paths?(G,p,q)}

     IMPORTING abstract_min


     min_dual_paths(G: Graph[T], r: Path(G), s: Path(G) | dual_paths?(G,r,s)): 
              Dual_paths(G) = min[[Path(G),Path(G)],
     (LAMBDA (r:Path(G),s:Path(G)): length(r)+length(s)),
     (LAMBDA (r:Path(G),s:Path(G)): dual_paths?(G,r,s))]


     is_min_dual?(G,(p:Path(G)),(q:Path(G))):bool = dual_paths?(G,p,q) 
                        AND FORALL (r:Path(G),s:Path(G)): dual_paths?(G,r,s) 
                              IMPLIES  length(r) + length(s) >= length(p)+length(q)

     min_dual_def: LEMMA FORALL (G: Graph[T], r: Path(G), s: Path(G)):
                            dual_paths?(G,r,s) IMPLIES
                            is_min_dual?(G,proj_1(min_dual_paths(G,r,s)),
                                           proj_2(min_dual_paths(G,r,s))) 
                        AND  
                            dual_paths?(G,proj_1(min_dual_paths(G,r,s)),
                                          proj_2(min_dual_paths(G,r,s)))


     min_dual_exists: LEMMA FORALL (G: Graph[T], r: Path(G), s: Path(G)):
           dual_paths?(G,r,s) IMPLIES EXISTS (p,q:Path(G)): is_min_dual?(G,p,q)

     dual_path_trunc: LEMMA  FORALL (G: Graph[T], p: Path(G), q: Path(G)): 
       dual_paths?(G,p,q) IMPLIES 
           length(p)>1 AND length(q)>1 AND path?[T](G, p ^ (0, length(p) - 2)) 
           AND path?[T](G, q ^ (0, length(q) - 2)) 
           AND path?[T](G, p ^ (1, length(p) - 1)) AND path?[T](G, q ^ (1, length(q) - 1))

     dual_path_length: LEMMA FORALL (G: Graph[T], p: Path(G), q: Path(G)): 
           dual_paths?(G,p,q) IMPLIES length(p)>2 OR length(q)>2

     min_dual_reduc: LEMMA  FORALL (G: Graph[T], p: Path(G), q: Path(G)): 
           is_min_dual?(G,p,q) IMPLIES p(1) /= q(1) AND p(length(p)-2) /= q(length(q)-2)


     min_dual_distin: LEMMA  FORALL (G: Graph[T], p: Path(G), q: Path(G)): 
                is_min_dual?(G,p,q) IMPLIES 
                           (FORALL (i,j:nat):i<length(p)-1 AND j<length(q)-1 AND p(i)=q(j) 
                                        IMPLIES (i=0 AND j=0))

     dual_cycle: LEMMA  FORALL (G: Graph[T], p: Path(G), q: Path(G)): 
                    dual_paths?(G,p,q) AND 
                    (FORALL (i,j:nat):i<length(p)-1 AND j<length(q)-1 AND p(i)=q(j) 
                                         IMPLIES (i=0 AND j=0)) 
                        IMPLIES cycle?(G,trunc1(p) o rev(q)) 

                                      
     tree_one_path: LEMMA  tree?(G) AND
                                 path_from?(G,p,u,v) AND
                                 path_from?(G,q,u,v) IMPLIES
                                      p=q


  END tree_paths

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

  % Subtype TCC generated (at line 12, column 62) for  0
      % expected type  below[length(p)]
  dual_paths?_TCC1: OBLIGATION
    FORALL (G: graph[T], (p: Path[T](G)), (q: Path[T](G))):
      p /= q IMPLIES 0 < length(p);

  % Subtype TCC generated (at line 12, column 67) for  0
      % expected type  below[length(q)]
  dual_paths?_TCC2: OBLIGATION
    FORALL (G: graph[T], (p: Path[T](G)), (q: Path[T](G))):
      p /= q IMPLIES 0 < length(q);

  % Subtype TCC generated (at line 13, column 10) for  length(p) - 1
      % expected type  below[length(p)]
  dual_paths?_TCC3: OBLIGATION
    FORALL (G: graph[T], (p: Path[T](G)), (q: Path[T](G))):
      finseq_appl[T](p)(0) = finseq_appl[T](q)(0) AND p /= q IMPLIES
       length(p) - 1 >= 0 AND length(p) - 1 < length(p);

  % Subtype TCC generated (at line 13, column 25) for  length(q) - 1
      % expected type  below[length(q)]
  dual_paths?_TCC4: OBLIGATION
    FORALL (G: graph[T], (p: Path[T](G)), (q: Path[T](G))):
      finseq_appl[T](p)(0) = finseq_appl[T](q)(0) AND p /= q IMPLIES
       length(q) - 1 >= 0 AND length(q) - 1 < length(q);

  % Assuming TCC generated (at line 21, column 28) for
      % min
      %     [[Path(G), Path(G)],
      %      (LAMBDA (r: Path(G), s: Path(G)): length(r) + length(s)),
      %      (LAMBDA (r: Path(G), s: Path(G)): dual_paths?(G, r, s))]
      % generated from assumption abstract_min.T_ne
  min_dual_paths_TCC1: OBLIGATION
    FORALL (G: Graph[T], r: Path[T](G),
            s: Path[T](G) | dual_paths?(G, r, s)):
      EXISTS (t: [Path[T](G), Path[T](G)]): dual_paths?(G, t`1, t`2);

  % Subtype TCC generated (at line 21, column 28) for
      % min
      %     [[Path(G), Path(G)],
      %      (LAMBDA (r: Path(G), s: Path(G)): length(r) + length(s)),
      %      (LAMBDA (r: Path(G), s: Path(G)): dual_paths?(G, r, s))]
      % expected type  Dual_paths(G)
  min_dual_paths_TCC2: OBLIGATION
    FORALL (G: Graph[T], r: Path[T](G),
            s: Path[T](G) | dual_paths?(G, r, s)):
      dual_paths?(G,
                  min
                      [[Path[T](G), Path[T](G)],
                       (LAMBDA (r: Path[T](G), s: Path[T](G)):
                          length(r) + length(s)),
                       (LAMBDA (r: Path[T](G), s: Path[T](G)):
                          dual_paths?(G, r, s))]`1,
                  min
                      [[Path[T](G), Path[T](G)],
                       (LAMBDA (r: Path[T](G), s: Path[T](G)):
                          length(r) + length(s)),
                       (LAMBDA (r: Path[T](G), s: Path[T](G)):
                          dual_paths?(G, r, s))]`2);

  % Subtype TCC generated (at line 44, column 61) for  length(p) - 2
      % expected type  nat
  dual_path_trunc_TCC1: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      length(q) > 1 AND length(p) > 1 AND dual_paths?(G, p, q) IMPLIES
       length(p) - 2 >= 0;

  % Subtype TCC generated (at line 44, column 53) for  p ^ (0, length(p) - 2)
      % expected type  prewalk[T]
  dual_path_trunc_TCC2: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      length(q) > 1 AND length(p) > 1 AND dual_paths?(G, p, q) IMPLIES
       length(^[T](p, (0, length(p) - 2))) > 0;

  % Subtype TCC generated (at line 45, column 33) for  length(q) - 2
      % expected type  nat
  dual_path_trunc_TCC3: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      path?[T](G, p ^ (0, length(p) - 2)) AND
       length(q) > 1 AND length(p) > 1 AND dual_paths?(G, p, q)
       IMPLIES length(q) - 2 >= 0;

  % Subtype TCC generated (at line 45, column 25) for  q ^ (0, length(q) - 2)
      % expected type  prewalk[T]
  dual_path_trunc_TCC4: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      path?[T](G, p ^ (0, length(p) - 2)) AND
       length(q) > 1 AND length(p) > 1 AND dual_paths?(G, p, q)
       IMPLIES length(^[T](q, (0, length(q) - 2))) > 0;

  % Subtype TCC generated (at line 46, column 33) for  length(p) - 1
      % expected type  nat
  dual_path_trunc_TCC5: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
           path?[T](G, q ^ (0, length(q) - 2))
       AND path?[T](G, p ^ (0, length(p) - 2)) AND length(q) > 1
       AND length(p) > 1 AND dual_paths?(G, p, q)
       IMPLIES length(p) - 1 >= 0;

  % Subtype TCC generated (at line 46, column 25) for  p ^ (1, length(p) - 1)
      % expected type  prewalk[T]
  dual_path_trunc_TCC6: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
           path?[T](G, q ^ (0, length(q) - 2))
       AND path?[T](G, p ^ (0, length(p) - 2)) AND length(q) > 1
       AND length(p) > 1 AND dual_paths?(G, p, q)
       IMPLIES length(^[T](p, (1, length(p) - 1))) > 0;

  % Subtype TCC generated (at line 46, column 73) for  length(q) - 1
      % expected type  nat
  dual_path_trunc_TCC7: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
           path?[T](G, p ^ (1, length(p) - 1))
       AND path?[T](G, q ^ (0, length(q) - 2))
       AND path?[T](G, p ^ (0, length(p) - 2)) AND length(q) > 1
       AND length(p) > 1 AND dual_paths?(G, p, q)
       IMPLIES length(q) - 1 >= 0;

  % Subtype TCC generated (at line 46, column 65) for  q ^ (1, length(q) - 1)
      % expected type  prewalk[T]
  dual_path_trunc_TCC8: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
           path?[T](G, p ^ (1, length(p) - 1))
       AND path?[T](G, q ^ (0, length(q) - 2))
       AND path?[T](G, p ^ (0, length(p) - 2)) AND length(q) > 1
       AND length(p) > 1 AND dual_paths?(G, p, q)
       IMPLIES length(^[T](q, (1, length(q) - 1))) > 0;

  % Subtype TCC generated (at line 52, column 39) for  1
      % expected type  below[length(p)]
  min_dual_reduc_TCC1: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      is_min_dual?(G, p, q) IMPLIES 1 < length(p);

  % Subtype TCC generated (at line 52, column 47) for  1
      % expected type  below[length(q)]
  min_dual_reduc_TCC2: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      is_min_dual?(G, p, q) IMPLIES 1 < length(q);

  % Subtype TCC generated (at line 52, column 56) for  length(p) - 2
      % expected type  below[length(p)]
  min_dual_reduc_TCC3: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      finseq_appl[T](p)(1) /= finseq_appl[T](q)(1) AND is_min_dual?(G, p, q)
       IMPLIES length(p) - 2 >= 0 AND length(p) - 2 < length(p);

  % Subtype TCC generated (at line 52, column 74) for  length(q) - 2
      % expected type  below[length(q)]
  min_dual_reduc_TCC4: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      finseq_appl[T](p)(1) /= finseq_appl[T](q)(1) AND is_min_dual?(G, p, q)
       IMPLIES length(q) - 2 >= 0 AND length(q) - 2 < length(q);

  % Subtype TCC generated (at line 57, column 81) for  i
      % expected type  below[length(p)]
  min_dual_distin_TCC1: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      is_min_dual?(G, p, q) IMPLIES
       (FORALL (i, j: nat):
          j < length(q) - 1 AND i < length(p) - 1 IMPLIES i < length(p));

  % Subtype TCC generated (at line 57, column 86) for  j
      % expected type  below[length(q)]
  min_dual_distin_TCC2: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      is_min_dual?(G, p, q) IMPLIES
       (FORALL (i, j: nat):
          j < length(q) - 1 AND i < length(p) - 1 IMPLIES j < length(q));

  % Subtype TCC generated (at line 62, column 74) for  i
      % expected type  below[length(p)]
  dual_cycle_TCC1: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      dual_paths?(G, p, q) IMPLIES
       (FORALL (i, j: nat):
          j < length(q) - 1 AND i < length(p) - 1 IMPLIES i < length(p));

  % Subtype TCC generated (at line 62, column 79) for  j
      % expected type  below[length(q)]
  dual_cycle_TCC2: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      dual_paths?(G, p, q) IMPLIES
       (FORALL (i, j: nat):
          j < length(q) - 1 AND i < length(p) - 1 IMPLIES j < length(q));

  % Subtype TCC generated (at line 64, column 46) for  p
      % expected type  Longprewalk[T]
  dual_cycle_TCC3: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      (dual_paths?(G, p, q) AND
        (FORALL (i, j: nat):
           i < length(p) - 1 AND
            j < length(q) - 1 AND finseq_appl[T](p)(i) = finseq_appl[T](q)(j)
            IMPLIES (i = 0 AND j = 0)))
       IMPLIES length(p) >= 2;

  % Subtype TCC generated (at line 64, column 39) for  trunc1(p) o rev(q)
      % expected type  Seq[T](G)
  dual_cycle_TCC4: OBLIGATION
    FORALL (G: Graph[T], p: Path[T](G), q: Path[T](G)):
      (dual_paths?(G, p, q) AND
        (FORALL (i, j: nat):
           i < length(p) - 1 AND
            j < length(q) - 1 AND finseq_appl[T](p)(i) = finseq_appl[T](q)(j)
            IMPLIES (i = 0 AND j = 0)))
       IMPLIES
       length(o[T](trunc1[T](p), rev[T](q))) > 0 AND
        verts_in?[T](G, o[T](trunc1[T](p), rev[T](q)));


body:
  graph_pair[T: TYPE]: THEORY
  BEGIN

    i,j,k,l,m,n,h,g: VAR nat

    lsth(p1:[nat,nat], p2:[nat,nat]): bool = LET (i,j) = p1, (k,l) = p2 IN
                                                 i<k OR (i=k AND j<l)


    wf_lsth: LEMMA well_founded?[[nat,nat]](lsth) 

    p: VAR [[nat,nat]-> bool]

    gh: VAR [nat,nat]

    NAT_pair_induct: LEMMA (FORALL gh: LET (g,h) = gh IN 
                             (FORALL (l,m): lsth((l,m),(g,h))
  	                      IMPLIES p((l,m))) IMPLIES p((g,h)))
         	                  	IMPLIES (FORALL (i,j): p((i,j)))

    IMPORTING graphs[T]


    G,H,GG,HH: VAR graph[T]

    P,Q: VAR [graph[T],graph[T] -> bool]

    size_up: LEMMA (FORALL (G,H): Q((G,H))) IFF 
                       (FORALL (G,H): (FORALL (m,n) :
  	                (size(G),size(H)) = (m, n) IMPLIES Q((G,H))))

    graph_induct_pair    : THEOREM (FORALL (G,H): (FORALL (GG,HH): 
                                   (size(GG) < size(G) OR
                                   (size(GG)=size(G) AND size(HH) < size(H) ))
                                      IMPLIES Q((GG,HH)))
                                         IMPLIES Q((G,H)))
                                            IMPLIES (FORALL (G,H): Q((G,H)))

    graph_induct_pair_B  : THEOREM (FORALL (G,H): (FORALL (GG,HH): 
                                    lsth((size(GG),size(HH)),(size(G),size(H))) 
                                    IMPLIES Q((GG,HH)))
                                       IMPLIES Q((G,H)))
                                          IMPLIES (FORALL (G,H): Q((G,H)))

    graph_pair_induct_not: THEOREM (FORALL (G,H): P(G,H) IMPLIES
                                     (EXISTS (GG,HH): (size(GG) < size(G) 
  	                           OR (size(GG) = size(G) AND size(HH) < size(H)))
  			           AND P(GG,HH)))
                                       IMPLIES (FORALL (G,H): NOT P(G,H))



  END graph_pair


body:
  graph_conn_defs[T: TYPE]: THEORY

  BEGIN

     IMPORTING graph_deg[T]

     G,G1,G2: VAR graph[T]

     connected?(G): RECURSIVE bool = singleton?(G) OR
                                     (EXISTS (v: (vert(G))): deg(v,G) > 0 
                                         AND connected?(del_vert(G,v))) 
                    MEASURE size(G)

     IMPORTING walks[T]

     path_connected?(G): bool = NOT empty?(G) AND
                                (FORALL (x,y: (vert(G))): % x /= y IMPLIES
                                     (EXISTS (w: Walk(G)): seq(w)(0) = x AND 
                                                           seq(w)(length(w)-1) = y))


     H1,H2: VAR graph[T]
     piece_connected?(G): bool = NOT empty?(G) AND
                                 (FORALL H1,H2: G = union(H1,H2) AND
                                           NOT empty?(H1) AND NOT empty?(H2)
                                    IMPLIES NOT empty?(intersection(vert(H1),
                                                                     vert(H2))))

     complected?(G): bool = IF isolated?(G) THEN singleton?(G) 
                            ELSIF (EXISTS (v: (vert(G))): deg(v,G) = 1) THEN
                             (EXISTS (x: (vert(G))): deg(x,G) = 1 AND
                                connected?(del_vert(G,x)))
                            ELSE
                               (EXISTS (e: (edges(G))):
                                connected?(del_edge(G,e)))
                            ENDIF


  END graph_conn_defs

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

  % Termination TCC generated (at line 11, column 43) for
      % connected?(del_vert(G, v))
  connected?_TCC1: OBLIGATION
    FORALL (G: graph[T]):
      NOT singleton?(G) IMPLIES
       (FORALL (v: (vert(G))):
          deg(v, G) > 0 IMPLIES size[T](del_vert[T](G, v)) < size[T](G));

  % Subtype TCC generated (at line 18, column 64) for  0
      % expected type  below[w`length]
  path_connected?_TCC1: OBLIGATION
    FORALL (G: graph[T]):
      NOT empty?(G) IMPLIES
       (FORALL (x, y: (vert(G)), w: Walk[T](G)): 0 < w`length);

  % Subtype TCC generated (at line 19, column 64) for  length(w) - 1
      % expected type  below[w`length]
  path_connected?_TCC2: OBLIGATION
    FORALL (G: graph[T]):
      NOT empty?(G) IMPLIES
       (FORALL (x, y: (vert(G)), w: Walk[T](G)):
          seq(w)(0) = x IMPLIES
           length(w) - 1 >= 0 AND length(w) - 1 < w`length);


body:
  graph_complected[T: TYPE]: THEORY

  BEGIN

     IMPORTING graph_conn_defs[T], graph_ops[T], graph_deg[T],
               graph_inductions[T]

     G,G1,G2: VAR graph[T]
    
     v,v1,v2: VAR T
     e: VAR doubleton[T]
   

  %Consider moving below to graphs module.

     two_vertices: LEMMA FORALL (v1,v2: T): edges(G)(e) AND e(v2) AND
                              vert(G) = dbl(v1, v2) IMPLIES e(v1)

     sub_T: LEMMA FORALL (v: (vert(G))): 
                            NOT empty?(vert(del_vert(G,v))) AND deg(v,G) = 0
                               IMPLIES NOT connected?(G)

     rev_lem2  : LEMMA FORALL (v: (vert(G))): 
                       connected?(G) AND
                       deg(v, G) = 1 IMPLIES
                               connected?(del_vert(G, v))


     conn_lem2 : LEMMA FORALL (v: (vert(G))): 
                       connected?(G) AND NOT isolated?(G) AND
                       deg(v, G) = 1 IMPLIES
                           (EXISTS (x: (vert(G))): deg(x, G) = 1 
                                       AND connected?(del_vert(G, x)))
   
     del_rem_lem: LEMMA edges(G)(e) AND e(v)
                        IMPLIES del_vert(del_edge(G, e), v) = del_vert(G, v)

     conn_lem3 : LEMMA connected?(G) AND NOT isolated?(G) AND
                       NOT (EXISTS (v: (vert(G))): deg(v, G) = 1)
                       IMPLIES
                          (EXISTS (e: (edges(G))): connected?(del_edge(G, e)))


     BIG       : LEMMA connected?(del_edge(G, e)) IMPLIES connected?(G)

     conn_lem6 : LEMMA  edges(G)(e) AND connected?(del_edge(G, e)) 
                        AND NOT isolated?(G) AND
                        NOT (EXISTS (v: (vert(G))): deg(v, G) = 1)
                        IMPLIES
                           connected?(G )

     conn_eq_compl: LEMMA connected?(G) IFF
                          (IF isolated?(G) THEN singleton?(G) 
                          ELSIF (EXISTS (v: (vert(G))): deg(v,G) = 1) THEN
                             (EXISTS (x: (vert(G))): deg(x,G) = 1 AND
                                connected?(del_vert(G,x)))
                          ELSE
                             (EXISTS (e: (edges(G))):
                                connected?(del_edge(G,e)))
                          ENDIF)

      conn_del_vert: LEMMA  (EXISTS (v: (vert(G))): deg(v,G) = 1 AND                                             connected?(del_vert(G,v)))
                            IMPLIES connected?(G) 

      connected_not_empty: LEMMA connected?(G) IMPLIES NOT empty?(G)

  	connect_deg_0: LEMMA connected?(G) and vert(G)(v) and deg(v,G)= 0 IMPLIES G=singleton_graph(v)

  END graph_complected


body:
  walk_inductions[T: TYPE]: THEORY
  BEGIN

     IMPORTING walks[T]

     P: VAR pred[prewalk]
     n: VAR nat
     w,ww: VAR prewalk

     walk_prep              : LEMMA (FORALL w: P(w)) IFF 
                                         (FORALL n, w : length(w) = n IMPLIES P(w)) 
     
     
     graph_induction_walk    : THEOREM (FORALL w:
                                   (FORALL ww: length(ww) < length(w) IMPLIES P(ww))
                                                   IMPLIES P(w))
                                     IMPLIES (FORALL w: P(w))
      
  END walk_inductions


body:
  sep_sets[T: TYPE]: THEORY


  BEGIN

     IMPORTING graphs[T], walks[T]

     G: VAR graph[T]
     v,s,t: VAR T
     e: VAR doubleton[T]
     V: VAR finite_set[T]

     del_verts(G,V): graph[T] =
             (# vert := difference[T](vert(G),V),                    
                edges := {e | edges(G)(e) AND 
                             (FORALL v: V(v) IMPLIES NOT e(v))} #)

     separates(G,V,s,t): bool = NOT V(s) AND NOT V(t) AND 
                     NOT (EXISTS (w: prewalk): walk_from?(del_verts(G,V),w,s,t))

     seps(G,s,t): TYPE = {V: finite_set[T] | IF s = t OR edge?(G)(s,t) THEN 
                                                V = vert(G) 
                                             ELSE separates(G,V,s,t)
                                             ENDIF}

     IMPORTING abstract_min

     sep_set_exists: LEMMA (EXISTS (t: seps(G, s, t)): TRUE)
            
     min_sep_set(G,s,t): finite_set[T] = min[seps(G,s,t),
                                    (LAMBDA (v: seps(G,s,t)): card(v)),
                                    (LAMBDA (v: seps(G,s,t)): true)]

     separable?(G,s,t): bool = (s /= t AND NOT edge?(G)(s,t)) 


     min_sep_set_edge: LEMMA NOT separable?(G,s,t) IMPLIES 
                                    min_sep_set(G,s,t) = vert(G)

     min_sep_set_card: LEMMA FORALL (s,t: (vert(G))): separates(G,V,s,t)
                                    IMPLIES card(min_sep_set(G,s,t)) <= card(V)  

     min_sep_set_seps: LEMMA separable?(G,s,t) IMPLIES 
                                 separates(G,min_sep_set(G,s,t),s,t)

     min_sep_set_vert: LEMMA separable?(G,s,t) AND min_sep_set(G,s,t)(v) 
                                      IMPLIES vert(G)(v)

     ends_not_in_min_sep_set: LEMMA separable?(G,s,t)  AND min_sep_set(G, s, t)(v) 
                                    IMPLIES v /= s AND v /= t


     w: VAR prewalk
     walk?_del_verts_not : LEMMA walk?(G, w) AND 
                                    empty?(intersection(verts_of(w),V))
                                        IMPLIES walk?(del_verts(G, V), w)

     sep_num(G,s,t): nat = card(min_sep_set(G,s,t))

     IMPORTING graph_deg[T], finite_sets@finite_sets_card_eq


     adj_verts(G,s): finite_set[T] = {v: T | (EXISTS (e: Dbl[T]):
                                           incident_edges[T](s, G)(e)
                                             AND e(v) AND NOT v = s)}

     adj_verts_lem: LEMMA card(adj_verts(G,s)) = deg(s,G)

     sep_num_min: LEMMA FORALL (s,t: (vert(G))):
                        separable?(G,s,t) IMPLIES
                         sep_num(G,s,t) <= min(deg(s,G),deg(t,G))

  END sep_sets

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

  % Subtype TCC generated (at line 15, column 23) for
      % {e | edges(G)(e) AND (FORALL v: V(v) IMPLIES NOT e(v))}
      % expected type  finite_set[doubleton[T]]
  del_verts_TCC1: OBLIGATION
    FORALL (G: graph[T], V: finite_set[T]):
      is_finite[doubleton[T]]
          ({e | edges(G)(e) AND (FORALL v: V(v) IMPLIES NOT e(v))});

  % Subtype TCC generated (at line 14, column 11) for
      % (# vert := difference[T](vert(G), V),
      %    edges := {e | edges(G)(e) AND (FORALL v: V(v) IMPLIES NOT e(v))} #)
      % expected type  graph[T]
  del_verts_TCC2: OBLIGATION
    FORALL (G: graph[T], V: finite_set[T]):
      FORALL (e_1: doubleton[T]):
        (edges(G)(e_1) AND (FORALL v: V(v) IMPLIES NOT e_1(v))) IMPLIES
         (FORALL (x: T): e_1(x) IMPLIES difference[T](vert(G), V)(x));

  % Assuming TCC generated (at line 30, column 39) for
      % min
      %     [seps(G, s, t), (LAMBDA (v: seps(G, s, t)): card(v)),
      %      (LAMBDA (v: seps(G, s, t)): TRUE)]
      % generated from assumption abstract_min.T_ne
  min_sep_set_TCC1: OBLIGATION
    FORALL (G: graph[T], s: T, t: T): EXISTS (t_1: seps(G, s, t)): TRUE;

  % Subtype TCC generated (at line 63, column 35) for
      % {v: T |
      %    (EXISTS (e: Dbl[T]):
      %       incident_edges[T](s, G)(e) AND e(v) AND NOT v = s)}
      % expected type  finite_set[T]
  adj_verts_TCC1: OBLIGATION
    FORALL (G: graph[T], s: T):
      is_finite[T]
          ({v: T |
              EXISTS (e: Dbl[T]):
                incident_edges[T](s, G)(e) AND e(v) AND NOT v = s});


body:
  path_ops[T: TYPE]: THEORY
  BEGIN

     IMPORTING paths[T], subgraphs[T], sep_sets[T], graph_ops[T]

     G: VAR graph[T]
     u,v,s,t,yt: VAR T
     e: VAR doubleton[T]
     W,V: VAR finite_set[T]
     w,w1,p,p1,q,q1: VAR prewalk

     walk?_del_vert     : LEMMA walk?(del_vert(G, v), w) IMPLIES walk?[T](G, w)

     walk?_del_vert_not : LEMMA walk?(G, w) AND NOT verts_of(w)(v)
                                            IMPLIES walk?(del_vert(G, v), w)


     path?_del_vert     : LEMMA FORALL (w: prewalk): path?(del_vert(G, v), w) 
                                                         IMPLIES path?[T](G, w)

     path?_del_verts    : LEMMA FORALL (w: prewalk): path?(del_verts(G, W), w) 
                                                         IMPLIES path?[T](G, w)
    

     IMPORTING walk_inductions[T],path_circ[T]

     walk_to_path      : LEMMA (EXISTS (w: prewalk): walk_from?(G,w,s,t)) IMPLIES
                                   (EXISTS (p: prewalk): path?(G,p) AND
                                                     walk_from?(G,p,s,t))

     walk_to_path_less      : LEMMA  walk_from?(G,w,s,t) IMPLIES
                                   (EXISTS (p: prewalk): path?(G,p) AND
                                                     walk_from?(G,p,s,t)and length(p)<=length(w))



     walk_to_path_from : LEMMA walk_from?(G,w,s,t) IMPLIES
                                   (EXISTS (p: prewalk): path_from?(G,p,s,t))

     walk_to_path_from_less : LEMMA walk_from?(G,w,s,t) IMPLIES
                                   (EXISTS (p: prewalk): path_from?(G,p,s,t) AND 
                                                         length(p)<=length(w))

  % More lemmas to aid in Menger and other advanced theories.

     path_disjoint: LEMMA u /= yt AND path_from?(G, p, u, yt) 
                                  AND path_from?(G, q, yt, v) 
                                  AND empty?(intersection(verts_of(trunc1(p)),verts_of(q))) 
                          IMPLIES path_from?(G,trunc1(p) o q,u,v)


  END path_ops

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

  % Subtype TCC generated (at line 48, column 72) for  p
      % expected type  Longprewalk[T]
  path_disjoint_TCC1: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], u, v, yt: T):
      u /= yt AND path_from?(G, p, u, yt) AND path_from?(G, q, yt, v) IMPLIES
       length(p) >= 2;

  % Subtype TCC generated (at line 49, column 45) for  trunc1(p) o q
      % expected type  prewalk[T]
  path_disjoint_TCC2: OBLIGATION
    FORALL (G: graph[T], p, q: prewalk[T], u, v, yt: T):
      empty?(intersection(verts_of(trunc1(p)), verts_of(q))) AND
       path_from?(G, q, yt, v) AND path_from?(G, p, u, yt) AND u /= yt
       IMPLIES length(o[T](trunc1[T](p), q)) > 0;


body:
  min_lem: THEORY
  BEGIN

    S: VAR (nonempty?[nat])

    min_lem        : LEMMA minimum?(min(S), S)

  END min_lem


body:
  max_upto[N: nat]: THEORY

    EXPORTING ALL

  BEGIN

    IMPORTING min_lem

    S: VAR (nonempty?[upto[N]])
    n,a,x: VAR upto[N]

    max(S): {a: upto[N] | S(a) AND (FORALL x: S(x) IMPLIES a >= x)}

    maximum?(a, S) : bool = S(a) AND (FORALL x: S(x) IMPLIES a >= x)

    max_def         : LEMMA max(S) = a IFF maximum?(a, S)

    max_lem         : LEMMA maximum?(max(S), S)

  END max_upto

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

  % Existence TCC generated (at line 12, column 2) for
      % max(S): {a: upto[N] | S(a) AND (FORALL x: S(x) IMPLIES a >= x)}
  max_TCC1: OBLIGATION
    EXISTS (x1:
              [S: (nonempty?[upto[N]]) ->
                 {a: upto[N] | S(a) AND (FORALL x: S(x) IMPLIES a >= x)}]):
      TRUE;


body:
  max_subgraphs[T: TYPE]: THEORY
  BEGIN

     IMPORTING  subgraphs[T], max_upto

     G: VAR graph[T]

     Gpred(G): TYPE = {P: pred[graph[T]] | (EXISTS (S: graph[T]): 
                                               subgraph?(S,G) AND P(S))}

     n: VAR nat

     is_one_of_size(G: graph[T], P: Gpred(G),n: nat): bool =
              (EXISTS (S: Subgraph(G)): P(S) AND size(S) = n)

     prep0: LEMMA FORALL (G: graph[T], P: Gpred(G)):
         nonempty?[upto[size(G)]]({n: upto[size(G)] | is_one_of_size(G,P,n)})

     max_size(G: graph[T], P: Gpred(G)): upto[size(G)] =
               max({n: upto[size(G)] | is_one_of_size(G,P,n)})

     prep    : LEMMA FORALL (G: graph[T], P: Gpred(G)):
                              nonempty?[Subgraph(G)]({S: Subgraph(G)
                                  | size[T](S) = max_size(G,P) AND P(S)})

     
     maximal?(G: graph[T], S: Subgraph(G),P: Gpred(G)): bool = P(S) AND 
                         (FORALL (SS: Subgraph(G)): P(SS) IMPLIES 
                                                          size(SS) <= size(S))

  %  Existence TCC satisfied by
  %    choose({S: Subgraph(G) | size(S) = max_size AND P(S)})
               

     max_subgraph(G: graph[T], P: Gpred(G)): {S: Subgraph(G) | maximal?(G,S,P)}

     max_subgraph_def    : LEMMA FORALL (P: Gpred(G)): 
                                       maximal?(G,max_subgraph(G,P),P)

     max_subgraph_in     : LEMMA FORALL (P: Gpred(G)): P(max_subgraph(G,P)) 

     max_subgraph_is_max : LEMMA FORALL (P: Gpred(G)):
                            (FORALL (SS: Subgraph(G)): P(SS) IMPLIES 
                                            size(SS) <= size(max_subgraph(G,P))) 

  END max_subgraphs

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

  % Subtype TCC generated (at line 20, column 17) for
      % {n: upto[size(G)] | is_one_of_size(G, P, n)}
      % expected type  S: (nonempty?[upto[size(G)]])
  max_size_TCC1: OBLIGATION
    FORALL (G: graph[T], P: Gpred(G)):
      nonempty?[upto[size[T](G)]]
          ({n: upto[size[T](G)] | is_one_of_size(G, P, n)});

  % Existence TCC generated (at line 35, column 3) for
      % max_subgraph(G: graph[T], P: Gpred(G)):
      %       {S: Subgraph(G) | maximal?(G, S, P)}
  max_subgraph_TCC1: OBLIGATION
    EXISTS (x:
              [d: [G: graph[T], Gpred(G)] ->
                 {S: Subgraph[T](d`1) | maximal?(d`1, S, d`2)}]):
      TRUE;


body:
  max_subtrees[T: TYPE]: THEORY
  BEGIN

     IMPORTING trees[T]

     G: VAR Graph[T]    % not empty?(G)

     IMPORTING  max_subgraphs[T]

     v: VAR T
     sing_is_tree: LEMMA tree?[T](singleton_graph(v))

     tree_in: LEMMA (EXISTS (Tr: Tree[T]): subgraph?(Tr,G) AND
                            nonempty?[T](vert(Tr)))

     Tr,S: VAR Tree[T]

     Subtree(G: graph[T]): TYPE = {Tr: Tree | subgraph?(Tr,G)}

     max_subtree(G: Graph[T]): Subtree(G) = max_subgraph(G,(LAMBDA G: tree?(G)))

     max_subtree_tree    : LEMMA tree?(max_subtree(G)) 

     max_subtree_subgraph: LEMMA subgraph?(max_subtree(G),G)

     max_subtree_max     : LEMMA FORALL (SS: Subtree(G)): 
                                           size(SS) <= size(max_subtree(G)) 

  END max_subtrees

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

  % Subtype TCC generated (at line 20, column 58) for
      % (extend[graph[T], Graph[T], bool, FALSE]((LAMBDA G: tree?(G))))
      % expected type  Gpred[T](G)
  max_subtree_TCC1: OBLIGATION
    FORALL (G: Graph[T]):
      EXISTS (S: graph[T]):
        subgraph?[T](S, G) AND
         extend[graph[T], Graph[T], bool, FALSE]((LAMBDA G: tree?[T](G)))(S);

  % Subtype TCC generated (at line 20, column 42) for
      % max_subgraph(G,
      %              (extend[graph[T], Graph[T], bool, FALSE]
      %                   ((LAMBDA G: tree?(G)))))
      % expected type  Subtree(G)
  max_subtree_TCC2: OBLIGATION
    FORALL (G: Graph[T]):
      tree?[T]
          (max_subgraph[T]
               (G,
                (extend[graph[T], Graph[T], bool, FALSE]
                     ((LAMBDA G: tree?[T](G))))))
       AND
       subgraph?[T]
           (max_subgraph[T]
                (G,
                 (extend[graph[T], Graph[T], bool, FALSE]
                      ((LAMBDA G: tree?[T](G))))),
            G);


body:
  subtrees[T: TYPE]: THEORY
  BEGIN

     IMPORTING max_subtrees[T], graph_conn_defs[T]

     G: VAR Graph[T]    % not empty?(G)

     S: VAR graph[T]

     n: VAR nat 
     walk_acr: LEMMA FORALL (w: Walk(G)): n < length(w) AND
                                  vert(S)(seq(w)(0)) AND NOT vert(S)(seq(w)(n))
                                 IMPLIES
                      (EXISTS (j: posnat): (j <= n
                          AND (vert(S)(seq(w)(j - 1)) AND NOT vert(S)(seq(w)(j)))))


     walk_acr2: LEMMA FORALL (w: Walk(G)): n < length(w) AND
                                  vert(S)(seq(w)(0)) AND NOT vert(S)(seq(w)(n))
                                 IMPLIES
                      (EXISTS (j: posnat): (j <= n
                          AND (vert(S)(seq(w)(j - 1)) AND NOT vert(S)(seq(w)(j)))))

      e: VAR doubleton[T]
      v,w: VAR T
      add_dbl: LEMMA  vert(G)(v) AND v /= w AND
                   add(dbl[T](v, w), edges(G))(e)
                IMPLIES (FORALL (x: T): e(x) IMPLIES add(w, vert(G))(x))

      max_tree_all_verts: LEMMA path_connected?(G)   IMPLIES
                                 vert(max_subtree(G)) = vert(G)


  END subtrees

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

  % Subtype TCC generated (at line 12, column 47) for  0
      % expected type  below[w`length]
  walk_acr_TCC1: OBLIGATION
    FORALL (G: Graph[T], n: nat, w: Walk[T](G)):
      n < length(w) IMPLIES 0 < w`length;

  % Subtype TCC generated (at line 15, column 44) for  j - 1
      % expected type  below[w`length]
  walk_acr_TCC2: OBLIGATION
    FORALL (G: Graph[T], S: graph[T], n: nat, w: Walk[T](G)):
      n < length(w) AND vert(S)(seq(w)(0)) AND NOT vert(S)(seq(w)(n)) IMPLIES
       (FORALL (j: posnat): j <= n IMPLIES j - 1 >= 0 AND j - 1 < w`length);

  % Subtype TCC generated (at line 15, column 75) for  j
      % expected type  below[w`length]
  walk_acr_TCC3: OBLIGATION
    FORALL (G: Graph[T], S: graph[T], n: nat, w: Walk[T](G)):
      n < length(w) AND vert(S)(seq(w)(0)) AND NOT vert(S)(seq(w)(n)) IMPLIES
       (FORALL (j: posnat):
          vert(S)(seq(w)(j - 1)) AND j <= n IMPLIES j < w`length);

  % Subtype TCC generated (at line 27, column 21) for  dbl[T](v, w)
      % expected type  doubleton[T]
  add_dbl_TCC1: OBLIGATION
    FORALL (G: Graph[T], v, w: T):
      vert(G)(v) AND v /= w IMPLIES
       (EXISTS (x: T), (y: T): x /= y AND dbl[T](v, w) = dbl[T](x, y));


body:
  graph_path_conn[T: TYPE]: THEORY

  BEGIN

     IMPORTING graph_conn_defs[T], walks[T], subgraphs[T]

     G,G1,G2: VAR graph[T]

     isolated_not_path: LEMMA isolated?(G) AND NOT singleton?(G)
                                  IMPLIES NOT path_connected?(G)

     u,v,y: VAR T
     pic_A: LEMMA (EXISTS v: vert(G)(v) AND deg(v,G) = 0)
                      IMPLIES path_connected?(G) IMPLIES connected?(G)


     IMPORTING graph_inductions[T], subtrees[T], path_ops[T]



     thw_A: LEMMA  (FORALL (GG: graph[T]): size(GG) < size(G)
                                                IMPLIES
                       (FORALL (x: T, y: T): tree?(GG) AND vert(GG)(x) 
                                             AND vert(GG)(y) AND x /= y
                       IMPLIES (EXISTS (w: Walk(GG)): walk_from?(GG, w, x, y))))
                 AND deg(v, G) = 1 AND tree?(del_vert[T](G, v)) AND
  	       vert(G)(v) AND vert(G)(y) AND v /= y
  	 IMPLIES
   	    (EXISTS (w: Walk(G)): walk_from?(G, w, v, y))

     TR: VAR graph[T]
     x: VAR T
     tree_has_walk: LEMMA tree?(TR) AND vert(TR)(x) AND vert(TR)(y)
                             AND x /= y IMPLIES
                                (EXISTS (w: Walk(TR)):
                                     walk_from?(TR,w,x,y))

     path_implies_conn: THEOREM path_connected?(G) IMPLIES connected?(G)


  END graph_path_conn


body:
  graph_piece_path[T: TYPE]: THEORY

  BEGIN

     IMPORTING graph_conn_defs[T], walks[T], subgraphs[T]

     G,H1,H2: VAR graph[T]


     VV: VAR set[T]
     union_edge_disj: LEMMA NOT (EXISTS (u, w: T): vert(H1)(u) AND vert(H2)(w) 
                                             AND u /= w
                                             AND edges(G)(edg[T](u, w)))
                                AND H1 = subgraph(G,VV) 
                                AND H2 = subgraph(G,difference(vert(G),VV))
                             IMPLIES 
                                G = union(H1,H2)

     piece_implies_path: THEOREM piece_connected?(G) IMPLIES path_connected?(G)


  END graph_piece_path

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

  % Subtype TCC generated (at line 13, column 66) for  w
      % expected type  {y: T | y /= u}
  union_edge_disj_TCC1: OBLIGATION
    FORALL (H1, H2: graph[T], u, w: T):
      u /= w AND vert(H2)(w) AND vert(H1)(u) IMPLIES w /= u;


body:
  graph_conn_piece[T: TYPE]: THEORY

  BEGIN

     IMPORTING graph_conn_defs[T]

     G,H1,H2: VAR graph[T]
     x,y,v: VAR T

  %   piece_connected?(G): bool = NOT empty?(G) AND
  %                               (FORALL H1,H2: G = union(H1,H2) AND
  %                                         NOT empty?(H1) AND NOT empty?(H2)
  %                                  IMPLIES NOT empty?(intersection(vert(H1),
  %                                                                   vert(H2))))

     singleton_piece: LEMMA singleton?(G) IMPLIES 
                                piece_connected?(G)

     not_piece_has_2: LEMMA NOT piece_connected?(G) IMPLIES empty?(G) OR
                              size(G) > 1
    
     e: VAR doubleton[T] 
     vo: VAR T
     
     edge_not_across: LEMMA e(vo) AND vert(H1)(vo) AND
                            edges(union(H1, H2))(e) AND
                            empty?(intersection(vert(H1), vert(H2)))
                            IMPLIES  edges(H1)(e)
     
     lem1: LEMMA vert(H1)(vo) AND  empty?(intersection(vert(H1), vert(H2))) AND
             NOT empty?(H1) AND NOT empty?(H2)
            IMPLIES del_vert(union(H1, H2), vo) = union(del_vert(H1, vo), H2)
     
     
     
     H1P_not_empty: LEMMA vert(H1)(vo) AND
                           deg(vo, union(H1, H2)) > 0 AND
                           del_vert(G, vo) = union(del_vert(H1, vo), H2) AND
                           empty?(intersection(vert(H1), vert(H2))) AND
                           NOT empty?(H1) AND NOT empty?(H2) AND 
                           NOT empty?(del_vert(G, vo))
                   IMPLIES NOT empty?(del_vert(H1, vo))

     cip0: LEMMA (FORALL (GG: graph[T]): size(GG) < size(G)
                         IMPLIES connected?(GG) IMPLIES piece_connected?(GG)) AND
                 vert(H1)(vo) AND  
                 deg(vo, G) > 0 AND
                 connected?(del_vert(G, vo)) AND
                 G = union(H1, H2) AND
                 empty?(intersection(vert(H1), vert(H2))) AND
        	       NOT empty?(H1) AND NOT empty?(H2) 
               IMPLIES NOT empty?(intersection(vert(H1), vert(H2)))


     cip3: LEMMA (FORALL (GG: graph[T]): size(GG) < size(G)
                         IMPLIES connected?(GG) IMPLIES piece_connected?(GG)) AND
                 deg(vo, G) > 0 AND
        	       connected?(del_vert(G, vo)) AND
        	       G = union(H1, H2) AND
        	       NOT empty?(H1) AND NOT empty?(H2) AND vert(G)(vo)
               IMPLIES NOT empty?(intersection(vert(H1), vert(H2)))

     connected_not_empty: LEMMA connected?(G) IMPLIES NOT empty?(G)


     IMPORTING graph_inductions[T]

     conn_implies_piece: LEMMA connected?(G) IMPLIES piece_connected?(G)


  END graph_conn_piece


body:
  graph_connected[T: TYPE]: THEORY

  BEGIN

     IMPORTING graph_ops[T], graph_deg[T], walks[T],
               graph_conn_defs[T], 
               graph_conn_piece, graph_piece_path,  % FOR PROOF ONLY
               graph_path_conn, graph_complected    % FOR PROOF ONLY

     G,G1,G2,H1,H2: VAR graph[T]


     conn_eq_path       : THEOREM connected?(G) = path_connected?(G)

     path_eq_piece      : THEOREM path_connected?(G) = piece_connected?(G)

     piece_eq_conn      : THEOREM piece_connected?(G) = connected?(G)

     conn_eq_complected : THEOREM connected?(G) = complected?(G)

  %WHERE (defined in graph_conn_defs[T]) 
  %
  %   connected?(G): RECURSIVE bool = singleton?(G) OR
  %                                   (EXISTS (v: (vert(G))): deg(v,G) > 0 
  %                                       AND connected?(del_vert(G,v))) 
  %                  MEASURE size(G)
  %
  %   path_connected?(G): bool = (FORALL (x,y: (vert(G))): x /= y IMPLIES
  %                                   (EXISTS (w: Walk(G)): seq(w)(0) = x AND 
  %                                                         seq(w)(length(w)-1) = y))
  %
  %   piece_connected?(G): bool = NOT empty?(G) AND
  %                               (FORALL H1,H2: G = union(H1,H2) AND
  %                                         NOT empty?(H1) AND NOT empty?(H2)
  %                                  IMPLIES NOT empty?(intersection(vert(H1),
  %                                                                   vert(H2))))
  %
  %   complected?(G): bool = IF isolated?(G) THEN singleton?(G) 
  %                          ELSIF (EXISTS (v: (vert(G))): deg(v,G) = 1) THEN
  %                           (EXISTS (x: (vert(G))): deg(x,G) = 1 AND
  %                              connected?(del_vert(G,x)))
  %                          ELSE
  %                             (EXISTS (e: (edges(G))):
  %                              connected?(del_edge(G,e)))
  %                          ENDIF
  %
  % are defined in graph_conn_defs.pvs

  END graph_connected


body:
  mappings[T: TYPE]: THEORY
  BEGIN

    IMPORTING graphs[T], trees[T], walks[T],tree_paths[T],
              structures@seq_pigeon

    G1,G2,G,H,HH,U: VAR graph[T]
    x,y,s,t: VAR T 
    e: VAR doubleton[T]
    w,p,q: VAR prewalk
    k,l,m,n: VAR nat

    premap(G1,G2): TYPE = {psi:[T -> T]| FORALL (x:T):
                                    vert(G1)(x) IMPLIES vert(G2)(psi(x))}

    map(G1,G2)   : TYPE = {phi: premap(G1,G2) | FORALL (x,y: T):
                             edge?(G1)(x,y) IMPLIES
                                 edge?(G2)(phi(x),phi(y)) OR phi(x) = phi(y)} 
   
    proper?(G1:graph[T],G2:graph[T],M: map(G1,G2)): bool = 
                  (FORALL (x,y: T): edge?(G1)(x,y) IMPLIES
                            edge?(G2)(M(x),M(y)))

    injective?(G1:graph[T],G2:graph[T],M: map(G1,G2)): bool = 
                  injective?(M)

    fixed?(G:graph[T], phi:map(G,G)):bool = (FORALL (v: (vert(G))):  
                                             v /= phi(v))
                             IMPLIES (EXISTS (x,y: (vert(G))): 
                                 y = phi(x) AND x = phi(y) AND edge?(G)(x,y))

    reachable(G,x): finite_set[T] = {y: T |  vert(G)(y) AND 
                                      (EXISTS (w: Seq(G)): walk_from?(G,w,x,y))}

    reachable_subset: LEMMA subset?(reachable(G,x),vert(G))

  	
    IMPORTING graph_conn_defs[T], graph_connected, graph_pair[T], tree_paths
    IMPORTING subgraph_paths 
    IMPORTING graph_deg,graph_deg_sum,path_lems, doubletons 


    path_reach1: LEMMA path_connected?(G) IFF
                         (EXISTS (x: T): vert(G)(x) AND reachable(G,x) = vert(G))

    path_reach2:  LEMMA path_connected?(G) IFF
                        (FORALL (x: T): vert(G)(x) 
                             IMPLIES reachable(G,x) = vert(G)) 
                        AND NOT empty?(G)

    reachable_conn: LEMMA FORALL (x:(vert(G))): 
                                 connected?(subgraph(G,reachable(G,x)))

    sub_tree_k: LEMMA (FORALL k,H,G: subgraph?(H,G) AND tree?(G) AND 
                                     connected?(H) AND size(G)=size(H)+k 
                         IMPLIES tree?(H)) 
                    IMPLIES (FORALL H,G: subgraph?(H,G) AND 
                             tree?(G) AND connected?(H)  IMPLIES tree?(H))

    sub_tree_0     : LEMMA tree?(G) AND subgraph?(H,G) AND size(H)=size(G) 
  		          AND connected?(H) IMPLIES H=G

    sub_tree_k_lemm: LEMMA (FORALL k,H,G: subgraph?(H,G) AND tree?(G) AND
  	                   connected?(H) AND size(G)=size(H)+k IMPLIES tree?(H))
   
    sub_tree_all    : LEMMA tree?(G) AND subgraph?(H,G) AND connected?(H)
                              IMPLIES tree?(H)

    path_reach4    : LEMMA tree?(G) AND edges(G)(e) IMPLIES
                             NOT path_connected?(del_edge(G,e))

    size_subgraph_path: LEMMA path?(G,p) IMPLIES size(G_from(G,p))=length(p)

    path_gap     : LEMMA tree?(G) AND edges(G)(e) AND e(x) AND e(y) AND
                         walk_from?(del_edge(G,e),w,x,y) IMPLIES x=y

    set_card_less: LEMMA FORALL (A: finite_set[T], B: finite_set[T]):
  	                subset?(A,B) AND B(x) IMPLIES card(A) < card(B) OR A(x)

    conn_compon  : LEMMA FORALL (  x: (vert(G))): EXISTS H:
                                 (subgraph?(H,G) AND connected?(H) AND
                                  vert(H)(x) AND 
  	                         FORALL (y:(vert(H))): (deg(y,G)=deg(y,H)))  

   
    Bush(Tr:Tree, v:(vert(Tr)), e:(incident_edges(v,Tr))): Subgraph(Tr) = 
                                  subgraph(Tr, reachable(del_edge(Tr,e),v))

    Bush_less: LEMMA FORALL (Tr: Tree,v,z:(vert(Tr)), e:(incident_edges(v,Tr)),
                             f:(incident_edges(z,Tr))): 
                       f(v) AND NOT e(z) 
  	                 IMPLIES size(Bush(Tr,z,f)) < size(Bush(Tr,v,e))

    Fox(Tr:Tree, G: Subgraph(Tr), H: Subgraph(Tr), phi:map(Tr,Tr)): bool =
                     ( EXISTS w:path?(Tr,w) AND length(w)>1 AND 
                              phi(w(0))=w(length(w)-1) AND G = G_from(Tr,w) AND
                              H = Bush(Tr,w(length(w)-1),dbl(w(length(w)-2),w(length(w)-1))))

    short_hound: LEMMA FORALL (Tr:Tree, phi:map(Tr,Tr)): 
                       path_from?(Tr,w,x,phi(x)) AND length(w)=1 IMPLIES fixed?(Tr,phi)

    back_hound : LEMMA FORALL (Tr:Tree, phi:map(Tr,Tr)): 
                       path_from?(Tr,w,x,phi(x)) AND length(w)=2 AND 
                       phi(w(1))=w(length(w)-2) IMPLIES fixed?(Tr,phi)

    stuck_hound: LEMMA FORALL (Tr:Tree, phi:map(Tr,Tr)): 
                      path_from?(Tr,w,x,phi(x)) AND length(w)>1 AND phi(w(1))=w(length(w)-1)
                  IMPLIES
                      EXISTS (p:prewalk):
  	                      path_from?(Tr,p,w(1),phi(w(1))) AND length(p)<length(w) AND 
                              ((length(p)>1 AND p(length(p)-2)=w(length(w)-2)) OR fixed?(Tr,phi))

    whole_hound: LEMMA FORALL (Tr:Tree, phi:map(Tr,Tr)): 
                       path_from?(Tr,w,x,phi(x)) AND length(w)>2 AND 
                       phi(w(1))=w(length(w)-2) IMPLIES
                  EXISTS (p:prewalk):
  	            path_from?(Tr,p,w(1),phi(w(1))) AND length(p)<length(w) AND 
                    (length(p)>1 IMPLIES p(length(p)-2)=w(length(w)-3))

    fixed_fox  : LEMMA FORALL (Tr:Tree, phi:map(Tr,Tr)):
                         (EXISTS (G,H:Subgraph(Tr)):Fox(Tr,G,H,phi)) 
                         OR fixed?(Tr,phi)

    small_fox  : LEMMA FORALL (Tr:Tree, phi:map(Tr,Tr),(G,H:Subgraph(Tr))): 
                       Fox(Tr,G,H,phi) 
                       IMPLIES (EXISTS (GG,HH:Subgraph(Tr)): 
                                     Fox(Tr,GG,HH,phi) AND
  	                            lsth((size(GG),size(HH)),(size(G),size(H)))) 
                           OR fixed?(Tr,phi)

    num_edge_tree: LEMMA connected?(G) AND num_edges(G)<size(G) 
  	                     IMPLIES tree?(G)

    uniq_paths?(G): bool = FORALL (s,t,p,q): path_from?(G,p,s,t) AND
                                             path_from?(G,q,s,t) IMPLIES p = q

    uniq_del_vert: LEMMA FORALL ( v:(vert(G))): uniq_paths?(G) 
                                                IMPLIES uniq_paths?(del_vert(G,v))

    del_edge_uniq: LEMMA FORALL ( e:(edges(G))):connected?(del_edge(G,e)) 
                                     IMPLIES NOT uniq_paths?(G) 

    charact_tree : LEMMA connected?(G) AND uniq_paths?(G) IMPLIES tree?(G)

    iff_tree     : LEMMA tree?(G) IFF connected?(G) AND uniq_paths?(G)

    tree_num_iff : LEMMA connected?(G) and num_edges(G)=size(G)-1 IFF tree?(G)

    tree_map     : LEMMA FORALL (phi:map(G,G)):tree?(G)
   		            IMPLIES fixed?(G,phi)


  % We take advantage of some of the tree properties proved above to 
  % deduce the theorem stated in "graphs" context that a graph with vertices
  % only of degree > 1, must have a cycle.

    sub_cycle     : LEMMA FORALL (w: Seq(H)): subgraph?(H,G) and cycle?(H,w) 
                                                IMPLIES cycle?(G,w)

    exclus_cycl   : THEOREM connected?(G) IMPLIES 
                               tree?(G) XOR (EXISTS (w:Seq(G)): cycle?(G,w))

    deg_gt_1_cycle: LEMMA (FORALL (v: T): vert(G)(v) IMPLIES deg(v,G) > 1)
                            IMPLIES (EXISTS (w: Seq(G)): cycle?(G,w)) OR empty?(G)
   
                                     
  END mappings

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

  % Subtype TCC generated (at line 32, column 34) for
      % {y: T | vert(G)(y) AND (EXISTS (w: Seq(G)): walk_from?(G, w, x, y))}
      % expected type  finite_set[T]
  reachable_TCC1: OBLIGATION
    FORALL (G: graph[T], x: T):
      is_finite[T]
          ({y: T |
              vert(G)(y) AND
               (EXISTS (w: Seq[T](G)): walk_from?[T](G, w, x, y))});

  % Subtype TCC generated (at line 72, column 61) for  p
      % expected type  Walk[T](G)
  size_subgraph_path_TCC1: OBLIGATION
    FORALL (G: graph[T], p: prewalk[T]): path?(G, p) IMPLIES walk?[T](G, p);

  % Subtype TCC generated (at line 96, column 34) for  0
      % expected type  below[length(w)]
  Fox_TCC1: OBLIGATION
    FORALL (Tr: Tree[T], G: Subgraph[T](Tr), H: Subgraph[T](Tr),
            phi: map(Tr, Tr), w):
      length(w) > 1 AND path?(Tr, w) IMPLIES 0 < length(w);

  % Subtype TCC generated (at line 96, column 40) for  length(w) - 1
      % expected type  below[length(w)]
  Fox_TCC2: OBLIGATION
    FORALL (Tr: Tree[T], G: Subgraph[T](Tr), H: Subgraph[T](Tr),
            phi: map(Tr, Tr), w):
      length(w) > 1 AND path?(Tr, w) IMPLIES
       length(w) - 1 >= 0 AND length(w) - 1 < length(w);

  % Subtype TCC generated (at line 96, column 71) for  w
      % expected type  Walk[T](Tr)
  Fox_TCC3: OBLIGATION
    FORALL (Tr: Tree[T], G: Subgraph[T](Tr), H: Subgraph[T](Tr),
            phi: map(Tr, Tr), w):
      phi(finseq_appl[T](w)(0)) = finseq_appl[T](w)(length(w) - 1) AND
       length(w) > 1 AND path?(Tr, w)
       IMPLIES walk?[T](Tr, w);

  % Subtype TCC generated (at line 97, column 40) for
      % finseq_appl[T](w)(length(w) - 1)
      % expected type  (vert(Tr))
  Fox_TCC4: OBLIGATION
    FORALL (Tr: Tree[T], G: Subgraph[T](Tr), H: Subgraph[T](Tr),
            phi: map(Tr, Tr), w):
      G = G_from(Tr, w) AND
       phi(finseq_appl[T](w)(0)) = finseq_appl[T](w)(length(w) - 1) AND
        length(w) > 1 AND path?(Tr, w)
       IMPLIES vert(Tr)(finseq_appl[T](w)(length(w) - 1));

  % Subtype TCC generated (at line 97, column 61) for  length(w) - 2
      % expected type  below[length(w)]
  Fox_TCC5: OBLIGATION
    FORALL (Tr: Tree[T], G: Subgraph[T](Tr), H: Subgraph[T](Tr),
            phi: map(Tr, Tr), w):
      G = G_from(Tr, w) AND
       phi(finseq_appl[T](w)(0)) = finseq_appl[T](w)(length(w) - 1) AND
        length(w) > 1 AND path?(Tr, w)
       IMPLIES length(w) - 2 >= 0 AND length(w) - 2 < length(w);

  % Subtype TCC generated (at line 97, column 55) for
      % dbl(finseq_appl[T](w)(length(w) - 2),
      %     finseq_appl[T](w)(length(w) - 1))
      % expected type  (incident_edges(finseq_appl[T](w)(length(w) - 1), Tr))
  Fox_TCC6: OBLIGATION
    FORALL (Tr: Tree[T], G: Subgraph[T](Tr), H: Subgraph[T](Tr),
            phi: map(Tr, Tr), w):
      G = G_from(Tr, w) AND
       phi(finseq_appl[T](w)(0)) = finseq_appl[T](w)(length(w) - 1) AND
        length(w) > 1 AND path?(Tr, w)
       IMPLIES
       (EXISTS (x: T), (y: T):
          x /= y AND
           dbl[T]
               (finseq_appl[T](w)(length(w) - 2),
                finseq_appl[T](w)(length(w) - 1))
            = dbl[T](x, y))
        AND
        incident_edges[T]
            (finseq_appl[T](w)(length(w) - 1), Tr)
            (dbl[T]
                 (finseq_appl[T](w)(length(w) - 2),
                  finseq_appl[T](w)(length(w) - 1)));

  % Subtype TCC generated (at line 104, column 27) for  1
      % expected type  below[length(w)]
  back_hound_TCC1: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      length(w) = 2 AND path_from?(Tr, w, x, phi(x)) IMPLIES 1 < length(w);

  % Subtype TCC generated (at line 104, column 33) for  length(w) - 2
      % expected type  below[length(w)]
  back_hound_TCC2: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      length(w) = 2 AND path_from?(Tr, w, x, phi(x)) IMPLIES
       length(w) - 2 >= 0 AND length(w) - 2 < length(w);

  % Subtype TCC generated (at line 107, column 72) for  1
      % expected type  below[length(w)]
  stuck_hound_TCC1: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      length(w) > 1 AND path_from?(Tr, w, x, phi(x)) IMPLIES 1 < length(w);

  % Subtype TCC generated (at line 107, column 78) for  length(w) - 1
      % expected type  below[length(w)]
  stuck_hound_TCC2: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      length(w) > 1 AND path_from?(Tr, w, x, phi(x)) IMPLIES
       length(w) - 1 >= 0 AND length(w) - 1 < length(w);

  % Subtype TCC generated (at line 111, column 48) for  length(p) - 2
      % expected type  below[length(p)]
  stuck_hound_TCC3: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      path_from?(Tr, w, x, phi(x)) AND
       length(w) > 1 AND
        phi(finseq_appl[T](w)(1)) = finseq_appl[T](w)(length(w) - 1)
       IMPLIES
       (FORALL (p: prewalk[T]):
          length(p) > 1 AND
           length(p) < length(w) AND
            path_from?(Tr, p, finseq_appl[T](w)(1),
                       phi(finseq_appl[T](w)(1)))
           IMPLIES length(p) - 2 >= 0 AND length(p) - 2 < length(p));

  % Subtype TCC generated (at line 111, column 63) for  length(w) - 2
      % expected type  below[length(w)]
  stuck_hound_TCC4: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      path_from?(Tr, w, x, phi(x)) AND
       length(w) > 1 AND
        phi(finseq_appl[T](w)(1)) = finseq_appl[T](w)(length(w) - 1)
       IMPLIES
       (FORALL (p: prewalk[T]):
          length(p) > 1 AND
           length(p) < length(w) AND
            path_from?(Tr, p, finseq_appl[T](w)(1),
                       phi(finseq_appl[T](w)(1)))
           IMPLIES length(w) - 2 >= 0 AND length(w) - 2 < length(w));

  % Subtype TCC generated (at line 115, column 27) for  1
      % expected type  below[length(w)]
  whole_hound_TCC1: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      length(w) > 2 AND path_from?(Tr, w, x, phi(x)) IMPLIES 1 < length(w);

  % Subtype TCC generated (at line 115, column 33) for  length(w) - 2
      % expected type  below[length(w)]
  whole_hound_TCC2: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      length(w) > 2 AND path_from?(Tr, w, x, phi(x)) IMPLIES
       length(w) - 2 >= 0 AND length(w) - 2 < length(w);

  % Subtype TCC generated (at line 118, column 41) for  length(p) - 2
      % expected type  below[length(p)]
  whole_hound_TCC3: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      path_from?(Tr, w, x, phi(x)) AND
       length(w) > 2 AND
        phi(finseq_appl[T](w)(1)) = finseq_appl[T](w)(length(w) - 2)
       IMPLIES
       (FORALL (p: prewalk[T]):
          length(p) > 1 AND
           length(p) < length(w) AND
            path_from?(Tr, p, finseq_appl[T](w)(1),
                       phi(finseq_appl[T](w)(1)))
           IMPLIES length(p) - 2 >= 0 AND length(p) - 2 < length(p));

  % Subtype TCC generated (at line 118, column 56) for  length(w) - 3
      % expected type  below[length(w)]
  whole_hound_TCC4: OBLIGATION
    FORALL (w: prewalk[T], x: T, Tr: Tree[T], phi: map(Tr, Tr)):
      path_from?(Tr, w, x, phi(x)) AND
       length(w) > 2 AND
        phi(finseq_appl[T](w)(1)) = finseq_appl[T](w)(length(w) - 2)
       IMPLIES
       (FORALL (p: prewalk[T]):
          length(p) > 1 AND
           length(p) < length(w) AND
            path_from?(Tr, p, finseq_appl[T](w)(1),
                       phi(finseq_appl[T](w)(1)))
           IMPLIES length(w) - 3 >= 0 AND length(w) - 3 < length(w));

  % Subtype TCC generated (at line 158, column 63) for  w
      % expected type  Seq[T](G)
  sub_cycle_TCC1: OBLIGATION
    FORALL (G, H: graph[T], w: Seq[T](H)):
      subgraph?(H, G) AND cycle?(H, w) IMPLIES verts_in?[T](G, w);


body:
  %=============================================================================
  %
  %   Mantel's Theorem
  %  ——————————————————
  %
  %   Author: Aaron Dutle    University of South Carolina
  %
  %  Mantel's Theorem states that any graph on N vertices that does not contain
  %  a triangle can have at most N²/4 edges.   
  %
  %  Comment: This is the author's first attempt at proving a theorem using PVS. 
  %           Because of this, some of the proofs are likely longer than needed,
  %           and some of the organization of the file may be nonstandard. 
  % 
  %=============================================================================
  mantel[T: TYPE ]: THEORY

    BEGIN

  IMPORTING graphs[T], graph_ops[T], graph_inductions[T],
    graph_deg[T], finite_sets[doubleton[T]], sets[doubleton[T]], 
    sets_lemmas[doubleton[T]]

  x,y,z,w: VAR T
  G, GG, GS: VAR graph[T]
  e: VAR doubleton[T]

  %
  % Definitions for use in the proofs.

  tri?(G)(x,y,z): bool = vert(G)(x) AND vert(G)(y) AND vert(G)(z) 
  AND x/=y AND y/=z AND x/=z AND edge?(G)(x,y) AND edge?(G)(y,z) AND edge?(G)(x,z)

  tri?(G): bool = EXISTS x,y,z : tri?(G)(x,y,z)

  tri?(G)(x,y): bool = EXISTS z : tri?(G)(x,y,z)

  del2_vert(G, x,y): graph[T] = del_vert( del_vert(G,x), y)

  common_neighbor?(G)(x,y): bool = EXISTS z: x/=z AND y/=z 
                                   AND edge?(G)(x,z) AND edge?(G)(y,z) 

  %
  %  Three lemmas about the existence of triangles
  %

  one_to_some: LEMMA (tri?(G)(x,y,z) IMPLIES tri?(G)(x,y) )
  some_to_lots: LEMMA (tri?(G)(x,y) IMPLIES tri?(G) )
  one_to_lots: LEMMA (tri?(G)(x,y,z) IMPLIES tri?(G))

  % The collection of Lemmas used in the proof

  exst_tri: LEMMA (edge?(G)(x,y) AND common_neighbor?(G)(x,y)
                                   IMPLIES tri?(G)(x,y))

  one_vert_edges: LEMMA singleton?(G) IMPLIES edges(G) = emptyset[doubleton[T]] 

  edge_adjacent: LEMMA ( edge?(G)(x,y) IMPLIES member(y, adjacent(G,x)))

  disj_neighbor_sets: LEMMA ( disjoint?(adjacent(G,x), adjacent(G,y)) 
                           IMPLIES NOT common_neighbor?(G)(x,y))

  adj_is_subset: LEMMA subset?(union(adjacent(G,x), adjacent(G,y)),vert(G))

  adj_is_subset2: LEMMA subset?(adjacent(G,x), vert(G))

  no_cn: LEMMA NOT common_neighbor?(G)(x,y) 
                  IMPLIES disjoint?(adjacent(G,x), adjacent(G,y))

  disj_adj_card: LEMMA disjoint?(adjacent(G,x), adjacent(G,y))
                       IMPLIES card(adjacent(G,x))+card(adjacent(G,y))<=size(G)

  pre_edges_del21: LEMMA edges(G) = union(edges(del2_vert(G,x,y)),
                               union(incident_edges(x,G), incident_edges(y,G)))

  pre_edges_del22: LEMMA disjoint?(edges(del2_vert(G,x,y)),
                               union(incident_edges(x,G), incident_edges(y,G)))

  edges_del2: LEMMA  num_edges(del2_vert(G,x,y))+ 
                     card(union(incident_edges(x,G), incident_edges(y,G)))
                     =num_edges(G) 

  verts_del2: LEMMA vert(G)(x) AND vert(G)(y) AND x/=y 
                    IMPLIES size(del2_vert(G,x,y)) = size(G)-2 

  tri_del2: LEMMA tri?(del2_vert(G,x,y)) IMPLIES tri?(G)

  int_lem:    LEMMA edge?(G)(x,y) 
                    IMPLIES singleton?({e: doubleton[T] | 
                    (edges(G)(e) AND e(x)) AND edges(G)(e) AND e(y)}) 

  card_union: LEMMA edge?(G)(x,y) IMPLIES 
                    card(union(incident_edges(x,G),incident_edges(y,G))) =
                    card(incident_edges(x,G))+card(incident_edges(y,G))-1

  % Used in a previous proof attempt. Not required now.

  adj_helper: LEMMA empty?(G) IMPLIES card(adjacent(G,x))=0

  % Five lemmas, some with difficult proofs, used to prove the Obvious Fact. 
   
  adj_helper2: LEMMA edges(G)=emptyset[doubleton[T]] 
                     IMPLIES card(adjacent(G,x))=0

  inc_ind1: LEMMA edges(G)(e) AND NOT e(x) IMPLIES
                  incident_edges(x, del_edge(G,e)) = 
                  incident_edges(x, G)
  adj_ind1: LEMMA edges(G)(e) AND NOT e(x) IMPLIES
                  adjacent(del_edge(G,e),x)=
                  adjacent(G,x)
  inc_ind2: LEMMA edges(G)(e) AND e(x) IMPLIES
                  card(incident_edges(x, del_edge(G,e))) = 
                  card(incident_edges(x, G))-1
  adj_ind2: LEMMA edges(G)(e) AND e(x) IMPLIES
                 card(adjacent(del_edge(G,e),x))=
                  card(adjacent(G,x))-1

  %  The Obvious Fact. 

  inc_equals_adj: LEMMA card(incident_edges(x,G)) = card(adjacent(G,x))

  %
  %  Mantel's Theorem. Any graph on N vertices with no triangle has at 
  %                    most N^2/4 edges. 
  %

  Mantel: THEOREM ( FORALL G: NOT tri?(G) 
                  IMPLIES num_edges(G)<= size(G)*size(G)/4)

    END mantel


body:
  sep_set_lems[T: TYPE]: THEORY
  BEGIN

     IMPORTING paths[T], sep_sets[T], path_ops[T]

     G,MM: VAR graph[T]
     v,s,t,w1,w2: VAR T
     e: VAR doubleton[T]
     W: VAR finite_set[T]
     p: VAR prewalk	      


     sep_num_0: LEMMA separable?(G,s,t) AND sep_num(G, s, t) = 0 IMPLIES
                            separates(G, emptyset[T], s, t)
    
     sep_num_gt_0: LEMMA vert(G)(s) AND vert(G)(t) AND separable?(G,s,t) 
                         AND sep_num(G,s,t) > 0 IMPLIES
                                (EXISTS (w: prewalk): walk_from?(G,w,s,t))

    
     sep_num_is_1: LEMMA vert(G)(s) AND vert(G)(t) AND v /= s AND v /= t AND
                            (FORALL (p: prewalk): walk_from?(G,p,s,t) IMPLIES
                                    (EXISTS (i: below(length(p))): seq(p)(i) = v))
                               IMPLIES sep_num(G,s,t) <= 1

     av: VAR T
     sep_num_le1: LEMMA vert(G)(s) AND vert(G)(t) AND vert(G)(av) AND
                            av /= s AND av /= t AND
                            separable?(G, s, t) AND 
                            sep_num(G,s,t) <= 1 IMPLIES
                               (EXISTS (z: T): vert(G)(z) AND z /= s AND z /= t AND
                                                 separates(G,singleton(z),s,t))

     separable?_comm: LEMMA separable?(G,s,t) IMPLIES separable?(G,t,s)

     separates_comm:  LEMMA separates(G, W, s, t) = separates(G, W, t, s)


     sep_num_comm:    LEMMA vert(G)(s) AND vert(G)(t) IMPLIES
                              sep_num(G,s,t) = sep_num(G,t,s)


     v_not_in: LEMMA  walk_from?(del_verts(G, remove(v, W)), p,s,t)
     	           AND W(v) AND NOT verts_of(p)(v)
     	           IMPLIES walk_from?(del_verts(G, W), p, s, t)

     k: VAR nat
     path_thru_each: LEMMA     sep_num(G,s,t) = k 
                           AND separates(G, W, s, t)
                           AND card(W) = k AND W(v)
                           AND vert(G)(s) AND vert(G)(t)
                IMPLIES
                   (EXISTS (pv: prewalk): verts_of(pv)(v) AND path_from?(G,pv,s,t))
                   


     one_to_each: LEMMA     sep_num(G,s,t) = 2 
                        AND separates(G, dbl(w1, w2), s, t)
                        AND vert(G)(s) AND vert(G)(t)
                IMPLIES
     	         ( (EXISTS (Psw1: prewalk): path_from?(G, Psw1, s, w1)) AND
     		   (EXISTS (Psw2: prewalk): path_from?(G, Psw2, s, w2)))



     walk?_del_verts  : LEMMA walk?(del_verts(G, W), p) IMPLIES walk?[T](G, p)

     del_verts_eq: LEMMA del_vert(del_vert(G, w1), w2) = del_verts(G, dbl(w1, w2))

  END sep_set_lems


body:
  los_graph[T: TYPE]: THEORY
  BEGIN

  x,y,z: VAR T
  P,Q: VAR[T,T->bool]

  los_graphic: LEMMA (FORALL x,y,z: P(x,y)&P(y,z)=>P(x,z)) &
  	(FORALL x,y: P(x,y) => P(y,x)) &
  	(FORALL x,y,z: Q(x,y)&Q(y,z)=>Q(x,z)) &
  	(FORALL x,y: Q(x,y) => Q(y,x)) &
  	(FORALL x,y: P(x,y) OR Q(x,y)) =>
  	(FORALL x,y:P(x,y)) OR (FORALL x,y: Q(x,y))
   
  % Adjacy: LEMMA (FORALL x,y,z: P(x,y)&P(y,z)=>P(x,z)) &
  % 	(FORALL x,y,z: Q(x,y)&Q(y,z)=>Q(x,z)) &
  % 	(FORALL x,y: Q(x,y) => Q(y,x)) &
  % 	(FORALL x,y: P(x,y) OR Q(x,y)) =>
  % 	(FORALL x,y,z:P(x,y) OR (Q(y,z) AND Q(z,y))) 
  % Adjacx: LEMMA (FORALL x,y,z: P(x,y)&P(y,z)=>P(x,z)) &
  % 	(FORALL x,y,z: Q(x,y)&Q(y,z)=>Q(x,z)) &
  % 	(FORALL x,y: Q(x,y) => Q(y,x)) &
  % 	(FORALL x,y: P(x,y) OR Q(x,y)) =>
  % 	(FORALL x,y,z:P(x,y) OR (Q(x,z) AND Q(z,x))) 

  Los: LEMMA (FORALL x,y,z: P(x,y)&P(y,z)=>P(x,z)) &
  	(FORALL x,y,z: Q(x,y)&Q(y,z)=>Q(x,z)) &
  	(FORALL x,y: Q(x,y) => Q(y,x)) &
  	(FORALL x,y: P(x,y) OR Q(x,y)) =>
  	(FORALL x,y:P(x,y)) OR (FORALL x,y: Q(x,y))
  END los_graph	


body:
  complem[T: TYPE]: THEORY

  BEGIN

    IMPORTING graphs, subgraphs, graph_ops, abstract_min

    G,H,K: VAR graph[T]  
    V: VAR finite_set[T]

    powerset_finite : LEMMA  

    FORALL (A: finite_set[T]): is_finite[set[T]](powerset[T](A))

    doubleton_is_set: JUDGEMENT  doubleton[T] SUBTYPE_OF  set[T]


    all_edges(V):set[doubleton[T]] =
             {d: doubleton[T] | EXISTS (x,y: T): x /=y AND d = dbl[T](x,y) 
                                                 AND V(x) AND V(y)}

    all_edges_power  : LEMMA subset?(all_edges(V),powerset(V))

    all_edges_finite : LEMMA is_finite(all_edges(V))


    completion(G: graph[T]): graph[T] = 
                    (# vert  := vert(G),
                       edges := all_edges(vert(G)) #)


    completion_is_subgraph: LEMMA subgraph?[T](G, completion(G))


    complement(G: graph[T]): graph[T] = 
                    (# vert := vert(G),
                       edges := difference(all_edges(vert(G)),edges(G)) #)


    comp_comp_lem: LEMMA complement(complement(G)) = G


    isol(G: graph[T]): graph[T] = 
                    (# vert := vert(G),
                       edges := emptyset[doubleton[T]] #)


    IMPORTING graph_conn_defs

    x,y,z: VAR T
    P,Q: VAR[T,T->bool]
    w,w1,p,p1,r: VAR walks[T].prewalk

    % BEGINNING OF SECTION -------------------------------------------------
    % We show directly that either graph or its complement is path-connected.
    % Subsequently this is proved again using the Los graph theorem.
    % Results in this section depend only on above definitions and lemmas,
    % and are not referenced subsequently.

    path_or_not_path: THEOREM empty?(G) OR path_connected?(G) 
                              OR path_connected?(complement(G))

    % A stronger theorem.

    five_degrees_separation: PROPOSITION 
                             FORALL (x,y: (vert(G))): x = y 
                             OR (EXISTS w: walk_from?(G,w,x,y) and length(w)<5) 
                             OR FORALL (x,y: (vert(G))): x = y
                             OR (EXISTS w: walk_from?(complement(G),w,x,y) and length(w)<4 )

    % Using this stronger theORem we re-prove path_or_not

    paths_or_not: THEOREM empty?(G) OR path_connected?(G) OR path_connected?(complement(G))

    % Possibly a more compact formulation.


    five_degrees_separated: PROPOSITION 
                            (FORALL (x,y: (vert(G))): 
                                EXISTS w: walk_from?(G,w,x,y) AND length(w) < 5) 
                         OR
                            (FORALL (x,y: (vert(G))): 
                                EXISTS w: walk_from?(complement(G),w,x,y) AND length(w) < 4)


    % END OF PATH-CONNECTED SECTION -------------------------------------------

   
    strong_transitive?(G): bool = FORALL (x,y,z:(vert(G))): 
                                     edge?(G)(x,y) AND edge?(G)(y,z) AND x /= z 
                                  IMPLIES edge?(G)(x,z)

    transitive?(G): bool = FORALL (x,y,z: T):
                              edge?(G)(x,y) AND edge?(G)(y,z) AND x /= z 
                           IMPLIES edge?(G)(x,z)

    strong_implies: LEMMA strong_transitive?(G) IMPLIES transitive?(G)

    imply_strong  : LEMMA  transitive?(G) implies strong_transitive?(G) 


    completion_is_transitive: LEMMA strong_transitive?[T](completion(G))

   
    super(G1: graph[T])(G2: graph[T]): bool = subgraph?[T](G1,G2)


  % los_graphic: LEMMA (FORALL x,y,z: P(x,y)&P(y,z)=>P(x,z)) &
  %       (FORALL x,y: P(x,y) => P(y,x)) &
  %       (FORALL x,y,z: Q(x,y)&Q(y,z)=>Q(x,z)) &
  %       (FORALL x,y: Q(x,y) => Q(y,x)) &
  %       (FORALL x,y: P(x,y) OR Q(x,y)) =>
  %       (FORALL x,y:P(x,y)) OR (FORALL x,y: Q(x,y))

    IMPORTING los_graph

    trans_complem: LEMMA vert(G)=vert(H) AND strong_transitive?(G) 
                         AND strong_transitive?(H) AND union(G,H)=completion(G) 
                     IMPLIES G=completion(G) or H=completion(G)

          
    t_close(G): graph[T] = min[graph[T], num_edges[T],
                                 (LAMBDA (H: graph[T]): vert(H)=vert(G) AND super(G)(H) 
                                                        AND strong_transitive?(H))
                              ]

    t_close_1: LEMMA H=t_close(G) 
                     IMPLIES vert(H)=vert(G) AND super(G)(H) AND strong_transitive?(H)

    t_close_2: LEMMA H=t_close(G) AND super(G)(K) AND strong_transitive?(K) 
                     AND vert(K)=vert(G) 
                  IMPLIES num_edges[T](H) <= num_edges[T](K)

    t_close_3: LEMMA subgraph?[T](t_close(G),completion(G))

    trans_fill: LEMMA vert(G)=vert(H) AND union(G,H)=completion(G) 
                      IMPLIES union(t_close(G),t_close(H))=completion(G)

    complem_fill: THEOREM vert(G)=vert(H) AND  union(G,H)=completion(G) 
                          IMPLIES t_close(G)=completion(G) or t_close(H)=completion(G)


    IMPORTING graph_connected

    subgraph_conn: LEMMA subgraph?[T](H,G) AND connected?(H) AND vert(H)=vert(G) 
                         IMPLIES connected?(G)

    complete_conn: LEMMA empty?(G) OR connected?(completion(G))

    short_path     : LEMMA path_from?(G,p,x,y) AND length(p)>2 
                         AND edge?(G)(seq(p)(length(p)-3),seq(p)(length(p)-1)) 
                       IMPLIES (EXISTS p1: path_from?(G,p1,x,y) AND length(p1)=length(p)-1)

    trans_walk     : LEMMA strong_transitive?(G) AND walk_from?(G,w,x,y) 
                      IMPLIES x=y or edge?(G)(x,y)

    trans_connected: THEOREM strong_transitive?(G) AND connected?(G) 
                             IMPLIES G=completion(G)

    disjoint_trans : LEMMA empty?(intersection(vert(H),vert(K))) AND transitive?(H) 
                          AND transitive?(K) IMPLIES transitive?(union(H,K))

    disjoint_trans_strong: LEMMA empty?(intersection(vert(H),vert(K))) 
                                 AND strong_transitive?(H) AND strong_transitive?(K) 
                             IMPLIES strong_transitive?(union(H,K))

    subgraph_trans  : LEMMA subset?(V,vert(G)) AND transitive?(G) 
                            IMPLIES transitive?(subgraph(G,V))

    subgraph_trans_strong: LEMMA subset?(V,vert(G)) AND strong_transitive?(G) 
                                 IMPLIES strong_transitive?(subgraph(G,V))

    t_close_4       : LEMMA subgraph?[T](G,K) AND subgraph?[T](K,t_close(G))
                            AND strong_transitive?(K) 
                         IMPLIES K=t_close(G)

    closure_connect : LEMMA connected?(G) IFF connected?(t_close(G))

    connected_complem: THEOREM empty?(G) OR connected?(G) OR connected?(complement(G))

  % Up to this point we defined the transitive closure of a graph abstractly
  % as defining a type.  Now we show that the transitive closure "function" is
  % uniquely constructible.

    p_close(G): graph[T] = 
                (# vert:= vert(G), 
                   edges := {e:doubleton[T] | (FORALL (x,y:T): x /=y AND e(x) 
                             AND e(y) IMPLIES EXISTS (p:prewalk[T]): walk_from?(G,p,x,y))} 
                #)

    p_subgraph_t  : LEMMA subgraph?[T](p_close(G),t_close(G))

    p_transitive  : LEMMA strong_transitive?(p_close(G))

    p_close_1     : LEMMA H=p_close(G) IMPLIES vert(H)=vert(G) AND super(G)(H)

    p_close_trans : LEMMA t_close(G)=p_close(G)

    t_subgraph    : THEOREM subgraph?[T](H,G) IMPLIES subgraph?[T](t_close(H),t_close(G))

  END complem

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

  % Subtype TCC generated (at line 28, column 30) for  all_edges(vert(G))
      % expected type  finite_set[doubleton[T]]
  completion_TCC1: OBLIGATION
    FORALL (G: graph[T]): is_finite[doubleton[T]](all_edges(vert(G)));

  % Subtype TCC generated (at line 27, column 18) for
      % (# vert := vert(G), edges := all_edges(vert(G)) #)
      % expected type  graph[T]
  completion_TCC2: OBLIGATION
    FORALL (G: graph[T]):
      FORALL (e: doubleton[T]):
        all_edges(vert(G))(e) IMPLIES
         (FORALL (x: T): e(x) IMPLIES vert(G)(x));

  % Subtype TCC generated (at line 36, column 30) for
      % difference(all_edges(vert(G)), edges(G))
      % expected type  finite_set[doubleton[T]]
  complement_TCC1: OBLIGATION
    FORALL (G: graph[T]):
      is_finite[doubleton[T]]
          (difference[doubleton[T]](all_edges(vert(G)), edges(G)));

  % Subtype TCC generated (at line 35, column 18) for
      % (# vert := vert(G),
      %    edges := difference(all_edges(vert(G)), edges(G)) #)
      % expected type  graph[T]
  complement_TCC2: OBLIGATION
    FORALL (G: graph[T]):
      FORALL (e: doubleton[T]):
        difference[doubleton[T]](all_edges(vert(G)), edges(G))(e) IMPLIES
         (FORALL (x: T): e(x) IMPLIES vert(G)(x));

  % Subtype TCC generated (at line 43, column 18) for
      % (# vert := vert(G), edges := emptyset[doubleton[T]] #)
      % expected type  graph[T]
  isol_TCC1: OBLIGATION
    FORALL (G: graph[T]):
      FORALL (e: doubleton[T]):
        emptyset[doubleton[T]](e) IMPLIES
         (FORALL (x: T): e(x) IMPLIES vert(G)(x));

  % Assuming TCC generated (at line 121, column 25) for
      % min
      %     [graph[T], num_edges[T],
      %      (LAMBDA (H: graph[T]):
      %         vert(H) = vert(G) AND super(G)(H) AND strong_transitive?(H))]
      % generated from assumption abstract_min.T_ne
  t_close_TCC1: OBLIGATION
    FORALL (G: graph[T]):
      EXISTS (t: graph[T]):
        vert(t) = vert(G) AND super(G)(t) AND strong_transitive?(t);

  % Subtype TCC generated (at line 150, column 43) for  length(p) - 3
      % expected type  below[p`length]
  short_path_TCC1: OBLIGATION
    FORALL (G: graph[T], p: walks[T].prewalk, x, y: T):
      path_from?(G, p, x, y) AND length(p) > 2 IMPLIES
       length(p) - 3 >= 0 AND length(p) - 3 < p`length;

  % Subtype TCC generated (at line 150, column 63) for  length(p) - 1
      % expected type  below[p`length]
  short_path_TCC2: OBLIGATION
    FORALL (G: graph[T], p: walks[T].prewalk, x, y: T):
      path_from?(G, p, x, y) AND length(p) > 2 IMPLIES
       length(p) - 1 >= 0 AND length(p) - 1 < p`length;

  % Subtype TCC generated (at line 186, column 26) for
      % {e: doubleton[T] |
      %    (FORALL (x, y: T):
      %       x /= y AND e(x) AND e(y) IMPLIES
      %        (EXISTS (p: prewalk[T]): walk_from?(G, p, x, y)))}
      % expected type  finite_set[doubleton[T]]
  p_close_TCC1: OBLIGATION
    FORALL (G: graph[T]):
      is_finite[doubleton[T]]
          ({e: doubleton[T] |
              FORALL (x, y: T):
                x /= y AND e(x) AND e(y) IMPLIES
                 (EXISTS (p: prewalk[T]): walk_from?[T](G, p, x, y))});

  % Subtype TCC generated (at line 185, column 14) for
      % (# vert := vert(G),
      %    edges
      %      := {e: doubleton[T] |
      %            (FORALL (x, y: T):
      %               x /= y AND e(x) AND e(y) IMPLIES
      %                (EXISTS (p: prewalk[T]): walk_from?(G, p, x, y)))} #)
      % expected type  graph[T]
  p_close_TCC2: OBLIGATION
    FORALL (G: graph[T]):
      FORALL (e_1: doubleton[T]):
        (FORALL (x, y: T):
           x /= y AND e_1(x) AND e_1(y) IMPLIES
            (EXISTS (p: prewalk[T]): walk_from?[T](G, p, x, y)))
         IMPLIES (FORALL (x_1: T): e_1(x_1) IMPLIES vert(G)(x_1));


body:
  ind_paths[T: TYPE]: THEORY


  BEGIN

     IMPORTING paths[T]

     G: VAR graph[T]
     u,v,s,t: VAR T
     e: VAR doubleton[T]
     V: VAR finite_set[T]
     n: VAR nat

     independent?(w1,w2: prewalk): bool = 
                         (FORALL (i,j: nat): i > 0 AND i < length(w1) - 1 AND
                                             j > 0 AND j < length(w2) - 1 IMPLIES
                                      seq(w1)(i) /= seq(w2)(j))

     p1,p2: VAR prewalk
     independent?_comm: LEMMA independent?(p1,p2) IMPLIES
                                      independent?(p2,p1)

     independent_ne: LEMMA length(p1) > 2 AND independent?(p1,p2) IMPLIES p1 /= p2

     ps: VAR prewalk

  %   IMPORTING finite_sets

     set_of_paths(G,s,t): TYPE = finite_set[Path_from(G,s,t)]

     ind_path_set?(G,s,t,(pset: set_of_paths(G,s,t))): bool = 
                     (FORALL (p1,p2: Path_from(G,s,t)): 
                               pset(p1) AND pset(p2) AND  p1 /= p2
                                           IMPLIES independent?(p1,p2))

     ind_path_set_2: LEMMA FORALL (ips: set_of_paths(G,s,t)): 
                                      card(ips) = 2 AND
                                      ind_path_set?(G, s, t, ips)
                                IMPLIES
                           (EXISTS (P_1,P_2: prewalk): path_from?(G, P_1, s, t) AND
                                                      path_from?(G, P_2, s, t) AND
                                                        independent?(P_1,P_2) )

     internal_verts(w: prewalk): finite_set[T] = 
                 {t: T | (EXISTS (i: nat): i > 0 AND i < length(w) - 1 AND w(i) = t)}


     indep?(w1,w2: prewalk): bool = empty?(intersection(internal_verts(w1),
                                                        internal_verts(w2)))

     w1,w2: VAR prewalk
     indep?_lem: LEMMA indep?(w1,w2) IFF independent?(w1,w2) 

  END ind_paths

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

  % Subtype TCC generated (at line 17, column 44) for  i
      % expected type  below[w1`length]
  independent?_TCC1: OBLIGATION
    FORALL (w1, w2: prewalk[T], i, j: nat):
      i > 0 AND i < length(w1) - 1 AND j > 0 AND j < length(w2) - 1 IMPLIES
       i < w1`length;

  % Subtype TCC generated (at line 17, column 58) for  j
      % expected type  below[w2`length]
  independent?_TCC2: OBLIGATION
    FORALL (w1, w2: prewalk[T], i, j: nat):
      i > 0 AND i < length(w1) - 1 AND j > 0 AND j < length(w2) - 1 IMPLIES
       j < w2`length;

  % Subtype TCC generated (at line 45, column 75) for  i
      % expected type  below[length(w)]
  internal_verts_TCC1: OBLIGATION
    FORALL (w: prewalk[T], t: T, i: nat):
      i < length(w) - 1 AND i > 0 IMPLIES i < length(w);

  % Subtype TCC generated (at line 45, column 15) for
      % {t: T |
      %    (EXISTS (i: nat):
      %       i > 0 AND i < length(w) - 1 AND finseq_appl[T](w)(i) = t)}
      % expected type  finite_set[T]
  internal_verts_TCC2: OBLIGATION
    FORALL (w: prewalk[T]):
      is_finite[T]
          ({t: T |
              EXISTS (i: nat):
                i > 0 AND i < length(w) - 1 AND finseq_appl[T](w)(i) = t});


body:
  easy_menger[T: TYPE]: THEORY
  BEGIN

     IMPORTING sep_sets[T], ind_paths[T]

     G: VAR graph[T]
     v,s,t: VAR T
     e: VAR doubleton[T]
     V: VAR finite_set[T]


     m: VAR nat
     easy_menger: LEMMA FORALL (ips:  set_of_paths(G,s,t)):
                           separable?(G,s,t) AND
                           ind_path_set?(G,s,t,ips) IMPLIES
                           card(ips) <= sep_num(G,s,t)


  % --------------------------- PLAY STUFF ------------------------------ %


     easy_meng_1: LEMMA FORALL (ips:  set_of_paths(G,s,t)):
                           separable?(G,s,t) AND
                           ind_path_set?(G,s,t,ips) IMPLIES
                           card(ips) <= sep_num(G,s,t)


  END easy_menger


body:
  finite_sets_card_from[T1 : TYPE, T2 : TYPE FROM T1] : THEORY
  %-------------------------------------------------------------------------
  %
  %      by Jon Sjogren AFOSR/NE
  % Establishes:
  %
  %       card_eq_bij : LEMMA card(E) = card(F) IFF 
  %                                  EXISTS (f: [(E)->(F)]): bijective?(f)
  %
  %-------------------------------------------------------------------------

  BEGIN

    IMPORTING finite_sets, finite_sets@func_composition, finite_sets@finite_sets_card_eq

    E: VAR finite_set[T1]
    F: VAR finite_set[T2]

    N: VAR nat
   
    card_extension: LEMMA card(extend[T1,T2,bool,false](F))=card(F)



   

  END finite_sets_card_from


body:
  k_menger[T: TYPE]: THEORY 
  BEGIN
     %% IMPORTING h_menger[T], 

     %% IMPORTING meng_scaff_prelude[T], 
        IMPORTING ind_paths[T]


     IMPORTING graph_inductions[T], graph_ops[T], path_ops[T]
     IMPORTING finite_sets@finite_sets_inductions[T]

     G,GG,H,HH,MM: VAR graph[T]
     v,s,t,w,w1,w2,a,b,c,av,ajm,z,x: VAR T
     W,W1,W2: VAR finite_set[T]
     p,p1,p2,q,q1,q2: VAR prewalk
     e: VAR doubleton[T]
     U,U1,V,V1,V2: VAR finite_set[T]
     k,i,j,m,n: VAR nat
   
          
     good?(G,s,t):bool = separable?(G,s,t) AND vert(G)(s) AND vert(G)(t)

     green?(V,s,t):bool = NOT V(s) AND NOT V(t)

     B(G,s,t,k): bool = good?(G,s,t) AND (FORALL V: separates(G,V,s,t) IMPLIES card(V)>=k)

     set_of_prewalks: TYPE = finite_set[prewalk]

     ips,ipt,ips1,ips2,ipss,ipst,ipsg: VAR set_of_prewalks

     ind_prewalk_set?(ips): bool = 
                     (FORALL (p1,p2): 
                               ips(p1) AND ips(p2) AND  p1 /= p2
                                           IMPLIES independent?(p1,p2))
     st_path_set?(G,s,t,ips): bool = (FORALL p1 : ips(p1) IMPLIES path_from?(G,p1,s,t))

     many_ind(G,s,t,j):bool = EXISTS (ips): ind_prewalk_set?(ips) 
                                            AND st_path_set?(G,s,t,ips) 
                                            AND card[prewalk](ips)=j


     B_many(G,s,t,k): bool = B(G,s,t,k) IMPLIES many_ind(G,s,t,k)

  %  Relation to sep_num is mentioned for comparison; minimal separating set or 
  %  separating number will not be used in the sequel.

     sep_num_B:       LEMMA  B(G,s,t,k) IMPLIES sep_num(G,s,t)>=k

     sep_num_implies: LEMMA  good?(G,s,t) AND sep_num(G,s,t)=k IMPLIES B(G,s,t,k)

  % We do not perform a new proof of easy_menger but simply recast it in our
  % notation.

    % We use some basic results on card from extension that are originally found
    % in finite_sets module.

    IMPORTING finite_sets_card_from

    card_extension_W   : LEMMA subset?(V,W) IMPLIES 
                               card(extend[T,(W),bool,false](V))=card(V)

    card_extension_same: LEMMA card(extend[T,(W),bool,false](W))=card(W)

    % This last result will be used in comparing card for prewalk sets AND vertex
    % sets.

     %% IMPORTING menger

     IMPORTING easy_menger[T], subgraph_paths[T] %% , meng_scaff_defs[T]
     IMPORTING complem 

     easy_menger_B: LEMMA good?(G,s,t) AND many_ind(G,s,t,k) IMPLIES B(G,s,t,k)


  % No min_sep_set after this point.  Also specifications from "menger.pvs"
  % will no longer be used. Lemma "easy_menger" was the basis of "easy_menger_B"
  % above. 

     C(G,s,t):bool = (FORALL k: B_many(G,s,t,k))

     sep_set_small: LEMMA B(G,s,t,k) AND green?(V,s,t) AND card(V) < k 
                          IMPLIES EXISTS p : path_from?(del_verts(G,V),p,s,t)

     B_many_1     : LEMMA B_many(G,s,t,1)

  % Here you prove all special cases.

    tight?(G,s,t,W): bool = subset?(W, intersection(path_verts(G,s),path_verts(G,t)))

    sub_tight     : LEMMA subset?(V,W) AND tight?(G,s,t,W) IMPLIES tight?(G,s,t,V)

    smaller_tight : LEMMA separates(G,W,s,t) 
                          IMPLIES tight?(G,s,t,W)
                             OR EXISTS V :subset?(V,W) AND NOT V=W AND separates(G,V,s,t)

    small_tight   : LEMMA separates(G,W,s,t) IMPLIES
                          EXISTS V :subset?(V,W) AND separates(G,V,s,t) AND tight?(G,s,t,V)

    exists_tight  : LEMMA good?(G,s,t) IMPLIES 
                                     EXISTS V: separates(G,V,s,t) AND tight?(G,s,t,V)

    close?(G,s,t,W): bool = FORALL (w:T) :  W(w) 
                            IMPLIES EXISTS p: path_from?(G,p,s,t) 
                                      AND intersection(W,internal_verts(p))=singleton[T](w)

    close_tight   : LEMMA close?(G,s,t,W) IMPLIES tight?(G,s,t,W)

    smaller_close : LEMMA separates(G,W,s,t) AND tight?(G,s,t,W) IMPLIES
                         close?(G,s,t,W) OR EXISTS V :subset?(V,W) AND 
                                NOT V=W AND separates(G,V,s,t) AND tight?(G,s,t,V)
          
    small_close   : LEMMA separates(G,W,s,t) IMPLIES
                          EXISTS V :subset?(V,W) AND separates(G,V,s,t) AND close?(G,s,t,V)

    exists_close: LEMMA good?(G,s,t) 
                          IMPLIES EXISTS V: separates(G,V,s,t) AND close?(G,s,t,V)

    closed_minimal: LEMMA separates(G,W,s,t) AND close?(G,s,t,W) 
                          AND subset?(V,W) AND separates(G,V,s,t) IMPLIES V=W

    closed_verts: LEMMA close?(G,s,t,W) IMPLIES subset?(W,vert(G))

    attached?(G,s,t,W): bool = (FORALL w: W(w) IMPLIES edge?(G)(s,w)) OR 
                               (FORALL w: W(w) IMPLIES edge?(G)(t,w))

    attach_edges(W,x): finite_set[doubleton[T]] 
                           = {e :doubleton[T]|EXISTS w: W(w) AND e=dbl[T](w,x)}

    %%%%%%%  Definition of special graphs.

    Hverts(G,W,x): finite_set[T] = path_verts(del_verts(G,W),x)

    Kgraph(G,W,x): graph = subgraph(G, difference[T](vert(G),Hverts(G,W,x)))

    Mgraph(G,W,x):graph = (# vert :=  add(x,vert(Kgraph(G,W,x))), 
                             edges := union(edges(Kgraph(G,W,x)),
                                            attach_edges(intersection(vert(G),W),x))
                           #)

    %%%%%%%   End of definitions.

    Hst_intersect: LEMMA separates(G,W,s,t) 
                         IMPLIES empty?(intersection(Hverts(G,W,s),Hverts(G,W,t)))       

    subset_Ws: LEMMA good?(G,s,t) AND separates(G,W,s,t) AND NOT attached?(G,s,t,W) 
                     IMPLIES subset?(vert(Mgraph(G,W,s)),vert(G))

    subset_Wt: LEMMA good?(G,s,t) AND separates(G,W,s,t) AND NOT attached?(G,s,t,W) 
                     IMPLIES subset?(vert(Mgraph(G,W,t)),vert(G))

    size_Ws: LEMMA good?(G,s,t) AND separates(G,W,s,t) 
                   AND close?(G,s,t,W) AND NOT attached?(G,s,t,W) 
                   IMPLIES size(Mgraph(G,W,s)) < size(G)

    size_Wt: LEMMA good?(G,s,t) AND separates(G,W,s,t) 
                   AND close?(G,s,t,W) AND NOT attached?(G,s,t,W) 
                   IMPLIES size(Mgraph(G,W,t)) < size(G)

    C_induct(G,s,t):bool = (FORALL GG: size(GG)<size(G) IMPLIES C(GG,s,t))
                                IMPLIES C(G,s,t)

    Menger_hard: LEMMA (FORALL G:C_induct(G,s,t)) IMPLIES
                             (FORALL G: C(G,s,t))          %Proved from graph inductions.

     % We include some elementary lemmas on paths.  Some were proved 
     % earlier in meng_scaff_defs.pvs, and the "greatest" and "least"
     % constructions would follow from meng_scaff.pvs. We give a formulation
     % specific to subsets of vertices in a graph.

    subgraph_walks: LEMMA subgraph?(GG,G) AND walk?(GG,p1) IMPLIES walk?(G,p1)


    subgraph_paths: LEMMA subgraph?(GG,G) AND path_from?(GG,p1,s,t) 
                          IMPLIES path_from?(G,p1,s,t)

    greatest?(p,V,i): bool = i<length(p) AND V(seq(p)(i)) AND 
                      FORALL j:(j<length(p) AND V(seq(p)(j)) IMPLIES j<=i)

    least?(p,V,i): bool = i<length(p) AND V(seq(p)(i)) AND FORALL j:(j<length(p) AND V(seq(p)(j)) 
                          IMPLIES j>=i)

    greatest_is: LEMMA i<length(p) AND V(seq(p)(i)) IMPLIES EXISTS k: greatest?(p,V,k)

    least_is: LEMMA i<length(p) AND V(seq(p)(i)) IMPLIES EXISTS k: least?(p,V,k)

    set_small_s: LEMMA B(G,s,t,k) AND good?(G,s,t) 
                       AND separates(G,W,s,t) AND green?(V,s,t) AND card(V) < k 
                       IMPLIES EXISTS p : path_from?(del_verts(Mgraph(G,W,s),V),p,s,t)

    set_small_t: LEMMA B(G,s,t,k) AND good?(G,s,t) AND separates(G,W,s,t) 
                       AND green?(V,s,t) AND card(V) < k 
                       IMPLIES EXISTS p : path_from?(del_verts(Mgraph(G,W,t),V),p,s,t)

    separates_Ws: LEMMA B(G,s,t,k) AND separates(G,W,s,t) IMPLIES B(Mgraph(G,W,s),s,t,k) 

    separates_Wt: LEMMA B(G,s,t,k) AND separates(G,W,s,t) IMPLIES B(Mgraph(G,W,t),s,t,k) 


    separ_sub: LEMMA subgraph?(GG,G) AND separates(G,V,s,t) 
                     IMPLIES separates(GG,V,s,t)

    separ_plus: LEMMA separates(del_vert(G,a),V,s,t) 
                      IMPLIES separates(G,add(a,V),s,t) or a=s or a=t

    % A main lemma based on graph induction is used only in the version of k_Menger
    % Theorem below called 'Many_indep_paths'.

    super_separ: LEMMA good?(G,s,t) AND subset?(V,W) 
                       AND green?(W,s,t) AND separates(G,V,s,t) 
                       IMPLIES separates(G,W,s,t)

    % Requires a graph induction.

    intermediate_subgraph: LEMMA (good?(G,s,t) AND subgraph?(H,G) AND green?(vert(H),s,t) 
                                  AND size(H)<=k AND k< size(G)-1) 
                            IMPLIES (EXISTS HH: (green?(vert(HH),s,t) AND 
                                                 subgraph?(H,HH) AND size(HH)=k AND 
                                                 subgraph?(HH,G)))

    intermediate_verts: LEMMA good?(G,s,t) AND green?(V,s,t) 
                              AND subset?(V,vert(G)) AND card(V)<=k AND k<size(G)-1 
                          IMPLIES (EXISTS W: subset?(V,W) AND card(W)=k AND 
                                             green?(W,s,t) AND subset?(W,vert(G)))

    % The section necessary for 'Many_indep_paths' is closed. 

    one_wedge_s: LEMMA good?(G,s,t) 
                       AND path_from?(G,q,s,t) IMPLIES 
                               EXISTS k: k<length(q)-1 AND edge?(G)(s,seq(q)(k)) 
                       AND (FORALL j: j < length(q) AND edge?(G)(s, seq(q)(j)) IMPLIES j <= k) 
                       AND path_from?(G,gen_seq1(G,s) o q^(k,length(q)-1),s,t)

    one_edge_s: LEMMA good?(G,s,t) 
                      AND path_from?(G,q,s,t) IMPLIES EXISTS p:path_from?(G,p,s,t) 
                      AND FORALL (i: below(length(p))):( edge?(G)(s,seq(p)(i)) IMPLIES i=1)
                      AND subset?(verts_of(p),verts_of(q))

    % Auxiliary LEMMA  one_edge_t: LEMMA good?(G,s,t) AND path_from?(G,q,s,t) 
    %                  IMPLIES EXISTS p:path_from?(G,p,s,t) 
    %                      AND FORALL (i: below(length(p))):( edge?(G)(seq(p)(i),t) 
    %                      IMPLIES i=length(p)-2) AND subset?(verts_of(p),verts_of(q))


    IMPORTING sep_set_lems[T]

    short_path_k: LEMMA k>=1 AND B(G,s,t,k) IMPLIES EXISTS p:path_from?(G,p,s,t) AND
                         FORALL (i: below(length(p))): ((edge?(G)(s,seq(p)(i)) 
                                IMPLIES i=1) AND (edge?(G)(seq(p)(i),t) IMPLIES i=length(p)-2))

    indep_path_sub: LEMMA subgraph?(GG,G)AND many_ind(GG,s,t,j) IMPLIES many_ind(G,s,t,j)


    second: VAR [prewalk -> T]

    %  [{p:prewalk | length(p)>1} -> T]

    ips_lem1: LEMMA (FORALL q,q1:(ips(q) IMPLIES V(second(q))) AND (ips(q) AND ips(q1) 
                            AND q /= q1 IMPLIES second(q) /= second(q1)))
                 IMPLIES subset?(image(second,ips),V) AND 
                         injective?(restrict[prewalk,(ips),T](second)) 

    ips_lem2: LEMMA (FORALL q,q1:(ips(q) IMPLIES V(second(q))) AND (ips(q) 
                            AND ips(q1) AND q /= q1 IMPLIES second(q) /= second(q1))) 
                     AND card[prewalk](ips)=card[T](V) 
                 IMPLIES image(second,ips)=V 


    secoo(p:prewalk | length(p)>1): T = p(1)

    secpp(p:prewalk|length(p)>1): T = p(length(p)-2)
          
     inj_ips: LEMMA (FORALL (q,q1):(ips(q) IMPLIES V(second(q))) 
                                    AND (ips(q) AND ips(q1) AND q /= q1 IMPLIES
                                        second(q) /= second(q1)))
                    AND card[prewalk](ips)=card[T](V)
                 IMPLIES EXISTS (fq:[(V) -> prewalk]): image(fq,V)=ips AND 
                         (FORALL (v:(V)): second(fq(v))=v) AND 
                         (FORALL q2:ips(q2) IMPLIES fq(second(q2))=q2)

    long_ipss_paths: LEMMA good?(G,s,t) AND st_path_set?(Mgraph(G,W,s),s,t,ipss) 
                           AND ipss(p) IMPLIES length(p)>1 

    ipss_W: LEMMA good?(G,s,t) AND st_path_set?(Mgraph(G,W,s),s,t,ipss) 
                  AND separates(G,W,s,t) AND ipss(p) IMPLIES W(secoo(p))

    long_ipst_paths: LEMMA good?(G,s,t) AND st_path_set?(Mgraph(G,W,t),s,t,ipss) 
                           AND ipss(p) IMPLIES length(p)>1

    ipst_W: LEMMA good?(G,s,t) AND st_path_set?(Mgraph(G,W,t),s,t,ipss) 
                  AND separates(G,W,s,t) AND ipss(p) IMPLIES W(secpp(p))

    long_ipss_2: LEMMA good?(G,s,t) AND st_path_set?(Mgraph(G,W,s),s,t,ipss) 
                       AND ipss(p) AND separates(G,W,s,t) IMPLIES length(p)>2

    long_ipst_2: LEMMA good?(G,s,t) AND st_path_set?(Mgraph(G,W,t),s,t,ipss) 
                       AND ipss(p) AND separates(G,W,s,t) IMPLIES length(p)>2  

    ind_path_set_secoo: LEMMA good?(G,s,t) AND card[T](W)= card[prewalk](ipss) 
                              AND separates(G,W,s,t) AND ind_prewalk_set?(ipss) 
                              AND st_path_set?(Mgraph(G,W,s),s,t,ipss) 
                          IMPLIES image(secoo, ipss)=W AND 
                                 FORALL (q,q1):(ipss(q) AND ipss(q1) AND q /=q1 
                                                IMPLIES secoo(q) /= secoo(q1))


    ind_path_set_secpp: LEMMA good?(G,s,t) AND card[T](W)= card[prewalk](ipst) 
                              AND separates(G,W,s,t) AND ind_prewalk_set?(ipst) 
                              AND st_path_set?(Mgraph(G,W,t),s,t,ipst) 
                          IMPLIES image(secpp, ipst)=W 
                                  AND FORALL (q,q1):(ipst(q) AND ipst(q1) AND q /=q1 
                                                    IMPLIES secpp(q) /= secpp(q1))

    uniq_w_ipss:   LEMMA good?(G,s,t) AND card[T](W)= card[prewalk](ipss) 
                         AND ind_prewalk_set?(ipss) 
                         AND st_path_set?(Mgraph(G,W,s),s,t,ipss) AND separates(G,W,s,t) 
                         AND ipss(p) AND verts_of(p)(w) AND W(w) 
                      IMPLIES w=secoo(p)


    uniq_w_ipst:   LEMMA good?(G,s,t) AND card[T](W)= card[prewalk](ipst) 
                         AND ind_prewalk_set?(ipst) 
                         AND st_path_set?(Mgraph(G,W,t),s,t,ipst) AND separates(G,W,s,t) 
                         AND ipst(q) AND verts_of(q)(w) AND W(w) 
                     IMPLIES w=secpp(q) 

  % Instead of calling on minimal separating set, we show by induction that such a set EXISTS.

    low_card_sep: LEMMA B(G,s,t,k) IMPLIES EXISTS W: separates(G,W,s,t) 
                           AND card(W)>=k AND FORALL V: (separates(G,V,s,t) 
                       IMPLIES card(V)>= card(W))

    smaller_ips : LEMMA j<=card[prewalk](ips) 
                        IMPLIES EXISTS ips1: subset?(ips1,ips) AND card[prewalk](ips1)=j

    few_many    : LEMMA i>=j AND many_ind(G,s,t,i) 
                        IMPLIES many_ind(G,s,t,j)
     
    min_B       : LEMMA B(G,s,t,k) IMPLIES 
                          EXISTS (i,W): i>=k AND B(G,s,t,i) AND
                                        separates(G,W,s,t) AND card(W)=i

    no_sep_req  : LEMMA (FORALL k,W: B(G,s,t,k) AND separates(G,W,s,t) 
                         AND card(W)=k IMPLIES many_ind(G,s,t,k)) 
                       IMPLIES (FORALL k: B(G,s,t,k) IMPLIES many_ind(G,s,t,k))

    k_sep_close : LEMMA FORALL k,W: B(G,s,t,k) AND separates(G,W,s,t) 
                        AND card(W)=k IMPLIES close?(G,s,t,W)

    p_Ht        : LEMMA good?(G,s,t) AND separates(G,W,s,t) 
                        AND path_from?(Mgraph(G,W,s),p,s,t) AND length(p)>2 
                        AND (FORALL w: W(w) AND verts_of(p)(w) IMPLIES w=secoo(p)) 
                     IMPLIES subset?(verts_of(p^(2,length(p)-1)),Hverts(G,W,t))

    q_Hs        : LEMMA good?(G,s,t) AND separates(G,W,s,t) 
                        AND path_from?(Mgraph(G,W,t),q,s,t) AND length(q)>2 
                        AND (FORALL w: W(w) AND verts_of(q)(w) IMPLIES w=secpp(q)) 
                     IMPLIES subset?(verts_of(q^(0,length(q)-3)),Hverts(G,W,s))

    disjoint_M_paths: LEMMA good?(G,s,t) AND close?(G,s,t,W) AND separates(G,W,s,t) 
                            AND card[T](W)= card[prewalk](ipss) 
                            AND card[T](W)= card[prewalk](ipst) 
                            AND st_path_set?(Mgraph(G,W,s),s,t,ipss) 
                            AND st_path_set?(Mgraph(G,W,t),s,t,ipst) 
                            AND ind_prewalk_set?(ipss) AND ind_prewalk_set?(ipst) 
                            AND ipss(p) AND ipst(q)
                      IMPLIES (secoo(p)=secpp(q) AND 
                               intersection(verts_of(p^(1,length(p)-1)),verts_of(q^(0,length(q)-2)))
                                  =singleton[T](secoo(p)) AND 
                               W(secoo(p))) 
                          OR (secoo(p) /= secpp(q) AND 
                              empty?(intersection(verts_of(p^(1,length(p)-1)),
                                                  verts_of(q^(0,length(q)-2)))))

    % The first two hypotheses of sec_image are mainly to assure a non-empty type for
    % Thence for prewalk. We could have used the lemmas of prelude function_image and
    % function_inverse_def but a brute force approach is serviceable.  Note however
    % that producing an inverse for 'second' mapping involves the possibility of
    % (ipss) that is an empty set of prewalks.  Some of the work in sec_image
    % is to recall how a function defined from an empty set to an empty set
    % has an inverse.

     sec_image: LEMMA good?(G,s,t) AND separates(G,W,s,t) AND image(second, ipss)=W 
                      AND injective?(LAMBDA (s: (ipss)): second(s))
                            IMPLIES 
                  EXISTS (tau:[(W) -> prewalk]): image(tau,W)=ipss 
                                               AND FORALL w:(W(w) 
                                                      IMPLIES second(tau(w))=w) 

     Map_s    : LEMMA good?(G,s,t) AND separates(G,W,s,t) 
                      AND card[T](W)= card[prewalk](ipss) AND ind_prewalk_set?(ipss) 
                      AND st_path_set?(Mgraph(G,W,s),s,t,ipss) 
                 IMPLIES EXISTS (tau:[(W) -> prewalk]): image(tau,W)=ipss 
                            AND FORALL w: (W(w) IMPLIES secoo(tau(w))=w) 

     Map_t    : LEMMA good?(G,s,t) AND separates(G,W,s,t) 
                      AND card[T](W)= card[prewalk](ipst) AND ind_prewalk_set?(ipst) 
                      AND st_path_set?(Mgraph(G,W,t),s,t,ipst) 
               IMPLIES EXISTS (tau:[(W) -> prewalk]): image(tau,W)=ipst 
                            AND FORALL w: (W(w) IMPLIES secpp(tau(w))=w) 

  % The following took twenty days to complete.

     Mapper_ips:  LEMMA good?(G,s,t) AND close?(G,s,t,W) AND separates(G,W,s,t) 
                        AND card[T](W)= card[prewalk](ipss) 
                        AND card[T](W)= card[prewalk](ipst) 
                        AND st_path_set?(Mgraph(G,W,s),s,t,ipss) 
                        AND st_path_set?(Mgraph(G,W,t),s,t,ipst) 
                        AND ind_prewalk_set?(ipss) AND ind_prewalk_set?(ipst) 
                  IMPLIES EXISTS (phi:[(W) -> prewalk]): 
                               card[prewalk](image(phi,W))=card[T](W) AND 
                               st_path_set?(G,s,t,image(phi,W)) AND 
                               ind_prewalk_set?(image(phi,W)) 

     non_attached_induct: LEMMA good?(G,s,t) AND separates(G,W,s,t) AND B(G,s,t,k) 
                                AND card[T](W)=k 
                                AND (FORALL GG: size(GG)<size(G) IMPLIES C(GG,s,t)) 
                              IMPLIES many_ind(G,s,t,k) or attached?(G,s,t,W)

     plus_sep_vert : LEMMA good?(G,s,t) AND separates(del_vert(G,a),W,s,t) 
                           IMPLIES separates(G,add(a,W),s,t) or a=s or a=t

     separ_del_vert: LEMMA separates(G,W,s,t) 
                           IMPLIES separates(G,remove(x,W),s,t) OR vert(G)(x)

     plus_path_set : LEMMA good?(G,s,t) AND path_from?(G,q,s,t) 
                           AND st_path_set?(del_verts(G,verts_of(q^(1,length(q)-2))),s,t,ips) 
                           AND ind_prewalk_set?(ips) 
                     IMPLIES EXISTS ipss: card[prewalk](ipss)= card[prewalk](ips)+1 AND
                                          st_path_set?(G,s,t,ipss) AND 
                                          ind_prewalk_set?(ipss)

     short_path_attach: LEMMA B(G,s,t,k) AND separates(G,W,s,t) AND card[T](W)=k 
                              AND (FORALL V: separates(G,V,s,t) 
                              AND card[T](V)=k  IMPLIES attached?(G,s,t,V)) 
                              AND (FORALL GG: size(GG)<size(G) IMPLIES C(GG,s,t)) 
                     IMPLIES many_ind(G,s,t,k) 
                             OR EXISTS a: edge?(G)(s,a) AND (edge?(G)(a,t) 
                             OR EXISTS c: edge?(G)(a,c) AND edge?(G)(c,t))    

     bridge_one  : LEMMA edge?(G)(s,a) AND edge?(G)(a,t) 
                         AND (FORALL GG: size(GG)<size(G) IMPLIES C(GG,s,t)) 
                     IMPLIES B_many(G,s,t,k)

     bridge_two  : LEMMA k>=1 AND edge?(G)(s,a) AND edge?(G)(a,c) AND edge?(G)(c,t) 
                         AND  B(del_verts(G,dbl[T](a,c)),s,t,k-1) 
                         AND (FORALL GG: size(GG)<size(G) IMPLIES C(GG,s,t)) 
                     IMPLIES B_many(G,s,t,k)

     bridge_three: LEMMA  k>=1 AND edge?(G)(s,a) AND edge?(G)(a,c) AND edge?(G)(c,t) 
                          AND B(G,s,t,k) AND separates(G,W,s,t) AND card[T](W)=k 
                          AND (FORALL V: separates(G,V,s,t) 
                          AND card[T](V)=k IMPLIES attached?(G,s,t,V)) 
                    IMPLIES B(del_verts(G,dbl[T](a,c)),s,t,k-1) 
                            OR edge?(G)(s,c) OR edge?(G)(a,t)    

     C_induct_lemma: LEMMA  C_induct(G,s,t)   % Major lemma to prove.


     Menger_k_hard: THEOREM C(G,s,t)          % Proved from C_induct lemma.


     % Next is a 'constructive' version of hard Menger theorem. We search for separating
     % sets only among suitable subsets of the vertices of G, 
     % those not containing the terminals. If all such 
     % 'green' subsets of vert(G) of cardinality k (< size(G) -1) fail to separate s 
     % from t in G, one concludes that there are k+1 independent paths in G from s to t.

     Many_indep_paths: THEOREM good?(G,s,t) AND k<=size(G)-2 
                               AND (FORALL W: card[T](W)=k 
                               AND subset?(W,difference(vert(G), dbl(s,t))) 
                                      IMPLIES EXISTS q: walk_from?(del_verts(G,W),q,s,t)) 
                             IMPLIES many_ind(G,s,t,k+1)


     % We proved the general hard k-Menger theorem independently of the
     % proof for case k=2, without using 'sep_num' or
     % 'minimal separating set'. Using the definitions of these
     % terms, we may derive the traditional version directly from Menger_k_hard.

     hard_menger_trad: THEOREM  separable?(G,s,t) AND sep_num(G,s,t) = k 
                                AND vert(G)(s) AND vert(G)(t) 
                          IMPLIES
                              (EXISTS (ips: set_of_paths(G,s,t)):
                                     card(ips) = k AND ind_path_set?(G,s,t,ips))
    

  END k_menger

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

  % Subtype TCC generated (at line 127, column 27) for
      % {e: doubleton[T] | EXISTS w: W(w) AND e = dbl[T](w, x)}
      % expected type  finite_set[doubleton[T]]
  attach_edges_TCC1: OBLIGATION
    FORALL (W: finite_set[T], x: T):
      is_finite[doubleton[T]]
          ({e: doubleton[T] | EXISTS w: W(w) AND e = dbl[T](w, x)});

  % Subtype TCC generated (at line 131, column 33) for
      % path_verts(del_verts(G, W), x)
      % expected type  finite_set[T]
  Hverts_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], x: T):
      is_finite[T](path_verts[T](del_verts[T](G, W), x));

  % Subtype TCC generated (at line 135, column 24) for
      % (# vert := add(x, vert(Kgraph(G, W, x))),
      %    edges
      %      := union(edges(Kgraph(G, W, x)),
      %               attach_edges(intersection(vert(G), W), x)) #)
      % expected type  graph[T]
  Mgraph_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], x: T):
      FORALL (e: doubleton[T]):
        union[doubleton[T]]
            (edges(Kgraph(G, W, x)),
             attach_edges(intersection[T](vert(G), W), x))
            (e)
         IMPLIES
         (FORALL (x_1: T):
            e(x_1) IMPLIES add[T](x, vert(Kgraph(G, W, x)))(x_1));

  % Subtype TCC generated (at line 229, column 75) for  k
      % expected type  below[q`length]
  one_wedge_s_TCC1: OBLIGATION
    FORALL (G: graph[T], q: prewalk[T], s, t: T):
      path_from?(G, q, s, t) AND good?(G, s, t) IMPLIES
       (FORALL (k): k < length(q) - 1 IMPLIES k < q`length);

  % Subtype TCC generated (at line 231, column 49) for  s
      % expected type  (vert(G))
  one_wedge_s_TCC2: OBLIGATION
    FORALL (G: graph[T], q: prewalk[T], s, t: T):
      path_from?(G, q, s, t) AND good?(G, s, t) IMPLIES
       (FORALL (k):
          (FORALL j: j < length(q) AND edge?(G)(s, seq(q)(j)) IMPLIES j <= k)
           AND edge?(G)(s, seq(q)(k)) AND k < length(q) - 1
           IMPLIES vert(G)(s));

  % Subtype TCC generated (at line 231, column 59) for  length(q) - 1
      % expected type  nat
  one_wedge_s_TCC3: OBLIGATION
    FORALL (G: graph[T], q: prewalk[T], s, t: T):
      path_from?(G, q, s, t) AND good?(G, s, t) IMPLIES
       (FORALL (k):
          (FORALL j: j < length(q) AND edge?(G)(s, seq(q)(j)) IMPLIES j <= k)
           AND edge?(G)(s, seq(q)(k)) AND k < length(q) - 1
           IMPLIES length(q) - 1 >= 0);

  % Subtype TCC generated (at line 231, column 38) for
      % gen_seq1(G, s) o q ^ (k, length(q) - 1)
      % expected type  prewalk[T]
  one_wedge_s_TCC4: OBLIGATION
    FORALL (G: graph[T], q: prewalk[T], s, t: T):
      path_from?(G, q, s, t) AND good?(G, s, t) IMPLIES
       (FORALL (k):
          (FORALL j: j < length(q) AND edge?(G)(s, seq(q)(j)) IMPLIES j <= k)
           AND edge?(G)(s, seq(q)(k)) AND k < length(q) - 1
           IMPLIES
           length(o[T](gen_seq1[T](G, s), ^[T](q, (k, length(q) - 1)))) > 0);

  % Subtype TCC generated (at line 268, column 40) for  1
      % expected type  below[length(p)]
  secoo_TCC1: OBLIGATION
    FORALL (p: prewalk[T] | length(p) > 1): 1 < length(p);

  % Subtype TCC generated (at line 270, column 38) for  length(p) - 2
      % expected type  below[length(p)]
  secpp_TCC1: OBLIGATION
    FORALL (p: prewalk[T] | length(p) > 1):
      length(p) - 2 >= 0 AND length(p) - 2 < length(p);

  % Subtype TCC generated (at line 278, column 53) for  second(q2)
      % expected type  (V)
  inj_ips_TCC1: OBLIGATION
    FORALL (V: finite_set[T], ips: set_of_prewalks,
            second: [prewalk[T] -> T]):
      (card[prewalk](ips) = card[T](V) AND
        (FORALL (q, q1):
           (ips(q) IMPLIES V(second(q))) AND
            (ips(q) AND ips(q1) AND q /= q1 IMPLIES
              second(q) /= second(q1))))
       IMPLIES
       (FORALL (fq: [(V) -> prewalk[T]]):
          (FORALL (v: (V)): second(fq(v)) = v) AND
           image(fq, restrict[T, (V), boolean](V)) = ips
           IMPLIES (FORALL (q2): ips(q2) IMPLIES V(second(q2))));

  % Subtype TCC generated (at line 284, column 67) for  p
      % expected type  {p: prewalk | length(p) > 1}
  ipss_W_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss: set_of_prewalks,
            p: prewalk[T], s, t: T):
      ipss(p) AND
       separates(G, W, s, t) AND
        st_path_set?(Mgraph(G, W, s), s, t, ipss) AND good?(G, s, t)
       IMPLIES length(p) > 1;

  % Subtype TCC generated (at line 290, column 67) for  p
      % expected type  {p: prewalk | length(p) > 1}
  ipst_W_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss: set_of_prewalks,
            p: prewalk[T], s, t: T):
      ipss(p) AND
       separates(G, W, s, t) AND
        st_path_set?(Mgraph(G, W, t), s, t, ipss) AND good?(G, s, t)
       IMPLIES length(p) > 1;

  % Subtype TCC generated (at line 303, column 72) for  q1
      % expected type  {p: prewalk | length(p) > 1}
  ind_path_set_secoo_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss: set_of_prewalks, s, t: T):
           st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND ind_prewalk_set?(ipss) AND separates(G, W, s, t)
       AND card[T](W) = card[prewalk](ipss) AND good?(G, s, t)
       AND image(secoo,
                 restrict
                     [prewalk[T], {p: prewalk[T] | length(p) > 1}, boolean]
                     (ipss))
            = W
       IMPLIES
       (FORALL (q: prewalk[T], q1: prewalk[T]):
          ipss(q) AND ipss(q1) AND q /= q1 IMPLIES length(q1) > 1);

  % Subtype TCC generated (at line 311, column 76) for  q1
      % expected type  {p: prewalk | length(p) > 1}
  ind_path_set_secpp_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipst: set_of_prewalks, s, t: T):
           st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND ind_prewalk_set?(ipst) AND separates(G, W, s, t)
       AND card[T](W) = card[prewalk](ipst) AND good?(G, s, t)
       AND image(secpp,
                 restrict
                     [prewalk[T], {p: prewalk[T] | length(p) > 1}, boolean]
                     (ipst))
            = W
       IMPLIES
       (FORALL (q: prewalk[T], q1: prewalk[T]):
          ipst(q) AND ipst(q1) AND q /= q1 IMPLIES length(q1) > 1);

  % Subtype TCC generated (at line 351, column 77) for  p
      % expected type  {p: prewalk | length(p) > 1}
  p_Ht_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], p: prewalk[T], s, t: T):
      good?(G, s, t) AND
       separates(G, W, s, t) AND
        path_from?(Mgraph(G, W, s), p, s, t) AND length(p) > 2
       IMPLIES (FORALL (w): W(w) AND verts_of(p)(w) IMPLIES length(p) > 1);

  % Subtype TCC generated (at line 352, column 49) for  length(p) - 1
      % expected type  nat
  p_Ht_TCC2: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], p: prewalk[T], s, t: T):
           FORALL w: W(w) AND verts_of(p)(w) IMPLIES w = secoo(p)
       AND length(p) > 2 AND path_from?(Mgraph(G, W, s), p, s, t)
       AND separates(G, W, s, t) AND good?(G, s, t)
       IMPLIES length(p) - 1 >= 0;

  % Subtype TCC generated (at line 352, column 44) for  p ^ (2, length(p) - 1)
      % expected type  prewalk[T]
  p_Ht_TCC3: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], p: prewalk[T], s, t: T):
           FORALL w: W(w) AND verts_of(p)(w) IMPLIES w = secoo(p)
       AND length(p) > 2 AND path_from?(Mgraph(G, W, s), p, s, t)
       AND separates(G, W, s, t) AND good?(G, s, t)
       IMPLIES length(^[T](p, (2, length(p) - 1))) > 0;

  % Subtype TCC generated (at line 356, column 77) for  q
      % expected type  {p: prewalk | length(p) > 1}
  q_Hs_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], q: prewalk[T], s, t: T):
      good?(G, s, t) AND
       separates(G, W, s, t) AND
        path_from?(Mgraph(G, W, t), q, s, t) AND length(q) > 2
       IMPLIES (FORALL (w): W(w) AND verts_of(q)(w) IMPLIES length(q) > 1);

  % Subtype TCC generated (at line 357, column 49) for  length(q) - 3
      % expected type  nat
  q_Hs_TCC2: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], q: prewalk[T], s, t: T):
           FORALL w: W(w) AND verts_of(q)(w) IMPLIES w = secpp(q)
       AND length(q) > 2 AND path_from?(Mgraph(G, W, t), q, s, t)
       AND separates(G, W, s, t) AND good?(G, s, t)
       IMPLIES length(q) - 3 >= 0;

  % Subtype TCC generated (at line 357, column 44) for  q ^ (0, length(q) - 3)
      % expected type  prewalk[T]
  q_Hs_TCC3: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], q: prewalk[T], s, t: T):
           FORALL w: W(w) AND verts_of(q)(w) IMPLIES w = secpp(q)
       AND length(q) > 2 AND path_from?(Mgraph(G, W, t), q, s, t)
       AND separates(G, W, s, t) AND good?(G, s, t)
       IMPLIES length(^[T](q, (0, length(q) - 3))) > 0;

  % Subtype TCC generated (at line 366, column 44) for  q
      % expected type  {p: prewalk | length(p) > 1}
  disjoint_M_paths_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t)
       IMPLIES length(q) > 1;

  % Subtype TCC generated (at line 367, column 56) for  length(p) - 1
      % expected type  nat
  disjoint_M_paths_TCC2: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t) AND secoo(p) = secpp(q)
       IMPLIES length(p) - 1 >= 0;

  % Subtype TCC generated (at line 367, column 51) for  p ^ (1, length(p) - 1)
      % expected type  prewalk[T]
  disjoint_M_paths_TCC3: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t) AND secoo(p) = secpp(q)
       IMPLIES length(^[T](p, (1, length(p) - 1))) > 0;

  % Subtype TCC generated (at line 367, column 84) for  length(q) - 2
      % expected type  nat
  disjoint_M_paths_TCC4: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t) AND secoo(p) = secpp(q)
       IMPLIES length(q) - 2 >= 0;

  % Subtype TCC generated (at line 367, column 79) for  q ^ (0, length(q) - 2)
      % expected type  prewalk[T]
  disjoint_M_paths_TCC5: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t) AND secoo(p) = secpp(q)
       IMPLIES length(^[T](q, (0, length(q) - 2))) > 0;

  % Subtype TCC generated (at line 371, column 62) for  length(p) - 1
      % expected type  nat
  disjoint_M_paths_TCC6: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t)
       AND NOT (secoo(p) = secpp(q) AND
                 intersection(verts_of(p ^ (1, length(p) - 1)),
                              verts_of(q ^ (0, length(q) - 2)))
                  = singleton[T](secoo(p))
                  AND W(secoo(p)))
       AND secoo(p) /= secpp(q)
       IMPLIES length(p) - 1 >= 0;

  % Subtype TCC generated (at line 371, column 57) for  p ^ (1, length(p) - 1)
      % expected type  prewalk[T]
  disjoint_M_paths_TCC7: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t)
       AND NOT (secoo(p) = secpp(q) AND
                 intersection(verts_of(p ^ (1, length(p) - 1)),
                              verts_of(q ^ (0, length(q) - 2)))
                  = singleton[T](secoo(p))
                  AND W(secoo(p)))
       AND secoo(p) /= secpp(q)
       IMPLIES length(^[T](p, (1, length(p) - 1))) > 0;

  % Subtype TCC generated (at line 372, column 62) for  length(q) - 2
      % expected type  nat
  disjoint_M_paths_TCC8: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t)
       AND NOT (secoo(p) = secpp(q) AND
                 intersection(verts_of(p ^ (1, length(p) - 1)),
                              verts_of(q ^ (0, length(q) - 2)))
                  = singleton[T](secoo(p))
                  AND W(secoo(p)))
       AND secoo(p) /= secpp(q)
       IMPLIES length(q) - 2 >= 0;

  % Subtype TCC generated (at line 372, column 57) for  q ^ (0, length(q) - 2)
      % expected type  prewalk[T]
  disjoint_M_paths_TCC9: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss, ipst: set_of_prewalks,
            p, q: prewalk[T], s, t: T):
           ipst(q) AND ipss(p) AND ind_prewalk_set?(ipst)
       AND ind_prewalk_set?(ipss)
       AND st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND card[T](W) = card[prewalk](ipst)
       AND card[T](W) = card[prewalk](ipss) AND separates(G, W, s, t)
       AND close?(G, s, t, W) AND good?(G, s, t)
       AND NOT (secoo(p) = secpp(q) AND
                 intersection(verts_of(p ^ (1, length(p) - 1)),
                              verts_of(q ^ (0, length(q) - 2)))
                  = singleton[T](secoo(p))
                  AND W(secoo(p)))
       AND secoo(p) /= secpp(q)
       IMPLIES length(^[T](q, (0, length(q) - 2))) > 0;

  % Subtype TCC generated (at line 393, column 60) for  tau(w)
      % expected type  {p: prewalk | length(p) > 1}
  Map_s_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipss: set_of_prewalks, s, t: T):
           st_path_set?(Mgraph(G, W, s), s, t, ipss)
       AND ind_prewalk_set?(ipss) AND card[T](W) = card[prewalk](ipss)
       AND separates(G, W, s, t) AND good?(G, s, t)
       IMPLIES
       (FORALL (tau: [(W) -> prewalk[T]]):
          image(tau, restrict[T, (W), boolean](W)) = ipss IMPLIES
           (FORALL (w): W(w) IMPLIES length(tau(w)) > 1));

  % Subtype TCC generated (at line 399, column 60) for  tau(w)
      % expected type  {p: prewalk | length(p) > 1}
  Map_t_TCC1: OBLIGATION
    FORALL (G: graph[T], W: finite_set[T], ipst: set_of_prewalks, s, t: T):
           st_path_set?(Mgraph(G, W, t), s, t, ipst)
       AND ind_prewalk_set?(ipst) AND card[T](W) = card[prewalk](ipst)
       AND separates(G, W, s, t) AND good?(G, s, t)
       IMPLIES
       (FORALL (tau: [(W) -> prewalk[T]]):
          image(tau, restrict[T, (W), boolean](W)) = ipst IMPLIES
           (FORALL (w): W(w) IMPLIES length(tau(w)) > 1));

  % Subtype TCC generated (at line 426, column 68) for  length(q) - 2
      % expected type  nat
  plus_path_set_TCC1: OBLIGATION
    FORALL (G: graph[T], q: prewalk[T], s, t: T):
      good?(G, s, t) AND path_from?(G, q, s, t) IMPLIES length(q) - 2 >= 0;

  % Subtype TCC generated (at line 426, column 63) for  q ^ (1, length(q) - 2)
      % expected type  prewalk[T]
  plus_path_set_TCC2: OBLIGATION
    FORALL (G: graph[T], q: prewalk[T], s, t: T):
      good?(G, s, t) AND path_from?(G, q, s, t) IMPLIES
       length(^[T](q, (1, length(q) - 2))) > 0;

  % Subtype TCC generated (at line 445, column 59) for  k - 1
      % expected type  nat
  bridge_two_TCC1: OBLIGATION
    FORALL (G: graph[T], a, c: T, k: nat, s, t: T):
      k >= 1 AND edge?(G)(s, a) AND edge?(G)(a, c) AND edge?(G)(c, t) IMPLIES
       k - 1 >= 0;


