# TheoryBodies

body:
  %-----------------------------------------------------------------------------
  % Prefixes of sequences of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_prefix[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_concatenate[T], csequence_extract[T], orders[csequence]

    p: VAR pred[T]
    n, m: VAR nat
    cseq, cseq1, cseq2: VAR csequence
    fseq, fseq1, fseq2: VAR finite_csequence
    eseq: VAR empty_csequence
    nseq, nseq1, nseq2: VAR nonempty_csequence
    iseq: VAR infinite_csequence

    prefix?(cseq1, cseq2): COINDUCTIVE bool =
        empty?(cseq1) OR
         (nonempty?(cseq2) AND
           first(cseq1) = first(cseq2) AND prefix?(rest(cseq1), rest(cseq2)))

    prefix?(cseq2)(cseq1): MACRO bool = prefix?(cseq1, cseq2)

    prefix?_finite: THEOREM
      FORALL cseq, fseq: prefix?(cseq, fseq) IMPLIES is_finite(cseq)

    prefix?_infinite: THEOREM
      FORALL iseq, cseq: prefix?(iseq, cseq) IFF iseq = cseq

    prefix?_empty: THEOREM
      FORALL cseq, eseq: prefix?(cseq, eseq) IFF empty?(cseq)

    prefix?_empty_is_prefix: THEOREM FORALL eseq, cseq: prefix?(eseq, cseq)

    prefix?_first: THEOREM
      FORALL nseq1, nseq2:
        prefix?(nseq1, nseq2) IMPLIES first(nseq1) = first(nseq2)

    prefix?_rest: THEOREM
      FORALL nseq1, nseq2:
        prefix?(nseq1, nseq2) IMPLIES prefix?(rest(nseq1), rest(nseq2))

    prefix?_length: THEOREM
      FORALL fseq1, fseq2:
        prefix?(fseq1, fseq2) IMPLIES length(fseq1) <= length(fseq2)

    prefix?_length_eq: THEOREM
      FORALL fseq1, fseq2:
        prefix?(fseq1, fseq2) AND length(fseq1) = length(fseq2) IMPLIES
         fseq1 = fseq2

    prefix?_index: THEOREM
      FORALL cseq1, cseq2, n:
        prefix?(cseq1, cseq2) AND index?(cseq1)(n) IMPLIES index?(cseq2)(n)

    prefix?_nth: THEOREM
      FORALL cseq1, cseq2, (n: indexes(cseq1)):
        prefix?(cseq1, cseq2) IMPLIES nth(cseq1, n) = nth(cseq2, n)

    prefix?_concatenate: THEOREM
      FORALL cseq1, cseq2: prefix?(cseq1, cseq1 o cseq2)

    prefix?_def: THEOREM
      FORALL cseq1, cseq2:
        prefix?(cseq1, cseq2) IFF (EXISTS cseq: cseq1 o cseq = cseq2)

    % Unlike suffix?, prefix? is a partial order
    prefix?_is_partial_order: JUDGEMENT
      prefix? HAS_TYPE (partial_order?[csequence])

    % Prefixes of a given sequence are totally ordered
    prefix?_total_order: THEOREM
      FORALL cseq:
        total_order?(restrict
                         [[csequence, csequence],
                          [(prefix?(cseq)), (prefix?(cseq))], bool]
                         (prefix?))


    % The prefix of cseq of length at most n
    prefix(cseq, n): RECURSIVE {fseq | prefix?(fseq, cseq)} =
      IF n = 0 OR empty?(cseq) THEN empty_cseq
      ELSE add(first(cseq), prefix(rest(cseq), n - 1))
      ENDIF
       MEASURE n

    prefix_0: THEOREM FORALL cseq: empty?(prefix(cseq, 0))

    prefix_extract: THEOREM
      FORALL cseq, n: prefix(cseq, n + 1) = cseq ^ (0, n)

    prefix_rest: THEOREM
      FORALL nseq, n: prefix(rest(nseq), n) = rest(prefix(nseq, n + 1))

    prefix_prefix: THEOREM
      FORALL cseq, n, m: prefix(prefix(cseq, n), m) = prefix(cseq, min(n, m))

    prefix_length: THEOREM
      FORALL cseq, n:
        length(prefix(cseq, n)) =
         IF is_finite(cseq) THEN min(n, length(cseq)) ELSE n ENDIF

    prefix_index: THEOREM
      FORALL cseq, n, m:
        index?(prefix(cseq, n))(m) IFF index?(cseq)(m) AND m < n

    prefix_full: THEOREM
      FORALL cseq, n: index?(cseq)(n) OR prefix(cseq, n) = cseq

    prefix_concatenate: THEOREM
      FORALL cseq1, cseq2, n:
        prefix(cseq1 o cseq2, n) =
         IF index?(cseq1)(n) THEN prefix(cseq1, n)
         ELSE cseq1 o prefix(cseq2, n - length(cseq1))
         ENDIF

    prefix?_prefix: THEOREM
      FORALL cseq1, cseq2:
        prefix?(cseq1, cseq2) IFF
         cseq1 = cseq2 OR (EXISTS n: cseq1 = prefix(cseq2, n))

    prefix_some: THEOREM
      FORALL cseq, n, p:
        some(p)(prefix(cseq, n)) IFF
         (EXISTS (i: indexes(cseq)): i < n AND p(nth(cseq, i)))

    prefix_every: THEOREM
      FORALL cseq, n, p:
        every(p)(prefix(cseq, n)) IFF
         (FORALL (i: indexes(cseq)): i < n IMPLIES p(nth(cseq, i)))

    % Prefixes of a given sequence are ordered by number
    prefix?_order: THEOREM
      FORALL cseq, n, m:
        n <= m IMPLIES prefix?(prefix(cseq, n), prefix(cseq, m))

   END csequence_prefix

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

  prefix?_weak_coinduction: AXIOM
    FORALL (P: [[csequence[T], csequence[T]] -> boolean]):
      (FORALL (cseq1, cseq2):
         P(cseq1, cseq2) IMPLIES
          empty?(cseq1) OR
           (nonempty?(cseq2) AND
             first(cseq1) = first(cseq2) AND P(rest(cseq1), rest(cseq2))))
       IMPLIES
       (FORALL (cseq1, cseq2): P(cseq1, cseq2) IMPLIES prefix?(cseq1, cseq2));

  prefix?_coinduction: AXIOM
    FORALL (P: [[csequence[T], csequence[T]] -> boolean]):
      (FORALL (cseq1, cseq2):
         P(cseq1, cseq2) IMPLIES
          empty?(cseq1) OR
           (nonempty?(cseq2) AND
             first(cseq1) = first(cseq2) AND
              (prefix?(rest(cseq1), rest(cseq2)) OR
                P(rest(cseq1), rest(cseq2)))))
       IMPLIES
       (FORALL (cseq1, cseq2): P(cseq1, cseq2) IMPLIES prefix?(cseq1, cseq2));

  % Subtype TCC generated (at line 30, column 15) for  cseq1
      % expected type  (nonempty?[T])
  prefix?_TCC1: OBLIGATION
    FORALL (cseq1: csequence[T], cseq2: csequence[T]):
      nonempty?(cseq2) AND NOT empty?(cseq1) IMPLIES nonempty?[T](cseq1);

  % Subtype TCC generated (at line 68, column 63) for  n
      % expected type  indexes[T](cseq2)
  prefix?_nth_TCC1: OBLIGATION
    FORALL (cseq1, cseq2, n: indexes[T](cseq1)):
      prefix?(cseq1, cseq2) IMPLIES index?[T](cseq2)(n);

  % Judgement subtype TCC generated (at line 79, column 4) for  prefix?
      % expected type  (partial_order?[csequence])
  prefix?_is_partial_order: OBLIGATION partial_order?[csequence[T]](prefix?);

  % Subtype TCC generated (at line 92, column 34) for  empty_cseq
      % expected type  {fseq | prefix?(fseq, cseq)}
  prefix_TCC1: OBLIGATION
    FORALL (cseq: csequence[T], n: nat):
      n = 0 OR empty?(cseq) IMPLIES prefix?(empty_cseq[T], cseq);

  % Subtype TCC generated (at line 93, column 19) for  cseq
      % expected type  (nonempty?[T])
  prefix_TCC2: OBLIGATION
    FORALL (cseq: csequence[T], n: nat):
      NOT n = 0 AND NOT empty?(cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 93, column 45) for  n - 1
      % expected type  nat
  prefix_TCC3: OBLIGATION
    FORALL (cseq: csequence[T], n: nat):
      NOT n = 0 AND NOT empty?(cseq) IMPLIES n - 1 >= 0;

  % Termination TCC generated (at line 93, column 26) for
      % prefix(rest(cseq), n - 1)
  prefix_TCC4: OBLIGATION
    FORALL (cseq: csequence[T], n: nat):
      NOT n = 0 AND NOT empty?(cseq) IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 93, column 9) for
      % add(first(cseq), prefix(rest(cseq), n - 1))
      % expected type  {fseq | prefix?(fseq, cseq)}
  prefix_TCC5: OBLIGATION
    FORALL (cseq: csequence[T], n: nat,
            v:
              [d1: {z: [csequence[T], nat] | z`2 < n} ->
                 {fseq | prefix?(fseq, d1`1)}]):
      NOT n = 0 AND NOT empty?(cseq) IMPLIES
       prefix?(add[T](first[T](cseq), v(rest[T](cseq), n - 1)), cseq);

  % Subtype TCC generated (at line 103, column 49) for  prefix(nseq, n + 1)
      % expected type  (nonempty?[T])
  prefix_rest_TCC1: OBLIGATION
    FORALL (nseq, n): nonempty?[T](prefix(nseq, n + 1));

  % Subtype TCC generated (at line 124, column 45) for  cseq1
      % expected type  fseq: finite_csequence[T]
  prefix_concatenate_TCC1: OBLIGATION
    FORALL (cseq1, n): NOT index?(cseq1)(n) IMPLIES is_finite[T](cseq1);

  % Subtype TCC generated (at line 124, column 34) for  n - length(cseq1)
      % expected type  nat
  prefix_concatenate_TCC2: OBLIGATION
    FORALL (cseq1, n): NOT index?(cseq1)(n) IMPLIES n - length[T](cseq1) >= 0;


body:
  %-----------------------------------------------------------------------------
  % Subsequences of sequences of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_subsequence[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_prefix[T], csequence_suffix[T]

    p: VAR pred[T]
    n, m: VAR nat
    cseq, cseq1, cseq2: VAR csequence
    nseq, nseq1, nseq2: VAR nonempty_csequence
    fseq, fseq1, fseq2: VAR finite_csequence

    subsequence?(cseq1, cseq2): COINDUCTIVE bool =
        empty?(cseq1) OR
         (EXISTS (n: indexes(cseq2)):
            first(cseq1) = nth(cseq2, n) AND
             subsequence?(rest(cseq1), suffix(cseq2, n + 1)))

    subsequence?(cseq2)(cseq1): MACRO bool = subsequence?(cseq1, cseq2)

    subsequence?_empty_left: THEOREM
      FORALL cseq: subsequence?(empty_cseq, cseq)

    subsequence?_empty_right: THEOREM
      FORALL cseq: subsequence?(cseq, empty_cseq) IFF empty?(cseq)

    subsequence?_rest1: THEOREM
      FORALL nseq1, nseq2:
        subsequence?(nseq1, nseq2) IMPLIES
         subsequence?(rest(nseq1), rest(nseq2))

    subsequence?_rest2: THEOREM
      FORALL cseq, nseq:
        subsequence?(cseq, rest(nseq)) IMPLIES subsequence?(cseq, nseq)

    subsequence?_extensionality: THEOREM
      FORALL nseq1, nseq2:
        subsequence?(rest(nseq1), rest(nseq2)) AND
         first(nseq1) = first(nseq2)
         IMPLIES subsequence?(nseq1, nseq2)

    subsequence?_finite: THEOREM
      FORALL cseq, fseq: subsequence?(cseq, fseq) IMPLIES is_finite(cseq)

    subsequence?_nth: THEOREM
      FORALL cseq1, cseq2:
        subsequence?(cseq1, cseq2) IMPLIES
         (FORALL (n: indexes(cseq1)):
            EXISTS (m: indexes(cseq2)):
              nth(cseq1, n) = nth(cseq2, m) AND
               subsequence?(suffix(cseq1, n + 1), suffix(cseq2, m + 1)))

    subsequence?_concatenate_left: THEOREM
      FORALL cseq1, cseq2:
        subsequence?(cseq1, cseq2) IMPLIES
         (FORALL fseq: subsequence?(cseq1, fseq o cseq2))

    subsequence?_concatenate_right: THEOREM
      FORALL cseq1, cseq2:
        subsequence?(cseq1, cseq2) IMPLIES
         (FORALL cseq: subsequence?(cseq1, cseq2 o cseq))

    subsequence?_prefix: THEOREM
      FORALL cseq, n, m:
        n <= m IMPLIES subsequence?(prefix(cseq, n), prefix(cseq, m))

    subsequence?_suffix: THEOREM
      FORALL cseq, n, m:
        n <= m IMPLIES subsequence?(suffix(cseq, m), suffix(cseq, n))

    subsequence?_length: THEOREM
      FORALL fseq1, fseq2:
        subsequence?(fseq1, fseq2) IMPLIES length(fseq1) <= length(fseq2)

    subsequence?_length_eq: THEOREM
      FORALL fseq1, fseq2:
        subsequence?(fseq1, fseq2) AND length(fseq1) = length(fseq2) IMPLIES
         fseq1 = fseq2

    %  Note that subsequence? is not a partial order, because it is not
    %  antisymmetric.  These two sequences are subsequences of each other,
    %  but are not equal:
    %
    %    1, 2, 1, 2, 1, 2, ...
    %    2, 1, 2, 1, 2, 1, ...

    subsequence?_is_preorder: JUDGEMENT
      subsequence? HAS_TYPE (preorder?[csequence])

    %  However, subsequence? is a partial order when restricted to finite
    %  sequences.

    subsequence?_finite_antisymmetric: THEOREM
      partial_order?[finite_csequence]
          (restrict
               [[csequence, csequence], [finite_csequence, finite_csequence],
                bool]
               (subsequence?))

    prefix?_is_subsequence?: JUDGEMENT
      (prefix?(cseq)) SUBTYPE_OF (subsequence?(cseq))

    suffix?_is_subsequence?: JUDGEMENT
      (suffix?(cseq)) SUBTYPE_OF (subsequence?(cseq))

    subsequence?_some: THEOREM
      FORALL cseq1, cseq2, p:
        subsequence?(cseq1, cseq2) AND some(p)(cseq1) IMPLIES some(p)(cseq2)

    subsequence?_every: THEOREM
      FORALL cseq1, cseq2, p:
        subsequence?(cseq1, cseq2) AND every(p)(cseq2) IMPLIES every(p)(cseq1)


    % An alternative characterization of subsequences: there exists a
    % monotonically increasing function from the indexes of the "smaller"
    % sequence to the indexes of the "larger" sequence such that the
    % mapped elements are equal
    subsequence_func(cseq2, (cseq1: (subsequence?(cseq2))))
                    (n: indexes(cseq1)): RECURSIVE
          indexes(cseq2) =
      LET index =
            min[indexes(cseq2)]
                ({i: indexes(cseq2) | first(cseq1) = nth(cseq2, i)})
        IN
        IF n = 0 THEN index
        ELSE index + 1 +
              subsequence_func(suffix(cseq2, index + 1), rest(cseq1))(n - 1)
        ENDIF
       MEASURE n

    subsequence_func_monotonic: LEMMA
      FORALL cseq1, cseq2, (n, m: indexes(cseq1)):
        subsequence?(cseq1, cseq2) AND n < m IMPLIES
         subsequence_func(cseq2, cseq1)(n) < subsequence_func(cseq2, cseq1)(m)

    subsequence_func_nth: LEMMA
      FORALL cseq1, cseq2, (n: indexes(cseq1)):
        subsequence?(cseq1, cseq2) IMPLIES
         nth(cseq1, n) = nth(cseq2, subsequence_func(cseq2, cseq1)(n))

    subsequence?_def: THEOREM
      FORALL cseq1, cseq2:
        subsequence?(cseq1, cseq2) IFF
         (EXISTS (f: [indexes(cseq1) -> indexes(cseq2)]):
            (FORALL (i1, i2: indexes(cseq1)): i1 < i2 IMPLIES f(i1) < f(i2))
             AND
             (FORALL (i: indexes(cseq1)): nth(cseq1, i) = nth(cseq2, f(i))))

   END csequence_subsequence

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

  subsequence?_weak_coinduction: AXIOM
    FORALL (P: [[csequence[T], csequence[T]] -> boolean]):
      (FORALL (cseq1, cseq2):
         P(cseq1, cseq2) IMPLIES
          empty?(cseq1) OR
           (EXISTS (n: indexes(cseq2)):
              first(cseq1) = nth(cseq2, n) AND
               P(rest(cseq1), suffix(cseq2, n + 1))))
       IMPLIES
       (FORALL (cseq1, cseq2):
          P(cseq1, cseq2) IMPLIES subsequence?(cseq1, cseq2));

  subsequence?_coinduction: AXIOM
    FORALL (P: [[csequence[T], csequence[T]] -> boolean]):
      (FORALL (cseq1, cseq2):
         P(cseq1, cseq2) IMPLIES
          empty?(cseq1) OR
           (EXISTS (n: indexes(cseq2)):
              first(cseq1) = nth(cseq2, n) AND
               (subsequence?(rest(cseq1), suffix(cseq2, n + 1)) OR
                 P(rest(cseq1), suffix(cseq2, n + 1)))))
       IMPLIES
       (FORALL (cseq1, cseq2):
          P(cseq1, cseq2) IMPLIES subsequence?(cseq1, cseq2));

  % Subtype TCC generated (at line 28, column 16) for  cseq1
      % expected type  (nonempty?[T])
  subsequence?_TCC1: OBLIGATION
    FORALL (cseq1: csequence[T], cseq2: csequence[T]):
      NOT empty?(cseq1) IMPLIES
       (FORALL (n: indexes[T](cseq2)): nonempty?[T](cseq1));

  % Judgement subtype TCC generated (at line 100, column 4) for  subsequence?
      % expected type  (preorder?[csequence])
  subsequence?_is_preorder: OBLIGATION preorder?[csequence[T]](subsequence?);

  % Judgement subtype TCC generated (at line 113, column 4) for  x
      % expected type  (LAMBDA (cseq1): subsequence?(cseq1, cseq))
  prefix?_is_subsequence?: OBLIGATION
    FORALL (cseq: csequence[T],
            x: (LAMBDA (cseq1: csequence[T]): prefix?(cseq1, cseq))):
      subsequence?(x, cseq);

  % Judgement subtype TCC generated (at line 116, column 4) for  x
      % expected type  (LAMBDA (cseq1): subsequence?(cseq1, cseq))
  suffix?_is_subsequence?: OBLIGATION
    FORALL (cseq: csequence[T],
            x: (LAMBDA (cseq1: csequence[T]): suffix?(cseq1, cseq))):
      subsequence?(x, cseq);

  % Subtype TCC generated (at line 140, column 68) for  n - 1
      % expected type  indexes[T](rest(cseq1))
  subsequence_func_TCC1: OBLIGATION
    FORALL (cseq2: csequence[T],
            (cseq1: (LAMBDA (cseq1): subsequence?(cseq1, cseq2))),
            n: indexes[T](cseq1),
            index:
              {a |
                       first[T](cseq1) = nth[T](cseq2, a) AND
                        (FORALL (x: indexes[T](cseq2)):
                           first[T](cseq1) = nth[T](cseq2, x) IMPLIES
                            a <= x)}):
      NOT n = 0 AND
       index =
        min[indexes[T](cseq2)]
            ({i: indexes(cseq2) | first(cseq1) = nth(cseq2, i)})
       IMPLIES n - 1 >= 0 AND index?[T](rest[T](cseq1))(n - 1);

  % Subtype TCC generated (at line 140, column 60) for  cseq1
      % expected type  (nonempty?[T])
  subsequence_func_TCC2: OBLIGATION
    FORALL (cseq2: csequence[T],
            (cseq1: (LAMBDA (cseq1): subsequence?(cseq1, cseq2))),
            n: indexes[T](cseq1),
            index:
              {a |
                       first[T](cseq1) = nth[T](cseq2, a) AND
                        (FORALL (x: indexes[T](cseq2)):
                           first[T](cseq1) = nth[T](cseq2, x) IMPLIES
                            a <= x)}):
      NOT n = 0 AND
       index =
        min[indexes[T](cseq2)]
            ({i: indexes(cseq2) | first(cseq1) = nth(cseq2, i)})
       IMPLIES nonempty?[T](cseq1);

  % Subtype TCC generated (at line 140, column 55) for  rest(cseq1)
      % expected type  (LAMBDA (cseq1_1: csequence[T]):
                     %    subsequence?(cseq1_1, suffix(cseq2, index + 1)))
  subsequence_func_TCC3: OBLIGATION
    FORALL (cseq2: csequence[T],
            (cseq1: (LAMBDA (cseq1): subsequence?(cseq1, cseq2))),
            n: indexes[T](cseq1),
            index:
              {a |
                       first[T](cseq1) = nth[T](cseq2, a) AND
                        (FORALL (x: indexes[T](cseq2)):
                           first[T](cseq1) = nth[T](cseq2, x) IMPLIES
                            a <= x)}):
      NOT n = 0 AND
       index =
        min[indexes[T](cseq2)]
            ({i: indexes(cseq2) | first(cseq1) = nth(cseq2, i)})
       IMPLIES subsequence?(rest[T](cseq1), suffix[T](cseq2, 1 + index));

  % Termination TCC generated (at line 140, column 12) for
      % subsequence_func(suffix(cseq2, index + 1), rest(cseq1))(n - 1)
  subsequence_func_TCC4: OBLIGATION
    FORALL (cseq2: csequence[T],
            (cseq1: (LAMBDA (cseq1): subsequence?(cseq1, cseq2))),
            n: indexes[T](cseq1),
            index:
              {a |
                       first[T](cseq1) = nth[T](cseq2, a) AND
                        (FORALL (x: indexes[T](cseq2)):
                           first[T](cseq1) = nth[T](cseq2, x) IMPLIES
                            a <= x)}):
      NOT n = 0 AND
       index =
        min[indexes[T](cseq2)]
            ({i: indexes(cseq2) | first(cseq1) = nth(cseq2, i)})
       IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 139, column 11) for
      % index + 1 +
      %  subsequence_func(suffix(cseq2, index + 1), rest(cseq1))(n - 1)
      % expected type  indexes[T](cseq2)
  subsequence_func_TCC5: OBLIGATION
    FORALL (cseq2: csequence[T],
            (cseq1: (LAMBDA (cseq1): subsequence?(cseq1, cseq2))),
            n: indexes[T](cseq1),
            v:
              [d1:
                 [cseq2: csequence[T],
                  (LAMBDA (cseq1): subsequence?(cseq1, cseq2))] ->
                 [{z: indexes[T](d1`2) | z < n} -> indexes[T](d1`1)]],
            index:
              {a |
                       first[T](cseq1) = nth[T](cseq2, a) AND
                        (FORALL (x: indexes[T](cseq2)):
                           first[T](cseq1) = nth[T](cseq2, x) IMPLIES
                            a <= x)}):
      NOT n = 0 AND
       index =
        min[indexes[T](cseq2)]
            ({i: indexes(cseq2) | first(cseq1) = nth(cseq2, i)})
       IMPLIES
       index?[T]
           (cseq2)
           (index + 1 +
             v(suffix[T](cseq2, index + 1), rest[T](cseq1))(n - 1));

  % Subtype TCC generated (at line 136, column 42) for  cseq1
      % expected type  (nonempty?[T])
  subsequence_func_TCC6: OBLIGATION
    FORALL (cseq2: csequence[T],
            (cseq1: (LAMBDA (cseq1): subsequence?(cseq1, cseq2))),
            n: indexes[T](cseq1), i: indexes[T](cseq2),
            index:
              {a |
                       first[T](cseq1) = nth[T](cseq2, a) AND
                        (FORALL (x: indexes[T](cseq2)):
                           first[T](cseq1) = nth[T](cseq2, x) IMPLIES
                            a <= x)}):
      index =
       min[indexes[T](cseq2)]
           ({i: indexes(cseq2) | first(cseq1) = nth(cseq2, i)})
       IMPLIES nonempty?[T](cseq1);

  % Subtype TCC generated (at line 136, column 15) for
      % {i: indexes(cseq2) | first(cseq1) = nth(cseq2, i)}
      % expected type  S: (nonempty?[indexes(cseq2)])
  subsequence_func_TCC7: OBLIGATION
    FORALL (cseq2: csequence[T],
            (cseq1: (LAMBDA (cseq1): subsequence?(cseq1, cseq2))),
            n: indexes[T](cseq1)):
      nonempty?[indexes[T](cseq2)]
          ({i: indexes[T](cseq2) | first[T](cseq1) = nth[T](cseq2, i)});


body:
  %-----------------------------------------------------------------------------
  % Proper prefixes of sequences of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_strict_prefix[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_prefix[T]

    p: VAR pred[T]
    n: VAR nat
    cseq, cseq1, cseq2: VAR csequence
    nseq: VAR nonempty_csequence
    fseq: VAR finite_csequence

    strict_prefix?(cseq1, cseq2): INDUCTIVE bool =
        nonempty?(cseq2) AND
         (empty?(cseq1) OR
           (first(cseq1) = first(cseq2) AND
             strict_prefix?(rest(cseq1), rest(cseq2))))

    strict_prefix?(cseq2)(cseq1): MACRO bool = strict_prefix?(cseq1, cseq2)

    strict_prefix?_prefix?: THEOREM
      FORALL cseq1, cseq2:
        strict_prefix?(cseq1, cseq2) IFF
         prefix?(cseq1, cseq2) AND cseq1 /= cseq2

    strict_prefix?_finite: THEOREM
      FORALL cseq1, cseq2:
        strict_prefix?(cseq1, cseq2) IMPLIES is_finite(cseq1)

    strict_prefix?_first: THEOREM
      FORALL nseq, cseq:
        strict_prefix?(nseq, cseq) IMPLIES first(nseq) = first(cseq)

    strict_prefix?_rest: THEOREM
      FORALL nseq, cseq:
        strict_prefix?(nseq, cseq) IMPLIES
         strict_prefix?(rest(nseq), rest(cseq))

    strict_prefix?_length: THEOREM
      FORALL cseq, fseq:
        strict_prefix?(cseq, fseq) IMPLIES length(cseq) < length(fseq)

    strict_prefix?_index: THEOREM
      FORALL cseq1, cseq2, n:
        strict_prefix?(cseq1, cseq2) AND index?(cseq1)(n) IMPLIES
         index?(cseq2)(n)

    strict_prefix?_nth: THEOREM
      FORALL cseq1, cseq2, (n: indexes(cseq1)):
        strict_prefix?(cseq1, cseq2) IMPLIES nth(cseq1, n) = nth(cseq2, n)

    strict_prefix?_concatenate: THEOREM
      FORALL fseq, nseq: strict_prefix?(fseq, fseq o nseq)

    strict_prefix?_def: THEOREM
      FORALL cseq1, cseq2:
        strict_prefix?(cseq1, cseq2) IFF
         is_finite(cseq1) AND (EXISTS nseq: cseq1 o nseq = cseq2)

    strict_prefix?_is_strict_order: JUDGEMENT
      strict_prefix? HAS_TYPE (strict_order?[csequence])

    % Strict prefixes of a given sequence are well-ordered
    strict_prefix?_well_ordered: THEOREM
      FORALL cseq:
        well_ordered?(restrict
                          [[csequence, csequence],
                           [(strict_prefix?(cseq)), (strict_prefix?(cseq))],
                           bool]
                          (strict_prefix?))

    strict_prefix?_prefix: THEOREM
      FORALL cseq1, cseq2:
        strict_prefix?(cseq1, cseq2) IFF
         (EXISTS n:
            cseq1 = prefix(cseq2, n) AND
             (is_finite(cseq2) IMPLIES n < length(cseq2)))

   END csequence_strict_prefix

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

  strict_prefix?_weak_induction: AXIOM
    FORALL (P: [[csequence[T], csequence[T]] -> boolean]):
      (FORALL (cseq1, cseq2):
         nonempty?(cseq2) AND
          (empty?(cseq1) OR
            (first(cseq1) = first(cseq2) AND P(rest(cseq1), rest(cseq2))))
          IMPLIES P(cseq1, cseq2))
       IMPLIES
       (FORALL (cseq1, cseq2):
          strict_prefix?(cseq1, cseq2) IMPLIES P(cseq1, cseq2));

  strict_prefix?_induction: AXIOM
    FORALL (P: [[csequence[T], csequence[T]] -> boolean]):
      (FORALL (cseq1, cseq2):
         nonempty?(cseq2) AND
          (empty?(cseq1) OR
            (first(cseq1) = first(cseq2) AND
              strict_prefix?(rest(cseq1), rest(cseq2)) AND
               P(rest(cseq1), rest(cseq2))))
          IMPLIES P(cseq1, cseq2))
       IMPLIES
       (FORALL (cseq1, cseq2):
          strict_prefix?(cseq1, cseq2) IMPLIES P(cseq1, cseq2));

  % Subtype TCC generated (at line 28, column 16) for  cseq1
      % expected type  (nonempty?[T])
  strict_prefix?_TCC1: OBLIGATION
    FORALL (cseq1: csequence[T], cseq2: csequence[T]):
      NOT empty?(cseq1) AND nonempty?(cseq2) IMPLIES nonempty?[T](cseq1);

  % Subtype TCC generated (at line 44, column 61) for  cseq
      % expected type  (nonempty?[T])
  strict_prefix?_first_TCC1: OBLIGATION
    FORALL (nseq, cseq):
      strict_prefix?(nseq, cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 53, column 48) for  cseq
      % expected type  fseq: finite_csequence[T]
  strict_prefix?_length_TCC1: OBLIGATION
    FORALL (cseq, fseq):
      strict_prefix?(cseq, fseq) IMPLIES is_finite[T](cseq);

  % Subtype TCC generated (at line 62, column 70) for  n
      % expected type  indexes[T](cseq2)
  strict_prefix?_nth_TCC1: OBLIGATION
    FORALL (cseq1, cseq2, n: indexes[T](cseq1)):
      strict_prefix?(cseq1, cseq2) IMPLIES index?[T](cseq2)(n);

  % Judgement subtype TCC generated (at line 73, column 4) for  strict_prefix?
      % expected type  (strict_order?[csequence])
  strict_prefix?_is_strict_order: OBLIGATION
    strict_order?[csequence[T]](strict_prefix?);


body:
  %-----------------------------------------------------------------------------
  % Split a sequence of countable length into a sequence containing the
  % even-numbered elements and a sequence containing the odd-numbered elements.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_split[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T], csequence_codt_coreduce[T, csequence]

    t: VAR T
    p: VAR pred[T]
    n: VAR nat
    cseq, cseq1, cseq2: VAR csequence
    nseq: VAR nonempty_csequence
    fseq: VAR finite_csequence
    iseq: VAR infinite_csequence

    split_left_struct(cseq): csequence_struct =
        IF empty?(cseq) THEN inj_empty_cseq
        ELSE inj_add(first(cseq),
                     IF empty?(rest(cseq)) THEN empty_cseq
                     ELSE rest(rest(cseq))
                     ENDIF)
        ENDIF

    split_right_struct(cseq): csequence_struct =
        IF empty?(cseq) OR empty?(rest(cseq)) THEN inj_empty_cseq
        ELSE inj_add(first(rest(cseq)), rest(rest(cseq)))
        ENDIF

    split(cseq): [csequence, csequence] =
        (coreduce(split_left_struct)(cseq),
         coreduce(split_right_struct)(cseq))

    split_empty_left: THEOREM
      FORALL cseq: empty?(split(cseq)`1) IFF empty?(cseq)

    split_empty_right: THEOREM
      FORALL cseq:
        empty?(split(cseq)`2) IFF empty?(cseq) OR empty?(rest(cseq))

    split_nonempty_left: THEOREM
      FORALL cseq: nonempty?(split(cseq)`1) IFF nonempty?(cseq)

    split_nonempty_right: THEOREM
      FORALL cseq:
        nonempty?(split(cseq)`2) IFF nonempty?(cseq) AND nonempty?(rest(cseq))

    split_first_left: THEOREM FORALL nseq: first(split(nseq)`1) = first(nseq)

    split_first_right: THEOREM
      FORALL nseq:
        nonempty?(rest(nseq)) IMPLIES first(split(nseq)`2) = first(rest(nseq))

    split_rest_left: THEOREM
      FORALL nseq:
        rest(split(nseq)`1) =
         IF empty?(rest(nseq)) THEN empty_cseq
         ELSE split(rest(rest(nseq)))`1
         ENDIF

    split_rest_right: THEOREM
      FORALL nseq:
        nonempty?(rest(nseq)) IMPLIES
         rest(split(nseq)`2) = split(rest(rest(nseq)))`2

    split_rest_swap_left: THEOREM
      FORALL nseq: split(rest(nseq))`1 = split(nseq)`2

    split_rest_swap_right: THEOREM
      FORALL nseq: split(rest(nseq))`2 = rest(split(nseq)`1)

    split_finite: JUDGEMENT
      split(fseq) HAS_TYPE [finite_csequence, finite_csequence]

    split_infinite: JUDGEMENT
      split(iseq) HAS_TYPE [infinite_csequence, infinite_csequence]

    split_length_left: THEOREM
      FORALL fseq: length(split(fseq)`1) = ceiling(length(fseq) / 2)

    split_length_right: THEOREM
      FORALL fseq: length(split(fseq)`2) = floor(length(fseq) / 2)

    split_length: THEOREM
      FORALL fseq:
        length(fseq) = length(split(fseq)`1) + length(split(fseq)`2)

    split_index_left: THEOREM
      FORALL cseq, n: index?(split(cseq)`1)(n) IFF index?(cseq)(2 * n)

    split_index_right: THEOREM
      FORALL cseq, n: index?(split(cseq)`2)(n) IFF index?(cseq)(2 * n + 1)

    split_nth_left: THEOREM
      FORALL cseq, (n: indexes(split(cseq)`1)):
        nth(split(cseq)`1, n) = nth(cseq, 2 * n)

    split_nth_right: THEOREM
      FORALL cseq, (n: indexes(split(cseq)`2)):
        nth(split(cseq)`2, n) = nth(cseq, 2 * n + 1)

    split_add: THEOREM
      FORALL cseq, t:
        split(add(t, cseq)) = (add(t, split(cseq)`2), split(cseq)`1)

    split_last_left: THEOREM
      FORALL fseq:
        nonempty?(split(fseq)`1) IMPLIES
         last(split(fseq)`1) =
          IF odd?(length(fseq)) THEN last(fseq)
          ELSE nth(fseq, length(fseq) - 2)
          ENDIF

    split_last_right: THEOREM
      FORALL fseq:
        nonempty?(split(fseq)`2) IMPLIES
         last(split(fseq)`2) =
          IF even?(length(fseq)) THEN last(fseq)
          ELSE nth(fseq, length(fseq) - 2)
          ENDIF

    split_extensionality: THEOREM
      FORALL cseq1, cseq2: split(cseq1) = split(cseq2) IMPLIES cseq1 = cseq2

    split_some: THEOREM
      FORALL cseq, p:
        some(p)(cseq) IFF some(p)(split(cseq)`1) OR some(p)(split(cseq)`2)

    split_every: THEOREM
      FORALL cseq, p:
        every(p)(cseq) IFF every(p)(split(cseq)`1) AND every(p)(split(cseq)`2)

   END csequence_split

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

  % Subtype TCC generated (at line 30, column 25) for  cseq
      % expected type  (nonempty?[T])
  split_left_struct_TCC1: OBLIGATION
    FORALL (cseq: csequence[T]): NOT empty?(cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 32, column 29) for  rest(cseq)
      % expected type  (nonempty?[T])
  split_left_struct_TCC2: OBLIGATION
    FORALL (cseq: csequence[T]):
      NOT empty?(rest(cseq)) AND NOT empty?(cseq) IMPLIES
       nonempty?[T](rest[T](cseq));

  % Subtype TCC generated (at line 59, column 47) for  split(nseq)`1
      % expected type  (nonempty?[T])
  split_first_left_TCC1: OBLIGATION
    FORALL (nseq): nonempty?[T](split(nseq)`1);

  % Subtype TCC generated (at line 63, column 42) for  split(nseq)`2
      % expected type  (nonempty?[T])
  split_first_right_TCC1: OBLIGATION
    FORALL (nseq): nonempty?(rest(nseq)) IMPLIES nonempty?[T](split(nseq)`2);

  % Subtype TCC generated (at line 69, column 23) for  rest(nseq)
      % expected type  (nonempty?[T])
  split_rest_left_TCC1: OBLIGATION
    FORALL (nseq): NOT empty?(rest(nseq)) IMPLIES nonempty?[T](rest[T](nseq));

  % Judgement subtype TCC generated (at line 84, column 4) for  split(fseq)
      % expected type  [finite_csequence[T], finite_csequence[T]]
  split_finite: OBLIGATION
    FORALL (fseq):
      is_finite[T](split(fseq)`2) AND is_finite[T](split(fseq)`1);

  % Judgement subtype TCC generated (at line 87, column 4) for  split(iseq)
      % expected type  [infinite_csequence[T], infinite_csequence[T]]
  split_infinite: OBLIGATION
    FORALL (iseq):
      NOT is_finite[T](split(iseq)`2) AND NOT is_finite[T](split(iseq)`1);

  % Subtype TCC generated (at line 107, column 40) for  2 * n
      % expected type  indexes[T](cseq)
  split_nth_left_TCC1: OBLIGATION
    FORALL (cseq, n: indexes[T](split(cseq)`1)): index?[T](cseq)(2 * n);

  % Subtype TCC generated (at line 111, column 40) for  2 * n + 1
      % expected type  indexes[T](cseq)
  split_nth_right_TCC1: OBLIGATION
    FORALL (cseq, n: indexes[T](split(cseq)`2)): index?[T](cseq)(2 * n + 1);

  % Subtype TCC generated (at line 121, column 40) for  fseq
      % expected type  nonempty_finite_csequence[T]
  split_last_left_TCC1: OBLIGATION
    FORALL (fseq):
      odd?(length(fseq)) AND nonempty?(split(fseq)`1) IMPLIES
       nonempty?[T](fseq);

  % Subtype TCC generated (at line 122, column 23) for  length(fseq) - 2
      % expected type  indexes[T](fseq)
  split_last_left_TCC2: OBLIGATION
    FORALL (fseq):
      NOT odd?(length(fseq)) AND nonempty?(split(fseq)`1) IMPLIES
       length[T](fseq) - 2 >= 0 AND index?[T](fseq)(length[T](fseq) - 2);

  % Subtype TCC generated (at line 129, column 41) for  fseq
      % expected type  nonempty_finite_csequence[T]
  split_last_right_TCC1: OBLIGATION
    FORALL (fseq):
      even?(length(fseq)) AND nonempty?(split(fseq)`2) IMPLIES
       nonempty?[T](fseq);

  % Subtype TCC generated (at line 130, column 23) for  length(fseq) - 2
      % expected type  indexes[T](fseq)
  split_last_right_TCC2: OBLIGATION
    FORALL (fseq):
      NOT even?(length(fseq)) AND nonempty?(split(fseq)`2) IMPLIES
       length[T](fseq) - 2 >= 0 AND index?[T](fseq)(length[T](fseq) - 2);


body:
  %-----------------------------------------------------------------------------
  % Singleton sequences, defined as coalgebraic datatypes.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_singleton[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T]

    t: VAR T
    p: VAR pred[T]
    n: VAR nat
    cseq: VAR csequence

    singleton_cseq?(cseq): bool = nonempty?(cseq) AND empty?(rest(cseq))

    singleton_is_nonempty_finite: JUDGEMENT
      (singleton_cseq?) SUBTYPE_OF nonempty_finite_csequence

    singleton_cseq_length: THEOREM
      FORALL cseq: singleton_cseq?(cseq) IMPLIES length(cseq) = 1

    singleton_cseq_index: THEOREM
      FORALL (single: (singleton_cseq?)), n: index?(single)(n) IFF n = 0

    singleton_cseq(t): (singleton_cseq?) = add(t, empty_cseq)

    singleton_def: THEOREM
      FORALL cseq:
        singleton_cseq?(cseq) IMPLIES cseq = singleton_cseq(first(cseq))

    singleton_cseq_first: THEOREM FORALL t: first(singleton_cseq(t)) = t

    singleton_cseq_rest: THEOREM FORALL t: rest(singleton_cseq(t)) = empty_cseq

    singleton_cseq_last: THEOREM FORALL t: last(singleton_cseq(t)) = t

    singleton_cseq_some: THEOREM
      FORALL t, p: some(p)(singleton_cseq(t)) IFF p(t)

    singleton_cseq_every: THEOREM
      FORALL t, p: every(p)(singleton_cseq(t)) IFF p(t)

   END csequence_singleton

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

  % Judgement subtype TCC generated (at line 27, column 4) for  x
      % expected type  nonempty_finite_csequence[T]
  singleton_is_nonempty_finite: OBLIGATION
    FORALL (x: (singleton_cseq?)): is_finite[T](x) AND nonempty?[T](x);

  % Subtype TCC generated (at line 30, column 54) for  cseq
      % expected type  fseq: finite_csequence[T]
  singleton_cseq_length_TCC1: OBLIGATION
    FORALL (cseq): singleton_cseq?(cseq) IMPLIES is_finite[T](cseq);

  % Subtype TCC generated (at line 35, column 41) for  add(t, empty_cseq)
      % expected type  (singleton_cseq?)
  singleton_cseq_TCC1: OBLIGATION
    FORALL (t: T): singleton_cseq?(add[T](t, empty_cseq[T]));

  % Subtype TCC generated (at line 39, column 64) for  cseq
      % expected type  (nonempty?[T])
  singleton_def_TCC1: OBLIGATION
    FORALL (cseq): singleton_cseq?(cseq) IMPLIES nonempty?[T](cseq);


body:
  %-----------------------------------------------------------------------------
  % Conversions between sequences of countable length and the prelude sequence
  % type.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_sequence[T: TYPE]: THEORY
   BEGIN

    IMPORTING sequences[T], csequence_nth[T]
    IMPORTING csequence_codt_coreduce[T, sequence]

    n: VAR nat
    seq: VAR sequence
    iseq: VAR infinite_csequence

    % Convert a sequence to an infinite_csequence
    from_sequence_struct(seq): csequence_struct =
        inj_add(seq(0), LAMBDA n: seq(1 + n))

    from_sequence(seq): infinite_csequence =
        coreduce(from_sequence_struct)(seq)

    from_sequence_nth: THEOREM
      FORALL seq, n: nth(from_sequence(seq), n) = seq(n)

    % Convert an infinite_csequence to a sequence
    to_sequence(iseq): sequence = LAMBDA n: nth(iseq, n)

    to_sequence_nth: THEOREM
      FORALL iseq, n: to_sequence(iseq)(n) = nth(iseq, n)

    % Applying both conversions gives you back what you started with

    to_from_sequence: THEOREM
      FORALL seq: to_sequence(from_sequence(seq)) = seq

    from_to_sequence: THEOREM
      FORALL iseq: from_sequence(to_sequence(iseq)) = iseq

   END csequence_sequence

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

  % Subtype TCC generated (at line 30, column 6) for
      % coreduce(from_sequence_struct)(seq)
      % expected type  infinite_csequence[T]
  from_sequence_TCC1: OBLIGATION
    FORALL (seq: sequence[T]):
      NOT is_finite[T](coreduce[T, sequence](from_sequence_struct)(seq));

  % Subtype TCC generated (at line 33, column 43) for  n
      % expected type  indexes[T](from_sequence(seq))
  from_sequence_nth_TCC1: OBLIGATION
    FORALL (seq, n): index?[T](from_sequence(seq))(n);

  % Subtype TCC generated (at line 36, column 52) for  n
      % expected type  indexes[T](iseq)
  to_sequence_TCC1: OBLIGATION
    FORALL (iseq: infinite_csequence[T], n): index?[T](iseq)(n);


body:
  %-----------------------------------------------------------------------------
  % Insert an element into a sequence of countable length defined as a
  % coalgebraic datatype.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_insert[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T]

    t, u: VAR T
    p: VAR pred[T]
    index, n, m: VAR nat
    cseq, cseq1, cseq2: VAR csequence
    fseq: VAR finite_csequence
    iseq: VAR infinite_csequence

    % Insert t at position index in sequence cseq.  If index is greater than
    % length(cseq), then t is appended instead.
    insert(t, index, cseq): RECURSIVE nonempty_csequence =
      IF index = 0 OR empty?(cseq) THEN add(t, cseq)
      ELSE add(first(cseq), insert(t, index - 1, rest(cseq)))
      ENDIF
       MEASURE index

    insert_finite: JUDGEMENT
      insert(t, index, fseq) HAS_TYPE nonempty_finite_csequence

    insert_infinite: JUDGEMENT
      insert(t, index, iseq) HAS_TYPE infinite_csequence

    insert_first: THEOREM
      FORALL t, index, cseq:
        first(insert(t, index, cseq)) =
         IF index = 0 OR empty?(cseq) THEN t ELSE first(cseq) ENDIF

    insert_rest: THEOREM
      FORALL t, index, cseq:
        rest(insert(t, index, cseq)) =
         IF index = 0 OR empty?(cseq) THEN cseq
         ELSE insert(t, index - 1, rest(cseq))
         ENDIF

    insert_length: THEOREM
      FORALL fseq, t, index: length(insert(t, index, fseq)) = length(fseq) + 1

    insert_index: THEOREM
      FORALL t, index, cseq, n:
        index?(insert(t, index, cseq))(n) IFF n = 0 OR index?(cseq)(n - 1)

    insert_nth: THEOREM
      FORALL cseq, t, index, (n: indexes(cseq)):
        nth(cseq, n) =
         nth(insert(t, index, cseq), n + IF n < index THEN 0 ELSE 1 ENDIF)

    insert_0: THEOREM FORALL t, cseq: insert(t, 0, cseq) = add(t, cseq)

    insert_add: THEOREM
      FORALL t, u, index, cseq:
        add(u, insert(t, index, cseq)) = insert(t, index + 1, add(u, cseq))

    insert_last: THEOREM
      FORALL t, index, fseq:
        last(insert(t, index, fseq)) =
         IF index?(fseq)(index) THEN last(fseq) ELSE t ENDIF

    insert_beyond: THEOREM
      FORALL t, index, fseq:
        index > length(fseq) IMPLIES
         insert(t, index, fseq) = insert(t, length(fseq), fseq)

    insert_insert: THEOREM
      FORALL t, u, n, m, cseq:
        insert(t, n, insert(u, m, cseq)) =
         IF is_finite(cseq) AND n > length(cseq) AND m > length(cseq)
           THEN insert(u, length(cseq), insert(t, n, cseq))
         ELSIF n <= m THEN insert(u, m + 1, insert(t, n, cseq))
         ELSE insert(u, m, insert(t, n - 1, cseq))
         ENDIF

    insert_extensionality: THEOREM
      FORALL t, index, cseq1, cseq2:
        insert(t, index, cseq1) = insert(t, index, cseq2) IMPLIES
         cseq1 = cseq2

    insert_some: THEOREM
      FORALL t, index, cseq:
        some(p)(insert(t, index, cseq)) IFF p(t) OR some(p)(cseq)

    insert_every: THEOREM
      FORALL t, index, cseq:
        every(p)(insert(t, index, cseq)) IFF p(t) AND every(p)(cseq)

   END csequence_insert

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

  % Subtype TCC generated (at line 31, column 19) for  cseq
      % expected type  (nonempty?[T])
  insert_TCC1: OBLIGATION
    FORALL (t: T, index: nat, cseq: csequence[T]):
      NOT index = 0 AND NOT empty?(cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 31, column 36) for  index - 1
      % expected type  nat
  insert_TCC2: OBLIGATION
    FORALL (t: T, index: nat, cseq: csequence[T]):
      NOT index = 0 AND NOT empty?(cseq) IMPLIES index - 1 >= 0;

  % Termination TCC generated (at line 31, column 26) for
      % insert(t, index - 1, rest(cseq))
  insert_TCC3: OBLIGATION
    FORALL (t: T, index: nat, cseq: csequence[T]):
      NOT index = 0 AND NOT empty?(cseq) IMPLIES index - 1 < index;

  % Judgement subtype TCC generated (at line 36, column 4) for
      % insert(t, index, fseq)
      % expected type  nonempty_finite_csequence[T]
  insert_finite: OBLIGATION
    FORALL (fseq, index, t):
      is_finite[T](insert(t, index, fseq)) AND
       nonempty?[T](insert(t, index, fseq));

  % Judgement subtype TCC generated (at line 39, column 4) for
      % insert(t, index, iseq)
      % expected type  infinite_csequence[T]
  insert_infinite: OBLIGATION
    FORALL (index, iseq, t): NOT is_finite[T](insert(t, index, iseq));

  % Subtype TCC generated (at line 58, column 66) for  n - 1
      % expected type  nat
  insert_index_TCC1: OBLIGATION FORALL (t, n): NOT n = 0 IMPLIES n - 1 >= 0;

  % Subtype TCC generated (at line 63, column 35) for
      % n + IF n < index THEN 0 ELSE 1 ENDIF
      % expected type  indexes[T](insert(t, index, cseq))
  insert_nth_TCC1: OBLIGATION
    FORALL (cseq, t, index, n: indexes[T](cseq)):
      index?[T](insert(t, index, cseq))(n + IF n < index THEN 0 ELSE 1 ENDIF);

  % Subtype TCC generated (at line 74, column 40) for  fseq
      % expected type  nonempty_finite_csequence[T]
  insert_last_TCC1: OBLIGATION
    FORALL (t, index, fseq): index?(fseq)(index) IMPLIES nonempty?[T](fseq);

  % Subtype TCC generated (at line 87, column 35) for  n - 1
      % expected type  nat
  insert_insert_TCC1: OBLIGATION
    FORALL (t, u, n, m, cseq):
      NOT n <= m AND
       NOT (is_finite(cseq) AND n > length(cseq) AND m > length(cseq))
       IMPLIES n - 1 >= 0;


body:
  %-----------------------------------------------------------------------------
  % Append an element to a sequence of countable length defined as a coalgebraic
  % datatype.  This operation has no effect if the sequence is infinite.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_append[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_insert[T]
    IMPORTING csequence_codt_coreduce[T, [csequence, T, bool]]

    n: VAR nat
    t, u: VAR T
    p: VAR pred[T]
    state: VAR [csequence, T, bool]
    cseq, cseq1, cseq2: VAR csequence
    nseq: VAR nonempty_csequence
    fseq: VAR finite_csequence
    iseq: VAR infinite_csequence

    % The boolean distinguishes between the two cases when the sequence part of
    % the state is empty?: (1) the T has been appended; and (2) the T has not
    % been appended.
    append_struct(state): csequence_struct =
        IF state`3 THEN inj_empty_cseq
        ELSIF empty?(state`1)
          THEN inj_add(state`2, (state`1, state`2, TRUE))
        ELSE inj_add(first(state`1), (rest(state`1), state`2, FALSE))
        ENDIF

    append(t, cseq): nonempty_csequence =
        coreduce(append_struct)(cseq, t, FALSE)

    append_finite: JUDGEMENT append(t, fseq) HAS_TYPE nonempty_finite_csequence

    append_first: THEOREM
      FORALL t, cseq:
        first(append(t, cseq)) = IF empty?(cseq) THEN t ELSE first(cseq) ENDIF

    append_rest: THEOREM
      FORALL t, nseq: rest(append(t, nseq)) = append(t, rest(nseq))

    append_finite_def: THEOREM
      FORALL t, fseq: append(t, fseq) = insert(t, length(fseq), fseq)

    append_infinite_def: THEOREM FORALL t, iseq: append(t, iseq) = iseq

    append_length: THEOREM
      FORALL t, fseq: length(append(t, fseq)) = length(fseq) + 1

    append_index: THEOREM
      FORALL t, cseq, n:
        index?(append(t, cseq))(n) IFF
         (is_finite(cseq) AND n = length(cseq)) OR index?(cseq)(n)

    append_nth: THEOREM
      FORALL t, cseq, (n: indexes(cseq)):
        nth(append(t, cseq), n) = nth(cseq, n)

    append_add: THEOREM
      FORALL t, u, cseq: add(u, append(t, cseq)) = append(t, add(u, cseq))

    append_last: THEOREM FORALL t, fseq: last(append(t, fseq)) = t

    append_extensionality: THEOREM
      FORALL t, cseq1, cseq2:
        append(t, cseq1) = append(t, cseq2) IMPLIES cseq1 = cseq2

    append_some: THEOREM
      FORALL t, cseq, p:
        some(p)(append(t, cseq)) IFF
         some(p)(cseq) OR (is_finite(cseq) AND p(t))

    append_every: THEOREM
      FORALL t, cseq, p:
        every(p)(append(t, cseq)) IFF
         every(p)(cseq) AND (is_infinite(cseq) OR p(t))

   END csequence_append

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

  % Subtype TCC generated (at line 37, column 25) for  state`1
      % expected type  (nonempty?[T])
  append_struct_TCC1: OBLIGATION
    FORALL (state: [csequence[T], T, bool]):
      NOT empty?(state`1) AND NOT state`3 IMPLIES nonempty?[T](state`1);

  % Subtype TCC generated (at line 41, column 6) for
      % coreduce(append_struct)(cseq, t, FALSE)
      % expected type  nonempty_csequence[T]
  append_TCC1: OBLIGATION
    FORALL (t: T, cseq: csequence[T]):
      nonempty?[T]
          (coreduce[T, [csequence, T, bool]](append_struct)(cseq, t, FALSE));

  % Judgement subtype TCC generated (at line 43, column 27) for
      % append(t, fseq)
      % expected type  nonempty_finite_csequence[T]
  append_finite: OBLIGATION
    FORALL (fseq, t):
      is_finite[T](append(t, fseq)) AND nonempty?[T](append(t, fseq));

  % Subtype TCC generated (at line 47, column 65) for  cseq
      % expected type  (nonempty?[T])
  append_first_TCC1: OBLIGATION
    FORALL (t, cseq): NOT empty?(cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 67, column 27) for  n
      % expected type  indexes[T](append(t, cseq))
  append_nth_TCC1: OBLIGATION
    FORALL (t, cseq, n: indexes[T](cseq)): index?[T](append(t, cseq))(n);


body:
  %-----------------------------------------------------------------------------
  % The reverse of a finite sequence.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_reverse[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_append[T]

    t: VAR T
    p: VAR pred[T]
    n: VAR nat
    fseq, fseq1, fseq2: VAR finite_csequence
    nfseq: VAR nonempty_finite_csequence

    reverse(fseq): RECURSIVE finite_csequence =
      IF empty?(fseq) THEN fseq
      ELSE append(first(fseq), reverse(rest(fseq)))
      ENDIF
       MEASURE length(fseq)

    reverse_empty: THEOREM FORALL fseq: empty?(reverse(fseq)) IFF empty?(fseq)

    reverse_nonempty: THEOREM
      FORALL fseq: nonempty?(reverse(fseq)) IFF nonempty?(fseq)

    reverse_first: THEOREM FORALL nfseq: first(reverse(nfseq)) = last(nfseq)

    reverse_last: THEOREM FORALL nfseq: last(reverse(nfseq)) = first(nfseq)

    reverse_length: THEOREM FORALL fseq: length(reverse(fseq)) = length(fseq)

    reverse_index: THEOREM FORALL fseq: index?(reverse(fseq)) = index?(fseq)

    reverse_nth: THEOREM
      FORALL fseq, (n: indexes(reverse(fseq))):
        nth(reverse(fseq), n) = nth(fseq, length(fseq) - n - 1)

    reverse_add1: THEOREM
      FORALL fseq, t: add(t, reverse(fseq)) = reverse(append(t, fseq))

    reverse_add2: THEOREM
      FORALL fseq, t: reverse(add(t, fseq)) = append(t, reverse(fseq))

    reverse_reverse: THEOREM FORALL fseq: reverse(reverse(fseq)) = fseq

    reverse_extensionality: THEOREM
      FORALL fseq1, fseq2:
        reverse(fseq1) = reverse(fseq2) IMPLIES fseq1 = fseq2

    reverse_some: THEOREM
      FORALL fseq, p: some(p)(reverse(fseq)) IFF some(p)(fseq)

    reverse_every: THEOREM
      FORALL fseq, p: every(p)(reverse(fseq)) IFF every(p)(fseq)

   END csequence_reverse

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

  % Subtype TCC generated (at line 27, column 22) for  fseq
      % expected type  (nonempty?[T])
  reverse_TCC1: OBLIGATION
    FORALL (fseq: finite_csequence[T]):
      NOT empty?(fseq) IMPLIES nonempty?[T](fseq);

  % Subtype TCC generated (at line 27, column 37) for  rest(fseq)
      % expected type  finite_csequence[T]
  reverse_TCC2: OBLIGATION
    FORALL (fseq: finite_csequence[T]):
      NOT empty?(fseq) IMPLIES is_finite[T](rest[T](fseq));

  % Termination TCC generated (at line 27, column 29) for  reverse(rest(fseq))
  reverse_TCC3: OBLIGATION
    FORALL (fseq: finite_csequence[T]):
      NOT empty?(fseq) IMPLIES length[T](rest[T](fseq)) < length[T](fseq);

  % Subtype TCC generated (at line 36, column 45) for  reverse(nfseq)
      % expected type  (nonempty?[T])
  reverse_first_TCC1: OBLIGATION FORALL (nfseq): nonempty?[T](reverse(nfseq));

  % Subtype TCC generated (at line 46, column 40) for  length(fseq) - n - 1
      % expected type  indexes[T](fseq)
  reverse_nth_TCC1: OBLIGATION
    FORALL (fseq, n: indexes[T](reverse(fseq))):
      length[T](fseq) - n - 1 >= 0 AND
       index?[T](fseq)(length[T](fseq) - n - 1);

  % Subtype TCC generated (at line 52, column 28) for  add(t, fseq)
      % expected type  finite_csequence[T]
  reverse_add2_TCC1: OBLIGATION
    FORALL (fseq, t): is_finite[T](add[T](t, fseq));


body:
  %-----------------------------------------------------------------------------
  % Properties of the rest function as applied to a sequence of countable
  % length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_rest[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T]

    n: VAR nat
    t: VAR T
    p: VAR pred[T]
    iseq: VAR infinite_csequence
    nseq: VAR nonempty_csequence
    nfseq: VAR nonempty_finite_csequence

    rest_finite: JUDGEMENT rest(nfseq) HAS_TYPE finite_csequence

    rest_infinite: JUDGEMENT rest(iseq) HAS_TYPE infinite_csequence

    rest_empty_add: THEOREM
      FORALL nseq:
        empty?(rest(nseq)) IFF (EXISTS t: nseq = add(t, empty_cseq))

    rest_empty: THEOREM
      FORALL nseq: empty?(rest(nseq)) IFF is_finite(nseq) AND length(nseq) = 1

    rest_nonempty: THEOREM
      FORALL nseq:
        nonempty?(rest(nseq)) IFF is_infinite(nseq) OR length(nseq) > 1

    rest_first: THEOREM
      FORALL nseq:
        nonempty?(rest(nseq)) IMPLIES first(rest(nseq)) = nth(nseq, 1)

    rest_length: THEOREM FORALL nfseq: length(rest(nfseq)) = length(nfseq) - 1

    rest_index: THEOREM
      FORALL nseq, n: index?(rest(nseq))(n) IFF index?(nseq)(n + 1)

    rest_nth: THEOREM
      FORALL nseq, (n: indexes(rest(nseq))):
        nth(rest(nseq), n) = nth(nseq, n + 1)

    rest_some: THEOREM
      FORALL nseq, p: some(p)(nseq) IFF p(first(nseq)) OR some(p)(rest(nseq))

    rest_every: THEOREM
      FORALL nseq, p:
        every(p)(nseq) IFF p(first(nseq)) AND every(p)(rest(nseq))

   END csequence_rest

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

  % Judgement subtype TCC generated (at line 27, column 25) for  rest(nfseq)
      % expected type  finite_csequence[T]
  rest_finite: OBLIGATION FORALL (nfseq): is_finite[T](rest[T](nfseq));

  % Judgement subtype TCC generated (at line 29, column 27) for  rest(iseq)
      % expected type  infinite_csequence[T]
  rest_infinite: OBLIGATION FORALL (iseq): NOT is_finite[T](rest[T](iseq));

  % Subtype TCC generated (at line 44, column 66) for  1
      % expected type  indexes[T](nseq)
  rest_first_TCC1: OBLIGATION
    FORALL (nseq): nonempty?(rest(nseq)) IMPLIES index?[T](nseq)(1);

  % Subtype TCC generated (at line 53, column 37) for  n + 1
      % expected type  indexes[T](nseq)
  rest_nth_TCC1: OBLIGATION
    FORALL (nseq, n: indexes[T](rest[T](nseq))): index?[T](nseq)(n + 1);


body:
  %-----------------------------------------------------------------------------
  % Remove an element from a sequence of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_remove[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T]

    t: VAR T
    p: VAR pred[T]
    index, n, m: VAR nat
    cseq, cseq1, cseq2: VAR csequence
    nseq: VAR nonempty_csequence
    fseq: VAR finite_csequence
    iseq: VAR infinite_csequence

    % Remove the element at position index in cseq.  If index >= length(cseq),
    % then we give back the original sequence.
    remove(cseq, index): RECURSIVE csequence =
      IF empty?(cseq) THEN cseq
      ELSIF index = 0 THEN rest(cseq)
      ELSE add(first(cseq), remove(rest(cseq), index - 1))
      ENDIF
       MEASURE index

    remove_finite: JUDGEMENT remove(fseq, index) HAS_TYPE finite_csequence

    remove_infinite: JUDGEMENT remove(iseq, index) HAS_TYPE infinite_csequence

    remove_0: THEOREM FORALL nseq: remove(nseq, 0) = rest(nseq)

    remove_empty: THEOREM
      FORALL cseq, index:
        empty?(remove(cseq, index)) IFF
         empty?(cseq) OR (index = 0 AND empty?(rest(cseq)))

    remove_nonempty: THEOREM
      FORALL cseq, index:
        nonempty?(remove(cseq, index)) IFF
         nonempty?(cseq) AND (index > 0 OR nonempty?(rest(cseq)))

    remove_first: THEOREM
      FORALL cseq, index:
        nonempty?(remove(cseq, index)) IMPLIES
         first(remove(cseq, index)) =
          IF index = 0 THEN first(rest(cseq)) ELSE first(cseq) ENDIF

    remove_rest: THEOREM
      FORALL nseq, index:
        nonempty?(remove(nseq, index)) IMPLIES
         rest(remove(nseq, index)) =
          IF index = 0 THEN rest(rest(nseq))
          ELSE remove(rest(nseq), index - 1)
          ENDIF

    remove_upfrom_length: THEOREM
      FORALL fseq, (index: upfrom[length(fseq)]): remove(fseq, index) = fseq

    remove_length: THEOREM
      FORALL fseq, index:
        length(remove(fseq, index)) =
         length(fseq) - IF index?(fseq)(index) THEN 1 ELSE 0 ENDIF

    remove_index: THEOREM
      FORALL index, cseq, n:
        index?(remove(cseq, index))(n) IFF
         index?(cseq)(n) AND
          NOT (is_finite(cseq) AND
                n = length(cseq) - 1 AND index?(cseq)(index))

    remove_nth: THEOREM
      FORALL cseq, n, (m: indexes(remove(cseq, n))):
        nth(remove(cseq, n), m) = nth(cseq, m + IF m < n THEN 0 ELSE 1 ENDIF)

    remove_add: THEOREM
      FORALL cseq, index, t:
        add(t, remove(cseq, index)) = remove(add(t, cseq), index + 1)

    remove_last: THEOREM
      FORALL fseq, index:
        nonempty?(remove(fseq, index)) IMPLIES
         last(remove(fseq, index)) =
          IF index = length(fseq) - 1 THEN nth(fseq, index - 1)
          ELSE last(fseq)
          ENDIF

    remove_remove: THEOREM
      FORALL cseq, n, m:
        remove(remove(cseq, n), m) =
         IF n <= m THEN remove(remove(cseq, m + 1), n)
         ELSE remove(remove(cseq, m), n - 1)
         ENDIF

    remove_extensionality: THEOREM
      FORALL cseq1, cseq2, n:
        remove(cseq1, n) = remove(cseq2, n) AND
         ((NOT index?(cseq1)(n) AND NOT index?(cseq2)(n)) OR
           (index?(cseq1)(n) AND
             index?(cseq2)(n) AND nth(cseq1, n) = nth(cseq2, n)))
         IMPLIES cseq1 = cseq2

    remove_some: THEOREM
      FORALL cseq, index, p:
        some(p)(remove(cseq, index)) IFF
         (EXISTS (n: indexes(cseq)): n /= index AND p(nth(cseq, n)))

    remove_every: THEOREM
      FORALL cseq, index, p:
        every(p)(remove(cseq, index)) IFF
         (FORALL (n: indexes(cseq)): n = index OR p(nth(cseq, n)))

   END csequence_remove

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

  % Subtype TCC generated (at line 31, column 30) for  cseq
      % expected type  (nonempty?[T])
  remove_TCC1: OBLIGATION
    FORALL (cseq: csequence[T], index: nat):
      index = 0 AND NOT empty?(cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 32, column 19) for  cseq
      % expected type  (nonempty?[T])
  remove_TCC2: OBLIGATION
    FORALL (cseq: csequence[T], index: nat):
      NOT index = 0 AND NOT empty?(cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 32, column 45) for  index - 1
      % expected type  nat
  remove_TCC3: OBLIGATION
    FORALL (cseq: csequence[T], index: nat):
      NOT index = 0 AND NOT empty?(cseq) IMPLIES index - 1 >= 0;

  % Termination TCC generated (at line 32, column 26) for
      % remove(rest(cseq), index - 1)
  remove_TCC4: OBLIGATION
    FORALL (cseq: csequence[T], index: nat):
      NOT index = 0 AND NOT empty?(cseq) IMPLIES index - 1 < index;

  % Judgement subtype TCC generated (at line 36, column 27) for
      % remove(fseq, index)
      % expected type  finite_csequence[T]
  remove_finite: OBLIGATION
    FORALL (fseq, index): is_finite[T](remove(fseq, index));

  % Judgement subtype TCC generated (at line 38, column 29) for
      % remove(iseq, index)
      % expected type  infinite_csequence[T]
  remove_infinite: OBLIGATION
    FORALL (index, iseq): NOT is_finite[T](remove(iseq, index));

  % Subtype TCC generated (at line 56, column 37) for  cseq
      % expected type  (nonempty?[T])
  remove_first_TCC1: OBLIGATION
    FORALL (cseq, index):
      index = 0 AND nonempty?(remove(cseq, index)) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 56, column 32) for  rest(cseq)
      % expected type  (nonempty?[T])
  remove_first_TCC2: OBLIGATION
    FORALL (cseq, index):
      index = 0 AND nonempty?(remove(cseq, index)) IMPLIES
       nonempty?[T](rest[T](cseq));

  % Subtype TCC generated (at line 56, column 55) for  cseq
      % expected type  (nonempty?[T])
  remove_first_TCC3: OBLIGATION
    FORALL (cseq, index):
      NOT index = 0 AND nonempty?(remove(cseq, index)) IMPLIES
       nonempty?[T](cseq);

  % Subtype TCC generated (at line 62, column 31) for  rest(nseq)
      % expected type  (nonempty?[T])
  remove_rest_TCC1: OBLIGATION
    FORALL (nseq, index):
      index = 0 AND nonempty?(remove(nseq, index)) IMPLIES
       nonempty?[T](rest[T](nseq));

  % Subtype TCC generated (at line 63, column 32) for  index - 1
      % expected type  nat
  remove_rest_TCC2: OBLIGATION
    FORALL (nseq, index):
      NOT index = 0 AND nonempty?(remove(nseq, index)) IMPLIES index - 1 >= 0;

  % Subtype TCC generated (at line 83, column 42) for
      % m + IF m < n THEN 0 ELSE 1 ENDIF
      % expected type  indexes[T](cseq)
  remove_nth_TCC1: OBLIGATION
    FORALL (cseq, n, m: indexes[T](remove(cseq, n))):
      index?[T](cseq)(m + IF m < n THEN 0 ELSE 1 ENDIF);

  % Subtype TCC generated (at line 93, column 51) for  index - 1
      % expected type  indexes[T](fseq)
  remove_last_TCC1: OBLIGATION
    FORALL (fseq, index):
      index = length(fseq) - 1 AND nonempty?(remove(fseq, index)) IMPLIES
       index - 1 >= 0 AND index?[T](fseq)(index - 1);

  % Subtype TCC generated (at line 94, column 18) for  fseq
      % expected type  nonempty_finite_csequence[T]
  remove_last_TCC2: OBLIGATION
    FORALL (fseq, index):
      NOT index = length(fseq) - 1 AND nonempty?(remove(fseq, index)) IMPLIES
       nonempty?[T](fseq);

  % Subtype TCC generated (at line 101, column 36) for  n - 1
      % expected type  nat
  remove_remove_TCC1: OBLIGATION FORALL (n, m): NOT n <= m IMPLIES n - 1 >= 0;


body:
  %-----------------------------------------------------------------------------
  % Prefixes and suffixes of sequences of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_prefix_suffix[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_prefix[T], csequence_suffix[T]

    n: VAR nat
    cseq, cseq1, cseq2: VAR csequence

    prefix_suffix_eta: THEOREM
      FORALL cseq, n: prefix(cseq, n) o suffix(cseq, n) = cseq

    prefix_suffix_extensionality: THEOREM
      FORALL cseq1, cseq2, n:
        prefix(cseq1, n) = prefix(cseq2, n) AND
         suffix(cseq1, n) = suffix(cseq2, n)
         IMPLIES cseq1 = cseq2

   END csequence_prefix_suffix


body:
  %-----------------------------------------------------------------------------
  % Prefix of an appended sequence of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_prefix_append[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_prefix[T], csequence_append[T]

    prefix_append_eta: THEOREM
      FORALL (fseq: finite_csequence), (t: T):
        prefix(append(t, fseq), length(fseq)) = fseq

   END csequence_prefix_append


body:
  %-----------------------------------------------------------------------------
  % Merge two sequences into a single sequence of countable length by taking one
  % element from the first sequence, then one element from the second sequence,
  % then ...
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_merge[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T], csequence_length_comp[T, T]
    IMPORTING csequence_codt_coreduce[T, [csequence, csequence]]

    t: VAR T
    p: VAR pred[T]
    n: VAR nat
    cseq, cseq1, cseq2, cseq3, cseq4: VAR csequence
    fseq1, fseq2: VAR finite_csequence
    iseq: VAR infinite_csequence
    eseq: VAR empty_csequence
    state: VAR [csequence, csequence]

    merge_struct(state): csequence_struct =
        IF empty?(state`1)
          THEN IF empty?(state`2) THEN inj_empty_cseq
               ELSE inj_add(first(state`2), (rest(state`2), state`1))
               ENDIF
        ELSE inj_add(first(state`1), (state`2, rest(state`1)))
        ENDIF

    merge(cseq1, cseq2): csequence = coreduce(merge_struct)(cseq1, cseq2)

    merge_empty: THEOREM
      FORALL cseq1, cseq2:
        empty?(merge(cseq1, cseq2)) IFF empty?(cseq1) AND empty?(cseq2)

    merge_nonempty: THEOREM
      FORALL cseq1, cseq2:
        nonempty?(merge(cseq1, cseq2)) IFF
         nonempty?(cseq1) OR nonempty?(cseq2)

    merge_empty_left:  THEOREM FORALL eseq, cseq: merge(eseq, cseq) = cseq

    merge_empty_right: THEOREM FORALL cseq, eseq: merge(cseq, eseq) = cseq

    merge_first: THEOREM
      FORALL cseq1, cseq2:
        nonempty?(merge(cseq1, cseq2)) IMPLIES
         first(merge(cseq1, cseq2)) =
          IF nonempty?(cseq1) THEN first(cseq1) ELSE first(cseq2) ENDIF

    merge_rest: THEOREM
      FORALL cseq1, cseq2:
        nonempty?(merge(cseq1, cseq2)) IMPLIES
         rest(merge(cseq1, cseq2)) =
          IF nonempty?(cseq1) THEN merge(cseq2, rest(cseq1))
          ELSE rest(cseq2)
          ENDIF

    merge_finite: JUDGEMENT merge(fseq1, fseq2) HAS_TYPE finite_csequence

    % Avoid 2 nearly identical proofs for the next 2 judgements
    merge_finiteness: THEOREM
      FORALL cseq1, cseq2:
        is_finite(merge(cseq1, cseq2)) IMPLIES
         is_finite(cseq1) AND is_finite(cseq2)

    merge_infinite1: JUDGEMENT merge(iseq, cseq) HAS_TYPE infinite_csequence
    merge_infinite2: JUDGEMENT merge(cseq, iseq) HAS_TYPE infinite_csequence

    merge_length: THEOREM
      FORALL fseq1, fseq2:
        length(merge(fseq1, fseq2)) = length(fseq1) + length(fseq2)

    merge_index: THEOREM
      FORALL cseq1, cseq2, n:
        index?(merge(cseq1, cseq2))(n) IFF
         index?(cseq1)(n) OR
          (is_finite(cseq1) IMPLIES index?(cseq2)(n - length(cseq1)))

    merge_nth: THEOREM
      FORALL cseq1, cseq2, (n: indexes(merge(cseq1, cseq2))):
        nth(merge(cseq1, cseq2), n) =
         IF length_lt(cseq1, cseq2) AND n >= length(cseq1) * 2
           THEN nth(cseq2, n - length(cseq1))
         ELSIF length_lt(cseq2, cseq1) AND n >= length(cseq2) * 2
           THEN nth(cseq1, n - length(cseq2))
         ELSIF even?(n) THEN nth(cseq1, n / 2)
         ELSE nth(cseq2, (n - 1) / 2)
         ENDIF

    merge_add: THEOREM
      FORALL t, cseq1, cseq2:
        add(t, merge(cseq1, cseq2)) = merge(add(t, cseq2), cseq1)

    merge_last: THEOREM
      FORALL fseq1, fseq2:
        nonempty?(merge(fseq1, fseq2)) IMPLIES
         last(merge(fseq1, fseq2)) =
          IF length(fseq1) <= length(fseq2) THEN last(fseq2)
          ELSE last(fseq1)
          ENDIF

    merge_extensionality: THEOREM
      FORALL cseq1, cseq2, cseq3, cseq4:
        length_eq(cseq1, cseq2) AND
         length_eq(cseq3, cseq4) AND
          merge(cseq1, cseq2) = merge(cseq3, cseq4)
         IMPLIES cseq1 = cseq3 AND cseq2 = cseq4

    merge_some: THEOREM
      FORALL p, cseq1, cseq2:
        some(p)(merge(cseq1, cseq2)) IFF some(p)(cseq1) OR some(p)(cseq2)

    merge_every: THEOREM
      FORALL p, cseq1, cseq2:
        every(p)(merge(cseq1, cseq2)) IFF every(p)(cseq1) AND every(p)(cseq2)

   END csequence_merge

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

  % Subtype TCC generated (at line 34, column 32) for  state`2
      % expected type  (nonempty?[T])
  merge_struct_TCC1: OBLIGATION
    FORALL (state: [csequence[T], csequence[T]]):
      NOT empty?(state`2) AND empty?(state`1) IMPLIES nonempty?[T](state`2);

  % Subtype TCC generated (at line 36, column 25) for  state`1
      % expected type  (nonempty?[T])
  merge_struct_TCC2: OBLIGATION
    FORALL (state: [csequence[T], csequence[T]]):
      NOT empty?(state`1) IMPLIES nonempty?[T](state`1);

  % Subtype TCC generated (at line 58, column 57) for  cseq2
      % expected type  (nonempty?[T])
  merge_first_TCC1: OBLIGATION
    FORALL (cseq1, cseq2):
      NOT nonempty?(cseq1) AND nonempty?(merge(cseq1, cseq2)) IMPLIES
       nonempty?[T](cseq2);

  % Judgement subtype TCC generated (at line 68, column 26) for
      % merge(fseq1, fseq2)
      % expected type  finite_csequence[T]
  merge_finite: OBLIGATION
    FORALL (fseq1, fseq2): is_finite[T](merge(fseq1, fseq2));

  % Judgement subtype TCC generated (at line 76, column 29) for
      % merge(iseq, cseq)
      % expected type  infinite_csequence[T]
  merge_infinite1: OBLIGATION
    FORALL (cseq, iseq): NOT is_finite[T](merge(iseq, cseq));

  % Judgement subtype TCC generated (at line 77, column 29) for
      % merge(cseq, iseq)
      % expected type  infinite_csequence[T]
  merge_infinite2: OBLIGATION
    FORALL (cseq, iseq): NOT is_finite[T](merge(cseq, iseq));

  % Subtype TCC generated (at line 87, column 48) for  n - length(cseq1)
      % expected type  nat
  merge_index_TCC1: OBLIGATION
    FORALL (cseq1, n):
      is_finite(cseq1) AND NOT index?(cseq1)(n) IMPLIES
       n - length[T](cseq1) >= 0;

  % Subtype TCC generated (at line 92, column 50) for  cseq1
      % expected type  fseq: finite_csequence[T]
  merge_nth_TCC1: OBLIGATION
    FORALL (cseq1, cseq2, n: indexes[T](merge(cseq1, cseq2))):
      length_lt(cseq1, cseq2) IMPLIES is_finite[T](cseq1);

  % Subtype TCC generated (at line 93, column 25) for  n - length(cseq1)
      % expected type  indexes[T](cseq2)
  merge_nth_TCC2: OBLIGATION
    FORALL (cseq1, cseq2, n: indexes[T](merge(cseq1, cseq2))):
      length_lt(cseq1, cseq2) AND n >= length(cseq1) * 2 IMPLIES
       n - length[T](cseq1) >= 0 AND index?[T](cseq2)(n - length[T](cseq1));

  % Subtype TCC generated (at line 94, column 53) for  cseq2
      % expected type  fseq: finite_csequence[T]
  merge_nth_TCC3: OBLIGATION
    FORALL (cseq1, cseq2, n: indexes[T](merge(cseq1, cseq2))):
      length_lt(cseq2, cseq1) AND
       NOT (length_lt(cseq1, cseq2) AND n >= length(cseq1) * 2)
       IMPLIES is_finite[T](cseq2);

  % Subtype TCC generated (at line 95, column 25) for  n - length(cseq2)
      % expected type  indexes[T](cseq1)
  merge_nth_TCC4: OBLIGATION
    FORALL (cseq1, cseq2, n: indexes[T](merge(cseq1, cseq2))):
      length_lt(cseq2, cseq1) AND
       n >= length(cseq2) * 2 AND
        NOT (length_lt(cseq1, cseq2) AND n >= length(cseq1) * 2)
       IMPLIES
       n - length[T](cseq2) >= 0 AND index?[T](cseq1)(n - length[T](cseq2));

  % Subtype TCC generated (at line 96, column 38) for  n / 2
      % expected type  indexes[T](cseq1)
  merge_nth_TCC5: OBLIGATION
    FORALL (cseq1, cseq2, n: indexes[T](merge(cseq1, cseq2))):
      even?(n) AND
       NOT (length_lt(cseq2, cseq1) AND n >= length(cseq2) * 2) AND
        NOT (length_lt(cseq1, cseq2) AND n >= length(cseq1) * 2)
       IMPLIES integer_pred(n / 2) AND n / 2 >= 0 AND index?[T](cseq1)(n / 2);

  % Subtype TCC generated (at line 97, column 23) for  (n - 1) / 2
      % expected type  indexes[T](cseq2)
  merge_nth_TCC6: OBLIGATION
    FORALL (cseq1, cseq2, n: indexes[T](merge(cseq1, cseq2))):
      NOT even?(n) AND
       NOT (length_lt(cseq2, cseq1) AND n >= length(cseq2) * 2) AND
        NOT (length_lt(cseq1, cseq2) AND n >= length(cseq1) * 2)
       IMPLIES
       integer_pred((n - 1) / 2) AND
        (n - 1) / 2 >= 0 AND index?[T](cseq2)((n - 1) / 2);

  % Subtype TCC generated (at line 108, column 52) for  fseq2
      % expected type  nonempty_finite_csequence[T]
  merge_last_TCC1: OBLIGATION
    FORALL (fseq1, fseq2):
      length(fseq1) <= length(fseq2) AND nonempty?(merge(fseq1, fseq2))
       IMPLIES nonempty?[T](fseq2);

  % Subtype TCC generated (at line 109, column 18) for  fseq1
      % expected type  nonempty_finite_csequence[T]
  merge_last_TCC2: OBLIGATION
    FORALL (fseq1, fseq2):
      NOT length(fseq1) <= length(fseq2) AND nonempty?(merge(fseq1, fseq2))
       IMPLIES nonempty?[T](fseq1);


body:
  %-----------------------------------------------------------------------------
  % The combination of the merge and split operators on sequences of countable
  % length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_merge_split[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_merge[T], csequence_split[T]

    cseq, cseq1, cseq2: VAR csequence

    merge_split_eta: THEOREM FORALL cseq: merge(split(cseq)) = cseq

    split_merge_eta: THEOREM
      FORALL cseq1, cseq2:
        length_eq(cseq1, cseq2) IMPLIES
         split(merge(cseq1, cseq2)) = (cseq1, cseq2)

   END csequence_merge_split


body:
  %-----------------------------------------------------------------------------
  % Properties of mapping functions on sequences of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_map_props[T1, T2: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T1], csequence_nth[T2]
    IMPORTING csequence_codt_map[T1, T2]

    t: VAR T1
    p: VAR pred[T2]
    f: VAR [T1 -> T2]
    cseq, cseq1, cseq2: VAR csequence[T1]
    fseq: VAR finite_csequence[T1]
    iseq: VAR infinite_csequence[T1]
    nseq: VAR nonempty_csequence[T1]
    nfseq: VAR nonempty_finite_csequence[T1]

    map_empty: THEOREM FORALL f, cseq: empty?(map(f, cseq)) IFF empty?(cseq)

    map_nonempty: THEOREM
      FORALL f, cseq: nonempty?(map(f, cseq)) IFF nonempty?(cseq)

    map_finite: JUDGEMENT map(f, fseq) HAS_TYPE finite_csequence[T2]

    map_infinite: JUDGEMENT map(f, iseq) HAS_TYPE infinite_csequence[T2]

    map_first: THEOREM FORALL f, nseq: first(map(f, nseq)) = f(first(nseq))

    map_rest: THEOREM FORALL f, nseq: rest(map(f, nseq)) = map(f, rest(nseq))

    map_length: THEOREM FORALL f, fseq: length(map(f, fseq)) = length(fseq)

    map_index: THEOREM FORALL f, cseq: index?(map(f, cseq)) = index?(cseq)

    map_nth: THEOREM
      FORALL f, cseq, (n: indexes(cseq)):
        nth(map(f, cseq), n) = f(nth(cseq, n))

    map_add: THEOREM
      FORALL f, cseq, t: add(f(t), map(f, cseq)) = map(f, add(t, cseq))

    map_last: THEOREM FORALL f, nfseq: last(map(f, nfseq)) = f(last(nfseq))

    % The generated map theory includes both curried and uncurried definitions
    % of map, but doesn't prove that they are equal.
    map_map: THEOREM FORALL f, cseq: map(f)(cseq) = map(f, cseq)

    map_injective: THEOREM FORALL f: injective?(f) IMPLIES injective?(map(f))

    map_extensionality: THEOREM
      FORALL f, cseq1, cseq2:
        injective?(f) AND map(f, cseq1) = map(f, cseq2) IMPLIES cseq1 = cseq2

    map_some: THEOREM
      FORALL f, cseq, p: some(p)(map(f, cseq)) IFF some(p o f)(cseq)

    map_every: THEOREM
      FORALL f, cseq, p: every(p)(map(f, cseq)) IFF every(p o f)(cseq)

   END csequence_map_props

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

  % Judgement subtype TCC generated (at line 34, column 24) for  map(f, fseq)
      % expected type  finite_csequence[T2]
  map_finite: OBLIGATION
    FORALL (f, fseq): is_finite[T2](map[T1, T2](f, fseq));

  % Judgement subtype TCC generated (at line 36, column 26) for  map(f, iseq)
      % expected type  infinite_csequence[T2]
  map_infinite: OBLIGATION
    FORALL (f, iseq): NOT is_finite[T2](map[T1, T2](f, iseq));

  % Subtype TCC generated (at line 38, column 43) for  map(f, nseq)
      % expected type  (nonempty?[T2])
  map_first_TCC1: OBLIGATION
    FORALL (f, nseq): nonempty?[T2](map[T1, T2](f, nseq));

  % Subtype TCC generated (at line 48, column 24) for  n
      % expected type  indexes[T2](map(f, cseq))
  map_nth_TCC1: OBLIGATION
    FORALL (f, cseq, n: indexes[T1](cseq)):
      index?[T2](map[T1, T2](f, cseq))(n);

  % Subtype TCC generated (at line 53, column 42) for  map(f, nfseq)
      % expected type  nonempty_finite_csequence[T2]
  map_last_TCC1: OBLIGATION
    FORALL (f, nfseq): nonempty?[T2](map[T1, T2](f, nfseq));


body:
  %-----------------------------------------------------------------------------
  % Composition of mapping functions on sequences of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_map_composition[T1, T2, T3: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_codt_map[T1, T2]
    IMPORTING csequence_codt_map[T1, T3]
    IMPORTING csequence_codt_map[T2, T3]

    map_composition: THEOREM
      FORALL (f12: [T1 -> T2]), (f23: [T2 -> T3]), (cseq: csequence[T1]):
        map[T2, T3](f23)(map[T1, T2](f12)(cseq)) =
         map[T1, T3](f23 o f12)(cseq)

   END csequence_map_composition


body:
  %-----------------------------------------------------------------------------
  % Conversions between sequences of countable length and the prelude list type.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_list[T: TYPE]: THEORY
   BEGIN

    IMPORTING list[T], list_props[T], csequence_nth[T]

    n: VAR nat
    l: VAR list
    fseq: VAR finite_csequence

    % Convert a list to a finite_csequence
    from_list(l): RECURSIVE finite_csequence =
      IF null?(l) THEN empty_cseq ELSE add(car(l), from_list(cdr(l))) ENDIF
       MEASURE l BY <<

    from_list_length: THEOREM FORALL l: length(from_list(l)) = length(l)

    from_list_index: THEOREM
      FORALL l, n: index?(from_list(l))(n) IFF n < length(l)

    from_list_nth: THEOREM
      FORALL l, (n: below[length(l)]): nth(from_list(l), n) = nth(l, n)

    % Convert a finite_csequence to a list
    to_list(fseq): RECURSIVE list =
      IF empty?(fseq) THEN null
      ELSE cons(first(fseq), to_list(rest(fseq)))
      ENDIF
       MEASURE length(fseq)

    to_list_length: THEOREM FORALL fseq: length(to_list(fseq)) = length(fseq)

    to_list_index: THEOREM
      FORALL fseq, n: n < length(to_list(fseq)) IFF index?(fseq)(n)

    to_list_nth: THEOREM
      FORALL fseq, (n: indexes(fseq)): nth(to_list(fseq), n) = nth(fseq, n)

    % Applying both conversions gives you back what you started with

    to_from_list: THEOREM FORALL l: to_list(from_list(l)) = l

    from_to_list: THEOREM FORALL fseq: from_list(to_list(fseq)) = fseq

   END csequence_list

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

  % Subtype TCC generated (at line 25, column 45) for  l
      % expected type  (cons?)
  from_list_TCC1: OBLIGATION
    FORALL (l: list[T]): NOT null?(l) IMPLIES cons?[T](l);

  % Termination TCC generated (at line 25, column 49) for  from_list(cdr(l))
  from_list_TCC2: OBLIGATION
    FORALL (l: list[T]): NOT null?(l) IMPLIES <<[T](cdr[T](l), l);

  % Subtype TCC generated (at line 25, column 37) for
      % add(car(l), from_list(cdr(l)))
      % expected type  finite_csequence[T]
  from_list_TCC3: OBLIGATION
    FORALL (l: list[T], v: [{z: list[T] | z << l} -> finite_csequence[T]]):
      NOT null?(l) IMPLIES is_finite[T](add[T](car[T](l), v(cdr[T](l))));

  % Subtype TCC generated (at line 34, column 55) for  n
      % expected type  indexes[T](from_list(l))
  from_list_nth_TCC1: OBLIGATION
    FORALL (l, n: below[length[T](l)]): index?[T](from_list(l))(n);

  % Subtype TCC generated (at line 39, column 20) for  fseq
      % expected type  (nonempty?[T])
  to_list_TCC1: OBLIGATION
    FORALL (fseq: finite_csequence[T]):
      NOT empty?(fseq) IMPLIES nonempty?[T](fseq);

  % Subtype TCC generated (at line 39, column 35) for  rest(fseq)
      % expected type  finite_csequence[T]
  to_list_TCC2: OBLIGATION
    FORALL (fseq: finite_csequence[T]):
      NOT empty?(fseq) IMPLIES is_finite[T](rest[T](fseq));

  % Termination TCC generated (at line 39, column 27) for  to_list(rest(fseq))
  to_list_TCC3: OBLIGATION
    FORALL (fseq: finite_csequence[T]):
      NOT empty?(fseq) IMPLIES length[T](rest[T](fseq)) < length[T](fseq);

  % Subtype TCC generated (at line 49, column 56) for  n
      % expected type  below[length(to_list(fseq))]
  to_list_nth_TCC1: OBLIGATION
    FORALL (fseq, n: indexes[T](fseq)): n < length[T](to_list(fseq));


body:
  %-----------------------------------------------------------------------------
  % Ascending chains, a helper for the theory of limits of sequences of
  % countable length.
  %
  % FIXME: Should we use the NASA orders/monotone_functions theory instead?
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  ascending_chains[T: TYPE, <=: (partial_order?[T])]: THEORY
   BEGIN

    t, u: VAR T
    n, m: VAR nat

    ascending_chain?(f: [nat -> T]): bool = FORALL n: f(n) <= f(n + 1)

    ascending_chain: TYPE = (ascending_chain?)

    chain: VAR ascending_chain

    ascending_chain?_def: THEOREM
      FORALL chain, n, m: n <= m IMPLIES chain(n) <= chain(m)

    upperbound?(chain)(t): bool = FORALL n: chain(n) <= t

    least_upperbound?(chain)(t): bool =
        upperbound?(chain)(t) AND
         (FORALL u: upperbound?(chain)(u) IMPLIES t <= u)

    least_upperbound_inj: THEOREM
      FORALL chain, t, u:
        least_upperbound?(chain)(t) AND least_upperbound?(chain)(u) IMPLIES
         t = u

    bounded_above?(chain): bool = EXISTS t: upperbound?(chain)(t)

   END ascending_chains


body:
  %-----------------------------------------------------------------------------
  % The limit of a function that produces prefixes of a sequence of countable
  % length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_limit[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_prefix_suffix[T]
    IMPORTING ascending_chains[csequence, prefix?]
    IMPORTING csequence_codt_coreduce[T, ascending_chain]

    t: VAR T
    n, m, k: VAR nat
    chain: VAR ascending_chain
    cseq: VAR csequence
    fseq: VAR finite_csequence
    p: VAR pred[csequence]

    % FIXME: prefix_chain and suffix_chain sound like converses, but they are not

    prefix_chain(cseq): ascending_chain = LAMBDA n: prefix(cseq, n)

    suffix_chain(chain, n): ascending_chain = LAMBDA m: suffix(chain(m), n)

    rest_chain(chain): ascending_chain =
        LAMBDA n:
          IF empty?(chain(n)) THEN empty_cseq ELSE rest(chain(n)) ENDIF

    ascending_chain?_nth: THEOREM
      FORALL chain, n, m, k:
        n <= m AND index?(chain(n))(k) IMPLIES
         index?(chain(m))(k) AND nth(chain(n), k) = nth(chain(m), k)

    limit_struct(chain): csequence_struct[T, ascending_chain] =
        IF (FORALL n: empty?(chain(n))) THEN inj_empty_cseq
        ELSE inj_add(first(chain(min({n | nonempty?(chain(n))}))),
                     rest_chain(chain))
        ENDIF

    limit(chain): csequence = coreduce(limit_struct)(chain)

    limit_empty: THEOREM
      FORALL chain: empty?(limit(chain)) IFF (FORALL n: empty?(chain(n)))

    limit_nonempty: THEOREM
      FORALL chain:
        nonempty?(limit(chain)) IFF (EXISTS n: nonempty?(chain(n)))

    limit_first: THEOREM
      FORALL chain, n:
        nonempty?(chain(n)) IMPLIES first(chain(n)) = first(limit(chain))

    limit_rest_chain: THEOREM
      FORALL chain:
        nonempty?(limit(chain)) IMPLIES
         rest(limit(chain)) = limit(rest_chain(chain))

    limit_suffix_chain: THEOREM
      FORALL chain, n: suffix(limit(chain), n) = limit(suffix_chain(chain, n))

    limit_lub: THEOREM FORALL chain: least_upperbound?(chain)(limit(chain))

    limit_nth: THEOREM
      FORALL chain, cseq, n, m:
        index?(chain(n))(m) IMPLIES
         index?(limit(chain))(m) AND nth(chain(n), m) = nth(limit(chain), m)

    limit_def: THEOREM
      FORALL chain, cseq:
        limit(chain) = cseq IFF
         (FORALL t, n:
            index?(cseq)(n) AND nth(cseq, n) = t IFF
             (EXISTS m: index?(chain(m))(n) AND nth(chain(m), n) = t))

    limit_prefix_chain: THEOREM FORALL cseq: limit(prefix_chain(cseq)) = cseq

    limit_prefix_compact: THEOREM
      FORALL cseq, n, chain:
        (n = 0 OR index?(cseq)(n - 1)) IMPLIES
         (prefix?(prefix(cseq, n), limit(chain)) IMPLIES
           (EXISTS m: prefix?(prefix(cseq, n), chain(m))))

    limit_finite_compact: THEOREM
      FORALL cseq:
        is_finite(cseq) IFF
         (FORALL chain:
            prefix?(cseq, limit(chain)) IMPLIES
             (EXISTS m: prefix?(cseq, chain(m))))

    continuous?(p): bool =
        FORALL chain: (FORALL n: p(chain(n))) IMPLIES p(limit(chain))

    continuous?_infinite: THEOREM
      FORALL p:
        continuous?(p) AND (FORALL fseq: p(fseq)) IMPLIES
         (FORALL cseq: p(cseq))

   END csequence_limit

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

  % Subtype TCC generated (at line 31, column 40) for
      % LAMBDA n: prefix(cseq, n)
      % expected type  ascending_chain[csequence, prefix?]
  prefix_chain_TCC1: OBLIGATION
    FORALL (cseq: csequence[T]):
      ascending_chain?[csequence[T], prefix?[T]]
          (LAMBDA n: prefix[T](cseq, n));

  % Subtype TCC generated (at line 33, column 44) for
      % LAMBDA m: suffix(chain(m), n)
      % expected type  ascending_chain[csequence, prefix?]
  suffix_chain_TCC1: OBLIGATION
    FORALL (chain: ascending_chain[csequence[T], prefix?[T]], n: nat):
      ascending_chain?[csequence[T], prefix?[T]]
          (LAMBDA m: suffix[T](chain(m), n));

  % Subtype TCC generated (at line 37, column 54) for  chain(n)
      % expected type  (nonempty?[T])
  rest_chain_TCC1: OBLIGATION
    FORALL (chain: ascending_chain[csequence[T], prefix?[T]], n):
      NOT empty?(chain(n)) IMPLIES nonempty?[T](chain(n));

  % Subtype TCC generated (at line 36, column 6) for
      % LAMBDA n:
      %   IF empty?(chain(n)) THEN empty_cseq ELSE rest(chain(n)) ENDIF
      % expected type  ascending_chain[csequence, prefix?]
  rest_chain_TCC2: OBLIGATION
    FORALL (chain: ascending_chain[csequence[T], prefix?[T]]):
      ascending_chain?[csequence[T], prefix?[T]]
          (LAMBDA n:
             IF empty?[T](chain(n)) THEN empty_cseq[T]
             ELSE rest[T](chain(n))
             ENDIF);

  % Subtype TCC generated (at line 46, column 35) for
      % {n | nonempty?(chain(n))}
      % expected type  S: (nonempty?[nat])
  limit_struct_TCC1: OBLIGATION
    FORALL (chain: ascending_chain[csequence[T], prefix?[T]]):
      NOT (FORALL n: empty?(chain(n))) IMPLIES
       nonempty?[nat]({n | nonempty?[T](chain(n))});

  % Subtype TCC generated (at line 46, column 25) for
      % chain(min({n | nonempty?(chain(n))}))
      % expected type  (nonempty?[T])
  limit_struct_TCC2: OBLIGATION
    FORALL (chain: ascending_chain[csequence[T], prefix?[T]]):
      NOT (FORALL n: empty?(chain(n))) IMPLIES
       nonempty?[T](chain(min[nat]({n | nonempty?[T](chain(n))})));

  % Subtype TCC generated (at line 61, column 58) for  limit(chain)
      % expected type  (nonempty?[T])
  limit_first_TCC1: OBLIGATION
    FORALL (chain, n): nonempty?(chain(n)) IMPLIES nonempty?[T](limit(chain));

  % Subtype TCC generated (at line 89, column 29) for  n - 1
      % expected type  nat
  limit_prefix_compact_TCC1: OBLIGATION
    FORALL (n, chain): NOT n = 0 IMPLIES n - 1 >= 0;


body:
  %-----------------------------------------------------------------------------
  % The interaction between the insert and remove operations on a sequence of
  % countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_insert_remove[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_insert[T], csequence_remove[T]

    insert_remove_eta: THEOREM
      FORALL (cseq: csequence), (n: indexes(cseq)):
        insert(nth(cseq, n), n, remove(cseq, n)) = cseq

   END csequence_insert_remove


body:
  %-----------------------------------------------------------------------------
  % Additional induction rules for sequences of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_induction[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T]

    t: VAR T
    n, m: VAR nat
    cseq: VAR csequence
    fseq: VAR finite_csequence
    iseq: VAR infinite_csequence
    p: VAR pred[T]
    sp: VAR pred[csequence]

    % Shorthand to make the definitions below more comprehensible.
    % This predicate says that p holds at index n, if index n is valid.
    p_if_exists(p, cseq, n): MACRO bool =
        index?(cseq)(n) IMPLIES p(nth(cseq, n))

    % Weak induction over the elements: general / finite sequence case
    cseq_induction: THEOREM
      FORALL cseq, p:
        p_if_exists(p, cseq, 0) AND
         (FORALL n:
            p_if_exists(p, cseq, n) IMPLIES p_if_exists(p, cseq, n + 1))
         IMPLIES every(p)(cseq)

    % Weak induction over the elements: infinite sequence case
    cseq_infinite_induction: THEOREM
      FORALL iseq, p:
        p(nth(iseq, 0)) AND
         (FORALL n: p(nth(iseq, n)) IMPLIES p(nth(iseq, n + 1)))
         IMPLIES every(p)(iseq)

    % Strong induction over the elements: general / finite sequence case
    CSEQ_induction: THEOREM
      FORALL cseq, p:
        (FORALL n:
           (FORALL m: m < n IMPLIES p_if_exists(p, cseq, m)) IMPLIES
            p_if_exists(p, cseq, n))
         IMPLIES every(p)(cseq)

    % Strong induction over the elements: infinite sequence case
    CSEQ_infinite_induction: THEOREM
      FORALL iseq, p:
        (FORALL n:
           (FORALL m: m < n IMPLIES p(nth(iseq, m))) IMPLIES
            p(nth(iseq, n)))
         IMPLIES every(p)(iseq)

    % Weak induction over all finite sequences
    finite_sequence_induction: THEOREM
      FORALL sp:
        sp(empty_cseq) AND
         (FORALL n:
            (FORALL fseq: length(fseq) = n IMPLIES sp(fseq)) IMPLIES
             (FORALL fseq: length(fseq) = n + 1 IMPLIES sp(fseq)))
         IMPLIES (FORALL fseq: sp(fseq))

    % Strong induction over all finite sequences
    FINITE_SEQUENCE_induction: THEOREM
      FORALL sp:
        (FORALL n:
           (FORALL fseq: length(fseq) < n IMPLIES sp(fseq)) IMPLIES
            (FORALL fseq: length(fseq) = n IMPLIES sp(fseq)))
         IMPLIES (FORALL fseq: sp(fseq))

    % Weak induction over all sequences.  This is only useful when the property
    % in question is trivially satisfied by all infinite sequences.
    sequence_induction: THEOREM
      FORALL sp:
        sp(empty_cseq) AND
         (FORALL iseq: sp(iseq)) AND
          (FORALL n:
             (FORALL fseq: length(fseq) = n IMPLIES sp(fseq)) IMPLIES
              (FORALL fseq: length(fseq) = n + 1 IMPLIES sp(fseq)))
         IMPLIES (FORALL cseq: sp(cseq))

    % Strong induction over all sequences.
    SEQUENCE_induction: THEOREM
      FORALL sp:
        (FORALL iseq: sp(iseq)) AND
         (FORALL n:
            (FORALL fseq: length(fseq) < n IMPLIES sp(fseq)) IMPLIES
             (FORALL fseq: length(fseq) = n IMPLIES sp(fseq)))
         IMPLIES (FORALL cseq: sp(cseq))

   END csequence_induction

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

  % Subtype TCC generated (at line 43, column 18) for  0
      % expected type  indexes[T](iseq)
  cseq_infinite_induction_TCC1: OBLIGATION FORALL (iseq): index?[T](iseq)(0);

  % Subtype TCC generated (at line 44, column 30) for  n
      % expected type  indexes[T](iseq)
  cseq_infinite_induction_TCC2: OBLIGATION
    FORALL (iseq, p):
      p(nth(iseq, 0)) IMPLIES (FORALL (n): index?[T](iseq)(n));

  % Subtype TCC generated (at line 44, column 54) for  n + 1
      % expected type  indexes[T](iseq)
  cseq_infinite_induction_TCC3: OBLIGATION
    FORALL (iseq, p):
      p(nth(iseq, 0)) IMPLIES
       (FORALL (n): p(nth(iseq, n)) IMPLIES index?[T](iseq)(n + 1));

  % Subtype TCC generated (at line 59, column 46) for  m
      % expected type  indexes[T](iseq)
  CSEQ_infinite_induction_TCC1: OBLIGATION
    FORALL (iseq, n, m): m < n IMPLIES index?[T](iseq)(m);

  % Subtype TCC generated (at line 60, column 22) for  n
      % expected type  indexes[T](iseq)
  CSEQ_infinite_induction_TCC2: OBLIGATION
    FORALL (iseq, p, n):
      (FORALL m: m < n IMPLIES p(nth(iseq, m))) IMPLIES index?[T](iseq)(n);


body:
  %-----------------------------------------------------------------------------
  % Functions that generate sequences until a limit condition is met.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_generate_limit[T: TYPE]: THEORY
   BEGIN

    IMPORTING function_iterate[T], csequence_nth[T]
    IMPORTING csequence_codt_coreduce[T, [[T -> T], T, pred[T]]]

    t, u: VAR T
    p: VAR pred[T]
    f: VAR [T -> T]
    n: VAR nat
    stop?: VAR pred[T]
    state: VAR [[T -> T], T, pred[T]]

    % The sequence generated from a generator function, a starting element, and
    % a predicate that determines when the next T should not appear in the
    % sequence.
    generate_limit_struct(state): csequence_struct =
        IF state`3(state`2) THEN inj_empty_cseq
        ELSE inj_add(state`2, (state`1, state`1(state`2), state`3))
        ENDIF

    generate(f, t, stop?): csequence =
        coreduce(generate_limit_struct)((f, t, stop?))

    generate_empty: THEOREM
      FORALL f, t, stop?: empty?(generate(f, t, stop?)) IFF stop?(t)

    generate_first: THEOREM
      FORALL f, t, stop?: stop?(t) OR first(generate(f, t, stop?)) = t

    generate_rest: THEOREM
      FORALL f, t, stop?:
        stop?(t) OR rest(generate(f, t, stop?)) = generate(f, f(t), stop?)

    % This lemma is helpful in proving the next theorem
    generate_has_length: LEMMA
      FORALL f, t, stop?, n:
        has_length(generate(f, t, stop?), n) IFF
         (stop?(iterate(f, n)(t)) AND
           (FORALL (m: below[n]): NOT stop?(iterate(f, m)(t))))

    generate_finite: THEOREM
      FORALL f, t, stop?:
        is_finite(generate(f, t, stop?)) IFF (EXISTS n: stop?(iterate(f, n)(t)))

    generate_nth: THEOREM
      FORALL f, t, stop?, (n: indexes(generate(f, t, stop?))):
        nth(generate(f, t, stop?), n) = iterate(f, n)(t)

    generate_add: THEOREM
      FORALL f, t, stop?, u:
        t = f(u) AND NOT stop?(u) IMPLIES
         add(u, generate(f, t, stop?)) = generate(f, u, stop?)

    generate_some: THEOREM
      FORALL f, t, stop?, p:
        some(p)(generate(f, t, stop?)) IFF
         (EXISTS (n: indexes(generate(f, t, stop?))): p(iterate(f, n)(t)))

    generate_every: THEOREM
      FORALL f, t, stop?, p:
        every(p)(generate(f, t, stop?)) IFF
         (FORALL (n: indexes(generate(f, t, stop?))): p(iterate(f, n)(t)))

   END csequence_generate_limit

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

  % Subtype TCC generated (at line 42, column 42) for  generate(f, t, stop?)
      % expected type  (nonempty?[T])
  generate_first_TCC1: OBLIGATION
    FORALL (f, t, stop?):
      NOT stop?(t) IMPLIES nonempty?[T](generate(f, t, stop?));


body:
  %-----------------------------------------------------------------------------
  % Functions that generate infinite sequences.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_generate[T: TYPE]: THEORY
   BEGIN

    IMPORTING function_iterate[T], csequence_nth[T]
    IMPORTING csequence_codt_coreduce[T, [[T -> T], T]]

    n: VAR nat
    t, u: VAR T
    p: VAR pred[T]
    f, g: VAR [T -> T]
    state: VAR [[T -> T], T]

    % The generator is given a starting T, and a function that generates the
    % next T from the previous one.
    generate_struct(state): csequence_struct =
        inj_add(state`2, (state`1, state`1(state`2)))

    generate(f, t): infinite_csequence = coreduce(generate_struct)((f, t))

    generate_first: THEOREM FORALL f, t: first(generate(f, t)) = t

    generate_rest: THEOREM
      FORALL f, t: rest(generate(f, t)) = generate(f, f(t))

    generate_nth: THEOREM
      FORALL f, t, n: nth(generate(f, t), n) = iterate(f, n)(t)

    generate_add: THEOREM
      FORALL f, t, u: t = f(u) IMPLIES add(u, generate(f, t)) = generate(f, u)

    generate_some: THEOREM
      FORALL f, t, p:
        some(p)(generate(f, t)) IFF (EXISTS n: p(iterate(f, n)(t)))

    generate_every: THEOREM
      FORALL f, t, p:
        every(p)(generate(f, t)) IFF (FORALL n: p(iterate(f, n)(t)))

   END csequence_generate

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

  % Subtype TCC generated (at line 31, column 39) for
      % coreduce(generate_struct)(f, t)
      % expected type  infinite_csequence[T]
  generate_TCC1: OBLIGATION
    FORALL (f: [T -> T], t: T):
      NOT is_finite[T](coreduce[T, [[T -> T], T]](generate_struct)(f, t));

  % Subtype TCC generated (at line 39, column 40) for  n
      % expected type  indexes[T](generate(f, t))
  generate_nth_TCC1: OBLIGATION
    FORALL (f, t, n): index?[T](generate(f, t))(n);


body:
  %-----------------------------------------------------------------------------
  % The first index in a sequence of countable length where a predicate p holds.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_first_p[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_nth[T]

    p: VAR pred[T]
    cseq: VAR csequence

    % The indexes of a sequence where the elements satisfy p
    p_indexes(cseq, p): set[indexes(cseq)] =
        {i: indexes(cseq) | p(nth(cseq, i))}

    p_indexes_nonempty: LEMMA
      FORALL cseq, p: some(p)(cseq) IFF nonempty?(p_indexes(cseq, p))

    % The first element of a sequence satisfying p
    first_p(p, (cseq: (csequence_codt[T].some(p)))): indexes(cseq) =
        min(p_indexes(cseq, p))

    first_p_nth: LEMMA
      FORALL cseq, p: some(p)(cseq) IMPLIES p(nth(cseq, first_p(p, cseq)))

    first_p_rest: LEMMA
      FORALL cseq, p:
        some(p)(cseq) IMPLIES
         first_p(p, cseq) =
          IF p(first(cseq)) THEN 0 ELSE first_p(p, rest(cseq)) + 1 ENDIF

   END csequence_first_p

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

  % Subtype TCC generated (at line 31, column 10) for  p_indexes(cseq, p)
      % expected type  S: (nonempty?[indexes[T](cseq)])
  first_p_TCC1: OBLIGATION
    FORALL (p: pred[T], (cseq: (csequence_codt[T].some(p)))):
      nonempty?[indexes[T](cseq)](p_indexes(cseq, p));

  % Subtype TCC generated (at line 40, column 19) for  cseq
      % expected type  (nonempty?[T])
  first_p_rest_TCC1: OBLIGATION
    FORALL (cseq, p): some(p)(cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 40, column 49) for  rest(cseq)
      % expected type  (csequence_codt[T].some(p))
  first_p_rest_TCC2: OBLIGATION
    FORALL (cseq, p):
      NOT p(first(cseq)) AND some(p)(cseq) IMPLIES
       csequence_codt[T].some(p)(rest[T](cseq));


body:
  %-----------------------------------------------------------------------------
  % Determine whether one sequence of countable length is a filter of another.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_filter_of[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_first_p[T], csequence_suffix[T]

    t: VAR T
    p, q: VAR pred[T]
    cseq, cseq1, cseq2, filt_seq, filt_seq1, filt_seq2: VAR csequence

    filter_of?(filt_seq, cseq, p): COINDUCTIVE bool =
        (empty?(filt_seq) AND NOT some(p)(cseq)) OR
         (nonempty?(filt_seq) AND
           some(p)(cseq) AND
            IF p(first(cseq))
              THEN first(filt_seq) = first(cseq) AND
                    filter_of?(rest(filt_seq), rest(cseq), p)
            ELSE filter_of?(filt_seq, rest(cseq), p)
            ENDIF)

    filter_of?_empty: THEOREM
      FORALL filt_seq, cseq, p:
        filter_of?(filt_seq, cseq, p) IMPLIES
         (empty?(filt_seq) IFF NOT some(p)(cseq))

    filter_of?_nonempty: THEOREM
      FORALL filt_seq, cseq, p:
        filter_of?(filt_seq, cseq, p) IMPLIES
         (nonempty?(filt_seq) IFF some(p)(cseq))

    filter_of?_finite: THEOREM
      FORALL filt_seq, cseq, p:
        filter_of?(filt_seq, cseq, p) AND is_finite(cseq) IMPLIES
         is_finite(filt_seq)

    filter_of?_def: THEOREM
      FORALL filt_seq, cseq, p:
        filter_of?(filt_seq, cseq, p) IMPLIES every(p)(filt_seq)

    filter_of?_first_p: THEOREM
      FORALL filt_seq, cseq, p:
        some(p)(cseq) AND filter_of?(filt_seq, cseq, p) IMPLIES
         nth(cseq, first_p(p, cseq)) = first(filt_seq)

    filter_of?_suffix: THEOREM
      FORALL filt_seq, cseq, p:
        some(p)(cseq) AND filter_of?(filt_seq, cseq, p) IMPLIES
         filter_of?(rest(filt_seq), suffix(cseq, 1 + first_p(p, cseq)), p)

    filter_of?_injective: THEOREM
      FORALL filt_seq1, filt_seq2, cseq, p:
        filter_of?(filt_seq1, cseq, p) AND filter_of?(filt_seq2, cseq, p)
         IMPLIES filt_seq1 = filt_seq2

    filter_of?_concatenate: THEOREM
      FORALL filt_seq1, filt_seq2, cseq1, cseq2, p:
        is_finite(cseq1) AND
         filter_of?(filt_seq1, cseq1, p) AND filter_of?(filt_seq2, cseq2, p)
         IMPLIES filter_of?(filt_seq1 o filt_seq2, cseq1 o cseq2, p)

    filter_of?_implication: THEOREM
      FORALL filt_seq, cseq, p, q:
        (FORALL t: pred_IMPLIES(p, q)(t)) AND
         some(p)(cseq) AND filter_of?(filt_seq, cseq, q)
         IMPLIES some(p)(filt_seq)

    filter_of?_implication_rev: THEOREM
      FORALL filt_seq, cseq, p, q:
        filter_of?(filt_seq, cseq, p) AND some(q)(filt_seq) IMPLIES
         some(q)(cseq)

    filter_of?_some: THEOREM
      FORALL filt_seq1, filt_seq2, cseq, p, q:
        filter_of?(filt_seq1, cseq, p) AND
         filter_of?(filt_seq2, filt_seq1, q)
         IMPLIES
         (some(p)(cseq) AND some(q)(filt_seq1) IFF some(pred_AND(p, q))(cseq))

    filter_of?_filter_of?: THEOREM
      FORALL filt_seq1, filt_seq2, cseq, p, q:
        filter_of?(filt_seq1, cseq, p) AND
         filter_of?(filt_seq2, filt_seq1, q)
         IMPLIES filter_of?(filt_seq2, cseq, pred_AND(p, q))

   END csequence_filter_of

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

  filter_of?_weak_coinduction: AXIOM
    FORALL (p, P: [[csequence[T], csequence[T]] -> boolean]):
      (FORALL (filt_seq, cseq):
         P(filt_seq, cseq) IMPLIES
          (empty?(filt_seq) AND NOT some(p)(cseq)) OR
           (nonempty?(filt_seq) AND
             some(p)(cseq) AND
              IF p(first(cseq))
                THEN first(filt_seq) = first(cseq) AND
                      P(rest(filt_seq), rest(cseq))
              ELSE P(filt_seq, rest(cseq))
              ENDIF))
       IMPLIES
       (FORALL (filt_seq, cseq):
          P(filt_seq, cseq) IMPLIES filter_of?(filt_seq, cseq, p));

  filter_of?_coinduction: AXIOM
    FORALL (p, P: [[csequence[T], csequence[T]] -> boolean]):
      (FORALL (filt_seq, cseq):
         P(filt_seq, cseq) IMPLIES
          (empty?(filt_seq) AND NOT some(p)(cseq)) OR
           (nonempty?(filt_seq) AND
             some(p)(cseq) AND
              IF p(first(cseq))
                THEN first(filt_seq) = first(cseq) AND
                      (filter_of?(rest(filt_seq), rest(cseq), p) OR
                        P(rest(filt_seq), rest(cseq)))
              ELSE filter_of?(filt_seq, rest(cseq), p) OR
                    P(filt_seq, rest(cseq))
              ENDIF))
       IMPLIES
       (FORALL (filt_seq, cseq):
          P(filt_seq, cseq) IMPLIES filter_of?(filt_seq, cseq, p));

  % Subtype TCC generated (at line 27, column 21) for  cseq
      % expected type  (nonempty?[T])
  filter_of?_TCC1: OBLIGATION
    FORALL (filt_seq: csequence[T], cseq: csequence[T], p: pred[T]):
      some(p)(cseq) AND
       nonempty?(filt_seq) AND NOT (empty?(filt_seq) AND NOT some(p)(cseq))
       IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 55, column 43) for  filt_seq
      % expected type  (nonempty?[T])
  filter_of?_first_p_TCC1: OBLIGATION
    FORALL (filt_seq, cseq, p):
      some(p)(cseq) AND filter_of?(filt_seq, cseq, p) IMPLIES
       nonempty?[T](filt_seq);


body:
  %-----------------------------------------------------------------------------
  % Filters on countable sequences.  A filter is a predicate that decides
  % whether a given sequence element should be retained or discarded.  Applying
  % a filter to a sequence produces a new sequence containing only those
  % elements satisfying the predicate, in the same order as in the original
  % sequence.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Versoin history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_filter[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_filter_of[T], csequence_subsequence[T]
    IMPORTING csequence_codt_coreduce[T, [csequence, pred[T]]]

    t: VAR T
    p, q: VAR pred[T]
    cseq, cseq1, cseq2, filt_seq: VAR csequence
    eseq: VAR empty_csequence
    nseq: VAR nonempty_csequence
    fseq: VAR finite_csequence
    state: VAR [csequence, pred[T]]

    % The sequence consisting of elements satisfying p
    filter_struct(state): csequence_struct[T, [csequence, pred[T]]] =
        IF some(state`2)(state`1)
          THEN LET n = first_p(state`2, state`1) IN
                 inj_add[T, [csequence, pred[T]]]
                     (nth(state`1, n), (suffix(state`1, n + 1), state`2))
        ELSE inj_empty_cseq[T, [csequence, pred[T]]]
        ENDIF

    filter(cseq, p): (subsequence?(cseq)) = coreduce(filter_struct)((cseq, p))

    filter_empty: THEOREM FORALL eseq, p: empty?(filter(eseq, p))

    filter_nonempty: THEOREM
      FORALL cseq, p: some(p)(cseq) IFF nonempty?(filter(cseq, p))

    filter_def: THEOREM FORALL cseq, p: every(p)(filter(cseq, p))

    filter_finite: JUDGEMENT filter(fseq, p) HAS_TYPE finite_csequence

    filter_length: THEOREM
      FORALL fseq, p: length(filter(fseq, p)) <= length(fseq)

    filter_length_eq: THEOREM
      FORALL fseq, p:
        length(filter(fseq, p)) = length(fseq) IMPLIES filter(fseq, p) = fseq

    filter_reduce: THEOREM
      FORALL cseq, p:
        empty?(cseq) OR
         p(first(cseq)) OR filter(cseq, p) = filter(rest(cseq), p)

    filter_add: THEOREM
      FORALL cseq, p, t:
        filter(add(t, cseq), p) =
         IF p(t) THEN add(t, filter(cseq, p)) ELSE filter(cseq, p) ENDIF

    filter_rest: THEOREM
      FORALL nseq, p:
        filter(rest(nseq), p) =
         IF p(first(nseq)) THEN rest(filter(nseq, p))
         ELSE filter(nseq, p)
         ENDIF

    filter_suffix: THEOREM
      FORALL cseq, p:
        empty?(filter(cseq, p)) OR
         rest(filter(cseq, p)) = filter(suffix(cseq, first_p(p, cseq) + 1), p)

    filter_first: THEOREM
      FORALL cseq, p:
        some(p)(cseq) IMPLIES
         first(filter(cseq, p)) = nth(cseq, first_p(p, cseq))

    filter_first_first: COROLLARY
      FORALL cseq, p:
        some(p)(cseq) AND p(first(cseq)) IMPLIES
         first(filter(cseq, p)) = first(cseq)

    filter_full: THEOREM
      FORALL cseq, p: every(p)(cseq) IFF filter(cseq, p) = cseq

    filter_idem: THEOREM
      FORALL cseq, p: filter(filter(cseq, p), p) = filter(cseq, p)

    filter_some: THEOREM
      FORALL cseq, p, q:
        some(q)(filter(cseq, p)) IFF some(pred_AND(p, q))(cseq)

    filter_every: THEOREM
      FORALL cseq, p, q:
        every(q)(filter(cseq, p)) IFF every(pred_IMPLIES(p, q))(cseq)

    % The induction rules support reasoning based on first() and rest(), but
    % filter expands to a form containing suffix() and min().  This theorem
    % bridges the gap.
    filter_filter_of: THEOREM
      FORALL cseq, filt_seq, p:
        filter(cseq, p) = filt_seq IFF filter_of?(filt_seq, cseq, p)

    filter_concatenate: THEOREM
      FORALL cseq1, cseq2, p:
        filter(cseq1 o cseq2, p) =
         IF is_finite(cseq1) THEN filter(cseq1, p) o filter(cseq2, p)
         ELSE filter(cseq1, p)
         ENDIF

    filter_filter: THEOREM
      FORALL cseq, p, q:
        filter(filter(cseq, p), q) = filter(cseq, pred_AND(p, q))

   END csequence_filter

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

  % Subtype TCC generated (at line 41, column 42) for
      % coreduce(filter_struct)(cseq, p)
      % expected type  (LAMBDA (cseq1: csequence[T]):
                     %    subsequence?(cseq1, cseq))
  filter_TCC1: OBLIGATION
    FORALL (cseq: csequence[T], p: pred[T]):
      subsequence?[T]
          (coreduce[T, [csequence, pred[T]]](filter_struct)(cseq, p), cseq);

  % Judgement subtype TCC generated (at line 50, column 27) for
      % filter(fseq, p)
      % expected type  finite_csequence[T]
  filter_finite: OBLIGATION FORALL (fseq, p): is_finite[T](filter(fseq, p));

  % Subtype TCC generated (at line 62, column 15) for  cseq
      % expected type  (nonempty?[T])
  filter_reduce_TCC1: OBLIGATION
    FORALL (cseq): NOT empty?(cseq) IMPLIES nonempty?[T](cseq);

  % Subtype TCC generated (at line 72, column 35) for  filter(nseq, p)
      % expected type  (nonempty?[T])
  filter_rest_TCC1: OBLIGATION
    FORALL (nseq, p): p(first(nseq)) IMPLIES nonempty?[T](filter(nseq, p));

  % Subtype TCC generated (at line 79, column 12) for  filter(cseq, p)
      % expected type  (nonempty?[T])
  filter_suffix_TCC1: OBLIGATION
    FORALL (cseq, p):
      NOT empty?(filter(cseq, p)) IMPLIES nonempty?[T](filter(cseq, p));

  % Subtype TCC generated (at line 79, column 62) for  cseq
      % expected type  (csequence_codt[T].some(p))
  filter_suffix_TCC2: OBLIGATION
    FORALL (cseq, p):
      NOT empty?(filter(cseq, p)) IMPLIES csequence_codt[T].some(p)(cseq);

  % Subtype TCC generated (at line 84, column 13) for  filter(cseq, p)
      % expected type  (nonempty?[T])
  filter_first_TCC1: OBLIGATION
    FORALL (cseq, p): some(p)(cseq) IMPLIES nonempty?[T](filter(cseq, p));

  % Subtype TCC generated (at line 88, column 32) for  cseq
      % expected type  (nonempty?[T])
  filter_first_first_TCC1: OBLIGATION
    FORALL (cseq, p): some(p)(cseq) IMPLIES nonempty?[T](cseq);


body:
  %-----------------------------------------------------------------------------
  % Flatten, an operator that takes a sequence of sequences, and concatenates
  % the elements to form a single sequence of countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_flatten[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_prefix_suffix[T], csequence_filter[csequence[T]]

    nonempty_seq_seq: TYPE = {x: csequence[csequence[T]] | every(nonempty?)(x)}

    p: VAR pred[T]
    n: VAR nat
    tseq: VAR csequence[T]
    cseq: VAR csequence[csequence[T]]
    eseq: VAR empty_csequence[csequence[T]]
    nseq: VAR nonempty_seq_seq

    % A result we need several times in the ensuing proofs
    some_every_empty: LEMMA
      FORALL cseq: every(empty?)(cseq) IFF NOT some(nonempty?)(cseq)

    flatten_struct(nseq): csequence_struct[T, nonempty_seq_seq] =
        IF empty?(nseq) THEN inj_empty_cseq[T, nonempty_seq_seq]
        ELSE inj_add[T, nonempty_seq_seq]
                 (first(first(nseq)),
                  IF empty?(rest(first(nseq))) THEN rest(nseq)
                  ELSE add(rest(first(nseq)), rest(nseq))
                  ENDIF)
        ENDIF

    flatten(cseq): csequence[T] =
        coreduce(flatten_struct)(filter(cseq, nonempty?))

    flatten_empty: THEOREM
      FORALL cseq: empty?(flatten(cseq)) IFF every(empty?)(cseq)

    flatten_empty_cseq: COROLLARY FORALL eseq: empty?(flatten(eseq))

    flatten_nonempty: THEOREM
      FORALL cseq: nonempty?(flatten(cseq)) IFF some(nonempty?)(cseq)

    flatten_filter: THEOREM
      FORALL cseq: flatten(filter(cseq, nonempty?)) = flatten(cseq)

    flatten_reduce: THEOREM
      FORALL cseq:
        empty?(cseq) OR
         nonempty?(first(cseq)) OR flatten(cseq) = flatten(rest(cseq))

    flatten_rest: THEOREM
      FORALL cseq:
        nonempty?(flatten(cseq)) IMPLIES
         rest(flatten(cseq)) =
          flatten(add(rest(first(filter(cseq, nonempty?))),
                      rest(filter(cseq, nonempty?))))

    flatten_rest2: THEOREM
      FORALL cseq:
        empty?(cseq) OR
         empty?(first(cseq)) OR
          rest(flatten(cseq)) = flatten(add(rest(first(cseq)), rest(cseq)))

    flatten_first: THEOREM
      FORALL cseq:
        nonempty?(flatten(cseq)) IMPLIES
         first(flatten(cseq)) = first(first(filter(cseq, nonempty?)))

    flatten_suffix: THEOREM
      FORALL cseq:
        some(nonempty?)(cseq) IMPLIES
         flatten(cseq) = flatten(suffix(cseq, first_p(nonempty?, cseq)))

    % I would really like to define flatten like this:
    %   flatten(cseq) = reduce(o)(cseq)
    % but this theorem is as close as I can come
    flatten_concatenate: THEOREM
      FORALL cseq:
        nonempty?(cseq) IMPLIES
         flatten(cseq) = first(cseq) o flatten(rest(cseq))

    flatten_rest_suffix: THEOREM
      FORALL cseq:
        nonempty?(flatten(cseq)) IMPLIES
         LET first = first_p(nonempty?, cseq) IN
           rest(flatten(cseq)) =
            flatten(add(rest(nth(cseq, first)), suffix(cseq, first + 1)))

    flatten_finite: THEOREM
      FORALL cseq:
        is_finite(flatten(cseq)) IFF
         is_finite(filter(cseq, nonempty?)) AND every(is_finite)(cseq)

    flatten_infinite: THEOREM
      FORALL cseq:
        is_infinite(flatten(cseq)) IFF
         is_infinite(filter(cseq, nonempty?)) OR some(is_infinite)(cseq)

    finite_flatten_csequence: TYPE = {cseq | is_finite(flatten(cseq))}
    fseq: VAR finite_flatten_csequence

    length_of_flatten(fseq): RECURSIVE nat =
      IF empty?(flatten(fseq)) THEN 0
      ELSE length(nth(fseq, first_p(nonempty?, fseq))) +
            length_of_flatten(suffix(fseq, first_p(nonempty?, fseq) + 1))
      ENDIF
       MEASURE length(filter(fseq, nonempty?))

    length_of_flatten_add: THEOREM
      FORALL fseq, tseq:
        is_finite(tseq) IMPLIES
         length_of_flatten(add(tseq, fseq)) =
          length(tseq) + length_of_flatten(fseq)

    flatten_length: THEOREM
      FORALL cseq:
        is_finite(flatten(cseq)) IMPLIES
         length(flatten(cseq)) = length_of_flatten(cseq)

    flatten_some: THEOREM
      FORALL cseq, p: some(p)(flatten(cseq)) IMPLIES some(some(p))(cseq)

    flatten_some_finite: THEOREM
      FORALL cseq, p:
        every(is_finite)(cseq) IMPLIES
         (some(p)(flatten(cseq)) IFF some(some(p))(cseq))

    flatten_every: THEOREM
      FORALL cseq, p: every(every(p))(cseq) IMPLIES every(p)(flatten(cseq))

    flatten_every_finite: THEOREM
      FORALL cseq, p:
        every(is_finite)(cseq) IMPLIES
         (every(p)(flatten(cseq)) IFF every(every(p))(cseq))

    % I believe the following two theorems are true.  Proving them, however,
    % is a different matter.  If you have a proof strategy to suggest, or a
    % nicer way of stating these theorems, please contact me.
    %
    %   flatten_some_converse: THEOREM
    %     FORALL cseq, p:
    %       (EXISTS (i: indexes(cseq)):
    %          some(p)(nth(cseq, i)) AND
    %           (FORALL (j: indexes(cseq)):
    %              j < i IMPLIES is_finite(nth(cseq, j))))
    %        IMPLIES some(p)(flatten(cseq))
    %
    %   flatten_every_converse: THEOREM
    %     FORALL cseq, p:
    %       every(p)(flatten(cseq)) IMPLIES
    %        (FORALL (i: indexes(cseq)):
    %           (FORALL (j: indexes(cseq)):
    %              j < i IMPLIES is_finite(nth(cseq, j)))
    %            IMPLIES every(p)(nth(cseq, i)))

   END csequence_flatten

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

  % Subtype TCC generated (at line 36, column 28) for  nseq
      % expected type  (nonempty?[csequence[T]])
  flatten_struct_TCC1: OBLIGATION
    FORALL (nseq: nonempty_seq_seq):
      NOT empty?(nseq) IMPLIES nonempty?[csequence[T]](nseq);

  % Subtype TCC generated (at line 36, column 22) for  first(nseq)
      % expected type  (nonempty?[T])
  flatten_struct_TCC2: OBLIGATION
    FORALL (nseq: nonempty_seq_seq):
      NOT empty?(nseq) IMPLIES nonempty?[T](first[csequence[T]](nseq));

  % Subtype TCC generated (at line 37, column 50) for  rest(nseq)
      % expected type  nonempty_seq_seq
  flatten_struct_TCC3: OBLIGATION
    FORALL (nseq: nonempty_seq_seq):
      empty?(rest(first(nseq))) AND NOT empty?(nseq) IMPLIES
       every[csequence[T]](nonempty?[T])(rest[csequence[T]](nseq));

  % Subtype TCC generated (at line 38, column 21) for
      % add(rest(first(nseq)), rest(nseq))
      % expected type  nonempty_seq_seq
  flatten_struct_TCC4: OBLIGATION
    FORALL (nseq: nonempty_seq_seq):
      NOT empty?(rest(first(nseq))) AND NOT empty?(nseq) IMPLIES
       every[csequence[T]]
           (nonempty?[T])
           (add[csequence[T]]
                (rest[T](first[csequence[T]](nseq)),
                 rest[csequence[T]](nseq)));

  % Subtype TCC generated (at line 43, column 31) for  filter(cseq, nonempty?)
      % expected type  x: nonempty_seq_seq
  flatten_TCC1: OBLIGATION
    FORALL (cseq: csequence[csequence[T]]):
      every[csequence[T]]
          (nonempty?[T])(filter[csequence[T]](cseq, nonempty?[T]));

  % Subtype TCC generated (at line 59, column 23) for  cseq
      % expected type  (nonempty?[csequence[T]])
  flatten_reduce_TCC1: OBLIGATION
    FORALL (cseq): NOT empty?(cseq) IMPLIES nonempty?[csequence[T]](cseq);

  % Subtype TCC generated (at line 65, column 31) for  filter(cseq, nonempty?)
      % expected type  (nonempty?[csequence[T]])
  flatten_rest_TCC1: OBLIGATION
    FORALL (cseq):
      nonempty?(flatten(cseq)) IMPLIES
       nonempty?[csequence[T]](filter[csequence[T]](cseq, nonempty?[T]));

  % Subtype TCC generated (at line 65, column 25) for
      % first(filter(cseq, nonempty?))
      % expected type  (nonempty?[T])
  flatten_rest_TCC2: OBLIGATION
    FORALL (cseq):
      nonempty?(flatten(cseq)) IMPLIES
       nonempty?[T]
           (first[csequence[T]](filter[csequence[T]](cseq, nonempty?[T])));

  % Subtype TCC generated (at line 72, column 13) for  flatten(cseq)
      % expected type  (nonempty?[T])
  flatten_rest2_TCC1: OBLIGATION
    FORALL (cseq):
      NOT empty?(first(cseq)) AND NOT empty?(cseq) IMPLIES
       nonempty?[T](flatten(cseq));

  % Subtype TCC generated (at line 72, column 47) for  first(cseq)
      % expected type  (nonempty?[T])
  flatten_rest2_TCC2: OBLIGATION
    FORALL (cseq):
      NOT empty?(first(cseq)) AND NOT empty?(cseq) IMPLIES
       nonempty?[T](first[csequence[T]](cseq));

  % Subtype TCC generated (at line 95, column 38) for  cseq
      % expected type  (csequence_codt[csequence[T]].some(nonempty?))
  flatten_rest_suffix_TCC1: OBLIGATION
    FORALL (cseq):
      nonempty?(flatten(cseq)) IMPLIES
       csequence_codt[csequence[T]].some(nonempty?[T])(cseq);

  % Subtype TCC generated (at line 97, column 27) for  nth(cseq, first)
      % expected type  (nonempty?[T])
  flatten_rest_suffix_TCC2: OBLIGATION
    FORALL (cseq):
      nonempty?(flatten(cseq)) IMPLIES
       (FORALL (first: indexes[csequence[T]](cseq)):
          first = first_p(nonempty?, cseq) IMPLIES
           nonempty?[T](nth[csequence[T]](cseq, first)));

  % Subtype TCC generated (at line 117, column 20) for
      % filter(fseq, nonempty?)
      % expected type  fseq: finite_csequence[csequence[T]]
  length_of_flatten_TCC1: OBLIGATION
    FORALL (fseq: finite_flatten_csequence):
      is_finite[csequence[T]](filter[csequence[T]](fseq, nonempty?[T]));

  % Subtype TCC generated (at line 114, column 45) for  fseq
      % expected type  (csequence_codt[csequence[T]].some(nonempty?))
  length_of_flatten_TCC2: OBLIGATION
    FORALL (fseq: finite_flatten_csequence):
      NOT empty?(flatten(fseq)) IMPLIES
       csequence_codt[csequence[T]].some(nonempty?[T])(fseq);

  % Subtype TCC generated (at line 114, column 16) for
      % nth(fseq, first_p(nonempty?, fseq))
      % expected type  fseq: finite_csequence[T]
  length_of_flatten_TCC3: OBLIGATION
    FORALL (fseq: finite_flatten_csequence):
      NOT empty?(flatten(fseq)) IMPLIES
       is_finite[T]
           (nth[csequence[T]]
                (fseq, first_p[csequence[T]](nonempty?[T], fseq)));

  % Subtype TCC generated (at line 115, column 28) for
      % suffix(fseq, first_p(nonempty?, fseq) + 1)
      % expected type  finite_flatten_csequence
  length_of_flatten_TCC4: OBLIGATION
    FORALL (fseq: finite_flatten_csequence):
      NOT empty?(flatten(fseq)) IMPLIES
       is_finite[T]
           (flatten(suffix[csequence[T]]
                        (fseq,
                         first_p[csequence[T]](nonempty?[T], fseq) + 1)));

  % Termination TCC generated (at line 115, column 10) for
      % length_of_flatten(suffix(fseq, first_p(nonempty?, fseq) + 1))
  length_of_flatten_TCC5: OBLIGATION
    FORALL (fseq: finite_flatten_csequence):
      NOT empty?(flatten(fseq)) IMPLIES
       length[csequence[T]]
           (filter[csequence[T]]
                (suffix[csequence[T]]
                     (fseq, first_p[csequence[T]](nonempty?[T], fseq) + 1),
                 nonempty?[T]))
        < length[csequence[T]](filter[csequence[T]](fseq, nonempty?[T]));

  % Subtype TCC generated (at line 122, column 25) for  add(tseq, fseq)
      % expected type  finite_flatten_csequence
  length_of_flatten_add_TCC1: OBLIGATION
    FORALL (fseq, tseq):
      is_finite(tseq) IMPLIES
       is_finite[T](flatten(add[csequence[T]](tseq, fseq)));


body:
  %-----------------------------------------------------------------------------
  % Conversions between sequences of countable length defined as coalgebraic
  % datatypes and the prelude finseq type.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_finseq[T: TYPE]: THEORY
   BEGIN

    IMPORTING finite_sequences[T], csequence_nth[T]

    n: VAR nat
    fs: VAR finseq
    fseq: VAR finite_csequence

    % Convert a finseq to a finite_csequence
    from_finseq(fs): RECURSIVE finite_csequence =
      IF fs`length = 0 THEN empty_cseq
      ELSE add(fs`seq(0),
               from_finseq((# length := fs`length - 1,
                              seq
                                := LAMBDA (x: below[fs`length - 1]):
                                     fs`seq(x + 1) #)))
      ENDIF
       MEASURE fs`length

    from_finseq_length: THEOREM FORALL fs: length(from_finseq(fs)) = fs`length

    from_finseq_index: THEOREM
      FORALL fs, n: index?(from_finseq(fs))(n) IFF n < fs`length

    from_finseq_nth: THEOREM
      FORALL fs, (n: below[fs`length]): nth(from_finseq(fs), n) = fs`seq(n)

    % Convert a finite_csequence to a finseq
    to_finseq(fseq): finseq =
        (# length := length(fseq),
           seq := LAMBDA (x: below[length(fseq)]): nth(fseq, x) #)

    to_finseq_length: THEOREM
      FORALL fseq: to_finseq(fseq)`length = length(fseq)

    to_finseq_index: THEOREM
      FORALL fseq, n: n < to_finseq(fseq)`length IFF index?(fseq)(n)

    to_finseq_nth: THEOREM
      FORALL fseq, (n: indexes(fseq)): to_finseq(fseq)`seq(n) = nth(fseq, n)

    % Applying both conversions gives you back what you started with

    to_from_finseq: THEOREM FORALL fs: to_finseq(from_finseq(fs)) = fs

    from_to_finseq: THEOREM FORALL fseq: from_finseq(to_finseq(fseq)) = fseq

   END csequence_finseq

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

  % Subtype TCC generated (at line 27, column 20) for  0
      % expected type  below[fs`length]
  from_finseq_TCC1: OBLIGATION
    FORALL (fs: finseq[T]): NOT fs`length = 0 IMPLIES 0 < fs`length;

  % Subtype TCC generated (at line 28, column 38) for  fs`length - 1
      % expected type  nat
  from_finseq_TCC2: OBLIGATION
    FORALL (fs: finseq[T]): NOT fs`length = 0 IMPLIES fs`length - 1 >= 0;

  % Subtype TCC generated (at line 31, column 42) for  x + 1
      % expected type  below[fs`length]
  from_finseq_TCC3: OBLIGATION
    FORALL (fs: finseq[T]):
      NOT fs`length = 0 IMPLIES
       (FORALL (x: below[fs`length - 1]): x + 1 < fs`length);

  % Termination TCC generated (at line 28, column 13) for
      % from_finseq((# length := fs`length - 1,
      %                seq
      %                  := LAMBDA (x: below[fs`length - 1]):
      %                       fs`seq(x + 1) #))
  from_finseq_TCC4: OBLIGATION
    FORALL (fs: finseq[T]):
      NOT fs`length = 0 IMPLIES fs`length - 1 < fs`length;

  % Subtype TCC generated (at line 27, column 9) for
      % add(fs`seq(0),
      %     from_finseq((# length := fs`length - 1,
      %                    seq
      %                      := LAMBDA (x: below[fs`length - 1]):
      %                           fs`seq(x + 1) #)))
      % expected type  finite_csequence[T]
  from_finseq_TCC5: OBLIGATION
    FORALL (fs: finseq[T],
            v:
              [{z: finseq[T] | z`length < fs`length} ->
                 finite_csequence[T]]):
      NOT fs`length = 0 IMPLIES
       is_finite[T]
           (add[T]
                (fs`seq(0),
                 v((# length := fs`length - 1,
                      seq
                        := LAMBDA (x: below[fs`length - 1]):
                             fs`seq(x + 1) #))));

  % Subtype TCC generated (at line 41, column 59) for  n
      % expected type  indexes[T](from_finseq(fs))
  from_finseq_nth_TCC1: OBLIGATION
    FORALL (fs, n: below[fs`length]): index?[T](from_finseq(fs))(n);

  % Subtype TCC generated (at line 46, column 59) for  x
      % expected type  indexes[T](fseq)
  to_finseq_TCC1: OBLIGATION
    FORALL (fseq: finite_csequence[T], x: below[length[T](fseq)]):
      index?[T](fseq)(x);

  % Subtype TCC generated (at line 55, column 57) for  n
      % expected type  below[to_finseq(fseq)`length]
  to_finseq_nth_TCC1: OBLIGATION
    FORALL (fseq, n: indexes[T](fseq)): n < to_finseq(fseq)`length;


body:
  %-----------------------------------------------------------------------------
  % The conjunction of filters with mapping functions on sequences of countable
  % length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_filter_map[T1, T2: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_map_props[T1, T2]
    IMPORTING csequence_filter[T1], csequence_filter[T2]

    n: VAR nat
    p: VAR pred[T2]
    f: VAR [T1 -> T2]
    cseq: VAR csequence[T1]

    map_first_p: THEOREM
      FORALL f, p, cseq:
        some(p)(map(f, cseq)) IMPLIES
         first_p(p, map(f, cseq)) = first_p(p o f, cseq)

    map_suffix_empty: THEOREM
      FORALL f, cseq, n:
        empty?(suffix(map(f, cseq), n)) IFF empty?(suffix(cseq, n))

    map_suffix: THEOREM
      FORALL f, cseq, n: suffix(map(f, cseq), n) = map(f, suffix(cseq, n))

    filter_map: THEOREM
      FORALL f, p, cseq: filter(map(f, cseq), p) = map(f, filter(cseq, p o f))

   END csequence_filter_map

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

  % Subtype TCC generated (at line 29, column 49) for  cseq
      % expected type  (csequence_codt[T1].some(p o f))
  map_first_p_TCC1: OBLIGATION
    FORALL (f, p, cseq):
      some(p)(map(f, cseq)) IMPLIES
       csequence_codt[T1].some(o[T1, T2, boolean](p, f))(cseq);


body:
  %-----------------------------------------------------------------------------
  % Constant sequences, both finite and infinite, defined as coalgebraic
  % datatypes.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_constant[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_singleton[T], csequence_codt_coreduce[T, T]

    t: VAR T
    p: VAR pred[T]
    n, m: VAR nat

    % The finite sequence consisting of n copies of a single element
    constant_cseq(t, n): RECURSIVE finite_csequence =
      IF n = 0 THEN empty_cseq ELSE add(t, constant_cseq(t, n - 1)) ENDIF
       MEASURE n

    constant_cseq_empty: THEOREM
      FORALL t, n: empty?(constant_cseq(t, n)) IFF n = 0

    constant_cseq_1: THEOREM FORALL t: constant_cseq(t, 1) = singleton_cseq(t)

    constant_cseq_first: THEOREM
      FORALL t, n: n > 0 IMPLIES first(constant_cseq(t, n)) = t

    constant_cseq_rest: THEOREM
      FORALL t, n:
        n > 0 IMPLIES rest(constant_cseq(t, n)) = constant_cseq(t, n - 1)

    constant_cseq_length: THEOREM FORALL t, n: length(constant_cseq(t, n)) = n

    constant_cseq_index: THEOREM
      FORALL t, n, m: index?(constant_cseq(t, n))(m) IFF m < n

    constant_cseq_nth: THEOREM
      FORALL t, n, (m: below[n]): nth(constant_cseq(t, n), m) = t

    constant_cseq_add: THEOREM
      FORALL t, n: add(t, constant_cseq(t, n)) = constant_cseq(t, n + 1)

    constant_cseq_last: THEOREM
      FORALL t, n: n > 0 IMPLIES last(constant_cseq(t, n)) = t

    constant_cseq_some: THEOREM
      FORALL t, n, p: some(p)(constant_cseq(t, n)) IFF n > 0 AND p(t)

    constant_cseq_every: THEOREM
      FORALL t, n, p: every(p)(constant_cseq(t, n)) IFF n = 0 OR p(t)


    % The infinite sequence consisting of a single element
    constant_cseq_struct(t): csequence_struct[T, T] = inj_add(t, t)

    constant_cseq(t): infinite_csequence = coreduce(constant_cseq_struct)(t)

    constant_cseq_inf_first: THEOREM FORALL t: first(constant_cseq(t)) = t

    constant_cseq_inf_rest: THEOREM
      FORALL t: rest(constant_cseq(t)) = constant_cseq(t)

    constant_cseq_inf_nth: THEOREM FORALL t, n: nth(constant_cseq(t), n) = t

    constant_cseq_inf_add: THEOREM
      FORALL t, n: add(t, constant_cseq(t)) = constant_cseq(t)

    constant_cseq_inf_some: THEOREM
      FORALL t, p: some(p)(constant_cseq(t)) IFF p(t)

    constant_cseq_inf_every: THEOREM
      FORALL t, p: every(p)(constant_cseq(t)) IFF p(t)

   END csequence_constant

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

  % Subtype TCC generated (at line 26, column 58) for  n - 1
      % expected type  nat
  constant_cseq_TCC1: OBLIGATION
    FORALL (t: T, n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Termination TCC generated (at line 26, column 41) for
      % constant_cseq(t, n - 1)
  constant_cseq_TCC2: OBLIGATION
    FORALL (t: T, n: nat): NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 26, column 34) for
      % add(t, constant_cseq(t, n - 1))
      % expected type  finite_csequence[T]
  constant_cseq_TCC3: OBLIGATION
    FORALL (t: T, n: nat,
            v: [{z: [T, nat] | z`2 < n} -> finite_csequence[T]]):
      NOT n = 0 IMPLIES is_finite[T](add[T](t, v(t, n - 1)));

  % Subtype TCC generated (at line 35, column 37) for  constant_cseq(t, n)
      % expected type  (nonempty?[T])
  constant_cseq_first_TCC1: OBLIGATION
    FORALL (t, n): n > 0 IMPLIES nonempty?[T](constant_cseq(t, n));

  % Subtype TCC generated (at line 39, column 65) for  n - 1
      % expected type  nat
  constant_cseq_rest_TCC1: OBLIGATION FORALL (t, n): n > 0 IMPLIES n - 1 >= 0;

  % Subtype TCC generated (at line 47, column 57) for  m
      % expected type  indexes[T](constant_cseq(t, n))
  constant_cseq_nth_TCC1: OBLIGATION
    FORALL (t, n, m: below[n]): index?[T](constant_cseq(t, n))(m);

  % Subtype TCC generated (at line 65, column 41) for
      % coreduce(constant_cseq_struct)(t)
      % expected type  infinite_csequence[T]
  constant_cseq_TCC4: OBLIGATION
    FORALL (t: T): NOT is_finite[T](coreduce[T, T](constant_cseq_struct)(t));

  % Subtype TCC generated (at line 72, column 68) for  n
      % expected type  indexes[T](constant_cseq(t))
  constant_cseq_inf_nth_TCC1: OBLIGATION
    FORALL (t, n): index?[T](constant_cseq(t))(n);


body:
  %-----------------------------------------------------------------------------
  % Eta rule for use with the concatenate and extract operators on sequences of
  % countable length.
  %
  % Author: Jerry James <loganjerry@gmail.com>
  %
  % This file and its accompanying proof file are distributed under the CC0 1.0
  % Universal license: http://creativecommons.org/publicdomain/zero/1.0/.
  %
  % Version history:
  %   2007 Feb 14: PVS 4.0 version
  %   2011 May  6: PVS 5.0 version
  %   2013 Jan 14: PVS 6.0 version
  %-----------------------------------------------------------------------------
  csequence_concatenate_extract[T: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_concatenate[T], csequence_extract[T]

    i, j, k: VAR nat
    fseq: VAR finite_csequence

    o_extract: THEOREM
      FORALL fseq, i, j, k:
        i <= j AND j <= k IMPLIES
         (fseq ^ (i, j)) o (fseq ^ (j + 1, k)) = fseq ^ (i, k)

    o_extract_eta: THEOREM
      FORALL fseq, i, j:
        i < j AND j >= length(fseq) - 1 IMPLIES
         (fseq ^ (0, i)) o (fseq ^ (i + 1, j)) = fseq

   END csequence_concatenate_extract


body:
  %%% ADT file generated from csequence

  csequence_codt[T: TYPE]: THEORY
   BEGIN

    csequence: TYPE

    empty?, nonempty?: [csequence -> boolean]

    first: [(nonempty?) -> T]

    rest: [(nonempty?) -> csequence]

    empty_cseq: (empty?)

    add: [[T, csequence] -> (nonempty?)]

    csequence_ord: [csequence -> upto(1)]

    csequence_ord_defaxiom: AXIOM
      csequence_ord(empty_cseq) = 0 AND
       (FORALL (first: T, rest: csequence):
          csequence_ord(add(first, rest)) = 1);

    ord(x: csequence): [csequence -> upto(1)] =
        CASES x OF empty_cseq: 0, add(add1_var, add2_var): 1 ENDCASES

    csequence_empty_cseq_extensionality: AXIOM
      FORALL (empty?_var: (empty?), empty?_var2: (empty?)):
        empty?_var = empty?_var2;

    csequence_add_extensionality: AXIOM
      FORALL (nonempty?_var: (nonempty?), nonempty?_var2: (nonempty?)):
        first(nonempty?_var) = first(nonempty?_var2) AND
         rest(nonempty?_var) = rest(nonempty?_var2)
         IMPLIES nonempty?_var = nonempty?_var2;

    csequence_add_eta: AXIOM
      FORALL (nonempty?_var: (nonempty?)):
        add(first(nonempty?_var), rest(nonempty?_var)) = nonempty?_var;

    csequence_first_add: AXIOM
      FORALL (add1_var: T, add2_var: csequence):
        first(add(add1_var, add2_var)) = add1_var;

    csequence_rest_add: AXIOM
      FORALL (add1_var: T, add2_var: csequence):
        rest(add(add1_var, add2_var)) = add2_var;

    csequence_inclusive: AXIOM
      FORALL (csequence_var: csequence):
        empty?(csequence_var) OR nonempty?(csequence_var);

    bisimulation?(R: PRED[[csequence, csequence]]):  boolean =
        FORALL (x: csequence, y: csequence):
          R(x, y) IMPLIES
           empty?(x) AND empty?(y) OR
            nonempty?(x) AND
             nonempty?(y) AND first(x) = first(y) AND R(rest(x), rest(y));

    coinduction: AXIOM
      FORALL (B: (bisimulation?), x: csequence, y: csequence):
        B(x, y) => x = y;

    every(p: PRED[T])(a: csequence):  COINDUCTIVE boolean =
          CASES a
            OF empty_cseq: TRUE,
               add(add1_var, add2_var): p(add1_var) AND every(p)(add2_var)
            ENDCASES;

    every_weak_coinduction: AXIOM
      FORALL (p: PRED[T], P: [csequence -> boolean]):
        (FORALL (a: csequence):
           P(a) IMPLIES
            CASES a
              OF empty_cseq: TRUE,
                 add(add1_var, add2_var): p(add1_var) AND P(add2_var)
              ENDCASES)
         IMPLIES (FORALL (a: csequence): P(a) IMPLIES every(p)(a));

    every_coinduction: AXIOM
      FORALL (p: PRED[T], P: [csequence -> boolean]):
        (FORALL (a: csequence):
           P(a) IMPLIES
            CASES a
              OF empty_cseq: TRUE,
                 add(add1_var, add2_var):
                   p(add1_var) AND (every(p)(add2_var) OR P(add2_var))
              ENDCASES)
         IMPLIES (FORALL (a: csequence): P(a) IMPLIES every(p)(a));

    some(p: PRED[T])(a: csequence):  INDUCTIVE boolean =
          CASES a
            OF empty_cseq: FALSE,
               add(add1_var, add2_var): p(add1_var) OR some(p)(add2_var)
            ENDCASES;

    some_weak_induction: AXIOM
      FORALL (p: PRED[T], P: [csequence -> boolean]):
        (FORALL (a: csequence):
           CASES a
             OF empty_cseq: FALSE,
                add(add1_var, add2_var): p(add1_var) OR P(add2_var)
             ENDCASES
            IMPLIES P(a))
         IMPLIES (FORALL (a: csequence): some(p)(a) IMPLIES P(a));

    some_induction: AXIOM
      FORALL (p: PRED[T], P: [csequence -> boolean]):
        (FORALL (a: csequence):
           CASES a
             OF empty_cseq: FALSE,
                add(add1_var, add2_var):
                  p(add1_var) OR some(p)(add2_var) AND P(add2_var)
             ENDCASES
            IMPLIES P(a))
         IMPLIES (FORALL (a: csequence): some(p)(a) IMPLIES P(a));
   END csequence_codt


body:
  csequence_codt_map[T: TYPE, T1: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_codt

    map(f: [T -> T1])(a: csequence[T]):  csequence[T1] =
        CASES a
          OF empty_cseq: empty_cseq,
             add(add1_var, add2_var): add(f(add1_var), map(f)(add2_var))
          ENDCASES;

    map(f: [T -> T1], a: csequence[T]):  csequence[T1] =
        CASES a
          OF empty_cseq: empty_cseq,
             add(add1_var, add2_var): add(f(add1_var), map(f, add2_var))
          ENDCASES;

    every(R: [[T, T1] -> boolean])(x: csequence[T], y: csequence[T1]):
          boolean =
        empty?(x) AND empty?(y) OR
         nonempty?(x) AND
          nonempty?(y) AND
           R(first(x), first(y)) AND every(R)(rest(x), rest(y));
   END csequence_codt_map


body:
  csequence_codt_coreduce[T: TYPE, domain: TYPE]: THEORY
   BEGIN

    IMPORTING csequence_codt[T]

    csequence_struct: DATATYPE
     BEGIN
      inj_empty_cseq: inj_empty?
      inj_add(inj_first: T, inj_rest: domain): inj_nonempty?
     END csequence_struct

    csequence_struct: TYPE

    inj_empty?, inj_nonempty?: [csequence_struct -> boolean]

    inj_first: [(inj_nonempty?) -> T]

    inj_rest: [(inj_nonempty?) -> domain]

    inj_empty_cseq: (inj_empty?)

    inj_add: [[T, domain] -> (inj_nonempty?)]

    csequence_struct_ord: [csequence_struct -> upto(1)]

    csequence_struct_ord_defaxiom: AXIOM
      csequence_struct_ord(inj_empty_cseq) = 0 AND
       (FORALL (inj_first: T, inj_rest: domain):
          csequence_struct_ord(inj_add(inj_first, inj_rest)) = 1);

    ord(x: csequence_struct): [csequence_struct -> upto(1)] =
        CASES x OF inj_empty_cseq: 0, inj_add(inj_add1_var, inj_add2_var): 1
          ENDCASES

    csequence_struct_inj_empty_cseq_extensionality: AXIOM
      FORALL (inj_empty?_var: (inj_empty?), inj_empty?_var2: (inj_empty?)):
        inj_empty?_var = inj_empty?_var2;

    csequence_struct_inj_add_extensionality: AXIOM
      FORALL (inj_nonempty?_var: (inj_nonempty?),
              inj_nonempty?_var2: (inj_nonempty?)):
        inj_first(inj_nonempty?_var) = inj_first(inj_nonempty?_var2) AND
         inj_rest(inj_nonempty?_var) = inj_rest(inj_nonempty?_var2)
         IMPLIES inj_nonempty?_var = inj_nonempty?_var2;

    csequence_struct_inj_add_eta: AXIOM
      FORALL (inj_nonempty?_var: (inj_nonempty?)):
        inj_add(inj_first(inj_nonempty?_var), inj_rest(inj_nonempty?_var)) =
         inj_nonempty?_var;

    csequence_struct_inj_first_inj_add: AXIOM
      FORALL (inj_add1_var: T, inj_add2_var: domain):
        inj_first(inj_add(inj_add1_var, inj_add2_var)) = inj_add1_var;

    csequence_struct_inj_rest_inj_add: AXIOM
      FORALL (inj_add1_var: T, inj_add2_var: domain):
        inj_rest(inj_add(inj_add1_var, inj_add2_var)) = inj_add2_var;

    csequence_struct_inclusive: AXIOM
      FORALL (csequence_struct_var: csequence_struct):
        inj_empty?(csequence_struct_var) OR
         inj_nonempty?(csequence_struct_var);

    csequence_struct_induction: AXIOM
      FORALL (p: [csequence_struct -> boolean]):
        (p(inj_empty_cseq) AND
          (FORALL (inj_add1_var: T, inj_add2_var: domain):
             p(inj_add(inj_add1_var, inj_add2_var))))
         IMPLIES
         (FORALL (csequence_struct_var: csequence_struct):
            p(csequence_struct_var));

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

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

    csequence_struct_well_founded: AXIOM
      strict_well_founded?[csequence_struct](<<);

    reduce_nat(inj_empty?_fun: nat,
               inj_nonempty?_fun: [[T, domain] -> nat]):
          [csequence_struct -> nat] =
        LAMBDA (csequence_struct_adtvar: csequence_struct):
          LET red: [csequence_struct -> nat] =
                reduce_nat(inj_empty?_fun, inj_nonempty?_fun)
            IN
            CASES csequence_struct_adtvar
              OF inj_empty_cseq: inj_empty?_fun,
                 inj_add(inj_add1_var, inj_add2_var):
                   inj_nonempty?_fun(inj_add1_var, inj_add2_var)
              ENDCASES;

    REDUCE_nat(inj_empty?_fun: [csequence_struct -> nat],
               inj_nonempty?_fun: [[T, domain, csequence_struct] -> nat]):
          [csequence_struct -> nat] =
        LAMBDA (csequence_struct_adtvar: csequence_struct):
          LET red: [csequence_struct -> nat] =
                REDUCE_nat(inj_empty?_fun, inj_nonempty?_fun)
            IN
            CASES csequence_struct_adtvar
              OF inj_empty_cseq: inj_empty?_fun(csequence_struct_adtvar),
                 inj_add(inj_add1_var, inj_add2_var):
                   inj_nonempty?_fun(inj_add1_var, inj_add2_var,
                                     csequence_struct_adtvar)
              ENDCASES;

    reduce_ordinal(inj_empty?_fun: ordinal,
                   inj_nonempty?_fun: [[T, domain] -> ordinal]):
          [csequence_struct -> ordinal] =
        LAMBDA (csequence_struct_adtvar: csequence_struct):
          LET red: [csequence_struct -> ordinal] =
                reduce_ordinal(inj_empty?_fun, inj_nonempty?_fun)
            IN
            CASES csequence_struct_adtvar
              OF inj_empty_cseq: inj_empty?_fun,
                 inj_add(inj_add1_var, inj_add2_var):
                   inj_nonempty?_fun(inj_add1_var, inj_add2_var)
              ENDCASES;

    REDUCE_ordinal(inj_empty?_fun: [csequence_struct -> ordinal],
                   inj_nonempty?_fun:
                     [[T, domain, csequence_struct] -> ordinal]):
          [csequence_struct -> ordinal] =
        LAMBDA (csequence_struct_adtvar: csequence_struct):
          LET red: [csequence_struct -> ordinal] =
                REDUCE_ordinal(inj_empty?_fun, inj_nonempty?_fun)
            IN
            CASES csequence_struct_adtvar
              OF inj_empty_cseq: inj_empty?_fun(csequence_struct_adtvar),
                 inj_add(inj_add1_var, inj_add2_var):
                   inj_nonempty?_fun(inj_add1_var, inj_add2_var,
                                     csequence_struct_adtvar)
              ENDCASES;

    coreduce(op: [domain -> csequence_struct])(x: domain):
          {c: csequence[T] |
                   inj_empty?(op(x)) AND empty?(c) OR
                    inj_nonempty?(op(x)) AND nonempty?(c)} =
        CASES op(x)
          OF inj_empty_cseq: empty_cseq,
             inj_add(inj_add1_var, inj_add2_var):
               add(inj_add1_var, coreduce(op)(inj_add2_var))
          ENDCASES;
   END csequence_codt_coreduce


body:
  top: THEORY
  %-------------------------------------------------------------------------------
  % Complex Numbers
  %
  %     Author: David Lester, Manchester University & NIA
  %
  %
  % The complex numbers are defined (axiomatically) in this way so that we can
  % conveniently use the numeric constants 0, 1, 2 etc.
  %
  % The alternative -- using pairs of reals to represent the real and imaginary
  % components -- would lead to the somewhat unappealing formulation of Euler's
  % result as "exp((0,1)*(pi,0)) = (-1,0)". As a matter of taste, I prefer the
  % somewhat more elegant formulation: "exp(i*pi) = -1".
  %
  % When theory interpretations can handle this, we'll be able to prove that the
  % two formulations are equivalent, and hence use the beautiful version, and
  % consigning the undignified version to the background!
  %
  % If we get really lucky, the number_fields_bis ("bis" from the Italian for
  % extra) can be consigned to the dustbin of history, and it's functions
  % incorporated into the general PVS decision procedures. In the mean time...
  %
  %
  %     Version 1.0            5/29/04   Initial version (DRL)
  %     Version 2.9            4/25/07
  %------------------------------------------------------------------------------
  BEGIN

    IMPORTING complex_types,       % Basic Definitions of Complex Number Types
              polar,               % Polar coordinate complex numbers
              arithmetic,          % Basic Arithmetic on Complex Numbers
              exp,                 % Complex logarithm and exponential functions
              complex_sqrt,        % sqrt of a complex number
              complex_field,       % complex numbers form a field
              complex_sets         % set-valued complex functions

  END top


body:
  % A couple of useful results to add to trig@trig_basic
  % DRL

  trig_aux: THEORY

  BEGIN

    IMPORTING trig@trig_basic

    a,b: VAR real
    i:   VAR int

    sin_cos_eq_0:    LEMMA NOT (sin(a) = 0 AND cos(a) = 0)

    eq_iff_periodic: LEMMA sin(a) = sin(b) AND cos(a) = cos(b) IFF
                           EXISTS i: a = b + 2*i*pi

  END trig_aux


body:
  %------------------------------------------------------------------------------
  % Properties of (non-real) number fields
  %
  %     Author: David Lester, Manchester University & NIA
  %
  %     Version 1.0            5/27/04   Initial version (DRL)
  %
  %             Narkawicz 12/2013
  %------------------------------------------------------------------------------

  number_fields_bis: THEORY

    BEGIN

    w, x, y, z:              VAR number_field
    n0x, n0y, n0z, nzx, nzy: VAR nznum

  % We have (from the prelude) the following properties of number_fields:
  %
  %  commutative_add : POSTULATE x + y = y + x
  %  associative_add : POSTULATE x + (y + z) = (x + y) + z
  %  identity_add    : POSTULATE x + 0 = x
  %  inverse_add     : AXIOM x + -x = 0
  %  minus_add       : AXIOM x - y = x + -y
  %  commutative_mult: AXIOM x * y = y * x
  %  associative_mult: AXIOM x * (y * z) =  (x * y) * z
  %  identity_mult   : AXIOM 1 * x = x
  %  inverse_mult    : AXIOM n0x * (1/n0x) = 1
  %  div_def         : AXIOM y/n0x = y * (1/n0x)
  %  distributive    : POSTULATE x * (y + z) = (x * y) + (x * z)

  % Because the built-in decision procedures only work for reals, we'll restate
  % some of the above in order to define AUTO-REWRITEs. Because we don't expect
  % users to have to type the names, we'll make the names long so as to avoid
  % overloading and potential conflicts.

    number_fields_left_identity_add      : LEMMA 0 + x = x
    number_fields_right_identity_add     : LEMMA x + 0 = x
    number_fields_left_identity_mult     : LEMMA 1 * x = x
    number_fields_right_identity_mult    : LEMMA x * 1 = x
    number_fields_negate_is_left_inverse : LEMMA -x + x = 0
    number_fields_negate_is_right_inverse: LEMMA x + -x = 0

  % However, the following are not available unless the field is a subtype
  % of real. So we have to add them, proving from the AXIOMs above.

    % Cancellation Laws for equality

    both_sides_plus1:  LEMMA (x + z = y + z) IFF x = y
    both_sides_plus2:  LEMMA (z + x = z + y) IFF x = y
    both_sides_minus1: LEMMA (x - z = y - z) IFF x = y
    both_sides_minus2: LEMMA (z - x = z - y) IFF x = y

    number_fields_negate_negate          : LEMMA -(-x) = x

    zero_times1: LEMMA 0 * x = 0
    zero_times2: LEMMA x * 0 = 0
    nznum_times_nznum_is_nznum: JUDGEMENT *(nzx, nzy) HAS_TYPE nznum
    minus_nznum_is_nznum:       JUDGEMENT -(nzx)      HAS_TYPE nznum
    zero_times3: LEMMA x * y = 0 IFF x = 0 OR y = 0
    neg_times_neg: LEMMA (-x) * (-y) = x * y
    zero_is_neg_zero: LEMMA -0 = 0

    both_sides_times1: LEMMA (x * n0z = y * n0z) IFF x = y
    both_sides_times2: LEMMA (n0z * x = n0z * y) IFF x = y

    inv_ne_0: LEMMA 1/n0x /= 0
    nznum_div_nznum_is_nznum:   JUDGEMENT /(nzx, nzy) HAS_TYPE nznum
    both_sides_div1: LEMMA (x/n0z = y/n0z) IFF x = y
    both_sides_div2: LEMMA (n0z/n0x = n0z/n0y) IFF n0x = n0y

    times_plus: LEMMA (x + y) * (z + w) = x*z + x*w + y*z + y*w
    times_div1: LEMMA x * (y/n0z) = (x * y)/n0z
    times_div2: LEMMA (x/n0z) * y = (x * y)/n0z
    div_eq_zero: LEMMA x/n0z = 0 IFF x = 0

    div_simp:    LEMMA n0x/n0x = 1
    div_cancel1: LEMMA n0z * (x/n0z) = x
    div_cancel2: LEMMA (x/n0z) * n0z = x
    div_cancel3: LEMMA x/n0z = y IFF x = y * n0z
    div_cancel4: LEMMA y = x/n0z IFF y * n0z = x

    cross_mult: LEMMA (x/n0x = y/n0y) IFF (x * n0y = y * n0x)
    div_times:  LEMMA (x/n0x) * (y/n0y) = (x*y)/(n0x*n0y)
    add_div:    LEMMA (x/n0x) + (y/n0y) = (x * n0y + y * n0x)/(n0x * n0y)
    minus_div1: LEMMA (x/n0x) - (y/n0y) = (x * n0y - y * n0x)/(n0x * n0y)
    minus_div2: LEMMA (x/n0x - y/n0x) = (x - y)/n0x
    div_distributes: LEMMA (x/n0z) + (y/n0z) =  (x + y)/n0z
    div_distributes_minus: LEMMA (x/n0z) - (y/n0z) =  (x - y)/n0z
    div_div1:   LEMMA (x / (n0y / n0z)) = ((x * n0z) / n0y)
    div_div2:   LEMMA ((x / n0y) / n0z) = (x / (n0y * n0z))
    idem_add_is_zero: LEMMA x + x = x IMPLIES x = 0

    nonzero_times1: LEMMA n0x * y = 0 IFF y = 0
    nonzero_times2: LEMMA x * n0y = 0 IFF x = 0
    nonzero_times3: LEMMA n0x * n0y = 0 IFF FALSE

    idem_mult: LEMMA x * x = x IFF x = 0 OR x = 1

    number_fields_negative_times         : LEMMA (-x) * y = -(x * y)
    number_fields_times_negative         : LEMMA x * (-y) = -(x * y)

    number_fields_neg1_times	       : LEMMA -1*x = -x

  %  AUTO_REWRITE+  number_fields_left_identity_add
  %  AUTO_REWRITE+  number_fields_right_identity_add
  %  AUTO_REWRITE+  number_fields_left_identity_mult
  %  AUTO_REWRITE+  number_fields_right_identity_mult
  %  AUTO_REWRITE+  number_fields_negate_is_left_inverse
  %  AUTO_REWRITE+  number_fields_negate_is_right_inverse
  %  AUTO_REWRITE+  number_fields_negate_negate

  %  AUTO_REWRITE+  number_fields_bis.zero_times1
  %  AUTO_REWRITE+  number_fields_bis.zero_times2
  %  AUTO_REWRITE+  number_fields_bis.zero_is_neg_zero

  %  AUTO_REWRITE+  number_fields_bis.neg_times_neg
  %  AUTO_REWRITE+  number_fields_bis.times_div1
  %  AUTO_REWRITE+  number_fields_bis.times_div2

    END number_fields_bis

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

  % Judgement subtype TCC generated (at line 58, column 40) for  nzx * nzy
      % expected type  nznum
  nznum_times_nznum_is_nznum: OBLIGATION FORALL (nzx, nzy): nzx * nzy /= 0;

  % Judgement subtype TCC generated (at line 59, column 40) for  -nzx
      % expected type  nznum
  minus_nznum_is_nznum: OBLIGATION FORALL (nzx): -nzx /= 0;

  % Judgement subtype TCC generated (at line 68, column 40) for  nzx / nzy
      % expected type  nznum
  nznum_div_nznum_is_nznum: OBLIGATION FORALL (nzx, nzy): nzx / nzy /= 0;


body:
  number_fields_sq: THEORY
  BEGIN

    IMPORTING number_fields_bis

    a,b : VAR numfield
    d,nz: VAR nznum

    sq(a): numfield = a*a

    sq_nz_pos         : JUDGEMENT sq(nz) HAS_TYPE nznum
    sq_rew            : LEMMA a*a = sq(a) 
    sq_neg            : LEMMA sq(-a) = sq(a)
    sq_times          : LEMMA sq(a*b) = sq(a) * sq(b)
    sq_plus           : LEMMA sq(a+b) = sq(a) + 2*a*b + sq(b)
    sq_minus          : LEMMA sq(a-b) = sq(a) - 2*a*b + sq(b)
    sq_neg_minus      : LEMMA sq(a-b) = sq(b-a)
    sq_0              : LEMMA sq(0) = 0
    sq_1              : LEMMA sq(1) = 1
    sq_eq_0           : LEMMA sq(a) = 0 IFF a = 0
    sq_div            : LEMMA sq(a/nz) = sq(a)/sq(nz)

    AUTO_REWRITE-     sq_neg_minus   

  END number_fields_sq

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

  % Judgement subtype TCC generated (at line 11, column 32) for  sq(nz)
      % expected type  nznum
  sq_nz_pos: OBLIGATION FORALL (nz): sq(nz) /= 0;


body:
  %------------------------------------------------------------------------------
  % Basic Definitions of Complex Number Types.
  %
  %     Author: David Lester, Manchester University & NIA
  %
  %
  % The complex numbers are defined (axiomatically) in this way so that we can
  % conveniently use the numeric constants 0, 1, 2 etc.
  %
  % The alternative -- using pairs of reals to represent the real and imaginary
  % components -- would lead to the somewhat unappealing formulation of Euler's
  % result as "exp((0,1)*(pi,0)) = (-1,0)". As a matter of taste, I prefer the
  % somewhat more elegant formulation: "exp(i*pi) = -1".
  %
  % When theory interpretations can handle this, we'll be able to prove that the
  % two formulations are equivalent, and hence use the beautiful version, and
  % consigning the undignified version to the background!
  %
  % If we get really lucky, the number_fields_bis ("bis" from the Italian for
  % extra) can be consigned to the dustbin of history, and it's functions
  % incorporated into the general PVS decision procedures. In the mean time...
  %
  %
  %     Version 1.0            5/29/04   Initial version (DRL)
  %------------------------------------------------------------------------------

  complex_types: THEORY

    BEGIN

    IMPORTING number_fields_bis

    complex: TYPE+ FROM number_field

    i : complex

    nf:                VAR numfield
    z,z1,z2:           VAR complex
    x,x0,x1,y,y0,y1,r: VAR real

    i_axiom:                  AXIOM i*i = -1
    complex_characterization: AXIOM complex_pred(nf) IFF EXISTS x,y: nf = x+y*i

    real_complex: LEMMA complex_pred(x)
    i_not_real:   LEMMA r /= i

    unique_characterization: LEMMA x0+y0*i = x1+y1*i IFF x0 = x1 AND y0 = y1

    real_is_complex: JUDGEMENT real SUBTYPE_OF complex

    Re(z): {x | EXISTS y: z = x + y*i}
    Im(z): {y | EXISTS x: z = x + y*i}

    Re_def            : LEMMA (EXISTS y: z = x+y*i) IFF Re(z) = x
    Im_def            : LEMMA (EXISTS x: z = x+y*i) IFF Im(z) = y
    Re_is_real        : JUDGEMENT Re(z) HAS_TYPE real
    Im_is_real        : JUDGEMENT Im(z) HAS_TYPE real

    nonzero_complex   : TYPE+ = {z: complex | z /= 0} CONTAINING 1
    nzcomplex         : TYPE+ = nonzero_complex
    nzcomplex_is_nznum: JUDGEMENT nonzero_complex SUBTYPE_OF nonzero_number

    nzx, nzy, n0z:  VAR nzcomplex

    closed_plus       : LEMMA complex_pred(z1 + z2)
    closed_neg        : LEMMA complex_pred(-z)
    closed_minus      : LEMMA complex_pred(z1 - z2)
    closed_times      : LEMMA complex_pred(z1 * z2)
    closed_divides    : LEMMA complex_pred(z / n0z)

    complex_plus_complex_is_complex       : JUDGEMENT +(z1,z2) HAS_TYPE complex
    complex_minus_complex_is_complex      : JUDGEMENT -(z1,z2) HAS_TYPE complex
    complex_times_complex_is_complex      : JUDGEMENT *(z1,z2) HAS_TYPE complex
    complex_div_nzcomplex_is_complex      : JUDGEMENT /(z,n0z) HAS_TYPE complex
    minus_complex_is_complex              : JUDGEMENT -(z)     HAS_TYPE complex

    nzcomplex_times_nzcomplex_is_nzcomplex:
                                          JUDGEMENT *(nzx,nzy) HAS_TYPE nzcomplex
    nzcomplex_div_nzcomplex_is_nzcomplex: JUDGEMENT /(nzx,nzy) HAS_TYPE nzcomplex
    minus_nzcomplex_is_nzcomplex:         JUDGEMENT -(nzx)     HAS_TYPE nzcomplex

    END complex_types

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

  complex_nonempty: AXIOM EXISTS (x: complex): TRUE;

  complex_pred: [number_field -> boolean]

  % Judgement subtype TCC generated (at line 49, column 29) for  x
      % expected type  complex
  real_is_complex: OBLIGATION FORALL (x: real): complex_pred(x);

  % Existence TCC generated (at line 51, column 2) for
      % Re(z): {x | EXISTS y: z = x + y * i}
  Re_TCC1: OBLIGATION
    EXISTS (x1: [z: complex -> {x | EXISTS y: z = x + y * i}]): TRUE;

  % Existence TCC generated (at line 52, column 2) for
      % Im(z): {y | EXISTS x: z = x + y * i}
  Im_TCC1: OBLIGATION
    EXISTS (x1: [z: complex -> {y | EXISTS x: z = x + y * i}]): TRUE;

  % Judgement subtype TCC generated (at line 71, column 52) for  z1 + z2
      % expected type  complex
  complex_plus_complex_is_complex: OBLIGATION
    FORALL (z1, z2): complex_pred(z1 + z2);

  % Judgement subtype TCC generated (at line 72, column 52) for  z1 - z2
      % expected type  complex
  complex_minus_complex_is_complex: OBLIGATION
    FORALL (z1, z2): complex_pred(z1 - z2);

  % Judgement subtype TCC generated (at line 73, column 52) for  z1 * z2
      % expected type  complex
  complex_times_complex_is_complex: OBLIGATION
    FORALL (z1, z2): complex_pred(z1 * z2);

  % Judgement subtype TCC generated (at line 74, column 52) for  z / n0z
      % expected type  complex
  complex_div_nzcomplex_is_complex: OBLIGATION
    FORALL (n0z, z): complex_pred(z / n0z);

  % Judgement subtype TCC generated (at line 75, column 52) for  -z
      % expected type  complex
  minus_complex_is_complex: OBLIGATION FORALL (z): complex_pred(-z);

  % Judgement subtype TCC generated (at line 78, column 50) for  nzx * nzy
      % expected type  nzcomplex
  nzcomplex_times_nzcomplex_is_nzcomplex: OBLIGATION
    FORALL (nzx, nzy): nzx * nzy /= 0;

  % Judgement subtype TCC generated (at line 79, column 50) for  nzx / nzy
      % expected type  nzcomplex
  nzcomplex_div_nzcomplex_is_nzcomplex: OBLIGATION
    FORALL (nzx, nzy): nzx / nzy /= 0;

  % Judgement subtype TCC generated (at line 80, column 50) for  -nzx
      % expected type  nzcomplex
  minus_nzcomplex_is_nzcomplex: OBLIGATION FORALL (nzx): -nzx /= 0;


body:
  %------------------------------------------------------------------------------
  % Basic Arithmetic (including conjugation) on Complex Numbers.
  %
  %     Author: David Lester, Manchester University & NIA
  %
  %     Version 1.0            5/29/04   Initial version (DRL)
  %
  %              Narkawicz     12/2013 +
  %------------------------------------------------------------------------------

  arithmetic: THEORY

    BEGIN

    IMPORTING complex_types

    z,z1,z2: VAR complex
    x      : VAR real
    n0z    : VAR nzcomplex

    complex_is_Re_Im      : LEMMA z  = Re(z) + Im(z)*i
    complex_is_0_Re_Im    : LEMMA z  = 0 IFF (Re(z)  = 0 AND Im(z)  = 0)
    complex_is_ne_0_Re_Im : LEMMA z /= 0 IFF (Re(z) /= 0 OR  Im(z) /= 0)
    complex_diff_eq_0     : LEMMA z1=z2 IFF z1-z2=0

    conjugate(z):complex = Re(z) - Im(z)*i

    sq_abs_def      : LEMMA z * conjugate(z) = Re(z)*Re(z) + Im(z)*Im(z)
    conjugate_nz    : LEMMA conjugate(n0z) /= 0

    sq_abs_realpred : LEMMA real_pred(z*conjugate(z))  %% RWB

    AUTO_REWRITE+ sq_abs_realpred  

    nz_sq_abs_pos   : LEMMA n0z*conjugate(n0z) > 0
    sq_abs_nonneg   : LEMMA z*conjugate(z) >= 0

    Re_real         : LEMMA Re(x)     = x
    Im_real         : LEMMA Im(x)     = 0
    Re_imag         : LEMMA Re(x*i)   = 0
    Im_imag         : LEMMA Im(x*i)   = x
    Re_neg          : LEMMA Re(-z)    = -Re(z)
    Im_neg          : LEMMA Im(-z)    = -Im(z)
    Re_plus         : LEMMA Re(z1+z2) = Re(z1)+Re(z2)
    Im_plus         : LEMMA Im(z1+z2) = Im(z1)+Im(z2)
    Re_minus	  : LEMMA Re(z1-z2) = Re(z1)-Re(z2)
    Im_minus	  : LEMMA Im(z1-z2) = Im(z1)-Im(z2)
    Re_times        : LEMMA Re(z1*z2) = Re(z1)*Re(z2) - Im(z1)*Im(z2)
    Im_times        : LEMMA Im(z1*z2) = Im(z1)*Re(z2) + Re(z1)*Im(z2)
    Re_div          : LEMMA Re(z/n0z) = (Re(z)*Re(n0z) + Im(z)*Im(n0z))/
                                        (n0z*conjugate(n0z))
    Im_div          : LEMMA Im(z/n0z) = (Im(z)*Re(n0z) - Re(z)*Im(n0z))/
                                        (n0z*conjugate(n0z))

    plus_conjugate  : LEMMA z + conjugate(z) = 2*Re(z)
    minus_conjugate : LEMMA z - conjugate(z) = 2*Im(z)*i
    conjugate_plus  : LEMMA conjugate(z1+z2) = conjugate(z1) + conjugate(z2)
    conjugate_neg   : LEMMA conjugate(-z)    = -conjugate(z)
    conjugate_minus : LEMMA conjugate(z1-z2) = conjugate(z1) - conjugate(z2)
    conjugate_times : LEMMA conjugate(z1*z2) = conjugate(z1) * conjugate(z2)
    conjugate_inv   : LEMMA conjugate(1/n0z) = 1/conjugate(n0z)
    conjugate_div   : LEMMA conjugate(x/n0z) = conjugate(x) / conjugate(n0z)


    END arithmetic

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

  % Subtype TCC generated (at line 35, column 26) for  n0z * conjugate(n0z)
      % expected type  real
  nz_sq_abs_pos_TCC1: OBLIGATION
    FORALL (n0z: nzcomplex): real_pred(n0z * conjugate(n0z));

  % Subtype TCC generated (at line 36, column 26) for  z * conjugate(z)
      % expected type  real
  sq_abs_nonneg_TCC1: OBLIGATION
    FORALL (z: complex): real_pred(z * conjugate(z));

  % Subtype TCC generated (at line 51, column 39) for  (n0z * conjugate(n0z))
      % expected type  nznum
  Re_div_TCC1: OBLIGATION
    FORALL (n0z: nzcomplex): (n0z * conjugate(n0z)) /= 0;

  % Subtype TCC generated (at line 61, column 47) for  conjugate(n0z)
      % expected type  nznum
  conjugate_inv_TCC1: OBLIGATION FORALL (n0z: nzcomplex): conjugate(n0z) /= 0;


body:
  %------------------------------------------------------------------------------
  % Polar coordinate complex numbers
  %
  %     Author: David Lester, Manchester University & NIA
  %
  %     Version 1.0            5/29/04   Initial version (DRL)
  %     Version 1.1            4/10/07   abs_i, arg_i added (DRL)
  %
  %     Narkawicz              12/2013 +   
  %------------------------------------------------------------------------------

  polar: THEORY

    BEGIN

    IMPORTING arithmetic, reals@sqrt, trig@atan2,
              trig@atan2_props,
              number_fields_sq 
   

    argrng: TYPE+ = {x:real | -pi < x & x <= pi} CONTAINING 0

    z,z1,z2:     VAR complex
    n0x,n0y,n0z: VAR nzcomplex
    nnx:         VAR nnreal
    nx:          VAR negreal
    r,x,y:       VAR real
    j:           VAR int
    theta:       VAR argrng

    nzreal_is_nzcomplex: JUDGEMENT nzreal SUBTYPE_OF nzcomplex

    abs(z):nnreal = sqrt(z*conjugate(z))

    abs_def:       LEMMA abs(z) = sqrt(sq.sq(Re(z))+sq.sq(Im(z)))
    abs_real_rew:  LEMMA abs(r) = real_defs.abs(r)
    abs_imag_rew:  LEMMA abs(r*i) = real_defs.abs(r)

    abs_nzcomplex: LEMMA abs(n0z) > 0
    abs_nz_iff_nz: LEMMA abs(z) > 0 IFF z /= 0
    abs_is_0:      LEMMA abs(z) = 0 IFF z  = 0

    abs_neg:       LEMMA abs(-z)      = abs(z)
    abs_mult:      LEMMA abs(z1*z2)   = abs(z1)*abs(z2)
    abs_inv:       LEMMA abs(1/n0z)   = 1/abs(n0z)
    abs_div:       LEMMA abs(z/n0z)   = abs(z)/abs(n0z)
    abs_triangle:  LEMMA abs(z1+z2)  <= abs(z1) + abs(z2)
    abs_triangle_minus: LEMMA abs(z1-z2)>=abs(z1)-abs(z2)
    abs_abs:       LEMMA abs(abs(z))  = abs(z)
    abs_i:         LEMMA abs(i)       = 1

  % Lemmata "abs_is_0", "abs_neg" and "abs_triangle" suffice to demonstrate
  % that the complex numbers form a (normed) metric space, with metric
  % "d(x,y) = abs(x-y)".

  % We define a complex number's principal argument value as "arg", note:
  % lower case "a" for a real number.
  %
  % Observe unpleasant formulation of properties to cope with multiples of 2*pi.

    arg(z):argrng = IF    z = 0     THEN 0
                    ELSIF Im(z) < 0 THEN atan2(Re(z),Im(z)) - 2*pi
                                    ELSE atan2(Re(z),Im(z))        ENDIF

    arg_is_0_nz: LEMMA arg(n0z) =  0    IFF (Re(n0z) >  0 AND Im(n0z) = 0)
    arg_is_0:    LEMMA arg(z)   =  0    IFF (Re(z)   >= 0 AND Im(z)   = 0)
    arg_is_pi2:  LEMMA arg(z)   =  pi/2 IFF (Re(z)   =  0 AND Im(z)   > 0)
    arg_is_pi:   LEMMA arg(z)   =  pi   IFF (Re(z)   <  0 AND Im(z)   = 0)
    arg_is_mpi2: LEMMA arg(z)   = -pi/2 IFF (Re(z)   =  0 AND Im(z)   < 0)

    arg_lt_0:    LEMMA arg(z) < 0 IFF Im(z) < 0
    arg_p_lt_pi: LEMMA (0 < arg(z) AND arg(z) < pi) IFF Im(z) > 0
    arg_gt_0:    LEMMA arg(z) > 0 IFF (Im(z) > 0 OR (Im(z) = 0 AND Re(z) < 0))

    arg_div_abs: LEMMA arg(n0x) = arg(n0x/abs(n0x))
    Re_cos_abs1: LEMMA abs(n0x) = 1 IMPLIES Re(n0x) = cos(arg(n0x))
    Im_sin_abs1: LEMMA abs(n0x) = 1 IMPLIES Im(n0x) = sin(arg(n0x))

    arg_nnreal: LEMMA arg(nnx) = 0
    arg_nreal:  LEMMA arg(nx)  = pi
    arg_i:      LEMMA arg(i)   = pi/2

    arg_neg:  LEMMA arg(-n0x)    = IF 0 < arg(n0x) THEN arg(n0x) - pi
                                                   ELSE arg(n0x) + pi ENDIF
    arg_mult: LEMMA arg(n0x*n0y) = LET r = arg(n0x)+arg(n0y) IN
                                   IF    r >   pi THEN r-2*pi
                                   ELSIF r <= -pi THEN r+2*pi
                                                  ELSE r      ENDIF
    arg_inv:  LEMMA arg(1/n0z)   = IF    arg(n0z) = 0  THEN 0
                                   ELSIF arg(n0z) = pi THEN pi
                                                       ELSE -arg(n0z) ENDIF
    arg_div:  LEMMA arg(n0x/n0y) = LET r = arg(n0x)-arg(n0y) IN
                                   IF    r >   pi THEN r-2*pi
                                   ELSIF r <= -pi THEN r+2*pi
                                                  ELSE r      ENDIF

    polar(z):[nnreal,argrng]      = (abs(z),arg(z))
    rectangular(z):[real,real]    = (Re(z),Im(z))
    from_polar(r,theta):complex   = r*cos(theta) + r*sin(theta)*i
    from_rectangular(x,y):complex = x + y*i

    arg_from_polar: LEMMA r>0 AND -pi < theta AND theta<=pi IMPLIES
      arg(from_polar(r,theta))=theta

    idempotent_rectangular: LEMMA z   = from_rectangular(rectangular(z))
    idempotent_polar      : LEMMA n0z = from_polar(polar(n0z))

    END polar

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

  % Subtype TCC generated (at line 21, column 58) for  0
      % expected type  argrng
  argrng_TCC1: OBLIGATION -pi < 0 & 0 <= pi;

  % Subtype TCC generated (at line 33, column 23) for  z * conjugate(z)
      % expected type  nnx: nonneg_real
  abs_TCC1: OBLIGATION
    FORALL (z: complex):
      real_pred(z * conjugate(z)) AND z * conjugate(z) >= 0;

  % Subtype TCC generated (at line 45, column 40) for  abs(n0z)
      % expected type  nznum
  abs_inv_TCC1: OBLIGATION FORALL (n0z: nzcomplex): abs(n0z) /= 0;

  % Subtype TCC generated (at line 62, column 51) for  Im(z)
      % expected type  {z_1: real | Re(z) = 0 => z_1 /= 0}
  arg_TCC1: OBLIGATION
    FORALL (z: complex):
      Im(z) < 0 AND NOT z = 0 IMPLIES Re(z) = 0 => Im(z) /= 0;

  % Subtype TCC generated (at line 62, column 39) for
      % atan2(Re(z), Im(z)) - 2 * pi
      % expected type  argrng
  arg_TCC2: OBLIGATION
    FORALL (z: complex):
      Im(z) < 0 AND NOT z = 0 IMPLIES
       -pi < atan2(Re(z), Im(z)) - 2 * pi &
        atan2(Re(z), Im(z)) - 2 * pi <= pi;

  % Subtype TCC generated (at line 63, column 51) for  Im(z)
      % expected type  {z_1: real | Re(z) = 0 => z_1 /= 0}
  arg_TCC3: OBLIGATION
    FORALL (z: complex):
      NOT Im(z) < 0 AND NOT z = 0 IMPLIES Re(z) = 0 => Im(z) /= 0;

  % Subtype TCC generated (at line 63, column 39) for  atan2(Re(z), Im(z))
      % expected type  argrng
  arg_TCC4: OBLIGATION
    FORALL (z: complex):
      NOT Im(z) < 0 AND NOT z = 0 IMPLIES
       -pi < atan2(Re(z), Im(z)) & atan2(Re(z), Im(z)) <= pi;


body:
  %------------------------------------------------------------------------------
  % Complex logarithm and exponential  functions
  %
  %     Author: David Lester, Manchester University & NIA
  %
  %     Version 1.0            5/29/04   Initial version (DRL)
  %------------------------------------------------------------------------------

  exp: THEORY

    BEGIN

    IMPORTING polar,
              trig@trig_ineq,
              trig_aux, 
              lnexp@ln_exp

    r:           VAR real
    x,y,z:       VAR complex
    n0x,n0y,n0z: VAR nzcomplex
    theta:       VAR argrng
    j:           VAR int

    exp(z): nzcomplex = exp(Re(z))*(cos(Im(z))+i*sin(Im(z)))

    exp_real        : LEMMA exp(r)            = ln_exp.exp(r)
    exp_imag        : LEMMA exp(r*i)          = cos(r) + i*sin(r)
    abs_exp_imag    : LEMMA abs(exp(r*i))     = 1
    arg_exp_real    : LEMMA arg(exp(r))       = 0
    arg_exp_imag    : LEMMA arg(exp(theta*i)) = theta
    exp_0           : LEMMA exp(0)            = 1
    exp_1           : LEMMA exp(1)            = e
    exp_i_pi        : LEMMA exp(i*pi)         = -1
    exp_plus        : LEMMA exp(x+y)          = exp(x)*exp(y) 
    exp_negate      : LEMMA exp(-x)           = 1/exp(x)
    exp_minus       : LEMMA exp(x-y)          = exp(x)/exp(y) 
    exp_periodicity : LEMMA exp(x+2*j*pi*i)   = exp(x)
    abs_exp         : LEMMA abs(exp(z))       = ln_exp.exp(Re(z))

    ln(n0z): complex = ln(abs(n0z)) + arg(n0z)*i

    ln_1            : LEMMA ln(1)        = 0
    ln_e            : LEMMA ln(e)        = 1
    ln_exp          : LEMMA (2*j-1)*pi < Im(z) AND Im(z) <= (2*j+1)*pi IMPLIES
                            ln(exp(z)) = z - 2*j*pi*i
    exp_ln          : LEMMA exp(ln(n0z)) = n0z
    ln_mult         : LEMMA ln(n0x*n0y)  = ln(n0x) + ln(n0y) -
                            LET r = arg(n0x)+arg(n0y) IN
                            IF    r >   pi THEN 2*pi*i
                            ELSIF r <= -pi THEN -2*pi*i
                                           ELSE 0 ENDIF
    ln_inv          : LEMMA ln(1/n0x)   = IF arg(n0x) = pi THEN 2*pi
                                          ELSE 0 ENDIF*i - ln(n0x)
    ln_div          : LEMMA ln(n0x/n0y)  = ln(n0x) - ln(n0y) -
                            LET r = arg(n0x)-arg(n0y) IN
                            IF    r >   pi THEN 2*pi*i
                            ELSIF r <= -pi THEN -2*pi*i
                                           ELSE 0 ENDIF

  END exp

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

  % Subtype TCC generated (at line 24, column 22) for
      % exp(Re(z)) * (cos(Im(z)) + i * sin(Im(z)))
      % expected type  nzcomplex
  exp_TCC1: OBLIGATION
    FORALL (z: complex): exp(Re(z)) * (cos(Im(z)) + i * sin(Im(z))) /= 0;

  % Subtype TCC generated (at line 40, column 24) for  abs(n0z)
      % expected type  posreal
  ln_TCC1: OBLIGATION FORALL (n0z: nzcomplex): abs(n0z) > 0;


body:
  %------------------------------------------------------------------------------
  % Set-valued complex functions
  %
  %     Author: David Lester, Manchester University & NIA
  %
  %     Version 1.0            4/12/07   Initial version (DRL)
  %------------------------------------------------------------------------------

  complex_sets: THEORY

  BEGIN

    IMPORTING exp

    z,z1,z2:     VAR complex
    n0x,n0y,n0z: VAR nzcomplex
    nnx:         VAR nnreal
    nx:          VAR negreal
    r,x,y:       VAR real
    j:           VAR int
    theta:       VAR argrng

  % Considerable notational and practical convenience can be obtained by using
  % instead "Arg" to represent the set of all possible argument values.

  % To bring elegance into this theory we define addition and unary and
  % binary minus.
  ;
    -: MACRO [nonempty_set[real]->nonempty_set[real]]
        = (LAMBDA (X:nonempty_set[real]): {x | X(-x)});
    +: MACRO [nonempty_set[real],nonempty_set[real]->nonempty_set[real]]
        = (LAMBDA (X,Y:nonempty_set[real]): {z:real | EXISTS (x:(X),y:(Y)): z = x+y});
    -: MACRO [nonempty_set[real],nonempty_set[real]->nonempty_set[real]]
        = (LAMBDA (X,Y:nonempty_set[real]): {z:real | EXISTS (x:(X),y:(Y)): z = x-y});

    Arg(n0z): nonempty_set[real] = {x:real | EXISTS j: x = arg(n0z) + 2*j*pi}

    Arg_def:  LEMMA Arg(n0z) = {x:real | abs(n0z)*exp(x*i) = n0z}
    Arg_mult: LEMMA Arg(n0x*n0y) =  Arg(n0x) + Arg(n0y)
    Arg_inv:  LEMMA Arg(1/n0z)   = -Arg(n0z)
    Arg_div:  LEMMA Arg(n0x/n0y) =  Arg(n0x) - Arg(n0y)

  END complex_sets

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

  % Subtype TCC generated (at line 30, column 40) for  {x | X(-x)}
      % expected type  nonempty_set[real]
  difference_TCC1: OBLIGATION
    FORALL (X: nonempty_set[real]): nonempty?[real]({x | X(-x)});

  % Subtype TCC generated (at line 32, column 42) for
      % {z: real | EXISTS (x: (X), y: (Y)): z = x + y}
      % expected type  nonempty_set[real]
  plus_TCC1: OBLIGATION
    FORALL (X, Y: nonempty_set[real]):
      nonempty?[real]({z: real | EXISTS (x: (X), y: (Y)): z = x + y});

  % Subtype TCC generated (at line 34, column 42) for
      % {z: real | EXISTS (x: (X), y: (Y)): z = x - y}
      % expected type  nonempty_set[real]
  difference_TCC2: OBLIGATION
    FORALL (X, Y: nonempty_set[real]):
      nonempty?[real]({z: real | EXISTS (x: (X), y: (Y)): z = x - y});

  % Subtype TCC generated (at line 36, column 33) for
      % {x: real | EXISTS j: x = arg(n0z) + 2 * j * pi}
      % expected type  nonempty_set[real]
  Arg_TCC1: OBLIGATION
    FORALL (n0z: nzcomplex):
      nonempty?[real]({x: real | EXISTS j: x = arg(n0z) + 2 * j * pi});


body:
  %------------------------------------------------------------------------------
  % Complex numbers form a field
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            4/11/07   Initial version (DRL)
  %------------------------------------------------------------------------------

  complex_field: THEORY

  BEGIN

    IMPORTING complex_types,
              algebra@field_def[complex,+,*,0,1]

    fullset_is_field: LEMMA field?(fullset[complex])

    IMPORTING algebra@field[complex,+,*,0,1]

  END complex_field

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

  % Assuming TCC generated (at line 18, column 12) for
      % algebra@field
      %     [complex,
      %      restrict[[numfield, numfield], [complex, complex], numfield](+),
      %      restrict[[numfield, numfield], [complex, complex], numfield](*),
      %      0, 1]
      % generated from assumption field.fullset_is_field
  IMP_field_TCC1: OBLIGATION
    field?
        [complex,
         restrict[[numfield, numfield], [complex, complex], numfield](+),
         restrict[[numfield, numfield], [complex, complex], numfield](*), 0,
         1]
        (fullset[complex]);


body:
  %------------------------------------------------------------------------------
  % Sqrare root properties of Complex Numbers.
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            4/11/07   Initial version (DRL)
  %------------------------------------------------------------------------------

  complex_sqrt: THEORY

  BEGIN
    IMPORTING polar, trig@trig_basic, number_fields_sq

    nnx:         VAR nnreal
    npx:         VAR npreal
    x,y,z:       VAR complex
    n0x,n0y,n0z: VAR nzcomplex

    sqrt(z):complex = from_polar(sqrt(abs(z)),arg(z)/2)

    sqrt_nz_is_nz       : JUDGEMENT sqrt(n0z) HAS_TYPE nzcomplex

    sqrt_nnz  : LEMMA sqrt(nnx) = sqrt.sqrt(nnx)
    sqrt_npz  : LEMMA sqrt(npx) = i*sqrt.sqrt(-npx)
    sqrt_0    : LEMMA sqrt(0)  = 0
    sqrt_1    : LEMMA sqrt(1)  = 1
    sqrt_neg1 : LEMMA sqrt(-1) = i
    sqrt_eq_0 : LEMMA sqrt(z) = 0 IFF z = 0

    sqrt_sq   : LEMMA sqrt(sq(z)) = IF -pi/2 < arg(z) AND arg(z) <= pi/2
                                    THEN z ELSE -z ENDIF
    sq_sqrt   : LEMMA sq(sqrt(z)) = z
    sqrt_times: LEMMA sqrt(x*y) = IF -pi < arg(x)+arg(y) AND arg(x)+arg(y) <= pi
                                  THEN sqrt(x)*sqrt(y)
                                  ELSE -sqrt(x)*sqrt(y) ENDIF
    sqrt_neg   : LEMMA sqrt(-z) =
                        IF arg(z) <= 0 THEN i*sqrt(z) ELSE -i*sqrt(z) ENDIF
    sqrt_inv   : LEMMA sqrt(1/n0z)
                      = IF arg(n0z) = pi THEN -1/sqrt(n0z) ELSE 1/sqrt(n0z) ENDIF
    sqrt_div   : LEMMA sqrt(x/n0y)
             = IF (arg(n0y) = pi & arg(x) > 0) OR
                   arg(n0y) = 0 OR
                  (-pi < arg(x)-arg(n0y) & arg(x)-arg(n0y) <= pi)
               THEN sqrt(x) / sqrt(n0y) ELSE -sqrt(x) / sqrt(n0y) ENDIF

  END complex_sqrt

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

  % Subtype TCC generated (at line 19, column 44) for  arg(z) / 2
      % expected type  argrng
  sqrt_TCC1: OBLIGATION
    FORALL (z: complex): -pi < arg(z) / 2 & arg(z) / 2 <= pi;

  % Judgement subtype TCC generated (at line 21, column 34) for  sqrt(n0z)
      % expected type  nzcomplex
  sqrt_nz_is_nz: OBLIGATION FORALL (n0z): sqrt(n0z) /= 0;

  % Subtype TCC generated (at line 24, column 44) for  -npx
      % expected type  nnx: nonneg_real
  sqrt_npz_TCC1: OBLIGATION FORALL (npx: npreal): -npx >= 0;

  % Subtype TCC generated (at line 30, column 25) for  sq(z)
      % expected type  complex
  sqrt_sq_TCC1: OBLIGATION FORALL (z: complex): complex_pred(sq(z));


body:
  %------------------------------------------------------------------------------
  % Complex Numbers (an alternative version)
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            14/06/09  Initial Version
  %     Version 1.1            16/03/11  Additional rewrites added (DRL)
  %
  % This alternative formulation of the complex numbers integrates with
  % the standard PVS decision procedures. The technique is to auto-rewrite
  % complex equalities, such as z1 = z2 as the pair of rules:
  %
  % Re(z1) = Re(z2) & Im(Z1) = Im(z2)
  %
  %------------------------------------------------------------------------------
  top: THEORY

  BEGIN

    IMPORTING complex_types,  % Type definitions and basic arithmetic
              polar,          % Polar coordinates
              complex_lnexp,  % complex exp/ln
              complex_sqrt,   % complex sqrt
              complex_fun_ops % Functions [T->complex]

  END top


body:
  %------------------------------------------------------------------------------
  % Complex Numbers and basic arithmetic
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            5/29/04   Initial version (DRL)
  %     Version 2.0            10/7/09   PVS decision procedure compatible (DRL)
  %     Version 2.1            16/3/11   Modified equality definition (DRL)
  %
  %------------------------------------------------------------------------------

  complex_types: THEORY

  BEGIN

    IMPORTING reals@sq,
              reals@sqrt

    complex: DATATYPE BEGIN complex_(x,y:real): complex_? END complex

    z,z1,z2,z3: VAR complex
    x,y:        VAR real

    Re(z):real = cases z of complex_(x,y): x endcases
    Im(z):real = cases z of complex_(x,y): y endcases

    Re_rew: LEMMA Re(complex_(x,y)) = x
    Im_rew: LEMMA Im(complex_(x,y)) = y

    AUTO_REWRITE+ Re_rew
    AUTO_REWRITE+ Im_rew

    eq_rew: LEMMA equalities.=(z1,z2) <=> Re(z1) = Re(z2) AND Im(z1) = Im(z2)

    AUTO_REWRITE+ eq_rew

    nzcomplex:       TYPE+ = {z | Re(z)/=0 OR Im(z)/=0} CONTAINING complex_(1,0)
    nonzero_complex: TYPE+ = nzcomplex

    complex_i:nzcomplex = complex_(0,1)
    
    Re_i: LEMMA Re(complex_i) = 0
    Im_i: LEMMA Im(complex_i) = 1

    AUTO_REWRITE+ Re_i
    AUTO_REWRITE+ Im_i

    n0z,n0z1,n0z2: VAR nzcomplex
    n0x: VAR nzreal

    conjugate(z):complex = complex_(Re(z),-Im(z))

    Re_conjugate: LEMMA Re(conjugate(z)) = Re(z)
    Im_conjugate: LEMMA Im(conjugate(z)) = -Im(z)

    AUTO_REWRITE+ Re_conjugate
    AUTO_REWRITE+ Im_conjugate

    sq_abs(z):nnreal     = sq(Re(z)) + sq(Im(z))
    nz_sq_abs_pos:  JUDGEMENT sq_abs(n0z) HAS_TYPE posreal

  ;
    +(z1,z2):complex = complex_(Re(z1)+Re(z2),Im(z1)+Im(z2));
    +(x,z)  :complex = complex_(x+Re(z),Im(z));
    +(z,x)  :complex = complex_(Re(z)+x,Im(z));

    -(z)    :complex = complex_(-Re(z),-Im(z));

    -(z1,z2):complex = complex_(Re(z1)-Re(z2),Im(z1)-Im(z2));
    -(x,z)  :complex = complex_(x-Re(z),Im(z));
    -(z,x)  :complex = complex_(Re(z)-x,Im(z));

    *(z1,z2):complex = complex_(Re(z1)*Re(z2) - Im(z1)*Im(z2),
                                Im(z1)*Re(z2) + Re(z1)*Im(z2));
    *(x,z)  :complex = complex_(x*Re(z),x*Im(z));
    *(z,x)  :complex = complex_(Re(z)*x,Im(z)*x);

    /(z,n0z):complex = complex_((Re(z)*Re(n0z) + Im(z)*Im(n0z))/sq_abs(n0z),
                                (Im(z)*Re(n0z) - Re(z)*Im(n0z))/sq_abs(n0z));
    /(x,n0z):complex = complex_((x*Re(n0z))/sq_abs(n0z),
                               ((-x)*Im(n0z))/sq_abs(n0z));
    /(z,n0x):complex = complex_(Re(z)/n0x,Im(z)/n0x);
    sq(z):   complex = z*z

    complex_sq_def:   LEMMA sq(z)       = z*z
    complex_neg_neg:  LEMMA -(-z)       = z
    complex_plus_neg: LEMMA z1 + (-z2)  = z1-z2
    complex_div_def:  LEMMA z * (1/n0z) = z/n0z

    Re_add1: LEMMA Re(z1+z2) = Re(z1)+Re(z2)
    Re_add2: LEMMA Re(x+z)   = x+Re(z)
    Re_add3: LEMMA Re(z+x)   = Re(z)+x

    Re_neg1: LEMMA Re(-z)    = -Re(z)

    Re_sub1: LEMMA Re(z1-z2) = Re(z1)-Re(z2)
    Re_sub2: LEMMA Re(x-z)   = x-Re(z)
    Re_sub3: LEMMA Re(z-x)   = Re(z)-x

    Re_mul1: LEMMA Re(z1*z2) = Re(z1)*Re(z2) - Im(z1)*Im(z2)
    Re_mul2: LEMMA Re(x*z)   = x*Re(z)
    Re_mul3: LEMMA Re(z*x)   = Re(z)*x

    Re_div1: LEMMA Re(z/n0z) = (Re(z)*Re(n0z) + Im(z)*Im(n0z))/sq_abs(n0z)
    Re_div2: LEMMA Re(x/n0z) = (x*Re(n0z))/sq_abs(n0z)
    Re_div3: LEMMA Re(z/n0x) = Re(z)/n0x

    Im_add1: LEMMA Im(z1+z2) = Im(z1)+Im(z2)
    Im_add2: LEMMA Im(x+z)   = Im(z)
    Im_add3: LEMMA Im(z+x)   = Im(z)

    Im_neg1: LEMMA Im(-z)    = -Im(z)

    Im_sub1: LEMMA Im(z1-z2) = Im(z1)-Im(z2)
    Im_sub2: LEMMA Im(x-z)   = Im(z)
    Im_sub3: LEMMA Im(z-x)   = Im(z)

    Im_mul1: LEMMA Im(z1*z2) = Im(z1)*Re(z2) + Re(z1)*Im(z2)
    Im_mul2: LEMMA Im(x*z)   = x*Im(z)
    Im_mul3: LEMMA Im(z*x)   = Im(z)*x

    Im_div1: LEMMA Im(z/n0z) = (Im(z)*Re(n0z) - Re(z)*Im(n0z))/sq_abs(n0z)
    Im_div2: LEMMA Im(x/n0z) = ((-x)*Im(n0z))/sq_abs(n0z)
    Im_div3: LEMMA Im(z/n0x) = Im(z)/n0x

    AUTO_REWRITE+ Re_add1
    AUTO_REWRITE+ Re_add2
    AUTO_REWRITE+ Re_add3
    AUTO_REWRITE+ Re_neg1
    AUTO_REWRITE+ Re_sub1
    AUTO_REWRITE+ Re_sub2
    AUTO_REWRITE+ Re_sub3
    AUTO_REWRITE+ Re_mul1
    AUTO_REWRITE+ Re_mul2
    AUTO_REWRITE+ Re_mul3
    AUTO_REWRITE+ Re_div1
    AUTO_REWRITE+ Re_div2
    AUTO_REWRITE+ Re_div3
    AUTO_REWRITE+ Im_add1
    AUTO_REWRITE+ Im_add2
    AUTO_REWRITE+ Im_add3
    AUTO_REWRITE+ Im_neg1
    AUTO_REWRITE+ Im_sub1
    AUTO_REWRITE+ Im_sub2
    AUTO_REWRITE+ Im_sub3
    AUTO_REWRITE+ Im_mul1
    AUTO_REWRITE+ Im_mul2
    AUTO_REWRITE+ Im_mul3
    AUTO_REWRITE+ Im_div1
    AUTO_REWRITE+ Im_div2
    AUTO_REWRITE+ Im_div3
  ;
    =(z1,z2): bool = Re(z1) = Re(z2) AND Im(z1) = Im(z2);
    =(x,z)  : bool = x = Re(z) AND Im(z) = 0;
    =(z,x)  : bool = Re(z) = x AND Im(z) = 0;
    /=(z1,z2):bool = NOT (z1 = z2);
    /=(x,z) : bool = x /= Re(z) OR Im(z) /= 0;
    /=(z,x) : bool = Re(z) /= x OR Im(z) /= 0;

    c_eq1: LEMMA z1  = z2 <=> Re(z1) = Re(z2) AND Im(z1) = Im(z2)
    c_eq2: LEMMA x   = z  <=> x = Re(z) AND Im(z) = 0
    c_eq3: LEMMA z   = x  <=> Re(z) = x AND Im(z) = 0
    c_ne1: LEMMA z1 /= z2 <=> NOT (z1 = z2)
    c_ne2: LEMMA x  /= z  <=> x /= Re(z) OR Im(z) /= 0
    c_ne3: LEMMA z  /= x  <=> Re(z) /= x OR Im(z) /= 0

    AUTO_REWRITE+ c_eq1
    AUTO_REWRITE+ c_eq2
    AUTO_REWRITE+ c_eq3
    AUTO_REWRITE+ c_ne1
    AUTO_REWRITE+ c_ne2
    AUTO_REWRITE+ c_ne3

    complex_commutative_add:  LEMMA z1+z2      = z2+z1
    complex_associative_add:  LEMMA (z1+z2)+z3 = z1+(z2+z3)
    complex_commutative_mult: LEMMA z1*z2      = z2*z1
    complex_associative_mult: LEMMA (z1*z2)*z3 = z1*(z2*z3)

    complex_div_cancel1: LEMMA n0z * (z/n0z) = z
    complex_div_cancel2: LEMMA (z/n0z) * n0z = z
    complex_div_cancel3: LEMMA z1/n0z = z2 IFF z1 = z2 * n0z
    complex_div_cancel4: LEMMA z2 = z1/n0z IFF z2 * n0z = z1

    plus_conjugate  : LEMMA z + conjugate(z) = 2*Re(z)
    minus_conjugate : LEMMA z - conjugate(z) = 2*Im(z)*complex_i
    conjugate_plus  : LEMMA conjugate(z1+z2) = conjugate(z1) + conjugate(z2)
    conjugate_neg   : LEMMA conjugate(-z)    = -conjugate(z)
    conjugate_minus : LEMMA conjugate(z1-z2) = conjugate(z1) - conjugate(z2)
    conjugate_times : LEMMA conjugate(z1*z2) = conjugate(z1) * conjugate(z2)
    conjugate_inv   : LEMMA conjugate(1/n0z) = 1/conjugate(n0z)
    conjugate_div   : LEMMA conjugate(z/n0z) = conjugate(z) / conjugate(n0z)

    zero_times: LEMMA z1*z2 = 0 <=> z1 = 0 OR z2 = 0

    neg_nzcomplex:  JUDGEMENT -(n0z)       HAS_TYPE nzcomplex
    mul_nzcomplex1: JUDGEMENT *(n0z1,n0z2) HAS_TYPE nzcomplex
    mul_nzcomplex2: JUDGEMENT *(n0x,n0z)   HAS_TYPE nzcomplex
    mul_nzcomplex3: JUDGEMENT *(n0z,n0x)   HAS_TYPE nzcomplex
    div_nzcomplex1: JUDGEMENT /(n0z1,n0z2) HAS_TYPE nzcomplex
    div_nzcomplex2: JUDGEMENT /(n0x,n0z)   HAS_TYPE nzcomplex
    div_nzcomplex3: JUDGEMENT /(n0z,n0x)   HAS_TYPE nzcomplex

    complex_sq_neg:       LEMMA sq(-z)    = sq(z)
    complex_sq_times:     LEMMA sq(z1*z2) = sq(z1) * sq(z2)
    complex_sq_plus:      LEMMA sq(z1+z2) = sq(z1) + 2*z1*z2 + sq(z2)
    complex_sq_minus:     LEMMA sq(z1-z2) = sq(z1) - 2*z1*z2 + sq(z2)
    complex_sq_neg_minus: LEMMA sq(z1-z2) = sq(z2-z1)
    complex_sq_div:       LEMMA sq(z/n0z) = sq(z)/sq(n0z)

    AUTO_REWRITE+ complex_sq_def
    AUTO_REWRITE+ complex_sq_neg
    AUTO_REWRITE+ complex_sq_times

  END complex_types

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

  complex_ord_defaxiom: AXIOM
    FORALL (x: real, y: real): complex_ord(complex_(x, y)) = 0;

  complex_complex__extensionality: AXIOM
    FORALL (complex_?_var: (complex_?), complex_?_var2: (complex_?)):
      x(complex_?_var) = x(complex_?_var2) AND
       y(complex_?_var) = y(complex_?_var2)
       IMPLIES complex_?_var = complex_?_var2;

  complex_complex__eta: AXIOM
    FORALL (complex_?_var: (complex_?)):
      complex_(x(complex_?_var), y(complex_?_var)) = complex_?_var;

  complex_x_complex_: AXIOM
    FORALL (complex_1_var: real, complex_2_var: real):
      x(complex_(complex_1_var, complex_2_var)) = complex_1_var;

  complex_y_complex_: AXIOM
    FORALL (complex_1_var: real, complex_2_var: real):
      y(complex_(complex_1_var, complex_2_var)) = complex_2_var;

  complex_inclusive: AXIOM
    FORALL (complex_var: complex): complex_?(complex_var);

  complex_induction: AXIOM
    FORALL (p: [complex -> boolean]):
      (FORALL (complex_1_var: real, complex_2_var: real):
         p(complex_(complex_1_var, complex_2_var)))
       IMPLIES (FORALL (complex_var: complex): p(complex_var));

  complex_well_founded: AXIOM strict_well_founded?[complex](<<);

  complex: TYPE

  complex_?: [complex -> boolean]

  x: [complex -> real]

  y: [complex -> real]

  complex_: [[real, real] -> (complex_?)]

  complex_ord: [complex -> upto(0)]

  ord(x1: complex): [complex -> upto(0)] =
      CASES x1 OF complex_(complex_1_var, complex_2_var): 0 ENDCASES

  subterm(x1: complex, y1: complex):  boolean = x1 = y1;

  reduce_nat(complex_?_fun: [[real, real] -> nat]):  [complex -> nat] =
      LAMBDA (complex_adtvar: complex):
        LET red: [complex -> nat] = reduce_nat(complex_?_fun) IN
          CASES complex_adtvar
            OF complex_(complex_1_var, complex_2_var):
                 complex_?_fun(complex_1_var, complex_2_var)
            ENDCASES;

  REDUCE_nat(complex_?_fun: [[real, real, complex] -> nat]):
        [complex -> nat] =
      LAMBDA (complex_adtvar: complex):
        LET red: [complex -> nat] = REDUCE_nat(complex_?_fun) IN
          CASES complex_adtvar
            OF complex_(complex_1_var, complex_2_var):
                 complex_?_fun(complex_1_var, complex_2_var, complex_adtvar)
            ENDCASES;

  reduce_ordinal(complex_?_fun: [[real, real] -> ordinal]):
        [complex -> ordinal] =
      LAMBDA (complex_adtvar: complex):
        LET red: [complex -> ordinal] = reduce_ordinal(complex_?_fun) IN
          CASES complex_adtvar
            OF complex_(complex_1_var, complex_2_var):
                 complex_?_fun(complex_1_var, complex_2_var)
            ENDCASES;

  REDUCE_ordinal(complex_?_fun: [[real, real, complex] -> ordinal]):
        [complex -> ordinal] =
      LAMBDA (complex_adtvar: complex):
        LET red: [complex -> ordinal] = REDUCE_ordinal(complex_?_fun) IN
          CASES complex_adtvar
            OF complex_(complex_1_var, complex_2_var):
                 complex_?_fun(complex_1_var, complex_2_var, complex_adtvar)
            ENDCASES;

  <<:  (strict_well_founded?[complex]) = LAMBDA (x1, y1: complex): FALSE;

  % Subtype TCC generated (at line 37, column 65) for  complex_(1, 0)
      % expected type  nzcomplex
  nzcomplex_TCC1: OBLIGATION
    Re(complex_(1, 0)) /= 0 OR Im(complex_(1, 0)) /= 0;

  % Subtype TCC generated (at line 40, column 24) for  complex_(0, 1)
      % expected type  nzcomplex
  complex_i_TCC1: OBLIGATION
    Re(complex_(0, 1)) /= 0 OR Im(complex_(0, 1)) /= 0;

  % Judgement subtype TCC generated (at line 60, column 28) for  sq_abs(n0z)
      % expected type  posreal
  nz_sq_abs_pos: OBLIGATION FORALL (n0z): sq_abs(n0z) > 0;

  % Subtype TCC generated (at line 190, column 47) for  conjugate(n0z)
      % expected type  nzcomplex
  conjugate_inv_TCC1: OBLIGATION
    FORALL (n0z: nzcomplex):
      Re(conjugate(n0z)) /= 0 OR Im(conjugate(n0z)) /= 0;

  % Judgement subtype TCC generated (at line 195, column 28) for  -n0z
      % expected type  nzcomplex
  neg_nzcomplex: OBLIGATION FORALL (n0z): Re(-n0z) /= 0 OR Im(-n0z) /= 0;

  % Judgement subtype TCC generated (at line 196, column 28) for  n0z1 * n0z2
      % expected type  nzcomplex
  mul_nzcomplex1: OBLIGATION
    FORALL (n0z1, n0z2): Re(n0z1 * n0z2) /= 0 OR Im(n0z1 * n0z2) /= 0;

  % Judgement subtype TCC generated (at line 197, column 28) for  n0x * n0z
      % expected type  nzcomplex
  mul_nzcomplex2: OBLIGATION
    FORALL (n0x, n0z): Re(n0x * n0z) /= 0 OR Im(n0x * n0z) /= 0;

  % Judgement subtype TCC generated (at line 198, column 28) for  n0z * n0x
      % expected type  nzcomplex
  mul_nzcomplex3: OBLIGATION
    FORALL (n0x, n0z): Re(n0z * n0x) /= 0 OR Im(n0z * n0x) /= 0;

  % Judgement subtype TCC generated (at line 199, column 28) for  n0z1 / n0z2
      % expected type  nzcomplex
  div_nzcomplex1: OBLIGATION
    FORALL (n0z1, n0z2): Re(n0z1 / n0z2) /= 0 OR Im(n0z1 / n0z2) /= 0;

  % Judgement subtype TCC generated (at line 200, column 28) for  n0x / n0z
      % expected type  nzcomplex
  div_nzcomplex2: OBLIGATION
    FORALL (n0x, n0z): Re(n0x / n0z) /= 0 OR Im(n0x / n0z) /= 0;

  % Judgement subtype TCC generated (at line 201, column 28) for  n0z / n0x
      % expected type  nzcomplex
  div_nzcomplex3: OBLIGATION
    FORALL (n0x, n0z): Re(n0z / n0x) /= 0 OR Im(n0z / n0x) /= 0;

  % Subtype TCC generated (at line 208, column 48) for  sq(n0z)
      % expected type  nzcomplex
  complex_sq_div_TCC1: OBLIGATION
    FORALL (n0z: nzcomplex): Re(sq(n0z)) /= 0 OR Im(sq(n0z)) /= 0;


body:
  %------------------------------------------------------------------------------
  % Polar representation of Complex 
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            5/29/04   Initial version (DRL)
  %------------------------------------------------------------------------------

  polar: THEORY

  BEGIN

    IMPORTING complex_types, reals@sqrt, trig@atan2, trig@atan2_props

    argrng: TYPE+ = {x:real | -pi < x & x <= pi} CONTAINING 0

    z,z1,z2:     VAR complex
    n0x,n0y,n0z: VAR nzcomplex
    nzx:         VAR nzreal
    r,x,y:       VAR real
    j:           VAR int
    theta:       VAR argrng

    abs(z):nnreal = sqrt(sq_abs(z))

    abs_def:       LEMMA abs(z) = sqrt(sq(Re(z))+sq(Im(z)))
    abs_def2:      LEMMA abs(z) = sqrt(sq_abs(z))

    abs_nzcomplex: JUDGEMENT abs(n0z) HAS_TYPE posreal
    abs_nz_iff_nz: LEMMA abs(z) > 0 <=> z /= 0
    abs_is_0:      LEMMA abs(z) = 0 <=> z  = 0

    abs_neg:       LEMMA abs(-z)        = abs(z)
    abs_mult:      LEMMA abs(z1*z2)     = abs(z1)*abs(z2)
    abs_inv:       LEMMA abs(1/n0z)     = 1/abs(n0z)
    abs_div:       LEMMA abs(z/n0z)     = abs(z)/abs(n0z)
    abs_triangle:  LEMMA abs(z1+z2)    <= abs(z1) + abs(z2)
    abs_abs:       LEMMA abs(abs(z))    = abs(z)
    abs_i:         LEMMA abs(complex_i) = 1
    abs_div2:      LEMMA abs(z/nzx)     = abs(z)/abs(nzx)
    abs_div3:      LEMMA abs(x/n0z)     = abs(x)/abs(n0z)

    AUTO_REWRITE+ abs_neg
    AUTO_REWRITE+ abs_mult
    AUTO_REWRITE+ abs_inv
    AUTO_REWRITE+ abs_div
    AUTO_REWRITE+ abs_abs
    AUTO_REWRITE+ abs_i
    AUTO_REWRITE+ abs_div2
    AUTO_REWRITE+ abs_div3

    arg(z):argrng = IF    z = 0     THEN 0
                    ELSIF Im(z) < 0 THEN atan2(Re(z),Im(z)) - 2*pi
                                    ELSE atan2(Re(z),Im(z))        ENDIF

    arg_is_0_nz: LEMMA arg(n0z) =  0    <=> (Re(n0z) >  0 AND Im(n0z) = 0)
    arg_is_0:    LEMMA arg(z)   =  0    <=> (Re(z)   >= 0 AND Im(z)   = 0)
    arg_is_pi2:  LEMMA arg(z)   =  pi/2 <=> (Re(z)   =  0 AND Im(z)   > 0)
    arg_is_pi:   LEMMA arg(z)   =  pi   <=> (Re(z)   <  0 AND Im(z)   = 0)
    arg_is_mpi2: LEMMA arg(z)   = -pi/2 <=> (Re(z)   =  0 AND Im(z)   < 0)

    arg_lt_0:    LEMMA arg(z) < 0 <=> Im(z) < 0
    arg_p_lt_pi: LEMMA (0 < arg(z) AND arg(z) < pi) <=> Im(z) > 0
    arg_gt_0:    LEMMA arg(z) > 0 <=> (Im(z) > 0 OR (Im(z) = 0 AND Re(z) < 0))

    arg_div_abs: LEMMA arg(n0x) = arg(n0x/abs(n0x))
    Re_cos_abs1: LEMMA abs(n0x) = 1 => Re(n0x) = cos(arg(n0x))
    Im_sin_abs1: LEMMA abs(n0x) = 1 => Im(n0x) = sin(arg(n0x))
    abs_cos_arg: LEMMA abs(z) * cos(arg(z)) = Re(z)
    abs_sin_arg: LEMMA abs(z) * sin(arg(z)) = Im(z)

    arg_nnreal: LEMMA Im(z) = 0 AND Re(z) >= 0 => arg(z) = 0
    arg_nreal:  LEMMA Im(z) = 0 AND Re(z) <  0 => arg(z) = pi
    arg_i:      LEMMA arg(complex_i) = pi/2

    arg_neg:  LEMMA arg(-n0x)    = IF 0 < arg(n0x) THEN arg(n0x) - pi
                                                   ELSE arg(n0x) + pi ENDIF
    arg_conjugate:
              LEMMA arg(conjugate(z)) = IF arg(z) = 0 OR arg(z) = pi THEN arg(z)
                                                ELSE -arg(z) ENDIF
    arg_mult: LEMMA arg(n0x*n0y) = LET r = arg(n0x)+arg(n0y) IN
                                   IF    r >   pi THEN r-2*pi
                                   ELSIF r <= -pi THEN r+2*pi
                                                  ELSE r      ENDIF
    arg_inv:  LEMMA arg(1/n0z)   = IF    arg(n0z) = 0  THEN 0
                                   ELSIF arg(n0z) = pi THEN pi
                                                       ELSE -arg(n0z) ENDIF
    arg_div:  LEMMA arg(n0x/n0y) = LET r = arg(n0x)-arg(n0y) IN
                                   IF    r >   pi THEN r-2*pi
                                   ELSIF r <= -pi THEN r+2*pi
                                                  ELSE r      ENDIF

    polar(z):[nnreal,argrng]      = (abs(z),arg(z))
    rectangular(z):[real,real]    = (Re(z),Im(z))
    from_polar(r,theta):complex   = r*cos(theta) + r*sin(theta)*complex_i
    from_rectangular(x,y):complex = x + y*complex_i

    idempotent_rectangular: LEMMA z   = from_rectangular(rectangular(z))
    idempotent_polar      : LEMMA n0z = from_polar(polar(n0z))

  END polar

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

  % Subtype TCC generated (at line 15, column 58) for  0
      % expected type  argrng
  argrng_TCC1: OBLIGATION -pi < 0 & 0 <= pi;

  % Judgement subtype TCC generated (at line 29, column 27) for  abs(n0z)
      % expected type  posreal
  abs_nzcomplex: OBLIGATION FORALL (n0z): abs(n0z) > 0;

  % Subtype TCC generated (at line 53, column 51) for  Im(z)
      % expected type  {z_1: real | Re(z) = 0 => z_1 /= 0}
  arg_TCC1: OBLIGATION
    FORALL (z: complex):
      Im(z) < 0 AND NOT z = 0 IMPLIES Re(z) = 0 => Im(z) /= 0;

  % Subtype TCC generated (at line 53, column 39) for
      % atan2(Re(z), Im(z)) - 2 * pi
      % expected type  argrng
  arg_TCC2: OBLIGATION
    FORALL (z: complex):
      Im(z) < 0 AND NOT z = 0 IMPLIES
       -pi < atan2(Re(z), Im(z)) - 2 * pi &
        atan2(Re(z), Im(z)) - 2 * pi <= pi;

  % Subtype TCC generated (at line 54, column 51) for  Im(z)
      % expected type  {z_1: real | Re(z) = 0 => z_1 /= 0}
  arg_TCC3: OBLIGATION
    FORALL (z: complex):
      NOT Im(z) < 0 AND NOT z = 0 IMPLIES Re(z) = 0 => Im(z) /= 0;

  % Subtype TCC generated (at line 54, column 39) for  atan2(Re(z), Im(z))
      % expected type  argrng
  arg_TCC4: OBLIGATION
    FORALL (z: complex):
      NOT Im(z) < 0 AND NOT z = 0 IMPLIES
       -pi < atan2(Re(z), Im(z)) & atan2(Re(z), Im(z)) <= pi;


body:
  %------------------------------------------------------------------------------
  % Arithmetic Operations defined on functions [T->complex]
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            14/06/09  Initial Version
  %     Version 1.1            16/03/11  Additional rewrites added (DRL)
  %
  %------------------------------------------------------------------------------
  complex_fun_ops[T:TYPE]: THEORY

  BEGIN

    IMPORTING polar,
              structures@const_fun_def[T,complex]

    f,f1,f2: VAR [T->complex]
    f3,n0f:  VAR [T->nzcomplex]
    x,y:     VAR T
    a:       VAR complex
    n0a:     VAR nzcomplex
    c:       VAR real

    Re(f): [T -> real] = lambda x: Re(f(x));
    Im(f): [T -> real] = lambda x: Im(f(x));

    Re_fun_rew: LEMMA Re(f)(x) = Re(f(x))
    Im_fun_rew: LEMMA Im(f)(x) = Im(f(x))
    
    AUTO_REWRITE+ Re_fun_rew
    AUTO_REWRITE+ Im_fun_rew

    +(f1, f2) : [T -> complex] = lambda x : f1(x) + f2(x); 
    -(f1)     : [T -> complex] = lambda x : -f1(x);
    *(f1, f2) : [T -> complex] = lambda x : f1(x) * f2(x);
    *(a, f1)  : [T -> complex] = lambda x : a * f1(x);
    *(c, f1)  : [T -> complex] = lambda x : c * f1(x);
    -(f1, f2) : [T -> complex] = lambda x : f1(x) - f2(x);
    /(f1, f3) : [T -> complex] = lambda x : f1(x) / f3(x);
    /(f, n0a) : [T -> complex] = lambda x : f(x) / n0a;
    /(a, f3)  : [T -> complex] = lambda x : a / f3(x);
    /(c, f3)  : [T -> complex] = lambda x : c / f3(x);
    inv(f3)   : [T -> complex] = 1 / f3;
    sq(f)     : [T -> complex] = lambda x: sq(f(x));

    diff_function    : LEMMA f1 - f2 = f1 + (- f2)
    div_function     : LEMMA f1 / f3 = f1 * (1 /f3)
    scal_function    : LEMMA a * f1 = const_fun(a) * f1
    scaldiv_function : LEMMA a / f3 = const_fun(a) / f3
    negneg_function  : LEMMA - (- f1) = f1
    prod_def         : LEMMA *(f1,f2)   = (1/4)*(sq(f1+f2)-sq(f1-f2))

    conjugate(f): [T -> complex] = lambda x: conjugate(f(x));

    IMPORTING reals@real_fun_ops_aux[T]

    Re_fun_conjugate: LEMMA Re(conjugate(f)) = Re(f)
    Im_fun_conjugate: LEMMA Im(conjugate(f)) = -Im(f)

    AUTO_REWRITE+ Re_fun_conjugate
    AUTO_REWRITE+ Im_fun_conjugate

    sq_abs(f): [T -> nnreal]     = sq(Re(f)) + sq(Im(f))
    nz_fun_sq_abs_pos:  JUDGEMENT sq_abs(n0f) HAS_TYPE [T->posreal]

  ;
    abs(f1)   : [T->nonneg_real] = lambda x : abs(f1(x));
    complex_abs_nzfunction_pos: JUDGEMENT abs(n0f) HAS_TYPE [T->posreal]

    complex_abs_neg: LEMMA abs(-f) = abs(f)
    complex_abs_mul: LEMMA abs(f1*f2) = abs(f1)*abs(f2)

    Re_fun_add1: LEMMA Re(f1+f2) = Re(f1)+Re(f2)

    Re_fun_neg1: LEMMA Re(-f)    = -Re(f)

    Re_fun_sub1: LEMMA Re(f1-f2) = Re(f1)-Re(f2)

    Re_fun_mul1: LEMMA Re(f1*f2) = Re(f1)*Re(f2) - Im(f1)*Im(f2)
    Re_fun_mul2: LEMMA Re(a*f)   = Re(a)*Re(f) - Im(a)*Im(f)

    Re_fun_div1: LEMMA Re(f/n0f) = (Re(f)*Re(n0f) + Im(f)*Im(n0f))/sq_abs(n0f)
    Re_fun_div2: LEMMA Re(a/n0f) = (Re(a)*Re(n0f) + Im(a)*Im(n0f))/sq_abs(n0f)
    Re_fun_div3: LEMMA Re(f/n0a) = (Re(n0a)/sq_abs(n0a))*Re(f) +
                                   (Im(n0a)/sq_abs(n0a))*Im(f)

    Im_fun_add1: LEMMA Im(f1+f2) = Im(f1)+Im(f2)

    Im_fun_neg1: LEMMA Im(-f)    = -Im(f)

    Im_fun_sub1: LEMMA Im(f1-f2) = Im(f1)-Im(f2)

    Im_fun_mul1: LEMMA Im(f1*f2) = Im(f1)*Re(f2) + Re(f1)*Im(f2)
    Im_fun_mul2: LEMMA Im(a*f)   = Im(a)*Re(f) + Re(a)*Im(f)

    Im_fun_div1: LEMMA Im(f/n0f) = (Im(f)*Re(n0f) - Re(f)*Im(n0f))/sq_abs(n0f)
    Im_fun_div2: LEMMA Im(a/n0f) = (Im(a)*Re(n0f) - Re(a)*Im(n0f))/sq_abs(n0f)
    Im_fun_div3: LEMMA Im(f/n0a) = (Re(n0a)/sq_abs(n0a))*Im(f) -
                                   (Im(n0a)/sq_abs(n0a))*Re(f)

    AUTO_REWRITE+ complex_abs_neg
    AUTO_REWRITE+ complex_abs_mul
    AUTO_REWRITE+ Re_fun_add1
    AUTO_REWRITE+ Re_fun_neg1
    AUTO_REWRITE+ Re_fun_sub1
    AUTO_REWRITE+ Re_fun_mul1
    AUTO_REWRITE+ Re_fun_mul2
    AUTO_REWRITE+ Re_fun_div1
    AUTO_REWRITE+ Re_fun_div2
    AUTO_REWRITE+ Re_fun_div3
    AUTO_REWRITE+ Im_fun_add1
    AUTO_REWRITE+ Im_fun_neg1
    AUTO_REWRITE+ Im_fun_sub1
    AUTO_REWRITE+ Im_fun_mul1
    AUTO_REWRITE+ Im_fun_mul2
    AUTO_REWRITE+ Im_fun_div1
    AUTO_REWRITE+ Im_fun_div2
    AUTO_REWRITE+ Im_fun_div3
  ;
    =(f1,f2): bool = Re(f1) = Re(f2) AND Im(f1) = Im(f2);
    /=(f1,f2):bool = NOT (f1 = f2);
   
    c_fun_eq1: LEMMA f1  = f2 <=> Re(f1) = Re(f2) AND Im(f1) = Im(f2)
    c_fun_ne1: LEMMA f1 /= f2 <=> NOT (f1 = f2)

    AUTO_REWRITE+ c_fun_eq1
    AUTO_REWRITE+ c_fun_ne1


  END complex_fun_ops

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

  % Subtype TCC generated (at line 63, column 33) for  sq(Re(f)) + sq(Im(f))
      % expected type  [T -> nnreal]
  sq_abs_TCC1: OBLIGATION
    FORALL (f: [T -> complex]):
      FORALL (x1: T): ((+[T])(sq[T](Re(f)), sq[T](Im(f))))(x1) >= 0;

  % Judgement subtype TCC generated (at line 64, column 32) for  sq_abs(n0f)
      % expected type  [T -> posreal]
  nz_fun_sq_abs_pos: OBLIGATION FORALL (n0f, x1: T): sq_abs(n0f)(x1) > 0;

  % Judgement subtype TCC generated (at line 68, column 40) for  abs(n0f)
      % expected type  [T -> posreal]
  complex_abs_nzfunction_pos: OBLIGATION
    FORALL (n0f, x1: T): abs(n0f)(x1) > 0;


body:
  %------------------------------------------------------------------------------
  % Sqrare root properties of Complex Numbers.
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            4/11/07   Initial version (DRL)
  %------------------------------------------------------------------------------

  complex_sqrt: THEORY

  BEGIN

    IMPORTING polar, trig_aux

    r:           VAR real
    nnx:         VAR nnreal
    npx:         VAR npreal
    x,y,z:       VAR complex
    n0x,n0y,n0z: VAR nzcomplex

    sqrt(z):complex = from_polar(sqrt(abs(z)),arg(z)/2)

    sqrt_nz_is_nz       : JUDGEMENT sqrt(n0z) HAS_TYPE nzcomplex

    sqrt_eq_0 : LEMMA sqrt(z) = 0 IFF z = 0

    sqrt_sq   : LEMMA sqrt(sq(z)) = IF -pi/2 < arg(z) AND arg(z) <= pi/2
                                    THEN z ELSE -z ENDIF
    sq_sqrt   : LEMMA sq(sqrt(z)) = z
    sqrt_times: LEMMA sqrt(x*y) = IF -pi < arg(x)+arg(y) AND arg(x)+arg(y) <= pi
                                  THEN sqrt(x)*sqrt(y)
                                  ELSE -sqrt(x)*sqrt(y) ENDIF
    sqrt_neg   : LEMMA sqrt(-z) =
                        IF arg(z) <= 0 THEN complex_i*sqrt(z) ELSE
                                           -complex_i*sqrt(z) ENDIF
    sqrt_inv   : LEMMA sqrt(1/n0z)
                      = IF arg(n0z) = pi THEN -1/sqrt(n0z) ELSE 1/sqrt(n0z) ENDIF
    sqrt_div   : LEMMA sqrt(x/n0y)
             = IF (arg(n0y) = pi & arg(x) > 0) OR
                   arg(n0y) = 0 OR
                  (-pi < arg(x)-arg(n0y) & arg(x)-arg(n0y) <= pi)
               THEN sqrt(x) / sqrt(n0y) ELSE -sqrt(x) / sqrt(n0y) ENDIF

  END complex_sqrt

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

  % Subtype TCC generated (at line 21, column 44) for  arg(z) / 2
      % expected type  argrng
  sqrt_TCC1: OBLIGATION
    FORALL (z: complex): -pi < arg(z) / 2 & arg(z) / 2 <= pi;

  % Judgement subtype TCC generated (at line 23, column 34) for  sqrt(n0z)
      % expected type  nzcomplex
  sqrt_nz_is_nz: OBLIGATION
    FORALL (n0z): Re(sqrt(n0z)) /= 0 OR Im(sqrt(n0z)) /= 0;


body:
  %------------------------------------------------------------------------------
  % Complex logarithm and exponential  functions
  %
  %     Author: David Lester, Manchester University & NIA
  %
  %     Version 1.0            5/29/04   Initial version (DRL)
  %------------------------------------------------------------------------------

  complex_lnexp: THEORY

    BEGIN

    IMPORTING polar, trig@trig_ineq, trig_aux, lnexp@hyperbolic

    r:           VAR real
    x,y,z:       VAR complex
    n0x,n0y,n0z: VAR nzcomplex
    theta:       VAR argrng
    j:           VAR int

    exp(z): nzcomplex = complex_(exp(Re(z))*cos(Im(z)),
                                 exp(Re(z))*sin(Im(z)))

    Re_exp: LEMMA Re(exp(z)) = exp(Re(z))*cos(Im(z))
    Im_exp: LEMMA Im(exp(z)) = exp(Re(z))*sin(Im(z))

    AUTO_REWRITE+ Re_exp
    AUTO_REWRITE+ Im_exp

    exp_i_pi        : LEMMA exp(complex_i*pi) = -1
    exp_plus        : LEMMA exp(x+y)          = exp(x)*exp(y) 
    exp_negate      : LEMMA exp(-x)           = 1/exp(x)
    exp_minus       : LEMMA exp(x-y)          = exp(x)/exp(y) 
    exp_periodicity : LEMMA exp(x+(2*j*pi)*complex_i)   = exp(x)
    abs_exp         : LEMMA abs(exp(z))       = exp(Re(z))
    arg_exp         : LEMMA -pi < Im(z) AND Im(z) <= pi =>
                            arg(exp(z))       = Im(z)

    ln(n0z): complex = complex_(ln(abs(n0z)),arg(n0z))


    Re_ln: LEMMA Re(ln(n0z)) = ln(abs(n0z))
    Im_ln: LEMMA Im(ln(n0z)) = arg(n0z)

    AUTO_REWRITE+ Re_ln
    AUTO_REWRITE+ Im_ln
    AUTO_REWRITE+ abs_exp
    AUTO_REWRITE+ arg_exp

    ln_exp          : LEMMA (2*j-1)*pi < Im(z) AND Im(z) <= (2*j+1)*pi =>
                            ln(exp(z)) = z - (2*j*pi)*complex_i
    exp_ln          : LEMMA exp(ln(n0z)) = n0z
    ln_mult         : LEMMA ln(n0x*n0y)  = ln(n0x) + ln(n0y) -
                            LET r = arg(n0x)+arg(n0y) IN
                            IF    r >   pi THEN 2*pi
                            ELSIF r <= -pi THEN -2*pi
                                           ELSE 0 ENDIF*complex_i
    ln_inv          : LEMMA ln(1/n0x)   = IF arg(n0x) = pi THEN 2*pi
                                          ELSE 0 ENDIF*complex_i - ln(n0x)
    ln_div          : LEMMA ln(n0x/n0y)  = ln(n0x) - ln(n0y) -
                            LET r = arg(n0x)-arg(n0y) IN
                            IF    r >   pi THEN 2*pi
                            ELSIF r <= -pi THEN -2*pi
                                           ELSE 0 ENDIF*complex_i

    sin(z): complex = complex_(sin(Re(z))*cosh(Im(z)),-cos(Re(z))*sinh(Im(z)))
    cos(z): complex = complex_(cos(Re(z))*cosh(Im(z)),-sin(Re(z))*sinh(Im(z)))

    Re_sin: LEMMA Re(sin(z)) =  sin(Re(z))*cosh(Im(z))
    Im_sin: LEMMA Im(sin(z)) = -cos(Re(z))*sinh(Im(z))
    Re_cos: LEMMA Re(cos(z)) =  cos(Re(z))*cosh(Im(z))
    Im_cos: LEMMA Im(cos(z)) = -sin(Re(z))*sinh(Im(z))

    AUTO_REWRITE+ Re_sin
    AUTO_REWRITE+ Im_sin
    AUTO_REWRITE+ Re_cos
    AUTO_REWRITE+ Re_sin

    sinh(z):complex = (exp(z) - exp(-z))/2                                % 4.5.1
    cosh(z):complex = (exp(z) + exp(-z))/2                                % 4.5.2

    Re_sinh: LEMMA Re(sinh(z)) =  sinh(Re(z))*cos(Im(z))
    Im_sinh: LEMMA Im(sinh(z)) =  cosh(Re(z))*sin(Im(z))
    Re_cosh: LEMMA Re(cosh(z)) =  cosh(Re(z))*cos(Im(z))
    Im_cosh: LEMMA Im(cosh(z)) =  sinh(Re(z))*sin(Im(z))

    AUTO_REWRITE+ Re_sinh
    AUTO_REWRITE+ Im_sinh
    AUTO_REWRITE+ Re_cosh
    AUTO_REWRITE+ Im_cosh

    sinh_eq_0: LEMMA sinh(z) = 0 <=> EXISTS j: z = complex_i*(j*pi)
    cosh_eq_0: LEMMA cosh(z) = 0 <=> EXISTS j: z = complex_i*((j+1/2)*pi)

    Sinh?(z):bool = sinh(z) /= 0
    Cosh?(z):bool = cosh(z) /= 0

    sx,sy,sz: VAR (Sinh?)
    cx,cy,cz: VAR (Cosh?)

    tanh(cz):complex = sinh(cz)/cosh(cz)                                  % 4.5.3
    csch(sz):complex = 1/sinh(sz)                                         % 4.5.4
    sech(cz):complex = 1/cosh(cz)                                         % 4.5.5
    coth(sz):complex = cosh(sz)/sinh(sz)                                  % 4.5.6

  % Special Values of the Hyperbolic Functions

    c_sinh_0: LEMMA sinh(complex_(0,0)) = 0                              % 4.5.61
    c_cosh_0: LEMMA cosh(complex_(0,0)) = 1                              % 4.5.61
    c_tanh_0: LEMMA tanh(complex_(0,0)) = 0                              % 4.5.61
    c_sech_0: LEMMA sech(complex_(0,0)) = 1                              % 4.5.61

  % Relations between Hyperbolic Functions

    c_cosh_sinh_one:   LEMMA sq(cosh(z))  - sq(sinh(z))  = 1             % 4.5.16
    c_tanh_sech_one:   LEMMA sq(tanh(cz)) + sq(sech(cz)) = 1             % 4.5.17
    c_coth_csch_one:   LEMMA sq(coth(sz)) - sq(csch(sz)) = 1             % 4.5.18
    c_cosh_plus_sinh:  LEMMA cosh(z)      + sinh(z)      = exp(z)        % 4.5.19
    c_cosh_minus_sinh: LEMMA cosh(z)      - sinh(z)      = exp(-z)       % 4.5.20

  % Negative Angle Formulas

    c_sinh_neg: LEMMA sinh(-z)  = -sinh(z)                               % 4.5.21
    c_cosh_neg: LEMMA cosh(-z)  =  cosh(z)                               % 4.5.22
    c_tanh_neg: LEMMA tanh(-cz) = -tanh(cz)                              % 4.5.23
    c_csch_neg: LEMMA csch(-sz) = -csch(sz)
    c_sech_neg: LEMMA sech(-cz) =  sech(cz)
    c_coth_neg: LEMMA coth(-sz) = -coth(sz)

    AUTO_REWRITE+ c_sinh_neg
    AUTO_REWRITE+ c_cosh_neg
    AUTO_REWRITE+ c_tanh_neg
    AUTO_REWRITE+ c_csch_neg
    AUTO_REWRITE+ c_sech_neg
    AUTO_REWRITE+ c_coth_neg

  % Addition Formulas

    c_sinh_sum:  LEMMA sinh(x+y) = sinh(x)*cosh(y) + cosh(x)*sinh(y)     % 4.5.24
    c_sinh_diff: LEMMA sinh(x-y) = sinh(x)*cosh(y) - cosh(x)*sinh(y)
    c_cosh_sum:  LEMMA cosh(x+y) = cosh(x)*cosh(y) + sinh(x)*sinh(y)     % 4.5.25
    c_cosh_diff: LEMMA cosh(x-y) = cosh(x)*cosh(y) - sinh(x)*sinh(y)
  %  c_tanh_sum:  LEMMA tanh(cx)*tanh(cy) /= -1 =>                        % 4.5.26
  %                     tanh(cx+cy) = (tanh(cx)+tanh(cy))/(1+tanh(cx)*tanh(cy))

  %  c_coth_sum:  LEMMA n0x+n0y /= 0 IMPLIES                              % 4.5.27
  %                   coth(n0x+n0y)
  %                             = (1+coth(n0x)*coth(n0y))/(coth(n0x)+coth(n0y))

  % Half-angle Formulas

  %  sinh_half:  LEMMA sinh(x/2) = LET y = sqrt((cosh(x)-1)/2) IN         % 4.5.28
  %                                IF x >= 0 THEN y ELSE -y ENDIF
  %  cosh_half:  LEMMA cosh(x/2) = sqrt((cosh(x)+1)/2)                    % 4.5.29
  %  tanh_half1: LEMMA tanh(x/2) = LET y = sqrt((cosh(x)-1)/(cosh(x)+1))  % 4.5.30
  %                                IN IF x >= 0 THEN y ELSE -y ENDIF
  %  tanh_half2: LEMMA tanh(n0x/2) = (cosh(n0x)-1)/sinh(n0x)              % 4.5.30
  %  tanh_half3: LEMMA tanh(x/2) = sinh(x)/(cosh(x)+1)                    % 4.5.30

  % Multiple-angle Formulas

    c_sinh2x:     LEMMA sinh(2*x) = 2*sinh(x)*cosh(x)                    % 4.5.31
  % sinh2x_B:   LEMMA sinh(2*x) = 2*tanh(x)/(1-sq(tanh(x)))              % 4.5.31
    c_cosh2x:     LEMMA cosh(2*x) = 2*sq(cosh(x))-1                      % 4.5.32
    c_cosh2x_B:   LEMMA cosh(2*x) = 2*sq(sinh(x))+1                      % 4.5.32
    c_cosh2x_C:   LEMMA cosh(2*x) = sq(cosh(x)) + sq(sinh(x))            % 4.5.32
  %  tanh2x:     LEMMA tanh(2*x) = 2*tanh(x)/(1+sq(tanh(x)))              % 4.5.33
   % sinh3x:     LEMMA sinh(3*x) = 3*sinh(x) + 4*sinh(x)^3                % 4.5.34
   % cosh3x:     LEMMA cosh(3*x) = 4*cosh(x)^3-3*cosh(x)                  % 4.5.35
    c_sinh4x:     LEMMA sinh(4*x)                                        % 4.5.36
                                = 4*sinh(x)*cosh(x)*(sq(sinh(x)) + sq(cosh(x)))

    complex_sin_def: LEMMA sin(z) = -complex_i * sinh(complex_i*conjugate(z))
    complex_cos_def: LEMMA cos(z) = cosh(complex_i*z)

  END complex_lnexp

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

  % Subtype TCC generated (at line 21, column 22) for
      % complex_(exp(Re(z)) * cos(Im(z)), exp(Re(z)) * sin(Im(z)))
      % expected type  nzcomplex
  exp_TCC1: OBLIGATION
    FORALL (z: complex):
      Re(complex_(exp(Re(z)) * cos(Im(z)), exp(Re(z)) * sin(Im(z)))) /= 0 OR
       Im(complex_(exp(Re(z)) * cos(Im(z)), exp(Re(z)) * sin(Im(z)))) /= 0;

  % Subtype TCC generated (at line 101, column 30) for  cosh(cz)
      % expected type  nzcomplex
  tanh_TCC1: OBLIGATION
    FORALL (cz: (Cosh?)): Re(cosh(cz)) /= 0 OR Im(cosh(cz)) /= 0;

  % Subtype TCC generated (at line 102, column 23) for  sinh(sz)
      % expected type  nzcomplex
  csch_TCC1: OBLIGATION
    FORALL (sz: (Sinh?)): Re(sinh(sz)) /= 0 OR Im(sinh(sz)) /= 0;

  % Subtype TCC generated (at line 110, column 23) for  complex_(0, 0)
      % expected type  (Cosh?)
  c_tanh_0_TCC1: OBLIGATION Cosh?(complex_(0, 0));

  % Subtype TCC generated (at line 125, column 25) for  -cz
      % expected type  (Cosh?)
  c_tanh_neg_TCC1: OBLIGATION FORALL (cz: (Cosh?)): Cosh?(-cz);

  % Subtype TCC generated (at line 126, column 25) for  -sz
      % expected type  (Sinh?)
  c_csch_neg_TCC1: OBLIGATION FORALL (sz: (Sinh?)): Sinh?(-sz);


body:
  %------------------------------------------------------------------------------
  % Top file for Functional Analysis
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            12/3/10   Initial Version
  %------------------------------------------------------------------------------

  top: THEORY

  BEGIN

    IMPORTING
      complex_topology,       % complex_topology
      complex_measurable,     % measurable functions [T->complex]
      complex_measure_theory, % ae properties and cal_N
      complex_integral,       % integrable functions [T->complex]
      p_integrable_def,       % cal_L^p and norm defs
      young,                  % Young's inequality
      holder_scaf,            % Holder's inequality
      minkowski_scaf,         % Minkowski's inequality
      p_integrable,           % cal_L^p and norm properties
      essentially_bounded,    % essential bounds
      essential_bound_complete_scaf,
                              % completeness of essential bounds
      cal_L_inf,              % L^\infty
      complex_finite_measures,% class structure for finite measures
      cal_L_complex,          % complex integral classes
      cal_L_real              % real integral classes

  END top


body:
  %------------------------------------------------------------------------------
  % Young's Inequality (used in Holder's inequality)
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            12/3/10   Initial Version
  %------------------------------------------------------------------------------

  young: THEORY

  BEGIN

    IMPORTING power@real_expt,
              power@log,
              power@ln_exp_def % eventually this is part of lnexp_fnd@ln_exp

    x,y:   VAR real
    r:     VAR posreal
    a,b:   VAR nnreal
    p,q:   VAR {r | r > 1}
    c:     VAR {r | r < 1}

    youngs_aux:        LEMMA (1-c) + c*p - p^c > 0

    youngs_inequality: LEMMA 1/p + 1/q = 1 => a*b <= a^p/p + b^q/q    % SKB 3.1.3

  END young

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

  % Subtype TCC generated (at line 26, column 43) for  c
      % expected type  {a | a >= 0 OR p > 0}
  youngs_aux_TCC1: OBLIGATION
    FORALL (c: {r | r < 1}, p: {r | r > 1}): c >= 0 OR p > 0;

  % Subtype TCC generated (at line 28, column 53) for  p
      % expected type  {a_1 | a_1 >= 0 OR a > 0}
  youngs_inequality_TCC1: OBLIGATION
    FORALL (a: nnreal, p, q: {r | r > 1}):
      1 / p + 1 / q = 1 IMPLIES p >= 0 OR a > 0;

  % Subtype TCC generated (at line 28, column 61) for  q
      % expected type  {a | a >= 0 OR b > 0}
  youngs_inequality_TCC2: OBLIGATION
    FORALL (b: nnreal, p, q: {r | r > 1}):
      1 / p + 1 / q = 1 IMPLIES q >= 0 OR b > 0;


body:
  %------------------------------------------------------------------------------
  % Complex Topology
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            12/3/10   Initial Version
  %------------------------------------------------------------------------------

  complex_topology: THEORY

  BEGIN

    IMPORTING complex_alt@polar,
              metric_space@metric_space[complex,lambda (x,y:complex): abs(x-y)]

    a,x,y: VAR complex
    r:   VAR posreal
    q:   VAR {x | rational?(Re(x)) & rational?(Im(x))}
    pq:  VAR posrat
    X,A: VAR set[complex]


    IMPORTING metric_space@real_topology % Proof Only

    complex_is_complete: JUDGEMENT fullset[complex] HAS_TYPE
                         metric_complete[complex,lambda x,y: abs(x-y)]

  END complex_topology

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

  % Subtype TCC generated (at line 17, column 46) for
      % LAMBDA (x, y: complex): abs(x - y)
      % expected type  metric[complex]
  IMP_metric_space_TCC1: OBLIGATION
    metric?[complex](LAMBDA (x, y: complex): abs(x - y));

  % Judgement subtype TCC generated (at line 28, column 33) for
      % fullset[complex]
      % expected type  metric_complete
                     %     [complex, LAMBDA (x, y: complex): abs(x - y)]
  complex_is_complete: OBLIGATION
    complete_metric_space?[complex, LAMBDA (x, y: complex): abs(x - y)]
        (fullset[complex]);


body:
  %------------------------------------------------------------------------------
  % Measurable functions [T->complex]
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  % Definition and basic properties of measurable functions f: [T->complex]
  %
  %     Version 1.0            10/3/10   Initial Version
  %------------------------------------------------------------------------------

  complex_measurable[(IMPORTING measure_integration@subset_algebra_def,
                                measure_integration@measure_def)
                     T:TYPE, S:sigma_algebra[T]]: THEORY

  BEGIN

    IMPORTING measure_integration@measure_space[T,S],
              complex_alt@complex_fun_ops[T],
              structures@const_fun_def[T,complex],
              complex_topology

    f: VAR [T->complex]
    s: VAR sequence[[T->complex]]
    x: VAR T
    c: VAR complex
    n: VAR nat
    a: VAR posreal

    complex_measurable?(f):bool = measurable_function?(Re(f)) AND     % SKB 6.4.1
                                  measurable_function?(Im(f))

    complex_measurable: TYPE+ = (complex_measurable?)
                                             CONTAINING (LAMBDA x: complex_(0,0))

    complex_measurable_def:
      LEMMA complex_measurable?(f) <=>
            (measurable_function?(Re(f)) AND measurable_function?(Im(f)))

    AUTO_REWRITE+ complex_measurable_def

    g,g1,g2: VAR complex_measurable

    constant_is_complex_measurable: JUDGEMENT (constant?[T,complex]) SUBTYPE_OF
                                                              complex_measurable

    pointwise_convergence?(s,f):bool
      = FORALL x: convergence?(lambda n: s(n)(x),f(x))

    scal_complex_measurable:  JUDGEMENT *(c,g)   HAS_TYPE complex_measurable
    sum_complex_measurable:   JUDGEMENT +(g1,g2) HAS_TYPE complex_measurable
    opp_complex_measurable:   JUDGEMENT -(g)     HAS_TYPE complex_measurable
    diff_complex_measurable:  JUDGEMENT -(g1,g2) HAS_TYPE complex_measurable

    const_measurable:    LEMMA  complex_measurable?(lambda x: c)

    abs_complex_measurable:      JUDGEMENT abs(g)    HAS_TYPE measurable_function
    sq_complex_measurable:       JUDGEMENT sq(g)     HAS_TYPE complex_measurable
    prod_complex_measurable:     JUDGEMENT *(g1,g2)  HAS_TYPE complex_measurable
    abs_expt_measurable: LEMMA measurable_function?(abs(g)^a)

    u: VAR sequence[complex_measurable]

    pointwise_complex_measurable: LEMMA            % complex analog to SKB 4.1.20
      pointwise_convergence?(u,f) => complex_measurable?(f)


  END complex_measurable

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

  % Subtype TCC generated (at line 36, column 55) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  complex_measurable
  complex_measurable_TCC1: OBLIGATION
    complex_measurable?((LAMBDA x: complex_(0, 0)));

  % Judgement subtype TCC generated (at line 46, column 44) for  x
      % expected type  complex_measurable
  constant_is_complex_measurable: OBLIGATION
    FORALL (x: (constant?[T, complex])): complex_measurable?(x);

  % Judgement subtype TCC generated (at line 52, column 38) for  c * g
      % expected type  complex_measurable
  scal_complex_measurable: OBLIGATION
    FORALL (c, g): complex_measurable?(*[T](c, g));

  % Judgement subtype TCC generated (at line 53, column 38) for  g1 + g2
      % expected type  complex_measurable
  sum_complex_measurable: OBLIGATION
    FORALL (g1, g2): complex_measurable?((+[T])(g1, g2));

  % Judgement subtype TCC generated (at line 54, column 38) for  -g
      % expected type  complex_measurable
  opp_complex_measurable: OBLIGATION FORALL (g): complex_measurable?(-g);

  % Judgement subtype TCC generated (at line 55, column 38) for  g1 - g2
      % expected type  complex_measurable
  diff_complex_measurable: OBLIGATION
    FORALL (g1, g2): complex_measurable?((-[T])(g1, g2));

  % Judgement subtype TCC generated (at line 59, column 41) for  abs(g)
      % expected type  measurable_function[T, S]
  abs_complex_measurable: OBLIGATION
    FORALL (g): measurable_function?[T, S](abs[T](g));

  % Judgement subtype TCC generated (at line 60, column 41) for  sq(g)
      % expected type  complex_measurable
  sq_complex_measurable: OBLIGATION FORALL (g): complex_measurable?(sq[T](g));

  % Judgement subtype TCC generated (at line 61, column 41) for  g1 * g2
      % expected type  complex_measurable
  prod_complex_measurable: OBLIGATION
    FORALL (g1, g2): complex_measurable?(*[T](g1, g2));


body:
  %------------------------------------------------------------------------------
  % Complex Measure Theory [T->complex]
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  % Definition and basic properties of measurable functions f: [T->complex]
  %
  %     Version 1.0            11/3/10   Initial Version
  %------------------------------------------------------------------------------

  complex_measure_theory[(IMPORTING measure_integration@subset_algebra_def,
                                     measure_integration@measure_def)
                       T:TYPE, S:sigma_algebra[T], mu:measure_type[T,S]]: THEORY

  BEGIN

    IMPORTING measure_integration@measure_theory[T,S,mu],
              complex_measurable[T,S]

    p:   VAR pred[[complex,complex]]
    f,g: VAR [T->complex]
    x:   VAR T
    n:   VAR nat
    K:   VAR nnreal

    pointwise_ae?(p)(f,g):bool = ae?(LAMBDA x: p(f(x),g(x)))

    ae?(p)(f,g):   bool = pointwise_ae?(p)(f,g)
    ae_eq?(f,g):   bool = pointwise_ae?(=)(f,g)
    ae_0?(f):      bool = pointwise_ae?(=)(f,lambda x: complex_(0,0))

    ae_bounded?(f):bool = EXISTS K: ae_le?(abs(f),lambda x: K)

    cal_N?(f):bool = ae_0?(f) AND complex_measurable?(f)

    cal_N: TYPE+ = (cal_N?) CONTAINING (lambda x: complex_(0,0))

    cal_N_is_measurable: JUDGEMENT cal_N SUBTYPE_OF complex_measurable

    cal_N_def: LEMMA cal_N?(f) <=>
                     ae_0?(Re(f)) AND measurable_function?(Re(f)) AND
                     ae_0?(Im(f)) AND measurable_function?(Im(f))

  END complex_measure_theory

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

  % Assuming TCC generated (at line 16, column 52) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 39, column 38) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  cal_N
  cal_N_TCC1: OBLIGATION cal_N?((LAMBDA x: complex_(0, 0)));

  % Judgement subtype TCC generated (at line 41, column 33) for  x
      % expected type  complex_measurable[T, S]
  cal_N_is_measurable: OBLIGATION
    FORALL (x: cal_N): complex_measurable?[T, S](x);


body:
  %------------------------------------------------------------------------------
  % Integrals of functions [T->complex]
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  % Definition and basic properties of integrals for functions f: [T->complex]
  %
  %     Version 1.0            1/5/07   Initial Version
  %------------------------------------------------------------------------------

  complex_integral[(IMPORTING measure_integration@subset_algebra_def,
                              measure_integration@measure_def)
                   T:TYPE, S:sigma_algebra[T], mu:measure_type[T,S]]: THEORY

  BEGIN

    IMPORTING measure_integration@integral[T,S,mu],
              complex_alt@complex_fun_ops[T],
              complex_measure_theory[T,S,mu]

    x: VAR T
    c: VAR complex

    integrable?(f:[T->complex]): bool =
      integrable?(Re(f)) AND integrable?(Im(f))

    integrable: TYPE+ = (integrable?) CONTAINING (lambda x: complex_(0,0))

    integral(f:integrable):complex = complex_(integral(Re(f)),integral(Im(f)))

    f,f1,f2: VAR integrable
   
    integrable_def: LEMMA FORALL (f:[T->complex]):
                          integrable?(f) IFF
                          (integrable?(Re(f)) AND integrable?(Im(f)))

    Re_integral: LEMMA Re(integral(f)) = integral(Re(f))
    Im_integral: LEMMA Im(integral(f)) = integral(Im(f))

    AUTO_REWRITE+ integrable_def
    AUTO_REWRITE+ Re_integral
    AUTO_REWRITE+ Im_integral

    integrable_is_measurable: JUDGEMENT integrable SUBTYPE_OF complex_measurable
    cal_N_is_measurable:      JUDGEMENT cal_N      SUBTYPE_OF integrable

    integrable_add:  JUDGEMENT +(f1,f2)    HAS_TYPE integrable
    integrable_scal: JUDGEMENT *(c,f)      HAS_TYPE integrable
    integrable_opp:  JUDGEMENT -(f)        HAS_TYPE integrable
    integrable_diff: JUDGEMENT -(f1,f2)    HAS_TYPE integrable
    integrable_abs:  JUDGEMENT abs(f)      HAS_TYPE integral.integrable

    integral_add:    LEMMA integral(f1+f2)  = integral(f1) + integral(f2)
    integral_scal:   LEMMA integral(c*f)    = c*integral(f)
    integral_opp:    LEMMA integral(-f)     = -integral(f)
    integral_diff:   LEMMA integral(f1-f2)  = integral(f1) - integral(f2)

    integral_abs:    LEMMA abs(integral(f)) <= integral(abs(f))           % 6.4.6

  END complex_integral

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

  % Assuming TCC generated (at line 16, column 48) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 30, column 48) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  integrable
  integrable_TCC1: OBLIGATION integrable?((LAMBDA x: complex_(0, 0)));

  % Subtype TCC generated (at line 32, column 53) for  Re(f)
      % expected type  integrable[T, S, mu]
  integral_TCC1: OBLIGATION
    FORALL (f: integrable): integrable?[T, S, mu](Re[T](f));

  % Subtype TCC generated (at line 32, column 69) for  Im(f)
      % expected type  integrable[T, S, mu]
  integral_TCC2: OBLIGATION
    FORALL (f: integrable): integrable?[T, S, mu](Im[T](f));

  % Judgement subtype TCC generated (at line 47, column 38) for  x
      % expected type  complex_measurable[T, S]
  integrable_is_measurable: OBLIGATION
    FORALL (x: integrable): complex_measurable?[T, S](x);

  % Judgement subtype TCC generated (at line 48, column 38) for  x
      % expected type  integrable
  cal_N_is_measurable: OBLIGATION FORALL (x: cal_N): integrable?(x);

  % Judgement subtype TCC generated (at line 50, column 29) for  f1 + f2
      % expected type  integrable
  integrable_add: OBLIGATION FORALL (f1, f2): integrable?((+[T])(f1, f2));

  % Judgement subtype TCC generated (at line 51, column 29) for  c * f
      % expected type  integrable
  integrable_scal: OBLIGATION FORALL (c, f): integrable?(*[T](c, f));

  % Judgement subtype TCC generated (at line 52, column 29) for  -f
      % expected type  integrable
  integrable_opp: OBLIGATION FORALL (f): integrable?(-f);

  % Judgement subtype TCC generated (at line 53, column 29) for  f1 - f2
      % expected type  integrable
  integrable_diff: OBLIGATION FORALL (f1, f2): integrable?((-[T])(f1, f2));

  % Judgement subtype TCC generated (at line 54, column 29) for  abs(f)
      % expected type  integral[T, S, mu].integrable
  integrable_abs: OBLIGATION FORALL (f): integrable?[T, S, mu](abs[T](f));


body:
  %------------------------------------------------------------------------------
  % p-th power integrable definitions
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            12/03/10   Initial version (DRL)
  %------------------------------------------------------------------------------

  p_integrable_def[(IMPORTING measure_integration@subset_algebra_def,
                              measure_integration@measure_def)
                   T:TYPE, S:sigma_algebra[T], 
                   mu:measure_type[T,S], p:{a:real | a >= 1}]: THEORY

  BEGIN

    IMPORTING complex_integral,
              complex_measure_theory[T,S,mu],
              measure_integration@integral[T,S,mu]

    h: VAR [T->complex]
    x: VAR T

    p_integrable?(h):bool = complex_measurable?(h) AND integrable?(abs(h)^p)

    p_integrable: TYPE+ = (p_integrable?) CONTAINING (lambda x: complex_(0,0))

    cal_N_is_p_integrable: JUDGEMENT cal_N SUBTYPE_OF p_integrable

    f: VAR p_integrable

    norm(f):nnreal = integral(abs(f)^p)^(1/p)

    norm_eq_0: LEMMA norm(f) = 0 <=> cal_N?(f)

  END p_integrable_def

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

  % Assuming TCC generated (at line 12, column 20) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 23, column 72) for  p
      % expected type  posreal
  p_integrable?_TCC1: OBLIGATION
    FORALL (h: [T -> complex]):
      complex_measurable?(h) IMPLIES p >= 0 AND p > 0;

  % Subtype TCC generated (at line 25, column 52) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  p_integrable
  p_integrable_TCC1: OBLIGATION p_integrable?((LAMBDA x: complex_(0, 0)));

  % Judgement subtype TCC generated (at line 27, column 35) for  x
      % expected type  p_integrable
  cal_N_is_p_integrable: OBLIGATION FORALL (x: cal_N): p_integrable?(x);

  % Subtype TCC generated (at line 31, column 35) for  p
      % expected type  posreal
  norm_TCC1: OBLIGATION p >= 0 AND p > 0;

  % Subtype TCC generated (at line 31, column 28) for  abs(f) ^ p
      % expected type  integrable[T, S, mu]
  norm_TCC2: OBLIGATION
    FORALL (f: p_integrable): integrable?[T, S, mu](^[T](abs[T](f), p));

  % Subtype TCC generated (at line 31, column 19) for  integral(abs(f) ^ p)
      % expected type  nnreal
  norm_TCC3: OBLIGATION
    FORALL (f: p_integrable): integral[T, S, mu](^[T](abs[T](f), p)) >= 0;

  % Subtype TCC generated (at line 31, column 41) for  p
      % expected type  nznum
  norm_TCC4: OBLIGATION p /= 0;

  % Subtype TCC generated (at line 31, column 39) for  (1 / p)
      % expected type  {a | a >= 0 OR integral(abs(f) ^ p) > 0}
  norm_TCC5: OBLIGATION
    FORALL (f: p_integrable):
      (1 / p) >= 0 OR integral[T, S, mu](^[T](abs[T](f), p)) > 0;


body:
  %------------------------------------------------------------------------------
  % Holder's Inequality
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            12/3/10   Initial Version
  %------------------------------------------------------------------------------

  holder_scaf[(IMPORTING measure_integration@subset_algebra_def,
                         measure_integration@measure_def)
              T:TYPE, S:sigma_algebra[T], mu:measure_type[T,S],
              p:{a:real | a > 1}, q:{a:posreal | 1/p + 1/a = 1}]: THEORY

  BEGIN

    IMPORTING p_integrable_def,
              young,                                   % Proof only
              measure_integration@integral[T,S,mu] % Proof only

    f: VAR p_integrable[T,S,mu,p]
    g: VAR p_integrable[T,S,mu,q]

    holder_aux: LEMMA
      p_integrable?[T,S,mu,1](f*g) AND
      norm[T,S,mu,1](f*g) <= norm[T,S,mu,p](f) * norm[T,S,mu,q](g)

    holder_judge1: JUDGEMENT *(f,g) HAS_TYPE p_integrable[T,S,mu,1]
    holder_judge2: JUDGEMENT *(g,f) HAS_TYPE p_integrable[T,S,mu,1]

    holder_scaf: LEMMA
      norm[T,S,mu,1](f*g) <= norm[T,S,mu,p](f) * norm[T,S,mu,q](g)

  END holder_scaf

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

  % Assuming TCC generated (at line 14, column 43) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 15, column 49) for  p
      % expected type  nznum
  q_TCC1: OBLIGATION p /= 0;

  % Subtype TCC generated (at line 23, column 9) for
      % p_integrable[T, S, mu, p]
      % expected type  {a: real | a >= 1}
  f_TCC1: OBLIGATION p >= 1;

  % Subtype TCC generated (at line 24, column 9) for
      % p_integrable[T, S, mu, q]
      % expected type  {a: real | a >= 1}
  g_TCC1: OBLIGATION q >= 1;

  % Judgement subtype TCC generated (at line 30, column 27) for  f * g
      % expected type  p_integrable[T, S, mu, 1]
  holder_judge1: OBLIGATION
    FORALL (f, g): p_integrable?[T, S, mu, 1](*[T](f, g));

  % Judgement subtype TCC generated (at line 31, column 27) for  g * f
      % expected type  p_integrable[T, S, mu, 1]
  holder_judge2: OBLIGATION
    FORALL (f, g): p_integrable?[T, S, mu, 1](*[T](g, f));


body:
  %------------------------------------------------------------------------------
  % Minkowski's inequality
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  % Definition and basic properties of measurable functions f: [T->complex]
  %
  %     Version 1.0            13/3/10   Initial Version
  %------------------------------------------------------------------------------
  minkowski_scaf[(IMPORTING measure_integration@subset_algebra_def,
                            measure_integration@measure_def)
                 T:TYPE, S:sigma_algebra[T], mu:measure_type[T,S],
                 p:{x:real | x>=1}]: THEORY

  BEGIN

    IMPORTING p_integrable_def[T,S,mu,p],
              holder_scaf

    f,g: VAR p_integrable

    minkowski_scaf: LEMMA p_integrable?(f+g) AND norm(f+g) <= norm(f) + norm(g)

  END minkowski_scaf

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

  % Assuming TCC generated (at line 15, column 46) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);


body:
  %------------------------------------------------------------------------------
  % p-th power integrable
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            12/03/10   Initial version (DRL)
  %------------------------------------------------------------------------------

  p_integrable[(IMPORTING measure_integration@subset_algebra_def,
                          measure_integration@measure_def)
               T:TYPE, S:sigma_algebra[T], 
               mu:measure_type[T,S], p:{a:real | a >= 1}]: THEORY

  BEGIN

    IMPORTING complex_integral,
              complex_measure_theory[T,S,mu],
              measure_integration@integral[T,S,mu],
              minkowski_scaf[T,S,mu,p]

    x: VAR T

    f,f0,f1: VAR p_integrable
    c: VAR complex

    scal_p_integrable: JUDGEMENT *(c,f)   HAS_TYPE p_integrable
    sum_p_integrable:  JUDGEMENT +(f0,f1) HAS_TYPE p_integrable
    opp_p_integrable:  JUDGEMENT -(f)     HAS_TYPE p_integrable
    diff_p_integrable: JUDGEMENT -(f0,f1) HAS_TYPE p_integrable

    norm_scal: LEMMA norm(c*f)    = abs(c)*norm(f)
    norm_add:  LEMMA norm(f0+f1) <= norm(f0)+norm(f1)
    norm_opp:  LEMMA norm(-f)     = norm(f)
    norm_diff: LEMMA norm(f0-f1) <= norm(f0)+norm(f1)

  END p_integrable

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

  % Assuming TCC generated (at line 12, column 16) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Judgement subtype TCC generated (at line 26, column 31) for  c * f
      % expected type  p_integrable[T, S, mu, p]
  scal_p_integrable: OBLIGATION
    FORALL (c, f): p_integrable?[T, S, mu, p](*[T](c, f));

  % Judgement subtype TCC generated (at line 27, column 31) for  f0 + f1
      % expected type  p_integrable[T, S, mu, p]
  sum_p_integrable: OBLIGATION
    FORALL (f0, f1): p_integrable?[T, S, mu, p]((+[T])(f0, f1));

  % Judgement subtype TCC generated (at line 28, column 31) for  -f
      % expected type  p_integrable[T, S, mu, p]
  opp_p_integrable: OBLIGATION FORALL (f): p_integrable?[T, S, mu, p](-f);

  % Judgement subtype TCC generated (at line 29, column 31) for  f0 - f1
      % expected type  p_integrable[T, S, mu, p]
  diff_p_integrable: OBLIGATION
    FORALL (f0, f1): p_integrable?[T, S, mu, p]((-[T])(f0, f1));


body:
  %------------------------------------------------------------------------------
  % Essentially Bounded functions [T->complex]
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  % Definition and basic properties of integrals for functions f: [T->complex]
  %
  %     Version 1.0            11/3/10   Initial Version
  %------------------------------------------------------------------------------

  essentially_bounded[(IMPORTING measure_integration@subset_algebra_def,
                                 measure_integration@measure_def)
                      T:TYPE, S:sigma_algebra[T], mu:measure_type[T,S]]: THEORY

  BEGIN

    IMPORTING complex_measure_theory[T,S,mu]

    h: VAR [T->complex]
    x: VAR T
    K: VAR nnreal
    c: VAR complex

    essentially_bounded?(h):bool = complex_measurable?(h) AND ae_bounded?(h)

    essentially_bounded: TYPE+ = (essentially_bounded?) CONTAINING
                                                  (lambda x: complex_(0,0))

    f,f0,f1: VAR essentially_bounded

    essential_bound(f): nnreal = inf({K | ae_le?(abs(f),lambda x: K)})

    essential_bound_def1: LEMMA ae_le?(abs(f),lambda x: K) =>
                                essential_bound(f) <= K
    essential_bound_def2: LEMMA ae_le?(abs(f),lambda x: essential_bound(f))

    scal_essentially_bounded: JUDGEMENT *(c,f)   HAS_TYPE essentially_bounded
    add_essentially_bounded:  JUDGEMENT +(f0,f1) HAS_TYPE essentially_bounded
    opp_essentially_bounded:  JUDGEMENT -(f)     HAS_TYPE essentially_bounded
    diff_essentially_bounded: JUDGEMENT -(f0,f1) HAS_TYPE essentially_bounded
    prod_essentially_bounded: JUDGEMENT *(f0,f1) HAS_TYPE essentially_bounded

    essential_bound_scal: LEMMA                                        % 6.6.5(2)
      essential_bound(c*f)    = abs(c)*essential_bound(f)
    essential_bound_add:  LEMMA                                        % 6.6.5(3)
       essential_bound(f0+f1) <= essential_bound(f0)+essential_bound(f1)
    essential_bound_opp:  LEMMA essential_bound(-f) = essential_bound(f)
    essential_bound_diff: LEMMA
      essential_bound(f0-f1) <= essential_bound(f0)+essential_bound(f1)
    essential_bound_eq_0: LEMMA essential_bound(f) = 0 <=> cal_N?(f)   % 6.6.5(4)
    essential_bound_prod: LEMMA                                        % 6.6.5(5)
      essential_bound(f0*f1) <= essential_bound(f0)*essential_bound(f1)


    IMPORTING p_integrable_def[T,S,mu,1]

    g: VAR p_integrable

    holder_judge_infty_1: JUDGEMENT *(f,g) HAS_TYPE p_integrable
    holder_judge_infty_2: JUDGEMENT *(g,f) HAS_TYPE p_integrable

    holder_infty_1: LEMMA norm(f*g) <= essential_bound(f) * norm(g)
    holder_infty_2: LEMMA norm(g*f) <= norm(g) * essential_bound(f)

  END essentially_bounded

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

  % Assuming TCC generated (at line 16, column 51) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 30, column 49) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  essentially_bounded
  essentially_bounded_TCC1: OBLIGATION
    essentially_bounded?((LAMBDA x: complex_(0, 0)));

  % Subtype TCC generated (at line 34, column 35) for
      % extend[real, nnreal, bool, FALSE]({K | ae_le?(abs(f), LAMBDA x: K)})
      % expected type  Sl: inf_set[real]
  essential_bound_TCC1: OBLIGATION
    FORALL (f: essentially_bounded):
      nonempty?[real]
          (extend[real, nnreal, bool, FALSE]
               ({K | ae_le?[T, S, mu](abs[T](f), LAMBDA x: K)}))
       AND
       below_bounded[real]
           (extend[real, nnreal, bool, FALSE]
                ({K | ae_le?[T, S, mu](abs[T](f), LAMBDA x: K)}));

  % Subtype TCC generated (at line 34, column 31) for
      % inf(extend[real, nnreal, bool, FALSE]
      %         ({K | ae_le?(abs(f), LAMBDA x: K)}))
      % expected type  nnreal
  essential_bound_TCC2: OBLIGATION
    FORALL (f: essentially_bounded):
      inf[real]
          (extend[real, nnreal, bool, FALSE]
               ({K | ae_le?[T, S, mu](abs[T](f), LAMBDA x: K)}))
       >= 0;

  % Judgement subtype TCC generated (at line 40, column 38) for  c * f
      % expected type  essentially_bounded
  scal_essentially_bounded: OBLIGATION
    FORALL (c, f): essentially_bounded?(*[T](c, f));

  % Judgement subtype TCC generated (at line 41, column 38) for  f0 + f1
      % expected type  essentially_bounded
  add_essentially_bounded: OBLIGATION
    FORALL (f0, f1): essentially_bounded?((+[T])(f0, f1));

  % Judgement subtype TCC generated (at line 42, column 38) for  -f
      % expected type  essentially_bounded
  opp_essentially_bounded: OBLIGATION FORALL (f): essentially_bounded?(-f);

  % Judgement subtype TCC generated (at line 43, column 38) for  f0 - f1
      % expected type  essentially_bounded
  diff_essentially_bounded: OBLIGATION
    FORALL (f0, f1): essentially_bounded?((-[T])(f0, f1));

  % Judgement subtype TCC generated (at line 44, column 38) for  f0 * f1
      % expected type  essentially_bounded
  prod_essentially_bounded: OBLIGATION
    FORALL (f0, f1): essentially_bounded?(*[T](f0, f1));

  % Judgement subtype TCC generated (at line 62, column 34) for  f * g
      % expected type  p_integrable[T, S, mu, 1]
  holder_judge_infty_1: OBLIGATION
    FORALL (f, g): p_integrable?[T, S, mu, 1](*[T](f, g));

  % Judgement subtype TCC generated (at line 63, column 34) for  g * f
      % expected type  p_integrable[T, S, mu, 1]
  holder_judge_infty_2: OBLIGATION
    FORALL (f, g): p_integrable?[T, S, mu, 1](*[T](g, f));


body:
  cal_L_complex[(IMPORTING measure_integration@subset_algebra_def)
                T:TYPE, S:sigma_algebra[T]]: THEORY

  BEGIN

    IMPORTING essentially_bounded,
              p_integrable

    mu:  VAR measure_type[T,S]
    nu:  VAR finite_measure[T,S]
    h,h1,h2:   VAR [T->complex]
    x:   VAR T
    c:   VAR complex
    p,q: VAR {a:real | a >= 1}

    cal_L_complex_infty?(mu,h):bool = essentially_bounded?[T,S,mu](h)

    cal_L_complex_infty(mu): TYPE+ = (lambda h: cal_L_complex_infty?(mu,h))
                                             CONTAINING (lambda x: complex_(0,0))

    cal_L_complex_infty?(nu,h): bool = cal_L_complex_infty?(to_measure(nu),h)

    cal_L_complex_infty(nu): TYPE+ = cal_L_complex_infty(to_measure(nu))
                                             CONTAINING (lambda x: complex_(0,0))

    cal_L_complex_infty_is_essentially_bounded: LEMMA
       cal_L_complex_infty?(mu,h) <=> essentially_bounded?[T,S,mu](h)

    cal_L_complex?(mu,p,h):bool = p_integrable?[T,S,mu,p](h)

    cal_L_complex(mu,p): TYPE+ = (lambda h: cal_L_complex?(mu,p,h))
                                             CONTAINING (lambda x: complex_(0,0))

    cal_L_complex?(nu,p,h):bool = cal_L_complex?(to_measure(nu),p,h)

    cal_L_complex(nu,p): TYPE+ = cal_L_complex(to_measure(nu),p)
                                             CONTAINING (lambda x: complex_(0,0))

    cal_L_complex_is_p_integrable: LEMMA
       cal_L_complex?(mu,p,h) <=> p_integrable?[T,S,mu,p](h)


    cal_L_complex_1_def: LEMMA cal_L_complex?(mu,1,h) <=> integrable?[T,S,mu](h)

    scal_cal_L: LEMMA cal_L_complex?(mu,p,h) => cal_L_complex?(mu,p,c*h)
    sum_cal_L:  LEMMA cal_L_complex?(mu,p,h1) AND cal_L_complex?(mu,p,h2) =>
                      cal_L_complex?(mu,p,h1+h2)
    opp_cal_L:  LEMMA cal_L_complex?(mu,p,h) => cal_L_complex?(mu,p,-h)
    diff_cal_L: LEMMA cal_L_complex?(mu,p,h1) AND cal_L_complex?(mu,p,h2) =>
                      cal_L_complex?(mu,p,h1-h2)

    prod_cal_L: LEMMA p > 1 AND 1/p + 1/q = 1  AND
                      cal_L_complex?(mu,p,h1) AND
                      cal_L_complex?(mu,q,h2) =>
                      cal_L_complex?(mu,1,h1*h2)

    scal_cal_L_infty: LEMMA cal_L_complex_infty?(mu,h) =>
                            cal_L_complex_infty?(mu,c*h)
    sum_cal_L_infty:  LEMMA cal_L_complex_infty?(mu,h1) AND
                            cal_L_complex_infty?(mu,h2) =>
                            cal_L_complex_infty?(mu,h1+h2)
    opp_cal_L_infty:  LEMMA cal_L_complex_infty?(mu,h) =>
                            cal_L_complex_infty?(mu,-h)
    diff_cal_L_infty: LEMMA cal_L_complex_infty?(mu,h1) AND
                            cal_L_complex_infty?(mu,h2) =>
                            cal_L_complex_infty?(mu,h1-h2)
    prod_cal_L_infty: LEMMA cal_L_complex_infty?(mu,h1) AND
                            cal_L_complex_infty?(mu,h2) =>
                            cal_L_complex_infty?(mu,h1*h2)

    prod_cal_L_1_infty: LEMMA cal_L_complex?(mu,1,h1)     AND
                              cal_L_complex_infty?(mu,h2) =>
                              cal_L_complex?(mu,1,h1*h2)

    prod_cal_L_infty_1: LEMMA cal_L_complex_infty?(mu,h1) AND
                              cal_L_complex?(mu,1,h2)     =>
                              cal_L_complex?(mu,1,h1*h2)

    scal_cal_L_fm: LEMMA cal_L_complex?(nu,p,h) => cal_L_complex?(nu,p,c*h)
    sum_cal_L_fm:  LEMMA cal_L_complex?(nu,p,h1) AND cal_L_complex?(nu,p,h2) =>
                         cal_L_complex?(nu,p,h1+h2)
    opp_cal_L_fm:  LEMMA cal_L_complex?(nu,p,h) => cal_L_complex?(nu,p,-h)
    diff_cal_L_fm: LEMMA cal_L_complex?(nu,p,h1) AND cal_L_complex?(nu,p,h2) =>
                         cal_L_complex?(nu,p,h1-h2)

    prod_cal_L_fm: LEMMA p > 1 AND 1/p + 1/q = 1  AND
                         cal_L_complex?(nu,p,h1) AND
                         cal_L_complex?(nu,q,h2) =>
                         cal_L_complex?(nu,1,h1*h2)

    scal_cal_L_infty_fm: LEMMA cal_L_complex_infty?(nu,h) =>
                               cal_L_complex_infty?(nu,c*h)
    sum_cal_L_infty_fm:  LEMMA cal_L_complex_infty?(nu,h1) AND
                               cal_L_complex_infty?(nu,h2) =>
                               cal_L_complex_infty?(nu,h1+h2)
    opp_cal_L_infty_fm:  LEMMA cal_L_complex_infty?(nu,h) =>
                               cal_L_complex_infty?(nu,-h)
    diff_cal_L_infty_fm: LEMMA cal_L_complex_infty?(nu,h1) AND
                               cal_L_complex_infty?(nu,h2) =>
                               cal_L_complex_infty?(nu,h1-h2)
    prod_cal_L_infty_fm: LEMMA cal_L_complex_infty?(nu,h1) AND
                               cal_L_complex_infty?(nu,h2) =>
                               cal_L_complex_infty?(nu,h1*h2)

    prod_cal_L_1_infty_fm: LEMMA cal_L_complex?(nu,1,h1)     AND
                                 cal_L_complex_infty?(nu,h2) =>
                                 cal_L_complex?(nu,1,h1*h2)

    prod_cal_L_infty_1_fm: LEMMA cal_L_complex_infty?(nu,h1) AND
                                 cal_L_complex?(nu,1,h2)     =>
                                 cal_L_complex?(nu,1,h1*h2)

  END cal_L_complex

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

  % Assuming TCC generated (at line 9, column 11) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 19, column 55) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  cal_L_complex_infty(mu)
  cal_L_complex_infty_TCC1: OBLIGATION
    FORALL (mu: measure_type[T, S]):
      cal_L_complex_infty?(mu, (LAMBDA x: complex_(0, 0)));

  % Subtype TCC generated (at line 24, column 55) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  cal_L_complex_infty(nu)
  cal_L_complex_infty_TCC2: OBLIGATION
    FORALL (nu: finite_measure[T, S]):
      cal_L_complex_infty?(to_measure[T, S](nu), (LAMBDA x: complex_(0, 0)));

  % Subtype TCC generated (at line 32, column 55) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  cal_L_complex(mu, p)
  cal_L_complex_TCC1: OBLIGATION
    FORALL (mu: measure_type[T, S], p: {a: real | a >= 1}):
      cal_L_complex?(mu, p, (LAMBDA x: complex_(0, 0)));

  % Subtype TCC generated (at line 37, column 55) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  cal_L_complex(nu, p)
  cal_L_complex_TCC2: OBLIGATION
    FORALL (nu: finite_measure[T, S], p: {a: real | a >= 1}):
      cal_L_complex?(to_measure[T, S](nu), p, (LAMBDA x: complex_(0, 0)));

  % Subtype TCC generated (at line 52, column 32) for  p
      % expected type  nznum
  prod_cal_L_TCC1: OBLIGATION
    FORALL (p: {a: real | a >= 1}): p > 1 IMPLIES p /= 0;

  % Subtype TCC generated (at line 52, column 38) for  q
      % expected type  nznum
  prod_cal_L_TCC2: OBLIGATION
    FORALL (p, q: {a: real | a >= 1}): p > 1 IMPLIES q /= 0;


body:
  cal_L_real[(IMPORTING measure_integration@subset_algebra_def)
             T:TYPE, S:sigma_algebra[T]]: THEORY

  BEGIN

    IMPORTING cal_L_complex[T,S]

    mu:  VAR measure_type[T,S]
    nu:  VAR finite_measure[T,S]
    h,h1,h2:   VAR [T->real]
    x:   VAR T
    c:   VAR real
    p,q: VAR {a:real | a >= 1}

    cal_L_real_infty?(mu,h):bool
      = cal_L_complex_infty?(mu,lambda x: complex_(h(x),0))

    cal_L_real_infty(mu): TYPE+ = (lambda h: cal_L_real_infty?(mu,h))
                                             CONTAINING (lambda x: 0)

    cal_L_real_infty?(nu,h): bool = cal_L_real_infty?(to_measure(nu),h)

    cal_L_real_infty(nu): TYPE+ = cal_L_real_infty(to_measure(nu))
                                             CONTAINING (lambda x: 0)

    cal_L_real?(mu,p,h):bool
      = cal_L_complex?(mu,p,lambda x: complex_(h(x),0))

    cal_L_real(mu,p): TYPE+ = (lambda h: cal_L_real?(mu,p,h))
                                             CONTAINING (lambda x: 0)

    cal_L_real?(nu,p,h):bool = cal_L_real?(to_measure(nu),p,h)

    cal_L_real(nu,p): TYPE+ = cal_L_real(to_measure(nu),p)
                                             CONTAINING (lambda x: 0)

    cal_L_real_1_def: LEMMA cal_L_real?(mu,1,h) <=> integrable?[T,S,mu](h)

    scal_cal_LR: LEMMA cal_L_real?(mu,p,h) => cal_L_real?(mu,p,c*h)
    sum_cal_LR:  LEMMA cal_L_real?(mu,p,h1) AND cal_L_real?(mu,p,h2) =>
                      cal_L_real?(mu,p,h1+h2)
    opp_cal_LR:  LEMMA cal_L_real?(mu,p,h) => cal_L_real?(mu,p,-h)
    diff_cal_LR: LEMMA cal_L_real?(mu,p,h1) AND cal_L_real?(mu,p,h2) =>
                      cal_L_real?(mu,p,h1-h2)

    prod_cal_LR: LEMMA p > 1 AND 1/p + 1/q = 1  AND
                      cal_L_real?(mu,p,h1) AND
                      cal_L_real?(mu,q,h2) =>
                      cal_L_real?(mu,1,h1*h2)

    scal_cal_L_inftyR: LEMMA cal_L_real_infty?(mu,h) =>
                            cal_L_real_infty?(mu,c*h)
    sum_cal_L_inftyR:  LEMMA cal_L_real_infty?(mu,h1) AND
                            cal_L_real_infty?(mu,h2) =>
                            cal_L_real_infty?(mu,h1+h2)
    opp_cal_L_inftyR:  LEMMA cal_L_real_infty?(mu,h) =>
                            cal_L_real_infty?(mu,-h)
    diff_cal_L_inftyR: LEMMA cal_L_real_infty?(mu,h1) AND
                            cal_L_real_infty?(mu,h2) =>
                            cal_L_real_infty?(mu,h1-h2)
    prod_cal_L_inftyR: LEMMA cal_L_real_infty?(mu,h1) AND
                            cal_L_real_infty?(mu,h2) =>
                            cal_L_real_infty?(mu,h1*h2)

    prod_cal_L_1_inftyR: LEMMA cal_L_real?(mu,1,h1)     AND
                              cal_L_real_infty?(mu,h2) =>
                              cal_L_real?(mu,1,h1*h2)

    prod_cal_L_infty_1R: LEMMA cal_L_real_infty?(mu,h1) AND
                              cal_L_real?(mu,1,h2)     =>
                              cal_L_real?(mu,1,h1*h2)

    scal_cal_L_fmR: LEMMA cal_L_real?(nu,p,h) => cal_L_real?(nu,p,c*h)
    sum_cal_L_fmR:  LEMMA cal_L_real?(nu,p,h1) AND cal_L_real?(nu,p,h2) =>
                         cal_L_real?(nu,p,h1+h2)
    opp_cal_L_fmR:  LEMMA cal_L_real?(nu,p,h) => cal_L_real?(nu,p,-h)
    diff_cal_L_fmR: LEMMA cal_L_real?(nu,p,h1) AND cal_L_real?(nu,p,h2) =>
                         cal_L_real?(nu,p,h1-h2)

    prod_cal_L_fmR: LEMMA p > 1 AND 1/p + 1/q = 1  AND
                         cal_L_real?(nu,p,h1) AND
                         cal_L_real?(nu,q,h2) =>
                         cal_L_real?(nu,1,h1*h2)

    scal_cal_L_infty_fmR: LEMMA cal_L_real_infty?(nu,h) =>
                               cal_L_real_infty?(nu,c*h)
    sum_cal_L_infty_fmR:  LEMMA cal_L_real_infty?(nu,h1) AND
                               cal_L_real_infty?(nu,h2) =>
                               cal_L_real_infty?(nu,h1+h2)
    opp_cal_L_infty_fmR:  LEMMA cal_L_real_infty?(nu,h) =>
                               cal_L_real_infty?(nu,-h)
    diff_cal_L_infty_fmR: LEMMA cal_L_real_infty?(nu,h1) AND
                               cal_L_real_infty?(nu,h2) =>
                               cal_L_real_infty?(nu,h1-h2)
    prod_cal_L_infty_fmR: LEMMA cal_L_real_infty?(nu,h1) AND
                               cal_L_real_infty?(nu,h2) =>
                               cal_L_real_infty?(nu,h1*h2)

    prod_cal_L_1_infty_fmR: LEMMA cal_L_real?(nu,1,h1)     AND
                                 cal_L_real_infty?(nu,h2) =>
                                 cal_L_real?(nu,1,h1*h2)

    prod_cal_L_infty_1_fmR: LEMMA cal_L_real_infty?(nu,h1) AND
                                 cal_L_real?(nu,1,h2)     =>
                                 cal_L_real?(nu,1,h1*h2)

  END cal_L_real

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

  % Assuming TCC generated (at line 8, column 11) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 19, column 55) for  (LAMBDA x: 0)
      % expected type  cal_L_real_infty(mu)
  cal_L_real_infty_TCC1: OBLIGATION
    FORALL (mu: measure_type[T, S]): cal_L_real_infty?(mu, (LAMBDA x: 0));

  % Subtype TCC generated (at line 24, column 55) for  (LAMBDA x: 0)
      % expected type  cal_L_real_infty(nu)
  cal_L_real_infty_TCC2: OBLIGATION
    FORALL (nu: finite_measure[T, S]):
      cal_L_real_infty?(to_measure[T, S](nu), (LAMBDA x: 0));

  % Subtype TCC generated (at line 30, column 55) for  (LAMBDA x: 0)
      % expected type  cal_L_real(mu, p)
  cal_L_real_TCC1: OBLIGATION
    FORALL (mu: measure_type[T, S], p: {a: real | a >= 1}):
      cal_L_real?(mu, p, (LAMBDA x: 0));

  % Subtype TCC generated (at line 35, column 55) for  (LAMBDA x: 0)
      % expected type  cal_L_real(nu, p)
  cal_L_real_TCC2: OBLIGATION
    FORALL (nu: finite_measure[T, S], p: {a: real | a >= 1}):
      cal_L_real?(to_measure[T, S](nu), p, (LAMBDA x: 0));

  % Subtype TCC generated (at line 46, column 33) for  p
      % expected type  nznum
  prod_cal_LR_TCC1: OBLIGATION
    FORALL (p: {a: real | a >= 1}): p > 1 IMPLIES p /= 0;

  % Subtype TCC generated (at line 46, column 39) for  q
      % expected type  nznum
  prod_cal_LR_TCC2: OBLIGATION
    FORALL (p, q: {a: real | a >= 1}): p > 1 IMPLIES q /= 0;


body:
  %------------------------------------------------------------------------------
  % Complex Integration with Finite Measures
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %%
  %     Version 1.0            20/3/11   Initial Version
  %------------------------------------------------------------------------------

  complex_finite_measures[(IMPORTING measure_integration@subset_algebra_def,
                                     measure_integration@measure_def)
                   T:TYPE, S:sigma_algebra[T], mu:finite_measure[T,S]]: THEORY

  BEGIN

    IMPORTING p_integrable,
              measure_integration@integral[T,S,to_measure(mu)],
              essentially_bounded[T,S,to_measure(mu)]

    p,q: VAR {a:real | a >= 1}
    f:   VAR [T -> complex]

    q_integrable_is_p_integrable: LEMMA
       p <= q AND
       p_integrable?[T,S,to_measure(mu),q](f) =>
       p_integrable?[T,S,to_measure(mu),p](f)

    essentially_bounded_is_p_integrable: LEMMA
       essentially_bounded?(f) => p_integrable?[T,S,to_measure(mu),p](f)

  END complex_finite_measures

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

  % Assuming TCC generated (at line 14, column 48) for  finite_measure[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);


body:
  %------------------------------------------------------------------------------
  % L^\infty
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  % Definition and basic properties of measurable functions f: [T->complex]
  %
  %     Version 1.0            11/3/10   Initial Version
  %------------------------------------------------------------------------------

  cal_L_inf[(IMPORTING measure_integration@subset_algebra_def,
                       measure_integration@measure_def)
            T:TYPE, S:sigma_algebra[T], mu:measure_type[T,S]]: THEORY

  BEGIN

    IMPORTING essentially_bounded[T,S,mu],
              complex_alt@complex_fun_ops[T]

    h: VAR [T->complex]
    x: VAR T

    cal_L_infty?(h):bool = essentially_bounded?(h)

    cal_L_infty: TYPE+ = (cal_L_infty?) CONTAINING (lambda x: complex_(0,0))

    cal_L_infty_is_essentially_bounded:
                             JUDGEMENT cal_L_infty SUBTYPE_OF essentially_bounded

    f,f0,f1: VAR cal_L_infty
    c: VAR complex

    scal_cal_L_infty: JUDGEMENT *(c,f)   HAS_TYPE cal_L_infty
    add_cal_L_infty:  JUDGEMENT +(f0,f1) HAS_TYPE cal_L_infty
    opp_cal_L_infty:  JUDGEMENT -(f)     HAS_TYPE cal_L_infty
    diff_cal_L_infty: JUDGEMENT -(f0,f1) HAS_TYPE cal_L_infty
    prod_cal_L_infty: JUDGEMENT *(f0,f1) HAS_TYPE cal_L_infty

    inf_norm(f):nnreal = essential_bound(f)                            % 6.6.5(1)

    inf_norm_scal: LEMMA inf_norm(c*f)    = abs(c)*inf_norm(f)         % 6.6.5(2)
    inf_norm_add:  LEMMA inf_norm(f0+f1) <= inf_norm(f0)+inf_norm(f1)  % 6.6.5(3)
    inf_norm_opp:  LEMMA inf_norm(-f)     = inf_norm(f)
    inf_norm_diff: LEMMA inf_norm(f0-f1) <= inf_norm(f0)+inf_norm(f1)
    inf_norm_eq_0: LEMMA inf_norm(f) = 0 <=> cal_N?(f)                 % 6.6.5(4)
    inf_norm_prod: LEMMA inf_norm(f0*f1) <= inf_norm(f0)*inf_norm(f1)  % 6.6.5(5)

    IMPORTING p_integrable_def[T,S,mu,1]

    g: VAR p_integrable

    holder_judge_inf_1: JUDGEMENT *(f,g) HAS_TYPE p_integrable
    holder_judge_inf_2: JUDGEMENT *(g,f) HAS_TYPE p_integrable

    holder_infty_1: LEMMA norm(f*g) <= inf_norm(f) * norm(g)

  END cal_L_inf

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

  % Assuming TCC generated (at line 16, column 41) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);

  % Subtype TCC generated (at line 28, column 50) for
      % (LAMBDA x: complex_(0, 0))
      % expected type  cal_L_infty
  cal_L_infty_TCC1: OBLIGATION cal_L_infty?((LAMBDA x: complex_(0, 0)));

  % Judgement subtype TCC generated (at line 31, column 37) for  x
      % expected type  essentially_bounded[T, S, mu]
  cal_L_infty_is_essentially_bounded: OBLIGATION
    FORALL (x: cal_L_infty): essentially_bounded?[T, S, mu](x);

  % Judgement subtype TCC generated (at line 36, column 30) for  c * f
      % expected type  cal_L_infty
  scal_cal_L_infty: OBLIGATION FORALL (c, f): cal_L_infty?(*[T](c, f));

  % Judgement subtype TCC generated (at line 37, column 30) for  f0 + f1
      % expected type  cal_L_infty
  add_cal_L_infty: OBLIGATION FORALL (f0, f1): cal_L_infty?((+[T])(f0, f1));

  % Judgement subtype TCC generated (at line 38, column 30) for  -f
      % expected type  cal_L_infty
  opp_cal_L_infty: OBLIGATION FORALL (f): cal_L_infty?(-f);

  % Judgement subtype TCC generated (at line 39, column 30) for  f0 - f1
      % expected type  cal_L_infty
  diff_cal_L_infty: OBLIGATION FORALL (f0, f1): cal_L_infty?((-[T])(f0, f1));

  % Judgement subtype TCC generated (at line 40, column 30) for  f0 * f1
      % expected type  cal_L_infty
  prod_cal_L_infty: OBLIGATION FORALL (f0, f1): cal_L_infty?(*[T](f0, f1));


body:
  %------------------------------------------------------------------------------
  % Completeness of Essential Bounds
  %
  %     Author: David Lester, Manchester University
  %
  % All references are to SK Berberian "Fundamentals of Real Analysis",
  % Springer, 1991
  %
  %     Version 1.0            19/3/11   Initial Version
  %------------------------------------------------------------------------------

  essential_bound_complete_scaf[
                      (IMPORTING measure_integration@subset_algebra_def,
                                 measure_integration@measure_def)
                      T:TYPE, S:sigma_algebra[T], mu:measure_type[T,S]]: THEORY

  BEGIN

    IMPORTING essentially_bounded[T,S,mu],
              topology@subseq[essentially_bounded], % Proof only
              complex_topology                      % Proof only

    F: VAR sequence[essentially_bounded]
    f: VAR essentially_bounded
    r: VAR posreal
    i,j,n: VAR nat

    essential_bound_complete_scaf: LEMMA
        (FORALL r: EXISTS n: FORALL i,j: i >= n AND j >= n =>
             essential_bound(F(j)-F(i)) < r)
      IMPLIES
        (EXISTS f: FORALL r: EXISTS n: FORALL i: i >= n =>
             essential_bound(f-F(i)) < r)

  END essential_bound_complete_scaf

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

  % Assuming TCC generated (at line 15, column 51) for  measure_type[T, S]
      % generated from assumption generalized_measure_def.S_empty
  mu_TCC1: OBLIGATION S(emptyset[T]);


body:
  %  min_walk_reduced      -- theorem that minimum walk is reduced
  %  min_walks             -- minimum walk satisfying a propertyx
  %  path_ops              -- deleting vertex and edge operations
  %  paths                 -- fundamental definition and properties about paths
  %  reduce_walks          -- operation to reduce a walk
  %  sep_sets              -- definition of separating sets
  %  di_subgraphs           -- generation of di_subgraphs from vertex sets
  %  di_subgraphs_from_walk -- generation of di_subgraphs from walks
  %  subtrees              -- subtrees of a digraph
  %  trees                 -- fundamental definition of trees
  %  walk_inductions       -- induction on length of a walk
  %  walks                 -- fundamental definition and properties of walks
  %
  %------------------------------------------------------------------------------
  top: THEORY

  BEGIN

     IMPORTING digraphs,
               digraph_deg, 
               walks,
               paths, 
               path_ops,
               dags,
               circuits, 
               cycles, 
               di_subgraphs, 
               di_subgraphs_from_walk, 
               digraph_ops,
               max_di_subgraphs,
               max_subtrees,
               trees, 
               subtrees, 
               walk_inductions,
               min_walk_reduced, 
               reduce_walks,
  	     abstract_min,
  	     abstract_max,
  	     pairs,
  	     digraph_conn_defs,
  	     digraph_inductions,
  	     ind_paths,
  	     min_walks,         
  	     sep_sets,
  	     weighted_digraphs,
               wgt_digraphs_props,
               Eulerian

  %  digraph_deg_sum       -- theorem relating vertex degree and number of edges
  %  tree_circ             -- theorem that tree has no circuits
  %  digraph_connected     -- all connected defs are equivalent
  %  ramsey_new            -- Ramsey's theorem
  %  menger                -- menger's theorem
  %  tree_paths            -- theorem that tree has only one path between vertices
  %  circuit_deg           -- degree of circuits
  %  cycle_deg             -- theorem about degree and existence of cycle
  %  digraph_complected    -- unusual definition of connected digraph
  %  digraph_conn_piece    -- structural connected ==> piece connected
  %  digraph_path_conn     -- path connected ==> structural connected
  %  digraph_piece_path    -- piece connected ==> path connected
  %  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
  %  sep_set_lems          -- properties of separating sets

  %            digraph_deg_sum, 
  %            tree_circ, 
  %            digraph_connected, 
  %            ramsey_new,
  %            menger, 
  %            tree_paths,         % Proof incorrect
  %            circuit_deg,  
  %	     cycle_deg,          % not attempted yet
  %	     digraph_complected  ,
  %	     digraph_conn_piece  ,
  %	     digraph_connected   ,
  %	     digraph_path_conn   ,
  %	     digraph_piece_path  ,
  %	     h_menger          ,
  %	     meng_scaff        ,
  %	     meng_scaff_defs   ,
  %	     meng_scaff_prelude,
  %	     menger            ,
  %	     sep_set_lems      ,


  END top


body:
  pairs[T: TYPE]: THEORY

  BEGIN

     x,y,v,z: VAR T

     pair: TYPE = [T,T]

     mk_pair(x,y): pair = (x,y)

     mk_pair_eq: LEMMA mk_pair(x,y) = mk_pair(v,z) IMPLIES (x = v AND y = z) 

     in?(z:T, p: pair): bool = LET (x,y) = p IN z = x OR z = y

     apair?(x,y): bool = (x /= y)

     apair: TYPE = {p: pair | LET (x,y) = p IN x /= y}

     ap: VAR apair
     apair_irreflexive  : LEMMA LET (x,y) = ap IN x /= y

  END pairs


body:
  digraphs[T: TYPE]: THEORY
  %-------------------------------------------------------------------------------
  %
  % Defines:
  %
  %      digraph[T] -- digraph over domain T
  %      vert(G)  -- vertices of digraph G
  %      edges(G) -- set of edges in a digraph G
  %
  %  Authors:
  %
  %      Ricky W. Butler, Kristin Y. Rozier   NASA Langley
  %      Jon Sjogren                          AFOSR
  %
  %  Version 1.0           Last modified 07/15/04
  %
  %  Maintained by:
  %
  %     Rick Butler        NASA Langley Research Center   
  %                        R.W.Butler@larc.nasa.gov
  %
  %  NOTE:
  %
  %-------------------------------------------------------------------------------
  BEGIN

    IMPORTING %finite_sets@finite_sets[T], 
               pairs[T] 
              %finite_sets@finite_sets[pair[T]]

    x,y,v: VAR T

    edgetype: TYPE = pair[T]     % ---------- ALLOW SELF LOOPS ----------

    predigraph: TYPE = [# vert : finite_set[T],
                          edges: finite_set[edgetype] #]

    e: VAR edgetype

    directed_graph: TYPE = {g: predigraph | FORALL e: edges(g)(e) IMPLIES 
                                        LET (x,y) = e IN vert(g)(x) AND vert(g)(y)}

    digraph       : TYPE = directed_graph

    % A simple digraph is a graph without loops
    simple_digraph: TYPE = {g: digraph | FORALL e: edges(g)(e) IMPLIES 
                                                   LET (x,y) = e IN x /= y}

    sd_graph      : TYPE = simple_digraph

    % An empty digraph: empty set of vertices and empty set of edges
    empty_digraph: digraph =
            (# vert := emptyset[T],
              edges := emptyset[edgetype] #)


    G: var digraph

    vert?(G)(x)  : bool = vert(G)(x)
    edge?(G)(x,y): bool = edges(G)((x,y))
   
    edge(G) : TYPE = (edge?(G))
    vert(G) : TYPE = (vert?(G))



    edges_vert      : LEMMA in?(x,e) AND edges(G)(e) IMPLIES
                               (EXISTS y: vert(G)(y) AND in?(y,e))


    other_vert      : LEMMA in?(v,e) AND edges(G)(e)
                            IMPLIES (EXISTS (u: T): vert(G)(u) AND 
                                         e = (u, v) OR e = (v,u))

    edges_to_pair   : LEMMA edges(G)(e) IMPLIES
                              (EXISTS x,y: edges(G)(x,y) 
                                       AND vert(G)(x) AND vert(G)(y)
                                       AND x = proj_1(e) AND y = proj_2(e)) 



  % -------------- size of digraphs --------------------


    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))

    bidirected?(G)(x,y): bool = edges(G)(x,y) AND edges(G)(y,x)

    %A complete digraph differs from a complete graph in that each edge must be
    %bidirected.
    complete?(G): bool = 
                        FORALL (x:T | (vert(G)(x)), y:T | (vert(G)(y) AND x /= y)):
                           edges(G)(x,y) OR edges(G)(y,x)

    digraph_complete?(G): bool = 
                        FORALL (x:T | (vert(G)(x)), y:T | (vert(G)(y) AND x /= y)):
                           bidirected?(G)(x,y)

    complete_digraph: TYPE = {g: digraph | complete?(g)}

    %An oriented graph has no bidirected edges:
    oriented?(G): bool = FORALL (x:T | (vert(G)(x)), y:T | (vert(G)(y) AND x/=y)):
                              NOT bidirected?(G)(x,y)

    oriented_digraph: TYPE = {g: digraph | oriented?(g)}

    tournament?(G): bool = complete?(G) AND oriented?(G)

    tournament: TYPE = {g: digraph | tournament?(g)}

    empty?_rew          : LEMMA empty?(G) = (card(vert(G)) = 0)

    empty_size          : LEMMA empty?(G) IFF size(G) = 0

    edges_of_empty      : LEMMA empty?(G) 
                                   IMPLIES edges(G) = emptyset[edgetype]

    singleton_edges     : LEMMA FORALL (SG: simple_digraph): 
                                     singleton?(SG) IMPLIES empty?(edges(SG))

    edge_in_card_gt_1   : LEMMA FORALL (SG: simple_digraph): 
                                     edges(SG)(e) IMPLIES card(vert(SG)) > 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))

    proj_rew: LEMMA (proj_1(e), proj_2(e)) = e

    infdigraph: TYPE = [# vert : set[T],
                        edges: set[edgetype] #]


    is_digraph(g: infdigraph): bool = is_finite[T](vert(g))
                                  AND is_finite[edgetype](edges(g))
                                  AND (FORALL (e: edgetype): edges(g)(e) 
                               IMPLIES (FORALL x: in?(x,e) IMPLIES vert(g)(x)))

    singleton_digraph(v): digraph = (# vert := singleton[T](v), 
                                         edges := emptyset[edgetype] #)
    
    is_sing:  LEMMA singleton?(singleton_digraph(x))

    Digraph: TYPE = {g: digraph | nonempty?(vert(g))}

  END digraphs

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

  % Subtype TCC generated (at line 53, column 10) for
      % (# vert := emptyset[T], edges := emptyset[edgetype] #)
      % expected type  digraph
  empty_digraph_TCC1: OBLIGATION
    FORALL e:
      emptyset[edgetype](e) IMPLIES emptyset[T](e`1) AND emptyset[T](e`2);

  % Subtype TCC generated (at line 145, column 34) for
      % (# vert := singleton[T](v), edges := emptyset[edgetype] #)
      % expected type  digraph
  singleton_digraph_TCC1: OBLIGATION
    FORALL (v: T):
      FORALL e:
        emptyset[edgetype](e) IMPLIES
         singleton[T](v)(e`1) AND singleton[T](v)(e`2);


body:
  walks[T: TYPE]: THEORY

  BEGIN

     IMPORTING digraphs[T],
               structures@seq_extras[T]
               


     G,GG: VAR digraph[T]
     n: VAR nat
     x,u,v,u1,u2,v1,v2,v3: VAR T
     e: VAR edgetype[T]
     i,j: VAR nat


  % -------------------------------------------------------------------------------
  %     Definitions
  % -------------------------------------------------------------------------------

     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)}

     from?(ps,u,v): bool = seq(ps)(0) = u AND seq(ps)(length(ps) - 1) = v

     walk_from?(G,ps,u,v): bool = from?(ps,u,v) AND walk?(G,ps)

     Walk_from(G,u,v): TYPE = {w: prewalk | walk_from?(G,w,u,v)}

     set_walk_from(G, e): set[prewalk] = 
           LET (u, v) = e IN {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[edgetype[T]] = {e: edgetype[T] |
                             EXISTS (i: below(length(ww)-1)): e = (ww(i),ww(i+1))}

  %  ----------------------- Properties -----------------------

     walk_from_l     : LEMMA walk_from?(G,ps,u,v) AND u /= v IMPLIES length(ps) >= 2

     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)

     prewalk_across: LEMMA ww(0) /= ww(length(ww)-1) AND length(ww) > 1 IMPLIES
                          (EXISTS (i: below(length(ww)-1)): ww(i) = ww(0) AND
                                                    ww(i+1) /= ww(0))
    
  %  ----------- 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}

     lWalk(G) : TYPE = {w: Longprewalk | walk?(G,w)}
     
     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)((u, v)) IMPLIES
                               walk?(G,gen_seq2(G,u,v))

     w1,w2: VAR prewalk

  %%%%%%%%%%%%%%%%%%%%% NOT THEOREMS for directed graphs %%%%%%%%%%%%%%
  %
  %   walk?_rev       : LEMMA walk?(G,ps) IMPLIES walk?(G,rev(ps))
  %
  %   
  %
  %   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, v, u2)
        		 IMPLIES
        		     walk_from?(G, w1 ^ (0, length(w1) - 2) o 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, u, yt) AND
        	             walk_from?(G, p2, yt, v )
                             IMPLIES
        	                (EXISTS (p: prewalk): walk_from?(G, p, u, v))




  %********************************************************************************%
  %
  %   Contributions from:
  %
  %       Andréia Borges Avelar -- Universidade de Brasília - Brasil  
  %       Mauricio Ayala-Rincon -- Universidade de Brasília - Brasil  
  %                 Cesar Muñoz -- NASA Langley Research Center - US
  %
  %********************************************************************************%

  % --------------------------------------------------------------------------------
  %     Definitions
  % --------------------------------------------------------------------------------

   sub_walk?(G: digraph, w: Walk(G), ww): bool =  
      EXISTS (i, j: below(length(w))): w^(i,j) = ww

   reachable?(G)( u, v : (vert(G)) ) : bool = (u = v OR
      EXISTS (w: prewalk) : walk_from?(G, w, u, v))

   reord_prewalk(w: prewalk, i: posnat): prewalk =
      w ^ (i, length(w) - 1) o w ^ (0, i - 1)

   eq_prewalk?(w1, w2: prewalk): bool =
      w1 = w2 OR EXISTS (i: posnat): w2 = reord_prewalk(w1, i)

   % owalk(G: digraph, w1, w2: Walk(G) | last(w1) = first(w2)): Walk(G) =
   %     w1 o rest(w2)


  % --------------------------------------------------------------------------------
  %     Properties
  % --------------------------------------------------------------------------------

   eq_relation_eq_prewalk: LEMMA
      equivalence?(eq_prewalk?)

   eq_prewalk_length: LEMMA
      FORALL(w1, w2: prewalk): eq_prewalk?(w1, w2) IMPLIES length(w1) = length(w2)

   subwalk_is_walk : LEMMA
      FORALL (w: Walk(G)): sub_walk?(G, w, ww) IMPLIES walk?(G, ww)

   walk_o: LEMMA
      walk?(G, w1) AND walk?(G, w2) AND seq(w1)(length(w1) - 1) = seq(w2)(0)
      IMPLIES walk?(G, w1 o w2^(1, length(w2) - 1))

   edges_o_walk: LEMMA
      walk?(G, w1) AND walk?(G, w2) AND last(w1) = first(w2)
      IMPLIES edges_of(w1 o rest(w2)) = union(edges_of(w1), edges_of(w2))


  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: digraph[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: digraph[T], ps: prewalk):
      verts_in?(G, ps) IMPLIES
       (FORALL (n): n < length(ps) - 1 IMPLIES n + 1 < length(ps));

  % Subtype TCC generated (at line 35, 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 35, 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 45, 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 48, column 68) for  i
      % expected type  below[length(ww)]
  edges_of_TCC1: OBLIGATION
    FORALL (ww: prewalk, e: edgetype[T], i: below(length(ww) - 1)):
      i < length(ww);

  % Subtype TCC generated (at line 48, column 74) for  i + 1
      % expected type  below[length(ww)]
  edges_of_TCC2: OBLIGATION
    FORALL (ww: prewalk, e: edgetype[T], i: below(length(ww) - 1)):
      i + 1 < length(ww);

  % Subtype TCC generated (at line 47, column 43) for
      % {e: edgetype[T] |
      %    EXISTS (i: below(length(ww) - 1)):
      %      e = (finseq_appl[T](ww)(i), finseq_appl[T](ww)(i + 1))}
      % expected type  finite_set[edgetype[T]]
  edges_of_TCC3: OBLIGATION
    FORALL (ww: prewalk):
      is_finite[edgetype[T]]
          ({e: edgetype[T] |
              EXISTS (i: below(length(ww) - 1)):
                e = (finseq_appl[T](ww)(i), finseq_appl[T](ww)(i + 1))});

  % Subtype TCC generated (at line 54, column 63) for  s1 o s2
      % expected type  prewalk
  verts_in?_concat_TCC1: OBLIGATION
    FORALL (G: digraph[T], s1, s2: Seq(G)): length(o[T](s1, s2)) > 0;

  % Subtype TCC generated (at line 57, column 71) for  ps ^ (i, j)
      % expected type  prewalk
  verts_in?_caret_TCC1: OBLIGATION
    FORALL (G: digraph[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 80, column 28) for  0
      % expected type  below[length(ww)]
  prewalk_across_TCC1: OBLIGATION FORALL (ww: prewalk): 0 < length(ww);

  % Subtype TCC generated (at line 80, column 37) for  length(ww) - 1
      % expected type  below[length(ww)]
  prewalk_across_TCC2: OBLIGATION
    FORALL (ww: prewalk): length(ww) - 1 >= 0 AND length(ww) - 1 < length(ww);

  % Subtype TCC generated (at line 81, column 61) for  i
      % expected type  below[length(ww)]
  prewalk_across_TCC3: OBLIGATION
    FORALL (ww: prewalk):
      length(ww) > 1 AND
       finseq_appl[T](ww)(0) /= finseq_appl[T](ww)(length(ww) - 1)
       IMPLIES (FORALL (i: below(length(ww) - 1)): i < length(ww));

  % Subtype TCC generated (at line 82, column 53) for  i + 1
      % expected type  below[length(ww)]
  prewalk_across_TCC4: OBLIGATION
    FORALL (ww: prewalk):
      length(ww) > 1 AND
       finseq_appl[T](ww)(0) /= finseq_appl[T](ww)(length(ww) - 1)
       IMPLIES
       (FORALL (i: below(length(ww) - 1)):
          finseq_appl[T](ww)(i) = finseq_appl[T](ww)(0) IMPLIES
           i + 1 < length(ww));

  % Subtype TCC generated (at line 87, column 24) for
      % (# length := 1, seq := (LAMBDA (i: below(1)): u) #)
      % expected type  Seq(G)
  gen_seq1_TCC1: OBLIGATION
    FORALL (G: digraph[T], (u: (vert(G)))):
      1 > 0 AND
       verts_in?(G, (# length := 1, seq := LAMBDA (i: below(1)): u #));

  % Subtype TCC generated (at line 90, 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: digraph[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 98, column 43) for  length(p) - 2
      % expected type  nat
  trunc1_TCC1: OBLIGATION FORALL (p: Longprewalk): length(p) - 2 >= 0;

  % Subtype TCC generated (at line 98, 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 100, 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 109, column 48) for  u
      % expected type  (vert(G))
  edge_to_walk_TCC1: OBLIGATION
    FORALL (G: digraph[T], u, v: T):
      edges(G)(u, v) AND u /= v IMPLIES vert(G)(u);

  % Subtype TCC generated (at line 109, column 50) for  v
      % expected type  (vert(G))
  edge_to_walk_TCC2: OBLIGATION
    FORALL (G: digraph[T], u, v: T):
      edges(G)(u, v) AND u /= v IMPLIES vert(G)(v);

  % Subtype TCC generated (at line 123, column 47) for  ps ^ (i, j)
      % expected type  prewalk
  walk?_caret_TCC1: OBLIGATION
    FORALL (G: digraph[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 126, 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 138, column 37) for  w1 o w2
      % expected type  prewalk
  walk_concat_edge_TCC1: OBLIGATION
    FORALL (G: digraph[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 144, column 36) for  length(w1) - 2
      % expected type  nat
  walk_concat_TCC1: OBLIGATION
    FORALL (G: digraph[T], u1, u2, v: T, w1, w2: prewalk):
      walk_from?(G, w2, v, u2) AND
       walk_from?(G, w1, u1, v) AND length(w1) > 1
       IMPLIES length(w1) - 2 >= 0;

  % Subtype TCC generated (at line 144, column 27) for
      % w1 ^ (0, length(w1) - 2) o w2
      % expected type  prewalk
  walk_concat_TCC2: OBLIGATION
    FORALL (G: digraph[T], u1, u2, v: T, w1, w2: prewalk):
      walk_from?(G, w2, v, u2) AND
       walk_from?(G, w1, u1, v) AND length(w1) > 1
       IMPLIES length(o[T](^[T](w1, (0, length(w1) - 2)), w2)) > 0;

  % Subtype TCC generated (at line 150, column 67) for  length(ps) - 1
      % expected type  nat
  walk?_cut_TCC1: OBLIGATION
    FORALL (G: digraph[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 150, column 48) for
      % ps ^ (0, i) o ps ^ (j + 1, length(ps) - 1)
      % expected type  prewalk
  walk?_cut_TCC2: OBLIGATION
    FORALL (G: digraph[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;

  % Subtype TCC generated (at line 183, column 12) for  length(w) - 1
      % expected type  nat
  reord_prewalk_TCC1: OBLIGATION FORALL (w: prewalk): length(w) - 1 >= 0;

  % Subtype TCC generated (at line 183, column 37) for  i - 1
      % expected type  nat
  reord_prewalk_TCC2: OBLIGATION FORALL (w: prewalk, i: posnat): i - 1 >= 0;

  % Subtype TCC generated (at line 183, column 4) for
      % w ^ (i, length(w) - 1) o w ^ (0, i - 1)
      % expected type  prewalk
  reord_prewalk_TCC3: OBLIGATION
    FORALL (w: prewalk, i: posnat):
      length(o[T](^[T](w, (i, length(w) - 1)), ^[T](w, (0, i - 1)))) > 0;

  % Subtype TCC generated (at line 206, column 72) for  0
      % expected type  below[w2`length]
  walk_o_TCC1: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk):
      walk?(G, w1) AND walk?(G, w2) IMPLIES 0 < w2`length;

  % Subtype TCC generated (at line 207, column 33) for  length(w2) - 1
      % expected type  nat
  walk_o_TCC2: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk):
      seq(w1)(length(w1) - 1) = seq(w2)(0) AND walk?(G, w2) AND walk?(G, w1)
       IMPLIES length(w2) - 1 >= 0;

  % Subtype TCC generated (at line 207, column 21) for
      % w1 o w2 ^ (1, length(w2) - 1)
      % expected type  prewalk
  walk_o_TCC3: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk):
      seq(w1)(length(w1) - 1) = seq(w2)(0) AND walk?(G, w2) AND walk?(G, w1)
       IMPLIES length(o[T](w1, ^[T](w2, (1, length(w2) - 1)))) > 0;

  % Subtype TCC generated (at line 210, column 43) for  w1
      % expected type  not_empty_seq[T]
  edges_o_walk_TCC1: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk):
      walk?(G, w1) AND walk?(G, w2) IMPLIES length(w1) /= 0;

  % Subtype TCC generated (at line 210, column 55) for  w2
      % expected type  not_empty_seq[T]
  edges_o_walk_TCC2: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk):
      walk?(G, w1) AND walk?(G, w2) IMPLIES length(w2) /= 0;

  % Subtype TCC generated (at line 211, column 21) for  w1 o rest(w2)
      % expected type  prewalk
  edges_o_walk_TCC3: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk):
      last(w1) = first(w2) AND walk?(G, w2) AND walk?(G, w1) IMPLIES
       length(o[T](w1, rest[T](w2))) > 0;


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)) 
     
     
     digraph_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:
  %********************************************************************************%
  %
  %   Contributions from:
  %
  %       Andréia Borges Avelar -- Universidade de Brasília - Brasil  
  %       Mauricio Ayala-Rincon -- Universidade de Brasília - Brasil  
  %                 Cesar Muñoz -- NASA Langley Research Center - US
  %
  %********************************************************************************%

  % A circuit is a walk where the end points are the same

  circuits[T: TYPE]: THEORY

  BEGIN


     IMPORTING walks[T],
               structures@seq_extras[T]


             G: VAR digraph[T]
     w, w1, w2: VAR prewalk[T]


  % --------------------------------------------------------------------------------
  %     Definitions
  % --------------------------------------------------------------------------------

   pre_circuit?(G: digraph[T], w: prewalk): bool = 
     walk?(G,w) AND w(0) = w(length(w)-1)

   circuit?(G: digraph[T], w: prewalk): bool = 
     pre_circuit?(G,w) AND length(w) > 1
     
   loop?(G: digraph[T], w: prewalk): bool =
     pre_circuit?(G, w) AND length(w) = 2

   eq_circuit?(G, w, w1): bool =
     circuit?(G, w) AND circuit?(G, w1) AND eq_prewalk?(rest(w), rest(w1))


  % --------------------------------------------------------------------------------
  %     Properties
  % --------------------------------------------------------------------------------

   eq_circuit_length: LEMMA
     eq_circuit?(G, w1, w2) IMPLIES length(w1) = length(w2)

   eq_circuit_reflexive: LEMMA
     circuit?(G, w) IMPLIES eq_circuit?(G, w, w)

   eq_circuit_symmetric: LEMMA
     eq_circuit?(G, w1, w2) IMPLIES eq_circuit?(G, w2, w1)

   loop_is_circuit: LEMMA
     loop?(G, w) IMPLIES circuit?(G, w)

   equal_rest_equal_circuit: LEMMA
     circuit?(G, w1) AND circuit?(G, w2) AND rest(w1) = rest(w2)
     IMPLIES w1 = w2

   equal_eq_circuit: LEMMA
     eq_circuit?(G, w1, w2) AND rest(w1) = rest(w2)
     IMPLIES w1 = w2

   circuit_equal_fisrt: LEMMA
     circuit?(G, w1) AND circuit?(G, w2) AND circuit?(G, w1 o rest(w2))
     IMPLIES w1`seq(0) = w2`seq(0)

   comp_circuit_inter: LEMMA
     circuit?(G, w1 o rest(w2)) AND length(w2) > 1
     IMPLIES nonempty?(intersection(verts_of(w1), verts_of(w2)))

   eq_circuit_position: LEMMA
     eq_circuit?(G, w1, w2) IMPLIES
     EXISTS (i: below[length(w1)]): w2 = w1 ^ (i, length(w1) - 2) o w1 ^ (0, i)

   eq_circuit_edges: LEMMA
     eq_circuit?(G, w1, w2) IMPLIES edges_of(w1) = edges_of(w2)

   commuted_circuit: LEMMA
     FORALL (i : below[w`length]): circuit?(G, w)
     IMPLIES circuit?(G, w ^ (i, w`length-1) o w ^ (1,i))

   commuted_circuit_is_eq: LEMMA
     FORALL (i : below[w`length]): circuit?(G, w)
     IMPLIES eq_circuit?(G, w, w ^ (i, w`length-1) o w ^ (1,i))
   

   END circuits

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

  % Subtype TCC generated (at line 31, column 20) for  0
      % expected type  below[length(w)]
  pre_circuit?_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]): walk?(G, w) IMPLIES 0 < length(w);

  % Subtype TCC generated (at line 31, column 27) for  length(w) - 1
      % expected type  below[length(w)]
  pre_circuit?_TCC2: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      walk?(G, w) IMPLIES length(w) - 1 >= 0 AND length(w) - 1 < length(w);

  % Subtype TCC generated (at line 40, column 54) for  rest(w)
      % expected type  prewalk[T]
  eq_circuit?_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T], w1: prewalk[T]):
      circuit?(G, w1) AND circuit?(G, w) IMPLIES length(rest[T](w)) > 0;

  % Subtype TCC generated (at line 40, column 63) for  rest(w1)
      % expected type  prewalk[T]
  eq_circuit?_TCC2: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T], w1: prewalk[T]):
      circuit?(G, w1) AND circuit?(G, w) IMPLIES length(rest[T](w1)) > 0;

  % Subtype TCC generated (at line 68, column 55) for  w1 o rest(w2)
      % expected type  prewalk[T]
  circuit_equal_fisrt_TCC1: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk[T]):
      circuit?(G, w1) AND circuit?(G, w2) IMPLIES
       length(o[T](w1, rest[T](w2))) > 0;

  % Subtype TCC generated (at line 69, column 18) for  0
      % expected type  below[w1`length]
  circuit_equal_fisrt_TCC2: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk[T]):
      circuit?(G, w1 o rest(w2)) AND circuit?(G, w2) AND circuit?(G, w1)
       IMPLIES 0 < w1`length;

  % Subtype TCC generated (at line 69, column 30) for  0
      % expected type  below[w2`length]
  circuit_equal_fisrt_TCC3: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk[T]):
      circuit?(G, w1 o rest(w2)) AND circuit?(G, w2) AND circuit?(G, w1)
       IMPLIES 0 < w2`length;

  % Subtype TCC generated (at line 72, column 15) for  w1 o rest(w2)
      % expected type  prewalk[T]
  comp_circuit_inter_TCC1: OBLIGATION
    FORALL (w1, w2: prewalk[T]): length(o[T](w1, rest[T](w2))) > 0;

  % Subtype TCC generated (at line 77, column 48) for  length(w1) - 2
      % expected type  nat
  eq_circuit_position_TCC1: OBLIGATION
    FORALL (G: digraph[T], w1, w2: prewalk[T]):
      eq_circuit?(G, w1, w2) IMPLIES
       (FORALL (i: below[length(w1)]): length(w1) - 2 >= 0);

  % Subtype TCC generated (at line 84, column 31) for  w`length - 1
      % expected type  nat
  commuted_circuit_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T], i: below[w`length]):
      circuit?(G, w) IMPLIES w`length - 1 >= 0;

  % Subtype TCC generated (at line 84, column 23) for
      % w ^ (i, w`length - 1) o w ^ (1, i)
      % expected type  prewalk[T]
  commuted_circuit_TCC2: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T], i: below[w`length]):
      circuit?(G, w) IMPLIES
       length(o[T](^[T](w, (i, w`length - 1)), ^[T](w, (1, i)))) > 0;


body:
  %********************************************************************************%
  %
  %   Contributions from:
  %
  %       Andréia Borges Avelar -- Universidade de Brasília - Brasil  
  %       Mauricio Ayala-Rincon -- Universidade de Brasília - Brasil  
  %                 Cesar Muñoz -- NASA Langley Research Center - US
  %
  %********************************************************************************%

  % A cycle is a simple circuit; i.e., a walk without repetions except for the end points

  cycles[T: TYPE]: THEORY

  BEGIN

     IMPORTING circuits[T]

     G: VAR digraph[T]
     w: VAR prewalk


  % --------------------------------------------------------------------------------
  %     Definitions
  % --------------------------------------------------------------------------------

    cycle?(G: digraph[T], w: prewalk): bool = 
         circuit?(G,w) AND 
         (FORALL (i,j: below(length(w)-1)): i /= j IMPLIES w(i) /= w(j))


  % --------------------------------------------------------------------------------
  %     Properties
  % --------------------------------------------------------------------------------

    cycle_is_circuit : LEMMA
       FORALL (G: digraph[T], w: prewalk) : cycle?(G,w) IMPLIES circuit?(G,w)

    % cycle_has_path: LEMMA FORALL (w: prewalk): cycle?(G,w) IMPLIES
    %                        (EXISTS (j: below(length(w))): path?(G,w^(0,j)))

    circuit_subwalk_cycle: LEMMA
      circuit?(G, w) IMPLIES
      EXISTS (w1: prewalk): sub_walk?(G, w, w1) AND cycle?(G,w1)

    cycle_prefix: LEMMA
      circuit?(G,w) IMPLIES 
      (cycle?(G,w) OR EXISTS (w1, w2 : prewalk): eq_circuit?(G, w, w1 o w2) 
      AND cycle?(G,w1))
     
    cycle_o_circuit: LEMMA
      circuit?(G,w) IMPLIES 
      (cycle?(G,w) OR EXISTS (w1, w2 : prewalk): eq_circuit?(G, w, w1 o rest(w2))
      AND cycle?(G,w1) AND circuit?(G,w2))


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

     IMPORTING digraphs, finite_sets@finite_sets_card_eq, structures@seq_pigeon

     GF: VAR Digraph[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 cycles

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

  % Subtype TCC generated (at line 29, column 59) for  i
      % expected type  below[length(w)]
  cycle?_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      circuit?(G, w) IMPLIES
       (FORALL (i, j: below(length(w) - 1)): i /= j IMPLIES i < length(w));

  % Subtype TCC generated (at line 29, column 67) for  j
      % expected type  below[length(w)]
  cycle?_TCC2: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      circuit?(G, w) IMPLIES
       (FORALL (i, j: below(length(w) - 1)): i /= j IMPLIES j < length(w));

  % Subtype TCC generated (at line 44, column 39) for  w
      % expected type  Walk[T](G)
  circuit_subwalk_cycle_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      circuit?(G, w) IMPLIES (FORALL (w1: prewalk[T]): walk?[T](G, w));

  % Subtype TCC generated (at line 48, column 65) for  w1 o w2
      % expected type  prewalk[T]
  cycle_prefix_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      circuit?(G, w) AND NOT cycle?(G, w) IMPLIES
       (FORALL (w1, w2: prewalk[T]): length(o[T](w1, w2)) > 0);

  % Subtype TCC generated (at line 53, column 65) for  w1 o rest(w2)
      % expected type  prewalk[T]
  cycle_o_circuit_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      circuit?(G, w) AND NOT cycle?(G, w) IMPLIES
       (FORALL (w1, w2: prewalk[T]): length(o[T](w1, rest[T](w2))) > 0);


body:
  %********************************************************************************%
  %
  %   Contributions from:
  %
  %       Andréia Borges Avelar -- Universidade de Brasília - Brasil  
  %       Mauricio Ayala-Rincon -- Universidade de Brasília - Brasil  
  %                 Cesar Muñoz -- NASA Langley Research Center - US
  %
  %********************************************************************************%

  Eulerian[T:TYPE] : THEORY
  BEGIN
    
    IMPORTING cycles[T],
              walk_inductions[T]


    G : VAR digraph
    w : VAR prewalk


    %%% For walks it means that we don't have repeated edges
    no_repeat_subseq?(w) : bool =
      FORALL (i,j:below(length(w) - 1)) :
        i < j AND w`seq(i) = w`seq(j) IMPLIES w`seq(i+1) /= w`seq(j+1)

    pre_Eulerian_walk?(G,w) : bool =
      walk?(G,w) AND no_repeat_subseq?(w)

    Eulerian_walk?(G,w) : bool =
      pre_Eulerian_walk?(G,w) AND
      edges_of(w) = edges(G)

    pre_Eulerian_circuit?(G,w) : bool =
      pre_Eulerian_walk?(G,w) AND circuit?(G, w)
      % w(0) = w(length(w)-1) AND
      % length(w) > 1

    Eulerian_circuit?(G,w) : bool =
      pre_Eulerian_circuit?(G,w) AND 
      edges_of(w) = edges(G)


  % ---------------------------------------------------------------
  %         Properties
  % ---------------------------------------------------------------

    cycle_is_pre_Eulerian_circuit: LEMMA
      cycle?(G, w) IMPLIES pre_Eulerian_circuit?(G,w)

    pre_Eulerian_circuit_is_a_circuit: LEMMA
      pre_Eulerian_circuit?(G,w) IMPLIES
      circuit?(G,w)

    Eulerian_circuit_is_circuit: LEMMA
      Eulerian_circuit?(G,w) IMPLIES
      circuit?(G,w)

    Eulerian_walk_is_Eulerian_circuit: LEMMA
      Eulerian_circuit?(G,w) IMPLIES
      Eulerian_walk?(G,w)

    circuit_subwalk_pre_Eulerian: LEMMA
      circuit?(G, w) IMPLIES
      EXISTS (w1: prewalk): sub_walk?(G, w, w1) AND
        pre_Eulerian_circuit?(G,w1)

    pre_Eulerian_circuit_prefix: LEMMA
      circuit?(G,w) IMPLIES (pre_Eulerian_circuit?(G,w) OR
      EXISTS (w1, w2 : prewalk): eq_circuit?(G, w, w1 o w2) AND
           pre_Eulerian_circuit?(G,w1))

    pre_Eulerian_circuit_o_circuit: LEMMA
      circuit?(G,w) IMPLIES (pre_Eulerian_circuit?(G,w) OR
      EXISTS (w1, w2 : prewalk): eq_circuit?(G, w, w1 o rest(w2)) AND
           pre_Eulerian_circuit?(G,w1) AND circuit?(G,w2))


  END Eulerian

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

  % Subtype TCC generated (at line 25, column 22) for  i
      % expected type  below[w`length]
  no_repeat_subseq?_TCC1: OBLIGATION
    FORALL (w: prewalk[T], i, j: below(length(w) - 1)):
      i < j IMPLIES i < w`length;

  % Subtype TCC generated (at line 25, column 33) for  j
      % expected type  below[w`length]
  no_repeat_subseq?_TCC2: OBLIGATION
    FORALL (w: prewalk[T], i, j: below(length(w) - 1)):
      i < j IMPLIES j < w`length;

  % Subtype TCC generated (at line 25, column 50) for  i + 1
      % expected type  below[w`length]
  no_repeat_subseq?_TCC3: OBLIGATION
    FORALL (w: prewalk[T], i, j: below(length(w) - 1)):
      i < j AND w`seq(i) = w`seq(j) IMPLIES i + 1 < w`length;

  % Subtype TCC generated (at line 25, column 64) for  j + 1
      % expected type  below[w`length]
  no_repeat_subseq?_TCC4: OBLIGATION
    FORALL (w: prewalk[T], i, j: below(length(w) - 1)):
      i < j AND w`seq(i) = w`seq(j) IMPLIES j + 1 < w`length;

  % Subtype TCC generated (at line 65, column 39) for  w
      % expected type  Walk[T](G)
  circuit_subwalk_pre_Eulerian_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      circuit?(G, w) IMPLIES (FORALL (w1: prewalk[T]): walk?[T](G, w));

  % Subtype TCC generated (at line 70, column 49) for  w1 o w2
      % expected type  prewalk[T]
  pre_Eulerian_circuit_prefix_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      circuit?(G, w) AND NOT pre_Eulerian_circuit?(G, w) IMPLIES
       (FORALL (w1, w2: prewalk[T]): length(o[T](w1, w2)) > 0);

  % Subtype TCC generated (at line 75, column 49) for  w1 o rest(w2)
      % expected type  prewalk[T]
  pre_Eulerian_circuit_o_circuit_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: prewalk[T]):
      circuit?(G, w) AND NOT pre_Eulerian_circuit?(G, w) IMPLIES
       (FORALL (w1, w2: prewalk[T]): length(o[T](w1, rest[T](w2))) > 0);


body:
  di_subgraphs[T: TYPE]: THEORY

  BEGIN

     IMPORTING digraphs[T]

     V: VAR set[T]
     G,G1,G2,SS: VAR digraph[T]
     i: VAR T
     e: VAR edgetype[T]

     di_subgraph?(G1,G2): bool = subset?(vert(G1),vert(G2)) AND
                                 subset?(edges(G1),edges(G2))

     equal?(G1,G2): bool = di_subgraph?(G1,G2) AND di_subgraph?(G2,G1)

     di_subgraph(G): TYPE = {S: digraph[T] | di_subgraph?(S,G)}

     finite_vert_subset: LEMMA is_finite(LAMBDA (i:T): vert(G)(i) AND V(i))

     finite_edge_subset: LEMMA is_finite[edgetype[T]]
                 ({e | G`edges(e) AND (LET (x, y) = e IN V(x) AND V(y))})


  %   di_subgraph(G, V): di_subgraph(G) =
  %       (G WITH [vert :=  {i | vert(G)(i) AND V(i)},
  %                edges := {e | edges(G)(e) AND 
  %                              (FORALL (x: T): in?(x,e) IMPLIES V(x))}])

     x,y: VAR T
     di_subgraph(G, V): di_subgraph(G) =
         (G WITH [vert :=  {i | vert(G)(i) AND V(i)},
                  edges := {e | edges(G)(e) AND (Let (x,y) = e IN V(x) AND V(y))}])

     di_subgraph_vert_sub: LEMMA subset?(V,vert(G)) IMPLIES
                                          vert(di_subgraph(G,V)) = V

     di_subgraph_lem     : LEMMA di_subgraph?(di_subgraph(G,V),G)

     di_subgraph_smaller: LEMMA di_subgraph?(SS, G) IMPLIES
     	                     size(SS) <= size(G)

  END di_subgraphs

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

  % Subtype TCC generated (at line 33, column 25) for
      % {e | edges(G)(e) AND (LET (x, y) = e IN V(x) AND V(y))}
      % expected type  finite_set[edgetype[T]]
  di_subgraph_TCC1: OBLIGATION
    FORALL (G: digraph[T], V: set[T]):
      is_finite[edgetype[T]]
          ({e | edges(G)(e) AND (LET (x, y) = e IN V(x) AND V(y))});

  % Subtype TCC generated (at line 32, column 25) for
      % {i | vert(G)(i) AND V(i)}
      % expected type  finite_set[T]
  di_subgraph_TCC2: OBLIGATION
    FORALL (G: digraph[T], V: set[T]):
      is_finite[T]({i | vert(G)(i) AND V(i)});

  % Subtype TCC generated (at line 32, column 8) for
      % (G
      %    WITH [vert := {i | vert(G)(i) AND V(i)},
      %          edges
      %            := {e |
      %                  edges(G)(e) AND (LET (x, y) = e IN V(x) AND V(y))}])
      % expected type  di_subgraph(G)
  di_subgraph_TCC3: OBLIGATION
    FORALL (G: digraph[T], V: set[T]):
      (FORALL (e_1: edgetype[T]):
         edges(G)(e_1) AND V(e_1`1) AND V(e_1`2) IMPLIES
          (vert(G)(e_1`1) AND V(e_1`1)) AND vert(G)(e_1`2) AND V(e_1`2))
       AND
       di_subgraph?((G
                       WITH [vert := {i | vert(G)(i) AND V(i)},
                             edges
                               := {e | edges(G)(e) AND V(e`1) AND V(e`2)}]),
                    G);


body:
  %********************************************************************************%
  %
  %   Contributions from:
  %
  %       Andréia Borges Avelar -- Universidade de Brasília - Brasil  
  %       Mauricio Ayala-Rincon -- Universidade de Brasília - Brasil  
  %                 Cesar Muñoz -- NASA Langley Research Center - US
  %
  %********************************************************************************%

  weighted_digraphs[T : TYPE, Weight : TYPE, 
                    + : {f : [[Weight, Weight] -> Weight] | associative?(f) },
                    0 : {zero: Weight | identity?(+)(zero)}] : THEORY

  BEGIN

  	IMPORTING circuits[T],
                    di_subgraphs[T]


                              u, v : VAR T
                                 g : VAR digraph
           i, i1, i2, j, j1, j2, n : VAR nat
                         w, w1, w2 : VAR prewalk



  % ----------------------------------------------------------------------------- %
  %            Defining a weighted digraph and sub- weighted digraph
  % ----------------------------------------------------------------------------- %


   wdg : TYPE = [#  dg : digraph,
                   wgt : [edge(dg) -> Weight] #]

   G : VAR wdg

   wgt(G) : TYPE = [edge(dg(G)) ->  Weight]

   Sub_wdg(G) : TYPE = {S: wdg | di_subgraph?(dg(S), dg(G))}


  % ----------------------------------------------------------------------------- %
  %            DEFINITIONS: about weights
  % ----------------------------------------------------------------------------- % 

   wgt_aux(G: wdg, w: Walk(dg(G)))(i, (j: below(length(w)))) : RECURSIVE Weight =
     IF j <= i THEN 0
     ELSE wgt_aux(G, w)(i, j - 1) + wgt(G)(w(j - 1), w(j))
     ENDIF
   MEASURE j

   wgt_walk(G: wdg, w: Walk(dg(G))) : Weight =
     wgt_aux(G, w)(0, length(w) - 1)


  % ----------------------------------------------------------------------------- %
  %            PROPERTIES
  % ----------------------------------------------------------------------------- %

   wgt_aux_shift_walk: LEMMA
     FORALL (w1, w2: Walk(dg(G)), j1: below(length(w1)), j2: below(length(w2))):
         w1^(i1, j1) = w2^(i2, j2)
       IMPLIES
         wgt_aux(G, w1)(i1, j1) = wgt_aux(G, w2)(i2, j2)

   wgt_aux_first : LEMMA
     FORALL (w : Walk(dg(G)), i, j):
         j < length(w) AND i < j
       IMPLIES
         wgt_aux(G, w)(i, j) = wgt(G)(w(i), w(i + 1)) + wgt_aux(G, w)(i + 1, j)

   wgt_aux_split : LEMMA
     FORALL (w : Walk(dg(G)), i, j, n):
         j < length(w) AND i <= n AND n <= j
       IMPLIES
         wgt_aux(G, w)(i, j) = wgt_aux(G, w)(i, n) + wgt_aux(G, w)(n, j)
   
   wgt_aux_sub_walk: LEMMA
     FORALL (w : Walk(dg(G)), i, j):
         j < length(w) AND i < j
       IMPLIES
         wgt_aux(G, w)(i, j) = wgt_aux(G, w^(i,j))(0, j - i)

   wgt_walk_to_aux: LEMMA
     FORALL(w: Walk(dg(G)), i, j):
        j < length(w) AND i < j IMPLIES
        wgt_walk(G, w^(i, j)) = wgt_aux(G, w)(i, j)

   wgt_walk_decomposed: LEMMA
     j < length(w) AND walk?(dg(G), w) IMPLIES
     wgt_walk(G, w) =  wgt_walk(G, w^(0, j)) + 
                       wgt_walk(G, w^(j, length(w)-1))

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

   wgt_walk_edge: LEMMA
     FORALL(w: Walk(dg(G))):
      length(w) = 2 IMPLIES wgt_walk(G, w) = wgt(G)(w(0), w(1))

   wgt_comp_rest: LEMMA
     FORALL (w1, w2: Walk(dg(G))):
       last(w1) = first(w2) IMPLIES
       wgt_walk(G, w1 o rest(w2)) = wgt_walk(G, w1) + wgt_walk(G, w2)

   % commutative_sum_eq_circuit: CONJECTURE
   %   FORALL (w1, w2: Walk(dg(G))):
   %     (FORALL(a, b : Weight): a + b = b + a) AND eq_circuit?(dg(G), w1, w2)
   %     IMPLIES wgt_walk(G, w1) = wgt_walk(G, w2)


  END weighted_digraphs

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

  % Subtype TCC generated (at line 49, column 25) for  j - 1
      % expected type  below(length(w))
  wgt_aux_TCC1: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, (j: below(length(w)))):
      NOT j <= i IMPLIES j - 1 >= 0 AND j - 1 < length(w);

  % Termination TCC generated (at line 49, column 8) for
      % wgt_aux(G, w)(i, j - 1)
  wgt_aux_TCC2: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, (j: below(length(w)))):
      NOT j <= i IMPLIES j - 1 < j;

  % Subtype TCC generated (at line 49, column 41) for
      % (finseq_appl[T](w)(j - 1), finseq_appl[T](w)(j))
      % expected type  edge[T](G`dg)
  wgt_aux_TCC3: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, (j: below(length(w)))):
      NOT j <= i IMPLIES
       edge?[T](G`dg)(finseq_appl[T](w)(j - 1), finseq_appl[T](w)(j));

  % Subtype TCC generated (at line 54, column 20) for  length(w) - 1
      % expected type  below(length(w))
  wgt_walk_TCC1: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G))):
      length(w) - 1 >= 0 AND length(w) - 1 < length(w);

  % Subtype TCC generated (at line 71, column 38) for  i
      % expected type  below[length(w)]
  wgt_aux_first_TCC1: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, j: nat):
      j < length(w) AND i < j IMPLIES i < length(w);

  % Subtype TCC generated (at line 71, column 44) for  i + 1
      % expected type  below[length(w)]
  wgt_aux_first_TCC2: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, j: nat):
      j < length(w) AND i < j IMPLIES i + 1 < length(w);

  % Subtype TCC generated (at line 71, column 36) for
      % (finseq_appl[T](w)(i), finseq_appl[T](w)(i + 1))
      % expected type  edge[T](G`dg)
  wgt_aux_first_TCC3: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, j: nat):
      j < length(w) AND i < j IMPLIES
       edge?[T](G`dg)(finseq_appl[T](w)(i), finseq_appl[T](w)(i + 1));

  % Subtype TCC generated (at line 77, column 46) for  n
      % expected type  below(length(w))
  wgt_aux_split_TCC1: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, j: nat, n: nat):
      j < length(w) AND i <= n AND n <= j IMPLIES n < length(w);

  % Subtype TCC generated (at line 83, column 52) for  j - i
      % expected type  below(length(w ^ (i, j)))
  wgt_aux_sub_walk_TCC1: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, j: nat):
      j < length(w) AND i < j IMPLIES
       j - i >= 0 AND j - i < length(^[T](w, (i, j)));

  % Subtype TCC generated (at line 83, column 40) for  w ^ (i, j)
      % expected type  Walk[T](dg(G))
  wgt_aux_sub_walk_TCC2: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G)), i: nat, j: nat):
      j < length(w) AND i < j IMPLIES
       length(^[T](w, (i, j))) > 0 AND walk?[T](dg(G), ^[T](w, (i, j)));

  % Subtype TCC generated (at line 92, column 33) for  w ^ (0, j)
      % expected type  Walk[T](dg(G))
  wgt_walk_decomposed_TCC1: OBLIGATION
    FORALL (G: wdg, j: nat, w: prewalk[T]):
      walk?(dg(G), w) AND j < length(w) IMPLIES
       length(^[T](w, (0, j))) > 0 AND walk?[T](dg(G), ^[T](w, (0, j)));

  % Subtype TCC generated (at line 93, column 39) for  length(w) - 1
      % expected type  nat
  wgt_walk_decomposed_TCC2: OBLIGATION
    FORALL (G: wdg, j: nat, w: prewalk[T]):
      walk?(dg(G), w) AND j < length(w) IMPLIES length(w) - 1 >= 0;

  % Subtype TCC generated (at line 93, column 33) for  w ^ (j, length(w) - 1)
      % expected type  Walk[T](dg(G))
  wgt_walk_decomposed_TCC3: OBLIGATION
    FORALL (G: wdg, j: nat, w: prewalk[T]):
      walk?(dg(G), w) AND j < length(w) IMPLIES
       length(^[T](w, (j, length(w) - 1))) > 0 AND
        walk?[T](dg(G), ^[T](w, (j, length(w) - 1)));

  % Subtype TCC generated (at line 99, column 52) for  0
      % expected type  below[length(w)]
  wgt_walk_edge_TCC1: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G))): length(w) = 2 IMPLIES 0 < length(w);

  % Subtype TCC generated (at line 99, column 58) for  1
      % expected type  below[length(w)]
  wgt_walk_edge_TCC2: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G))): length(w) = 2 IMPLIES 1 < length(w);

  % Subtype TCC generated (at line 99, column 50) for
      % (finseq_appl[T](w)(0), finseq_appl[T](w)(1))
      % expected type  edge[T](G`dg)
  wgt_walk_edge_TCC3: OBLIGATION
    FORALL (G: wdg, w: Walk[T](dg(G))):
      length(w) = 2 IMPLIES
       edge?[T](G`dg)(finseq_appl[T](w)(0), finseq_appl[T](w)(1));

  % Subtype TCC generated (at line 103, column 10) for  w1
      % expected type  not_empty_seq[T]
  wgt_comp_rest_TCC1: OBLIGATION
    FORALL (G: wdg, w1, w2: Walk[T](dg(G))): length(w1) /= 0;

  % Subtype TCC generated (at line 103, column 22) for  w2
      % expected type  not_empty_seq[T]
  wgt_comp_rest_TCC2: OBLIGATION
    FORALL (G: wdg, w1, w2: Walk[T](dg(G))): length(w2) /= 0;

  % Subtype TCC generated (at line 104, column 17) for  w1 o rest(w2)
      % expected type  Walk[T](dg(G))
  wgt_comp_rest_TCC3: OBLIGATION
    FORALL (G: wdg, w1, w2: Walk[T](dg(G))):
      last(w1) = first(w2) IMPLIES
       length(o[T](w1, rest[T](w2))) > 0 AND
        walk?[T](dg(G), o[T](w1, rest[T](w2)));


body:
  %********************************************************************************%
  %
  %   Contributions from:
  %
  %       Andréia Borges Avelar -- Universidade de Brasília - Brasil  
  %       Mauricio Ayala-Rincon -- Universidade de Brasília - Brasil  
  %                 Cesar Muñoz -- NASA Langley Research Center - US
  %
  %********************************************************************************%

  wgt_digraphs_props[T : TYPE, Weight : TYPE, 
                     + : {f : [[Weight, Weight] -> Weight] | 
                             commutative?(f) AND associative?(f) },
                     0 : {zero: Weight | identity?(+)(zero)},
                    <= : {<=: (partial_order?[Weight]) | FORALL(a, b, c : Weight):
                                                       a + b <= a + c => b <= c}
                     ] : THEORY

  BEGIN

  	IMPORTING weighted_digraphs[T, Weight, +, 0]


          G : VAR wdg
       u, v : VAR T


  % ----------------------------------------------------------------------------- %
  %            DEFINITIONS: about minimun weights
  % ----------------------------------------------------------------------------- % 

   min_walk?(G, u, v)( w: Walk(dg(G))) : bool =
     FORALL(w1: Walk(dg(G)) | from?(w1, u, v)):
       wgt_walk(G, w) <= wgt_walk(G, w1)

   set_min(G)(u, v): set[Walk(dg(G))] =
     {w: Walk(dg(G)) | from?(w, u, v) AND min_walk?(G, u, v)(w)}

   min_wgt(G)(e: edgetype | nonempty?(set_min(G)(e))): Weight =
      wgt_walk(G, choose(set_min(G)(e)))


  % ----------------------------------------------------------------------------- %
  %           More properties on weighted digraphs that require 
  %           a partial order, commutativity and homogeneity
  % ----------------------------------------------------------------------------- %

   walk_member_set_min: LEMMA
     FORALL (w: Walk(dg(G)), e: edgetype | nonempty?(set_min(G)(e))):
            from?(w, e`1, e`2) AND wgt_walk(G, w) = min_wgt(G)(e)
            IMPLIES member(w, set_min(G)(e))

   wgt_min_walk_choose: LEMMA
     FORALL (w: Walk(dg(G))):
         member(w, set_min(G)(u, v)) IMPLIES
         wgt_walk(G, w) = wgt_walk(G, choose(set_min(G)(u, v)))

   min_walk_min_wgt: LEMMA
     FORALL (w: Walk(dg(G))):
         member(w, set_min(G)(u, v)) IMPLIES
         wgt_walk(G, w) = min_wgt(G)(u, v)

   sub_min_walk_nonempty: LEMMA
     FORALL(w: Walk(dg(G)), 
            e: edgetype | nonempty?(set_min(G)(e)), 
            i, j: below(length(w))):
         walk_from?(dg(G), w, e`1, e`2) AND wgt_walk(G, w) = min_wgt(G)(e) AND i < j
       IMPLIES
         nonempty?( set_min(G)( w(i), w(j) ) )

   sub_min_walk_is_min: LEMMA
     FORALL(w: Walk(dg(G)), 
            e: edgetype | nonempty?(set_min(G)(e)), 
            i, j: below(length(w)) ):
        walk_from?(dg(G), w, e`1, e`2) AND wgt_walk(G, w) = min_wgt(G)(e) AND i < j
       IMPLIES
        wgt_walk(G, w^(i,j)) = min_wgt(G)(w(i), w(j))

  END wgt_digraphs_props

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

  % Subtype TCC generated (at line 40, column 23) for  set_min(G)(e)
      % expected type  p: (nonempty?[Walk[T](dg(G))])
  min_wgt_TCC1: OBLIGATION
    FORALL (G: wdg[T, Weight, +, 0],
            e: edgetype[T] | nonempty?[Walk[T](dg(G))](set_min(G)(e))):
      nonempty?[Walk[T](dg(G))](set_min(G)(e));

  % Subtype TCC generated (at line 56, column 43) for  set_min(G)(u, v)
      % expected type  p: (nonempty?[Walk[T](dg(G))])
  wgt_min_walk_choose_TCC1: OBLIGATION
    FORALL (G: wdg[T, Weight, +, 0], u, v: T, w: Walk[T](dg(G))):
      member(w, set_min(G)(u, v)) IMPLIES
       nonempty?[Walk[T](dg(G))](set_min(G)(u, v));

  % Subtype TCC generated (at line 77, column 18) for  w ^ (i, j)
      % expected type  Walk[T](dg(G))
  sub_min_walk_is_min_TCC1: OBLIGATION
    FORALL (G: wdg[T, Weight, +, 0], w: Walk[T](dg(G)),
            e: edgetype[T] | nonempty?[Walk[T](dg(G))](set_min(G)(e)),
            i, j: below(length(w))):
      walk_from?(dg(G), w, e`1, e`2) AND
       wgt_walk(G, w) = min_wgt(G)(e) AND i < j
       IMPLIES
       length(^[T](w, (i, j))) > 0 AND walk?[T](dg(G), ^[T](w, (i, j)));

  % Subtype TCC generated (at line 77, column 40) for
      % (finseq_appl[T](w)(i), finseq_appl[T](w)(j))
      % expected type  {e: edgetype | nonempty?(set_min(G)(e))}
  sub_min_walk_is_min_TCC2: OBLIGATION
    FORALL (G: wdg[T, Weight, +, 0], w: Walk[T](dg(G)),
            e: edgetype[T] | nonempty?[Walk[T](dg(G))](set_min(G)(e)),
            i, j: below(length(w))):
      walk_from?(dg(G), w, e`1, e`2) AND
       wgt_walk(G, w) = min_wgt(G)(e) AND i < j
       IMPLIES
       nonempty?[Walk[T](dg(G))]
           (set_min(G)(finseq_appl[T](w)(i), finseq_appl[T](w)(j)));


body:
  %------------------------------------------------------------------------
  % 
  %  Operations on a digraph
  %  ------------------------------------------------
  %
  %      Author: Ricky W. Butler   NASA Langley Research Center
  %
  %  Defines:
  %
  %      union(G1,G2)      -- creates digraph that is a union of G1 and G2  
  %
  %      del_vert(G,v)     -- removes a vertex and all adjacent edges from a digraph
  %
  %      del_edge(e,G)     --  creates di_subgraph with edge e removed
  %   
  %      num_edges(G): nat --  number of edges in a digraph
  %
  %------------------------------------------------------------------------
  digraph_ops[T: TYPE]: THEORY

  BEGIN

     IMPORTING digraphs[T]

     G, G1, G2: VAR digraph[T]
     t1,t2: VAR T
     x,v: VAR T
     e,e2: VAR edgetype[T]

     union(G1,G2): digraph[T] = (# vert := union(vert(G1),vert(G2)),
                                  edges := union(edges(G1),edges(G2)) #)
   
     del_vert(G: digraph[T], v: T): digraph[T] = 
                          (# vert := remove[T](v,vert(G)),
                             edges := {e | edges(G)(e) AND NOT in?(v,e)} #)
                              
     del_edge(G,e): digraph[T] = G WITH [edges := remove(e,edges(G))]

     num_edges(G): nat = card(edges(G))

  %  --------------------- 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 in?(v,e)) 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 in?(v,e) IMPLIES
                                 del_vert(del_edge(G,e),v) = del_vert(G,v)


  END digraph_ops

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

  % Subtype TCC generated (at line 30, column 30) for
      % (# vert := union(vert(G1), vert(G2)),
      %    edges := union(edges(G1), edges(G2)) #)
      % expected type  digraph[T]
  union_TCC1: OBLIGATION
    FORALL (G1: digraph[T], G2: digraph[T]):
      FORALL (e: edgetype[T]):
        union[edgetype[T]](edges(G1), edges(G2))(e) IMPLIES
         union[T](vert(G1), vert(G2))(e`1) AND
          union[T](vert(G1), vert(G2))(e`2);

  % Subtype TCC generated (at line 35, column 36) for
      % {e | edges(G)(e) AND NOT in?(v, e)}
      % expected type  finite_set[edgetype[T]]
  del_vert_TCC1: OBLIGATION
    FORALL (G: digraph[T], v: T):
      is_finite[edgetype[T]]({e | edges(G)(e) AND NOT in?[T](v, e)});

  % Subtype TCC generated (at line 34, column 24) for
      % (# vert := remove[T](v, vert(G)),
      %    edges := {e | edges(G)(e) AND NOT in?(v, e)} #)
      % expected type  digraph[T]
  del_vert_TCC2: OBLIGATION
    FORALL (G: digraph[T], v: T):
      FORALL (e_1: edgetype[T]):
        edges(G)(e_1) AND NOT in?[T](v, e_1) IMPLIES
         remove[T](v, vert(G))(e_1`1) AND remove[T](v, vert(G))(e_1`2);

  % Subtype TCC generated (at line 37, column 31) for
      % G WITH [edges := remove(e, edges(G))]
      % expected type  digraph[T]
  del_edge_TCC1: OBLIGATION
    FORALL (G: digraph[T], e: edgetype[T]):
      FORALL (e_1: edgetype[T]):
        remove[edgetype[T]](e, edges(G))(e_1) IMPLIES
         G`vert(e_1`1) AND G`vert(e_1`2);


body:
  digraph_deg[T: TYPE]: THEORY
  %------------------------------------------------------------------------
  % 
  %  Defines degree of a vertex
  %  ------------------------------------------------
  %
  %      Authors: Ricky W. Butler   NASA Langley Research Center
  %               Kristin Y. Rozier NASA Langley Research Center
  %
  %  Defines:
  %
  %    incident_edges(v,G) -- returns set of edges attached to vertex v
  %
  %    in_deg(v,G), out_deg(v,G) -- number of edges attached to vertex v    
  %
  %------------------------------------------------------------------------

  BEGIN

     IMPORTING digraphs[T], digraph_ops[T]

     v: VAR T
     G,GS: VAR digraph[T]

     incoming_edges(v,G): finite_set[edgetype[T]] 
                                = {e: edgetype[T] | edges(G)(e) AND e`2 = v}

     outgoing_edges(v,G): finite_set[edgetype[T]] 
                                = {e: edgetype[T] | edges(G)(e) AND e`1 = v}

     incident_edges(v,G)  : finite_set[edgetype[T]] 
                                = {e: edgetype[T] | edges(G)(e) AND in?(v,e)}

     incoming_edges_subset: LEMMA subset?(incoming_edges(v,G),edges(G))

     outgoing_edges_subset: LEMMA subset?(outgoing_edges(v,G),edges(G))

     incident_edges_subset: LEMMA subset?(incident_edges(v,G),edges(G))

     in_deg(v,G): nat = card(incoming_edges(v,G))

     out_deg(v,G): nat = card(outgoing_edges(v,G))

     %This definition of degree doesn't work for digraphs
     %deg(v,G): nat = card(incident_edges(v,G))

     deg(v,G): nat = in_deg(v,G) + out_deg(v,G)


     P : VAR pred[digraph[T]]
     n : VAR nat
     e: VAR edgetype[T]
     x,y: VAR T

     self_loop?(e): bool = (e`1 = e`2)
     %possible alternate: self_loop?(e,G): bool = edges(G)(e) AND (e`1 = e`2)

     incoming_edges_emptyset: LEMMA edges(G) = emptyset[edgetype[T]] IMPLIES
                                    incoming_edges(v,G) = emptyset[edgetype[T]]

     outgoing_edges_emptyset: LEMMA edges(G) = emptyset[edgetype[T]] IMPLIES
                                    outgoing_edges(v,G) = emptyset[edgetype[T]]

     %Define incident edges independently from in & out so self-loops aren't
     %counted twice (i.e. incident edges /= in_edges + out_edges)
     incident_edges_emptyset: LEMMA edges(G) = emptyset[edgetype[T]] IMPLIES
                                    incident_edges(v,G) = emptyset[edgetype[T]]

     deg_del_edge_incoming  : LEMMA e = (x,y) AND edges(G)(e) IMPLIES  
                                    in_deg(y, G) = in_deg(y, del_edge(G, e)) + 1

     deg_del_edge_outgoing  : LEMMA e = (x,y) AND edges(G)(e) IMPLIES  
                                    out_deg(x, G) = out_deg(x, del_edge(G, e)) + 1

     deg_del_non_edge       : LEMMA NOT in?(y,e)  IMPLIES  
                                    deg(y, G) = deg(y, del_edge(G, e))

     deg_del_non_edge_incoming : LEMMA NOT y = e`2  IMPLIES  
                                    in_deg(y, G) = in_deg(y, del_edge(G, e))

     deg_del_non_edge_outgoing : LEMMA NOT y = e`1  IMPLIES  
                                    out_deg(y, G) = out_deg(y, del_edge(G, e))

     deg_del_edge    : LEMMA in?(y,e) AND edges(G)(e) AND NOT self_loop?(e) 
                               IMPLIES deg(y, G) = deg(y, del_edge(G, e)) + 1

     deg_del_self_loop : LEMMA in?(y,e) AND edges(G)(e) AND self_loop?(e) 
                               IMPLIES deg(y, G) = deg(y, del_edge(G, e)) + 2

     deg_del_edge_ge_incoming : LEMMA in_deg(y, G) >= in_deg(y, del_edge(G, e))

     deg_del_edge_ge_outgoing : LEMMA out_deg(y, G) >= out_deg(y, del_edge(G, e))

     deg_del_edge_ge : LEMMA deg(y, G) >= deg(y, del_edge(G, e))

     deg_del_edge_le_incoming : LEMMA in_deg(y, G) - 1 <= in_deg(y, del_edge(G, e))

     deg_del_edge_le_outgoing : LEMMA out_deg(y, G) - 1 
                                           <= out_deg(y, del_edge(G, e))

     deg_del_edge_le : LEMMA deg(y, G) - 2 <= deg(y, del_edge(G, e))

     in_deg_edge_exists       : LEMMA in_deg(v,G) > 0 IMPLIES
                               (EXISTS e: (e`2 = v) AND edges(G)(e))
        
     out_deg_edge_exists      : LEMMA out_deg(v,G) > 0 IMPLIES
                               (EXISTS e: (e`1 = v) AND edges(G)(e))
        
     deg_edge_exists          : LEMMA deg(v,G) > 0 IMPLIES
                               (EXISTS e: in?(v,e) AND edges(G)(e))
        
     deg_to_card     : LEMMA FORALL (SG: simple_digraph):
                                 deg(v,SG) > 0 IMPLIES size(SG) >= 2

     del_vert_deg_0  : LEMMA deg(v,G) = 0 IMPLIES 
                                 edges(del_vert(G,v)) = edges(G)

     singleton_loops: LEMMA FORALL (SG: simple_digraph): singleton?(SG) 
                            IMPLIES FORALL (e | edges(SG)(e)): self_loop?(e)

     singleton_edges: LEMMA FORALL (SG: simple_digraph): singleton?(SG) IMPLIES 
                              incoming_edges(v, SG) = outgoing_edges(v, SG)

     singleton_deg: LEMMA FORALL (SG: simple_digraph):
                              singleton?(SG) IMPLIES in_deg(v, SG) = out_deg(v, SG)

     in_deg_1_sing    : LEMMA in_deg(v, G) = 1 IMPLIES 
                             (EXISTS e: incoming_edges(v, G) = singleton(e) AND
                                        e`2 = v AND edges(G)(e))

     out_deg_1_sing   : LEMMA out_deg(v, G) = 1 IMPLIES 
                             (EXISTS e: outgoing_edges(v, G) = singleton(e) AND
                                        e`1 = v AND edges(G)(e))

     deg_1_sing       : LEMMA deg(v, G) = 1 IMPLIES 
                             (EXISTS e: incident_edges(v, G) = singleton(e) AND
                                        in?(v,e) AND edges(G)(e))

     deg_1_in_out     : LEMMA deg(v, G) = 1 IMPLIES 
                             (in_deg(v, G) = 1 AND out_deg(v, G) = 0)
                             OR (in_deg(v, G) = 0 AND out_deg(v, G) = 1)

     deg_1_edge: LEMMA deg(v,G) = 1 IMPLIES 
  		EXISTS (e:{e:edgetype | edges(G)(e)}, u:{u:T | vert(G)(u)}):
                          (e = (v,u) OR e = (u,v))
  			AND v /= u
   
  END digraph_deg

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

  % Subtype TCC generated (at line 26, column 32) for
      % {e: edgetype[T] | edges(G)(e) AND e`2 = v}
      % expected type  finite_set[edgetype[T]]
  incoming_edges_TCC1: OBLIGATION
    FORALL (v: T, G: digraph[T]):
      is_finite[edgetype[T]]({e: edgetype[T] | edges(G)(e) AND e`2 = v});

  % Subtype TCC generated (at line 29, column 32) for
      % {e: edgetype[T] | edges(G)(e) AND e`1 = v}
      % expected type  finite_set[edgetype[T]]
  outgoing_edges_TCC1: OBLIGATION
    FORALL (v: T, G: digraph[T]):
      is_finite[edgetype[T]]({e: edgetype[T] | edges(G)(e) AND e`1 = v});

  % Subtype TCC generated (at line 32, column 32) for
      % {e: edgetype[T] | edges(G)(e) AND in?(v, e)}
      % expected type  finite_set[edgetype[T]]
  incident_edges_TCC1: OBLIGATION
    FORALL (v: T, G: digraph[T]):
      is_finite[edgetype[T]]({e: edgetype[T] | edges(G)(e) AND in?[T](v, e)});


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:
  sep_sets[T: TYPE]: THEORY


  BEGIN

     IMPORTING digraphs[T], walks[T]

     G: VAR digraph[T]
     v,s,t: VAR T
     e: VAR edgetype[T]
     V: VAR finite_set[T]

     del_verts(G,V): digraph[T] =
             (# vert := difference[T](vert(G),V),                    
                edges := {e | edges(G)(e) AND 
                             (FORALL v: V(v) IMPLIES NOT in?(v,e))} #)

     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 digraph_deg[T], finite_sets@finite_sets_card_eq


     adj_verts(G,s): finite_set[T] = {v: T | (EXISTS (e: edgetype[T]):
                                           incident_edges[T](s, G)(e)
                                             AND in?(v,e) 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 in?(v, e))}
      % expected type  finite_set[edgetype[T]]
  del_verts_TCC1: OBLIGATION
    FORALL (G: digraph[T], V: finite_set[T]):
      is_finite[edgetype[T]]
          ({e | edges(G)(e) AND (FORALL v: V(v) IMPLIES NOT in?[T](v, e))});

  % 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 in?(v, e))} #)
      % expected type  digraph[T]
  del_verts_TCC2: OBLIGATION
    FORALL (G: digraph[T], V: finite_set[T]):
      FORALL (e_1: edgetype[T]):
        (edges(G)(e_1) AND (FORALL v: V(v) IMPLIES NOT in?[T](v, e_1)))
         IMPLIES
         difference[T](vert(G), V)(e_1`1) AND
          difference[T](vert(G), V)(e_1`2);

  % 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: digraph[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: edgetype[T]):
      %       incident_edges[T](s, G)(e) AND in?(v, e) AND NOT v = s)}
      % expected type  finite_set[T]
  adj_verts_TCC1: OBLIGATION
    FORALL (G: digraph[T], s: T):
      is_finite[T]
          ({v: T |
              EXISTS (e: edgetype[T]):
                incident_edges[T](s, G)(e) AND in?[T](v, e) AND NOT v = s});


body:
  min_walks[T: TYPE]: THEORY

  BEGIN

     IMPORTING digraphs[T]

     IMPORTING walks[T], abstract_min

     v1,v2,x,y: VAR T
     G: VAR digraph[T]

     gr_walk(v1,v2): TYPE = {G: digraph[T] | vert(G)(v1) AND vert(G)(v2) AND
                                           (EXISTS (w: Seq(G)):
                                             walk_from?(G,w,v1,v2))}

     min_walk_from(x,y,(Gw:gr_walk(x,y))): Walk(Gw) =
                          min[Seq(Gw),(LAMBDA (w: Seq(Gw)): length(w)),
                                  (LAMBDA (w: Seq(Gw)): walk_from?(Gw,w,x,y))]

     is_min(G,(w: Seq(G)),x,y): bool = walk?(G,w) AND 
                         (FORALL (ww: Seq(G)): walk_from?(G,ww,x,y) IMPLIES 
                                                          length(w) <= length(ww))

     min_walk_def: LEMMA FORALL (Gw: gr_walk(x,y)): 
                            walk_from?(Gw,min_walk_from(x,y,Gw),x,y) AND
                            is_min(Gw, min_walk_from(x,y,Gw),x,y) 
     
     min_walk_in : LEMMA FORALL (Gw: gr_walk(x,y)): 
                            walk_from?(Gw,min_walk_from(x,y,Gw),x,y) 

     min_walk_is_min: LEMMA FORALL (Gw: gr_walk(x,y), ww: Seq(Gw)):
                                walk_from?(Gw,ww,x,y) IMPLIES 
                                          length(min_walk_from(x,y,Gw)) <= length(ww)


  END min_walks

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

  % Assuming TCC generated (at line 17, column 24) for
      % min
      %     [Seq(Gw), (LAMBDA (w: Seq(Gw)): length(w)),
      %      (LAMBDA (w: Seq(Gw)): walk_from?(Gw, w, x, y))]
      % generated from assumption abstract_min.T_ne
  min_walk_from_TCC1: OBLIGATION
    FORALL (x: T, y: T, (Gw: gr_walk(x, y))):
      EXISTS (t: Seq[T](Gw)): walk_from?[T](Gw, t, x, y);

  % Subtype TCC generated (at line 17, column 24) for
      % min
      %     [Seq(Gw), (LAMBDA (w: Seq(Gw)): length(w)),
      %      (LAMBDA (w: Seq(Gw)): walk_from?(Gw, w, x, y))]
      % expected type  Walk[T](Gw)
  min_walk_from_TCC2: OBLIGATION
    FORALL (x: T, y: T, (Gw: gr_walk(x, y))):
      walk?[T]
          (Gw,
           min
               [Seq[T](Gw), LAMBDA (w: Seq[T](Gw)): length(w),
                LAMBDA (w: Seq[T](Gw)): walk_from?[T](Gw, w, x, y)]);

  % Subtype TCC generated (at line 26, column 37) for  min_walk_from(x, y, Gw)
      % expected type  Seq[T](Gw)
  min_walk_def_TCC1: OBLIGATION
    FORALL (x, y: T, Gw: gr_walk(x, y)):
      walk_from?(Gw, min_walk_from(x, y, Gw), x, y) IMPLIES
       verts_in?[T](Gw, min_walk_from(x, y, Gw));


body:
  paths[T: TYPE]: THEORY

  BEGIN

     IMPORTING digraphs[T], walks[T] %%%%%MAR, seq_def

     G: VAR digraph[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     : 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))


  %%%%%%%%%%%%%%%%%%%% NOT TRUE fpr directed graphs %%%%%%%%%%%%%%%%%%%
  %
  %   path?_rev       : LEMMA path?(G,ps) IMPLIES path?(G,rev(ps))


     path?_gen_seq2  : LEMMA vert(G)(x) AND vert(G)(y) AND x /= 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 32, column 44) for  ps ^ (i, j)
      % expected type  prewalk[T]
  path?_caret_TCC1: OBLIGATION
    FORALL (G: digraph[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 35, column 47) for  ps ^ (i, j)
      % expected type  prewalk[T]
  path_from?_caret_TCC1: OBLIGATION
    FORALL (G: digraph[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 35, column 65) for  i
      % expected type  below[ps`length]
  path_from?_caret_TCC2: OBLIGATION
    FORALL (G: digraph[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 47, column 48) for  length(p) - 1
      % expected type  below[p`length]
  path?_add1_TCC1: OBLIGATION
    FORALL (G: digraph[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: digraph[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: digraph[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: digraph[T], p: prewalk[T]):
      length(p) > 1 AND path?(G, p) IMPLIES
       length(p) - 2 >= 0 AND length(p) - 2 < p`length;


body:
  ind_paths[T: TYPE]: THEORY


  BEGIN

     IMPORTING paths[T]

     G: VAR digraph[T]
     u,v,s,t: VAR T
     e: VAR edgetype[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:
  digraph_inductions[T: TYPE]: THEORY

  BEGIN


    IMPORTING digraphs[T]

    G,GG,GGG: VAR digraph[T]
    P: VAR pred[digraph[T]]
    n: VAR nat

    size_prep              : LEMMA (FORALL G : P(G)) IFF 
                                        (FORALL n, G : size(G) = n IMPLIES P(G)) 


    digraph_induction_vert    : THEOREM (FORALL G:
                                  (FORALL GG: size(GG) < size(G) IMPLIES P(GG))
                                                  IMPLIES P(G))
                                    IMPLIES (FORALL G: P(G))


    digraph_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 digraph_ops[T]

    num_edges_prep         : LEMMA (FORALL G : P(G)) IFF 
                                     (FORALL n, G : num_edges(G) = n IMPLIES P(G)) 

    digraph_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 digraph_inductions


body:
  min_lem: THEORY
  BEGIN

    IMPORTING min_nat

    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_di_subgraphs[T: TYPE]: THEORY
  BEGIN

     IMPORTING  di_subgraphs[T], max_upto

     G: VAR digraph[T]

     Gpred(G): TYPE = {P: pred[digraph[T]] | (EXISTS (S: digraph[T]): 
                                               di_subgraph?(S,G) AND P(S))}

     n: VAR nat

     is_one_of_size(G: digraph[T], P: Gpred(G),n: nat): bool =
              (EXISTS (S: di_subgraph(G)): P(S) AND size(S) = n)

     prep0: LEMMA FORALL (G: digraph[T], P: Gpred(G)):
         nonempty?[upto[size(G)]]({n: upto[size(G)] | is_one_of_size(G,P,n)})

     max_size(G: digraph[T], P: Gpred(G)): upto[size(G)] =
               max({n: upto[size(G)] | is_one_of_size(G,P,n)})

     prep    : LEMMA FORALL (G: digraph[T], P: Gpred(G)):
                              nonempty?[di_subgraph(G)]({S: di_subgraph(G)
                                  | size[T](S) = max_size(G,P) AND P(S)})

     
     maximal?(G: digraph[T], S: di_subgraph(G), P: Gpred(G)): bool = P(S) AND 
                         (FORALL (SS: di_subgraph(G)): P(SS) IMPLIES 
                                                          size(SS) <= size(S))

  %  Existence TCC satisfied by
  %    choose({S: di_subgraph(G) | size(S) = max_size AND P(S)})
               

     max_di_subgraph(G: digraph[T], P: Gpred(G)): 
                {S: di_subgraph(G) | maximal?(G,S,P)}

     max_di_subgraph_def    : LEMMA FORALL (P: Gpred(G)): 
                                       maximal?(G,max_di_subgraph(G,P),P)

     max_di_subgraph_in     : LEMMA FORALL (P: Gpred(G)): P(max_di_subgraph(G,P)) 

     max_di_subgraph_is_max : LEMMA FORALL (P: Gpred(G)):
                            (FORALL (SS: di_subgraph(G)): P(SS) IMPLIES 
                                            size(SS) <= size(max_di_subgraph(G,P))) 

  END max_di_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: digraph[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_di_subgraph(G: digraph[T], P: Gpred(G)):
      %       {S: di_subgraph(G) | maximal?(G, S, P)}
  max_di_subgraph_TCC1: OBLIGATION
    EXISTS (x:
              [d: [G: digraph[T], Gpred(G)] ->
                 {S: di_subgraph[T](d`1) | maximal?(d`1, S, d`2)}]):
      TRUE;


body:
  %********************************************************************************%
  %
  %   Contributions from:
  %
  %       Andréia Borges Avelar -- Universidade de Brasília - Brasil  
  %       Mauricio Ayala-Rincon -- Universidade de Brasília - Brasil  
  %                 Cesar Muñoz -- NASA Langley Research Center - US
  %
  %********************************************************************************%

  digraph_conn_defs[T: TYPE]: THEORY

  BEGIN

     IMPORTING digraph_deg[T],
               walks[T],
               max_di_subgraphs[T]


     G,G1,G2: VAR digraph[T]


   %%% Defines a strongly connected digraph
   connected?(G) : bool = FORALL (u, v : (vert(G))) : reachable?(G)(u, v)


   %%% Defines a strongly connected component (scc) of a digraph
   connected_component?(G)(G1) : bool = connected?(G1) AND di_subgraph?(G1, G)

   conn_comp_with_edges?(G)(G1) : bool =
       connected_component?(G)(G1) AND
       FORALL(u, v: (vert(G1)) ): edge?(G)(u,v) IMPLIES edge?(G1)(u,v)

   %%% Defines a maximal strongly connected component of a digraph
   max_strongly_conn_comp?(G)(G1: di_subgraph(G)) : bool =
       conn_comp_with_edges?(G)(G1) AND 
       FORALL (G2: di_subgraph(G)): strict_subset?(vert(G1), vert(G2))
                                     IMPLIES NOT connected_component?(G)(G2)

   %%% Defines a maximal strongly connected component containing a vertex v
   vertex_conn_comp?(G)(G1: di_subgraph(G), v: (vert(G))) : bool =
       max_strongly_conn_comp?(G)(G1) AND vert(G1)(v)


   % max_connected_component?(G)(G1: di_subgraph(G)) : bool =
   %     maximal?(G, G1, connected_component?(G))


  END digraph_conn_defs


body:
  abstract_max[T: TYPE, N: nat, size: [T -> upto[N]], P: pred[T]]: THEORY
  %------------------------------------------------------------------------------
  %
  %  The need for a function that returns the largest object that
  %  satisfies a particular predicate arises in many contexts.  Thus it is
  %  useful to develop an "abstract" max theory that can be instantiated in
  %  multiple ways to provide different max functions.  Such a theory must
  %  be parameterized by
  %
  %    -------------------------------------------------------------------------
  %    | T: TYPE          | the base type over which max is defined            |
  %    | size:[T -> nat]  | the size function by which objects are compared    |
  %    | P: pred[T]       | the property that the max 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 max_upto

     TP: TYPE = {t: T | P(t)}


     n: VAR upto[N]

     S,SS: VAR T

     is_one(n): bool = (EXISTS (S: T): P(S) AND size(S) = n)

     prep0: LEMMA nonempty?({n: upto[N] | is_one(n)})

     max_f: upto[N] = max({n: upto[N] | is_one(n)})

     prep1: LEMMA nonempty?({S: T | size(S) = max_f AND P(S)})

     maximal?(S): bool = P(S) AND 
                         (FORALL (SS: T): P(SS) IMPLIES size(S) >= size(SS))

     max: {S: T | maximal?(S)} 


     max_def: LEMMA maximal?(max)

     max_in : LEMMA P(max) 

     max_is_max: LEMMA P(SS) IMPLIES size(max) >= size(SS) 


  END abstract_max

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

  % Subtype TCC generated (at line 49, column 24) for
      % {n: upto[N] | is_one(n)}
      % expected type  S: (nonempty?[upto[N]])
  max_f_TCC1: OBLIGATION nonempty?[upto[N]]({n: upto[N] | is_one(n)});

  % Existence TCC generated (at line 56, column 3) for
      % max: {S: T | maximal?(S)}
  max_TCC1: OBLIGATION EXISTS (x: {S: T | maximal?(S)}): TRUE;


body:
  reduce_walks[T: TYPE]: THEORY

  BEGIN

     IMPORTING paths[T]

     G: VAR digraph[T]

     Long_walk(G): TYPE = {w: Walk(G) | length(w) > 3}

     reduce(G: digraph[T], w: Long_walk(G), 
            k: {n: nat | n > 0 AND n < length(w)-1}): Walk(G) =
                        IF w(k-1) = w(k+1) THEN
                            (# length := length(w) - 2,
                            seq := (LAMBDA (i: below(length(w)-2)):
                                       IF i < k THEN w(i)
                                       ELSE w(i+2)
                                       ENDIF) #) 
                        ELSE
                            w
                        ENDIF

     reduce_lem: LEMMA FORALL (w: Walk(G), 
                              k: {n: nat | n > 0 AND n < length(w)-1}):
         w(k-1) = w(k+1) AND length(w) > 3 IMPLIES
            reduce(G,w,k) = w^(0,k-1) o w^(k+2,length(w)-1)
              

  END reduce_walks

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

  % Subtype TCC generated (at line 13, column 27) for  k - 1
      % expected type  below[length(w)]
  reduce_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: Long_walk(G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      k - 1 >= 0 AND k - 1 < length(w);

  % Subtype TCC generated (at line 13, column 36) for  k + 1
      % expected type  below[length(w)]
  reduce_TCC2: OBLIGATION
    FORALL (G: digraph[T], w: Long_walk(G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      k + 1 < length(w);

  % Subtype TCC generated (at line 14, column 39) for  length(w) - 2
      % expected type  nat
  reduce_TCC3: OBLIGATION
    FORALL (G: digraph[T], w: Long_walk(G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      finseq_appl[T](w)(k - 1) = finseq_appl[T](w)(k + 1) IMPLIES
       length(w) - 2 >= 0;

  % Subtype TCC generated (at line 16, column 53) for  i
      % expected type  below[length(w)]
  reduce_TCC4: OBLIGATION
    FORALL (G: digraph[T], w: Long_walk(G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      finseq_appl[T](w)(k - 1) = finseq_appl[T](w)(k + 1) IMPLIES
       (FORALL (i: below(length(w) - 2)): i < k IMPLIES i < length(w));

  % Subtype TCC generated (at line 17, column 44) for  i + 2
      % expected type  below[length(w)]
  reduce_TCC5: OBLIGATION
    FORALL (G: digraph[T], w: Long_walk(G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      finseq_appl[T](w)(k - 1) = finseq_appl[T](w)(k + 1) IMPLIES
       (FORALL (i: below(length(w) - 2)):
          NOT i < k IMPLIES i + 2 < length(w));

  % Subtype TCC generated (at line 14, column 26) for
      % (# length := length(w) - 2,
      %    seq
      %      := (LAMBDA (i: below(length(w) - 2)):
      %            IF i < k THEN finseq_appl[T](w)(i)
      %            ELSE finseq_appl[T](w)(i + 2)
      %            ENDIF) #)
      % expected type  Walk[T](G)
  reduce_TCC6: OBLIGATION
    FORALL (G: digraph[T], w: Long_walk(G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      finseq_appl[T](w)(k - 1) = finseq_appl[T](w)(k + 1) IMPLIES
       length(w) - 2 > 0 AND
        walk?[T]
            (G,
             (# length := length(w) - 2,
                seq
                  := (LAMBDA (i: below(length(w) - 2)):
                        IF i < k THEN finseq_appl[T](w)(i)
                        ELSE finseq_appl[T](w)(i + 2)
                        ENDIF) #));

  % Subtype TCC generated (at line 25, column 9) for  k - 1
      % expected type  below[length(w)]
  reduce_lem_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: Walk[T](G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      k - 1 >= 0 AND k - 1 < length(w);

  % Subtype TCC generated (at line 25, column 18) for  k + 1
      % expected type  below[length(w)]
  reduce_lem_TCC2: OBLIGATION
    FORALL (G: digraph[T], w: Walk[T](G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      k + 1 < length(w);

  % Subtype TCC generated (at line 26, column 31) for  k - 1
      % expected type  nat
  reduce_lem_TCC3: OBLIGATION
    FORALL (G: digraph[T], w: Walk[T](G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      finseq_appl[T](w)(k - 1) = finseq_appl[T](w)(k + 1) AND length(w) > 3
       IMPLIES k - 1 >= 0;

  % Subtype TCC generated (at line 26, column 45) for  length(w) - 1
      % expected type  nat
  reduce_lem_TCC4: OBLIGATION
    FORALL (G: digraph[T], w: Walk[T](G),
            k: {n: nat | n > 0 AND n < length(w) - 1}):
      finseq_appl[T](w)(k - 1) = finseq_appl[T](w)(k + 1) AND length(w) > 3
       IMPLIES length(w) - 1 >= 0;


body:
  path_ops[T: TYPE]: THEORY
  BEGIN

     IMPORTING paths[T], di_subgraphs[T], sep_sets[T], digraph_ops[T]

     G: VAR digraph[T]
     v,s,t: VAR T
     e: VAR edgetype[T]
     W,V: VAR finite_set[T]
     w: 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]

     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_from : LEMMA walk_from?(G,w,s,t) IMPLIES
                                   (EXISTS (p: prewalk): path_from?(G,p,s,t))


  END path_ops


body:
  min_walk_reduced[T: TYPE]: THEORY

  BEGIN

     IMPORTING min_walks[T], path_ops[T]

     reduced?(G: digraph[T], w: Seq(G)): bool = 
            (FORALL (k: nat): k > 0 AND k < length(w) - 1 IMPLIES w(k-1) /= w(k+1))

     x,y: VAR T
     i: VAR nat
     min_walk_vert: LEMMA FORALL (Gw: gr_walk(x,y)): i < length(min_walk_from(x,y,Gw))
                                 IMPLIES vert(Gw)(min_walk_from(x,y,Gw)(i))

     min_walk_is_reduced: LEMMA FORALL (Gw: gr_walk(x,y)):
                                       reduced?(Gw,min_walk_from(x,y,Gw))

  END min_walk_reduced

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

  % Subtype TCC generated (at line 8, column 66) for  k - 1
      % expected type  below[length(w)]
  reduced?_TCC1: OBLIGATION
    FORALL (G: digraph[T], w: Seq[T](G), k: nat):
      k > 0 AND k < length(w) - 1 IMPLIES k - 1 >= 0 AND k - 1 < length(w);

  % Subtype TCC generated (at line 8, column 76) for  k + 1
      % expected type  below[length(w)]
  reduced?_TCC2: OBLIGATION
    FORALL (G: digraph[T], w: Seq[T](G), k: nat):
      k > 0 AND k < length(w) - 1 IMPLIES k + 1 < length(w);

  % Subtype TCC generated (at line 16, column 49) for  min_walk_from(x, y, Gw)
      % expected type  Seq[T](Gw)
  min_walk_is_reduced_TCC1: OBLIGATION
    FORALL (x, y: T, Gw: gr_walk[T](x, y)):
      verts_in?[T](Gw, min_walk_from[T](x, y, Gw));


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)

  %   IMPORTING finite_sets@finite_sets

     finite_dbl: LEMMA is_finite(dbl(x,y))


  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));


body:
  %trees, defined for directed graphs 
  %
  %  Authors:
  %
  %      Ricky W. Butler      NASA Langley Research Center
  %      Kristin Y. Rozier    NASA Langley Research Center
  %
  %  Last updated: 7/28/2004

  trees[T: TYPE]: THEORY
  BEGIN

     IMPORTING digraph_deg[T], digraph_ops[T], di_subgraphs[T]

     G,GP,C,GG: VAR digraph[T]
     v: VAR T

     leaf?(v,G): MACRO bool = in_deg(v,G) = 1 AND out_deg(v,G) = 0

     leaf?(G)(v): bool = leaf?(v,G)

     root?(v,G): MACRO bool = in_deg(v,G) = 0 AND out_deg(v,G) > 0

     root?(G)(v): bool = root?(v,G)


  %   tree?(G): RECURSIVE bool = card[T](vert(G)) = 1 OR
  %                  (EXISTS (v: (vert(G))): root?(G)(v)
  %                                         AND tree?(del_vert[T](G,v)))
  %                MEASURE size(G)


     tree?(G): RECURSIVE bool = card[T](vert(G)) = 1 OR
                    (EXISTS (v: (vert(G))): leaf?(G)(v)
                                            AND tree?(del_vert[T](G,v)))
               MEASURE size(G)

                      
     tree_nonempty: LEMMA tree?(G) IMPLIES NOT empty?(G)

     Tree: TYPE = {G: digraph[T] | tree?(G)}



  END trees

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

  % Termination TCC generated (at line 35, column 46) for
      % tree?(del_vert[T](G, v))
  tree?_TCC1: OBLIGATION
    FORALL (G: digraph[T]):
      NOT card[T](vert(G)) = 1 IMPLIES
       (FORALL (v: (vert(G))):
          leaf?(G)(v) IMPLIES size[T](del_vert[T](G, v)) < size[T](G));


body:
  max_subtrees[T: TYPE]: THEORY
  BEGIN

     IMPORTING trees[T]

     G: VAR Digraph[T]    % not empty?(G)

     IMPORTING  max_di_subgraphs[T], doubletons[T]

     v: VAR T
     sing_is_tree: LEMMA tree?[T](singleton_digraph(v))

     tree_in: LEMMA (EXISTS (Tr: Tree[T]): di_subgraph?(Tr,G) AND  %% UNPROVED %%
                            nonempty?[T](vert(Tr)))

     Tr,S: VAR Tree[T]

     Subtree(G: digraph[T]): TYPE = {Tr: Tree | di_subgraph?(Tr,G)}

     max_subtree(G: Digraph[T]): Subtree(G) = max_di_subgraph(G,tree?)

     max_subtree_tree    : LEMMA tree?(max_subtree(G)) 

     max_subtree_di_subgraph: LEMMA di_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 62) for  tree?
      % expected type  Gpred[T](G)
  max_subtree_TCC1: OBLIGATION
    FORALL (G: Digraph[T]):
      EXISTS (S: digraph[T]): di_subgraph?[T](S, G) AND tree?[T](S);

  % Subtype TCC generated (at line 20, column 44) for
      % max_di_subgraph(G, tree?)
      % expected type  Subtree(G)
  max_subtree_TCC2: OBLIGATION
    FORALL (G: Digraph[T]):
      tree?[T](max_di_subgraph[T](G, tree?[T])) AND
       di_subgraph?[T](max_di_subgraph[T](G, tree?[T]), G);


body:
  subtrees[T: TYPE]: THEORY
  %-------------------------------------------------------------------------------
  %  Authors:
  %
  %      Ricky W. Butler,    NASA Langley
  %      Kristin Y. Rozier,  NASA Langley
  %
  %  Last modified 07/30/04
  %
  %  Maintained by:
  %
  %     Rick Butler        NASA Langley Research Center   
  %                        R.W.Butler@larc.nasa.gov
  %-------------------------------------------------------------------------------
  BEGIN

     IMPORTING max_subtrees[T], digraph_conn_defs[T]

     G: VAR Digraph[T]    % not empty?(G)

     S: VAR digraph[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 edgetype[T]
      v,w: VAR T
      add_pair: LEMMA  vert(G)(v) AND v /= w AND
                   add((v, w), edges(G))(e)
                IMPLIES 
                   LET (x,y) = e IN add(w, vert(G))(x) AND add(w, vert(G))(y)


      no_self_loops?(G): bool = FORALL (e: (edges(G))): e`1 /= e`2

      max_tree_all_verts: LEMMA connected?(G) AND
                                no_self_loops?(G)
                             IMPLIES
                                 vert(max_subtree(G)) = vert(G)

  %Another possible lemma: (after a definition for root exists)
  % Starting from the root, there exists a walk from the root to
  % any other vertex in G

  END subtrees

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

  % Subtype TCC generated (at line 25, column 47) for  0
      % expected type  below[w`length]
  walk_acr_TCC1: OBLIGATION
    FORALL (G: Digraph[T], n: nat, w: Walk[T](G)):
      n < length(w) IMPLIES 0 < w`length;

  % Subtype TCC generated (at line 28, column 42) for  j - 1
      % expected type  below[w`length]
  walk_acr_TCC2: OBLIGATION
    FORALL (G: Digraph[T], S: digraph[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 28, column 73) for  j
      % expected type  below[w`length]
  walk_acr_TCC3: OBLIGATION
    FORALL (G: Digraph[T], S: digraph[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);


body:
  di_subgraphs_from_walk[T: TYPE]: THEORY

  BEGIN
     IMPORTING digraphs[T], walks[T], di_subgraphs[T]
     
     G,GG: VAR digraph[T]
     t,t1,t2,v: VAR T
     i: VAR nat
     e: VAR edgetype[T]

     G_from(G, (w: Walk(G))): di_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)) 

  %%%%%%%%%%%%%%%%%%%%%%%%%% not true for directed graphs %%%%%%%%%%%%%%%%%%%%
  %
  %   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 digraph_ops[T]

     del_vert_di_subgraph: LEMMA FORALL (w: Walk(G), v: (vert(GG))): 
                                di_subgraph?(G_from(G, w), GG) AND
                                NOT verts_of(w)(v) IMPLIES
                                      di_subgraph?(G_from(G, w), del_vert(GG, v))
          
  END di_subgraphs_from_walk

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

  % Subtype TCC generated (at line 11, column 45) for
      % (# vert := verts_of(w), edges := edges_of(w) #)
      % expected type  di_subgraph[T](G)
  G_from_TCC1: OBLIGATION
    FORALL (G: digraph[T], (w: Walk[T](G))):
      (FORALL (e: edgetype[T]):
         edges_of[T](w)(e) IMPLIES
          verts_of[T](w)(e`1) AND verts_of[T](w)(e`2))
       AND
       di_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: digraph[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: digraph[T], w: Walk[T](G), i: below(length(w) - 1)):
      i + 1 < length(w);


body:
  dags[T: TYPE+]: THEORY
  BEGIN

     IMPORTING paths[T]

     acyclic_digraph: TYPE = {G: digraph | (FORALL (w: Walk(G)): path?(G,w))}

     dag: TYPE = acyclic_digraph

     DG: VAR dag
     dag_no_self_loops: LEMMA FORALL (e: edgetype): edges(DG)(e) IMPLIES
                                    LET (x,y) = e IN x /= y
  END dags


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

  top: THEORY

  BEGIN

    IMPORTING prelude_aux,  % Various auxiliary results
              prelude_A4,   % Scaffolding for ...
              appendix,     % Approximation results
              prelude_sqrt, % Definition and properties of sqrt

              cauchy,       % Cauchy property
              int,          % int and nat definitions
              add,          % addition
              neg,          % negation
              sub,          % subtraction
              mul,          % multiplication
              inv,          % reciprocal
              div,          % division
              rat,          % Rationals
              shift,        % multiplication/division by 2^n
              min,          % min of two ERA numbers
              max,          % max of two ERA numbers
              sqrtx,        % sqrt of ERA
              power,        % raising an ERA to a natural power (x^n)
              sum,          % summation
              series,       % series
              powerseries,  % powerseries 
              atanx,        % arctangent of an ERA
              asinx,        % arcsine of an ERA
              acosx,        % arcosine of an ERA
              sincosx,      % sine and cosine of an ERA
              trigx,        % sec, cosec and cot
              log,          % log of an ERA
              exp,          % exp of an ERA
              hyperbolicx,  % hyperbolic functions
              test        

  END top


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

  prelude_aux: THEORY

  BEGIN

    IMPORTING reals@sqrt,
              lnexp_fnd@ln_exp

    i:               VAR int
    m, n:            VAR nat
    pn,pm:           VAR posnat
    px:              VAR posreal
    nnx,nnz:         VAR nnreal
    x,y,z,w:         VAR real
    lt1x,lt1y:       VAR {r:posreal | r < 1}
    npx,npy,npz,npw: VAR npreal
    n0x,n0y:         VAR nzreal
    N:               VAR (nonempty?[nat])

    smallreal: NONEMPTY_TYPE = {x | -1 < x AND x < 1} CONTAINING 0

    lt_times_lt_nn1: LEMMA nnx < y AND nnz < w => nnx*nnz < y*w
    lt_times_lt_np1: LEMMA x < npy AND z < npw => npy*npw < x*z
    both_sides_times_nonneg_le1: LEMMA x <= y => x*nnz <= y*nnz
    both_sides_times_nonpos_le1: LEMMA y <= x => x*npz <= y*npz

    abs_nonneg: LEMMA abs(nnx) =  nnx
    abs_nonpos: LEMMA abs(npx) = -npx

    odd_even: LEMMA FORALL (z:int): even?(z) <=> NOT odd?(z)
    odd_or_even: LEMMA FORALL (z:int): odd?(z) OR even?(z)

    expt_product_aux:  LEMMA (n0x*n0y)^n = n0x^n*n0y^n
    expt_product:      LEMMA (n0x*n0y)^i = n0x^i*n0y^i
    expt_division_aux: LEMMA (n0x/n0y)^n = n0x^n/n0y^n
    expt_division:     LEMMA (n0x/n0y)^i = n0x^i/n0y^i

    expt_minus1: LEMMA (even?(i) => (-1)^i = 1) AND (odd?(i) => (-1)^i = -1)

    lt_equiv_not_le: LEMMA x <  y <=> NOT y <= x
    le_equiv_not_lt: LEMMA x <= y <=> NOT y <  x

    lt_equiv_le_plus_one: LEMMA FORALL (x,y:int): x < y <=> x+1 <= y
    lt_plus_one_equiv_le: LEMMA FORALL (x,y:int): x < 1+y <=> x <= y

    lt_le_transitivity: LEMMA x <= y AND y < z => x < z
    le_lt_transitivity: LEMMA x < y AND y <= z => x < z

    exp_of2_exists_aux: LEMMA lt1x < 1-2^-pn => (EXISTS n: lt1x^n < 1/2)
    exp_of2_exists: LEMMA EXISTS n: lt1x^n < 1/2
    exp_of_exists2: LEMMA EXISTS n: lt1x^n < lt1y

    round(x): int = floor(x+1/2)

    floor_sqrt_val:   LEMMA (m*m <= n AND n < (m+1)*(m+1)) <=> floor(sqrt(n)) = m
    ceiling_sqrt_0:   LEMMA ceiling(sqrt(0)) = 0
    ceiling_sqrt_val: LEMMA (pn <= pm*pm AND (pm-1)*(pm-1) < pn) <=>
                                                           ceiling(sqrt(pn)) = pm

    log2(px:posreal):real = ln(px)/ln(2)

    log2_2_expt_i: LEMMA log2(2^i) = i

    log2_strict_increasing: LEMMA strict_increasing?(log2)

  END prelude_aux

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

  % Subtype TCC generated (at line 40, column 37) for  n
      % expected type  {i: int | (n0x * n0y) /= 0 OR i >= 0}
  expt_product_aux_TCC1: OBLIGATION
    FORALL (n: nat, n0x, n0y: nzreal): (n0x * n0y) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 40, column 45) for  n
      % expected type  {i: int | n0x /= 0 OR i >= 0}
  expt_product_aux_TCC2: OBLIGATION
    FORALL (n: nat, n0x: nzreal): n0x /= 0 OR n >= 0;

  % Subtype TCC generated (at line 41, column 37) for  i
      % expected type  {i: int | (n0x * n0y) /= 0 OR i >= 0}
  expt_product_TCC1: OBLIGATION
    FORALL (i: int, n0x, n0y: nzreal): (n0x * n0y) /= 0 OR i >= 0;

  % Subtype TCC generated (at line 41, column 45) for  i
      % expected type  {i: int | n0x /= 0 OR i >= 0}
  expt_product_TCC2: OBLIGATION
    FORALL (i: int, n0x: nzreal): n0x /= 0 OR i >= 0;

  % Subtype TCC generated (at line 42, column 37) for  n
      % expected type  {i: int | (n0x / n0y) /= 0 OR i >= 0}
  expt_division_aux_TCC1: OBLIGATION
    FORALL (n: nat, n0x, n0y: nzreal): (n0x / n0y) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 43, column 37) for  i
      % expected type  {i: int | (n0x / n0y) /= 0 OR i >= 0}
  expt_division_TCC1: OBLIGATION
    FORALL (i: int, n0x, n0y: nzreal): (n0x / n0y) /= 0 OR i >= 0;

  % Subtype TCC generated (at line 56, column 62) for  n
      % expected type  {i: int | lt1x /= 0 OR i >= 0}
  exp_of2_exists_aux_TCC1: OBLIGATION
    FORALL (lt1x: {r: posreal | r < 1}, pn: posnat):
      lt1x < 1 - 2 ^ -pn IMPLIES (FORALL (n): lt1x /= 0 OR n >= 0);

  % Subtype TCC generated (at line 57, column 39) for  n
      % expected type  {i: int | lt1x /= 0 OR i >= 0}
  exp_of2_exists_TCC1: OBLIGATION
    FORALL (lt1x: {r: posreal | r < 1}, n): lt1x /= 0 OR n >= 0;

  % Subtype TCC generated (at line 67, column 33) for  ln(2)
      % expected type  nznum
  log2_TCC1: OBLIGATION ln(2) /= 0;


body:
  %------------------------------------------------------------------------------
  % Scaffolding for Appendix Lemma 4
  %
  %     Author: David Lester, Manchester University
  %
  %     Version 1.0            18/2/09   Initial Release Version
  %------------------------------------------------------------------------------

  prelude_A4: THEORY

    BEGIN
    IMPORTING prelude_aux,
              reals@sqrt

    i:           VAR int
    l,n:         VAR nat
    pn:          VAR posnat
    e1,e2,x,y,z: VAR real
    nx:          VAR negreal
    n0x,n0y:     VAR nzreal

    expt_neg_even:    LEMMA even?(n) => nx^n = (-nx)^n
    expt_neg_odd:     LEMMA odd?(n)  => nx^n = -((-nx)^n)
    expt_0pn:         LEMMA 0^pn = 0
    expt_inverse_inv: LEMMA (1/n0x)^i = 1/(n0x^i)
    expt_product_n0i: LEMMA (x*y)^pn = x^pn*y^pn
    expt_division:    LEMMA (x/n0y)^pn = x^pn/n0y^pn

    A4_0:   LEMMA -1 < y => 0 <= n/(n+1+y) AND n/(n+1+y) < 1
    A4_1:   LEMMA -1 < y => 0 < pn/(pn+1+y) AND pn/(pn+1+y) < 1
    A4_2:   LEMMA -1 < y AND z = n*y/(n+1+y) => -1 < z
    A4_3_n: LEMMA -1 < y AND y < 0 AND z = pn*y/(pn+1+y) => y < z
    A4_3_0: LEMMA y = 0  AND z = pn*y/(pn+1+y) => z = 0
    A4_3_p: LEMMA 0 < y  AND z = pn*y/(pn+1+y) => z < y
    A4_4:   LEMMA -1 < y AND z = pn*y/(pn+1+y) =>
                     (pn*x*(1+z) < z <=> (pn+1)*x*(1+y) < y)
    A4_5pp: LEMMA 0 < x => (FORALL n: (FORALL y: 0 < y =>
                              ((1+y)*n*x < y => (1+x)^n < 1+y)))

    A4_5nn: LEMMA -1 < x AND x < 0 =>
                  (FORALL pn:
                      (FORALL y: -1 < y AND y < 0 =>
                              ((1+y)*pn*x < y => (1+x)^pn < 1+y)))

    A4_5nn_general: LEMMA -1 < x AND x < 0 AND y < 0 AND (1+y)*n*x < y =>
                          (1+x)^n < 1+y

    A4_5:   LEMMA -1 < x AND -1 < y AND (1+y)*pn*x < y => (1+x)^pn < 1+y

    A4_6pp: LEMMA 0 < x => (FORALL n: (FORALL y: 0 < y =>
                              (y*(1+x) < n*x => 1+y < (1+x)^n)))

    A4_6pp_general: LEMMA 0 < x AND y*(1+x) < n*x => 1+y < (1+x)^n

    A4_6nn: LEMMA -1 < x AND x < 0 => (FORALL n: (FORALL y: -1 < y AND y
                              < 0 => (y*(1+x) < n*x => 1+y < (1+x)^n)))

    A4_6nn_general: LEMMA -1 < x AND x < 0 AND y < 0 AND y*(1+x) < n*x => 1+y < (1+x)^n

    A4_sqrt_ineq1: LEMMA 1/2 < 2-sqrt(2)
    A4_sqrt_ineq2: LEMMA 1/sqrt(2) + 2^-3 < 1
    A4_sqrt_ineq3: LEMMA 0 < 1/sqrt(2) - 2^-3

    A4_logsize: LEMMA 2 <= pn AND 1 <= pn*2^-l AND pn*2^-l < 2 => 1 <= l

    A4_lemma_ineq1: LEMMA 1 <= n AND 3 <= pn AND 2^-n/sqrt(2) <= x AND x < 2^-n
                          => x^pn + 2^-n < 2*x

    A4_lemma_ineq2: LEMMA 3 <= pn AND 2^-n <= x AND x < 1 AND
                          1 <= pn*2^-l AND pn*2^-l < 2 =>
                          x^pn + 2^-n < 2*x

    A4_lemma_large_UB_0: LEMMA 3 <= pn AND 1/sqrt(2) <= x AND x < 1 AND
                               1 <= pn*2^-l AND pn*2^-l < 2 =>
                               (x+2^ -(l+2))^pn < x^pn+1

    A4_lemma_large_UB: LEMMA 3 <= pn AND e2/sqrt(2) <= x AND x < 1 AND
                             1 <= pn*2^-l AND pn*2^-l < 2 AND
                             e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                             (x+e1)^pn < x^pn+e2

    A4_lemma_large_LB: LEMMA 3 <= pn AND e2/sqrt(2) <= x AND x < 1 AND
                             1 <= pn*2^-l AND pn*2^-l < 2 AND
                             e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                             x^pn-e2 < (x-e1)^pn

    A4_lemma_large_ge3: LEMMA 3 <= pn AND e2/sqrt(2) <= x AND x < 1 AND
                              1 <= pn*2^-l AND pn*2^-l < 2 AND
                              e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                              x^pn-e2 < (x-e1)^pn AND (x+e1)^pn < x^pn+e2

    A4_lemma_large_lt3: LEMMA (pn = 1 OR pn = 2) AND e2/sqrt(2) <= x AND x < 1 AND
                              1 <= pn*2^-l AND pn*2^-l < 2 AND
                              e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                              x^pn-e2 < (x-e1)^pn AND (x+e1)^pn < x^pn+e2

    A4_lemma_small_UB: LEMMA 2 <= pn AND 0 < x AND x < e2/sqrt(2) AND
                             1 <= l AND e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                             (x+e1)^pn < x^pn+e2

    A4_lemma_small_LB: LEMMA 2 <= pn AND 0 < x AND x < e2/sqrt(2) AND
                             1 <= l AND e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                             x^pn-e2 < (x-e1)^pn

    A4_lemma_small: LEMMA 0 < x AND x < e2/sqrt(2) AND
                          1 <= pn*2^-l AND pn*2^-l < 2 AND 
                          e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                          x^pn-e2 < (x-e1)^pn AND (x+e1)^pn < x^pn+e2

    A4_lemma_px: LEMMA e1 <= x AND x < 1 AND 1 <= pn*2^-l AND pn*2^-l < 2 AND
                       e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                       x^pn-e2 < (x-e1)^pn AND (x+e1)^pn < x^pn+e2

    A4_lemma_p: LEMMA e1 <= x AND x < 1 AND 1 <= pn*2^-l AND pn*2^-l < 2 AND
                      e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                      x^pn-e2 < (x-e1)^pn AND x^pn-e2 < (x+e1)^pn AND
                      (x-e1)^pn < x^pn+e2 AND (x+e1)^pn < x^pn+e2

    A4_lemma_0_px: LEMMA 0 < x AND x < e1 AND 1 <= pn*2^-l AND pn*2^-l < 2 AND
                      e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                      x^pn-e2 < (x-e1)^pn AND (x+e1)^pn < x^pn+e2

    A4_lemma_0_p: LEMMA 0 < x AND x < e1 AND 1 <= pn*2^-l AND pn*2^-l < 2 AND
                      e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                      x^pn-e2 < (x-e1)^pn AND x^pn-e2 < (x+e1)^pn AND
                      (x-e1)^pn < x^pn+e2 AND (x+e1)^pn < x^pn+e2

    A4_lemma_0: LEMMA -e1 < x AND x < e1 AND 1 <= pn*2^-l AND pn*2^-l < 2 AND
                      e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                      x^pn-e2 < (x-e1)^pn AND x^pn-e2 < (x+e1)^pn AND
                      (x-e1)^pn < x^pn+e2 AND (x+e1)^pn < x^pn+e2

    A4_lemma_n_even:
                LEMMA even?(pn) AND e1 = 2^ -(n+l+2) AND e2 = 2^-n AND
                      -1 < x AND x <= -e1 AND 1 <= pn*2^-l AND pn*2^-l < 2 =>
                      x^pn-e2 < (x+e1)^pn AND (x-e1)^pn < x^pn+e2

    A4_lemma_n_odd:
                LEMMA odd?(pn) AND e1 = 2^ -(n+l+2) AND e2 = 2^-n AND
                      -1 < x AND x <= -e1 AND 1 <= pn*2^-l AND pn*2^-l < 2 =>
                      x^pn-e2 < (x-e1)^pn AND (x+e1)^pn < x^pn+e2

    A4_lemma_n: LEMMA -1 < x AND x <= -e1 AND 1 <= pn*2^-l AND pn*2^-l < 2 AND
                      e1 = 2^ -(n+l+2) AND e2 = 2^-n =>
                      x^pn-e2 < (x-e1)^pn AND x^pn-e2 < (x+e1)^pn AND
                      (x-e1)^pn < x^pn+e2 AND (x+e1)^pn < x^pn+e2

    END prelude_A4

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

  % Subtype TCC generated (at line 22, column 41) for  n
      % expected type  {i: int | nx /= 0 OR i >= 0}
  expt_neg_even_TCC1: OBLIGATION
    FORALL (n: nat, nx: negreal): even?(n) IMPLIES nx /= 0 OR n >= 0;

  % Subtype TCC generated (at line 22, column 51) for  n
      % expected type  {i: int | (-nx) /= 0 OR i >= 0}
  expt_neg_even_TCC2: OBLIGATION
    FORALL (n: nat, nx: negreal): even?(n) IMPLIES (-nx) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 23, column 41) for  n
      % expected type  {i: int | nx /= 0 OR i >= 0}
  expt_neg_odd_TCC1: OBLIGATION
    FORALL (n: nat, nx: negreal): odd?(n) IMPLIES nx /= 0 OR n >= 0;

  % Subtype TCC generated (at line 23, column 53) for  n
      % expected type  {i: int | (-nx) /= 0 OR i >= 0}
  expt_neg_odd_TCC2: OBLIGATION
    FORALL (n: nat, nx: negreal): odd?(n) IMPLIES (-nx) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 25, column 45) for  i
      % expected type  {i: int | n0x /= 0 OR i >= 0}
  expt_inverse_inv_TCC1: OBLIGATION
    FORALL (i: int, n0x: nzreal): n0x /= 0 OR i >= 0;

  % Subtype TCC generated (at line 26, column 32) for  pn
      % expected type  {i: int | (x * y) /= 0 OR i >= 0}
  expt_product_n0i_TCC1: OBLIGATION
    FORALL (pn: posnat, x, y: real): (x * y) /= 0 OR pn >= 0;

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

  % Subtype TCC generated (at line 27, column 34) for  pn
      % expected type  {i: int | (x / n0y) /= 0 OR i >= 0}
  expt_division_TCC1: OBLIGATION
    FORALL (n0y: nzreal, pn: posnat, x: real): (x / n0y) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 27, column 48) for  pn
      % expected type  {i: int | n0y /= 0 OR i >= 0}
  expt_division_TCC2: OBLIGATION
    FORALL (n0y: nzreal, pn: posnat): n0y /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 29, column 34) for  (n + 1 + y)
      % expected type  nznum
  A4_0_TCC1: OBLIGATION
    FORALL (n: nat, y: real): -1 < y IMPLIES (n + 1 + y) /= 0;

  % Subtype TCC generated (at line 30, column 34) for  (pn + 1 + y)
      % expected type  nznum
  A4_1_TCC1: OBLIGATION
    FORALL (pn: posnat, y: real): -1 < y IMPLIES (pn + 1 + y) /= 0;

  % Subtype TCC generated (at line 33, column 37) for  (pn + 1 + y)
      % expected type  nznum
  A4_3_0_TCC1: OBLIGATION
    FORALL (pn: posnat, y: real): y = 0 IMPLIES (pn + 1 + y) /= 0;

  % Subtype TCC generated (at line 34, column 37) for  (pn + 1 + y)
      % expected type  nznum
  A4_3_p_TCC1: OBLIGATION
    FORALL (pn: posnat, y: real): 0 < y IMPLIES (pn + 1 + y) /= 0;

  % Subtype TCC generated (at line 38, column 52) for  n
      % expected type  {i: int | (1 + x) /= 0 OR i >= 0}
  A4_5pp_TCC1: OBLIGATION
    FORALL (x: real):
      0 < x IMPLIES
       (FORALL (n, y):
          (1 + y) * n * x < y AND 0 < y IMPLIES (1 + x) /= 0 OR n >= 0);

  % Subtype TCC generated (at line 43, column 53) for  pn
      % expected type  {i: int | (1 + x) /= 0 OR i >= 0}
  A4_5nn_TCC1: OBLIGATION
    FORALL (x: real):
      x < 0 AND -1 < x IMPLIES
       (FORALL (pn, y):
          (1 + y) * pn * x < y AND -1 < y AND y < 0 IMPLIES
           (1 + x) /= 0 OR pn >= 0);

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

  % Subtype TCC generated (at line 48, column 62) for  pn
      % expected type  {i: int | (1 + x) /= 0 OR i >= 0}
  A4_5_TCC1: OBLIGATION
    FORALL (pn: posnat, x, y: real):
      (1 + y) * pn * x < y AND -1 < y AND -1 < x IMPLIES
       (1 + x) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 51, column 58) for  n
      % expected type  {i: int | (1 + x) /= 0 OR i >= 0}
  A4_6pp_TCC1: OBLIGATION
    FORALL (x: real):
      0 < x IMPLIES
       (FORALL (n, y):
          y * (1 + x) < n * x AND 0 < y IMPLIES (1 + x) /= 0 OR n >= 0);

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

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

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

  % Subtype TCC generated (at line 75, column 43) for  pn
      % expected type  {i: int | NOT (x + 2 ^ -(2 + l)) = 0 OR i >= 0}
  A4_lemma_large_UB_0_TCC1: OBLIGATION
    FORALL (l: nat, pn: posnat, x: real):
           pn * 2 ^ -l < 2 AND 1 <= pn * 2 ^ -l AND x < 1 AND 1 / sqrt(2) <= x
       AND 3 <= pn
       IMPLIES NOT (x + 2 ^ -(2 + l)) = 0 OR pn >= 0;

  % Subtype TCC generated (at line 80, column 34) for  pn
      % expected type  {i: int | NOT e1 + x = 0 OR i >= 0}
  A4_lemma_large_UB_TCC1: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND pn * 2 ^ -l < 2
       AND 1 <= pn * 2 ^ -l AND x < 1 AND e2 / sqrt(2) <= x AND 3 <= pn
       IMPLIES NOT e1 + x = 0 OR pn >= 0;

  % Subtype TCC generated (at line 85, column 44) for  pn
      % expected type  {i: int | (x - e1) /= 0 OR i >= 0}
  A4_lemma_large_LB_TCC1: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND pn * 2 ^ -l < 2
       AND 1 <= pn * 2 ^ -l AND x < 1 AND e2 / sqrt(2) <= x AND 3 <= pn
       IMPLIES (x - e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 95, column 45) for  pn
      % expected type  {i: int | (x - e1) /= 0 OR i >= 0}
  A4_lemma_large_lt3_TCC1: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND pn * 2 ^ -l < 2
       AND 1 <= pn * 2 ^ -l AND x < 1 AND e2 / sqrt(2) <= x
       AND (pn = 1 OR pn = 2)
       IMPLIES (x - e1) /= 0 OR pn >= 0;

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

  % Subtype TCC generated (at line 99, column 34) for  pn
      % expected type  {i: int | NOT e1 + x = 0 OR i >= 0}
  A4_lemma_small_UB_TCC1: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND 1 <= l
       AND x < e2 / sqrt(2) AND 0 < x AND 2 <= pn
       IMPLIES NOT e1 + x = 0 OR pn >= 0;

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

  % Subtype TCC generated (at line 108, column 41) for  pn
      % expected type  {i: int | (x - e1) /= 0 OR i >= 0}
  A4_lemma_small_TCC1: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND pn * 2 ^ -l < 2
       AND 1 <= pn * 2 ^ -l AND x < e2 / sqrt(2) AND 0 < x
       IMPLIES (x - e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 108, column 55) for  pn
      % expected type  {i: int | NOT e1 + x = 0 OR i >= 0}
  A4_lemma_small_TCC2: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND pn * 2 ^ -l < 2
       AND 1 <= pn * 2 ^ -l AND x < e2 / sqrt(2) AND 0 < x
       AND x ^ pn - e2 < (x - e1) ^ pn
       IMPLIES NOT e1 + x = 0 OR pn >= 0;

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

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

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

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

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

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

  % Subtype TCC generated (at line 136, column 37) for  pn
      % expected type  {i: int | NOT e1 + x = 0 OR i >= 0}
  A4_lemma_n_even_TCC1: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           pn * 2 ^ -l < 2 AND 1 <= pn * 2 ^ -l AND x <= -e1 AND -1 < x
       AND e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND even?(pn)
       IMPLIES NOT e1 + x = 0 OR pn >= 0;

  % Subtype TCC generated (at line 136, column 51) for  pn
      % expected type  {i: int | (x - e1) /= 0 OR i >= 0}
  A4_lemma_n_even_TCC2: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           pn * 2 ^ -l < 2 AND 1 <= pn * 2 ^ -l AND x <= -e1 AND -1 < x
       AND e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND even?(pn)
       AND x ^ pn - e2 < (x + e1) ^ pn
       IMPLIES (x - e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 141, column 37) for  pn
      % expected type  {i: int | (x - e1) /= 0 OR i >= 0}
  A4_lemma_n_odd_TCC1: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           pn * 2 ^ -l < 2 AND 1 <= pn * 2 ^ -l AND x <= -e1 AND -1 < x
       AND e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND odd?(pn)
       IMPLIES (x - e1) /= 0 OR pn >= 0;

  % Subtype TCC generated (at line 141, column 51) for  pn
      % expected type  {i: int | NOT e1 + x = 0 OR i >= 0}
  A4_lemma_n_odd_TCC2: OBLIGATION
    FORALL (e1, e2: real, l, n: nat, pn: posnat, x: real):
           pn * 2 ^ -l < 2 AND 1 <= pn * 2 ^ -l AND x <= -e1 AND -1 < x
       AND e2 = 2 ^ -n AND e1 = 2 ^ -(n + l + 2) AND odd?(pn)
       AND x ^ pn - e2 < (x - e1) ^ pn
       IMPLIES NOT e1 + x = 0 OR pn >= 0;

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

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


