Лекция 4-1. Списки. Операции над списками

Свойства списков:

- каждый элемент может встретиться несколько раз

- порядок определен (и существенен)

Описание типа

type

LT1 = T1-list

NLT1 = T1-inflist

Литералы и агрегаты

<.1,2,3.>

<..>

списочное выражение (rangered list expression)

<.3...7>  =  <.3,4,5,6,7.>

<.3..3.> = <.3.>

<.3..2.> = <..>

генерация списка на основе имеющегося

<. 2*n | n in <.1..100.> :- true .>

<. 2*n | n in <.1..100.> .>

<.n | n in <.1..100.> :- is_a_prime(n).> = ...

value

     INTLIST : (Int >< Int)-list = <. (1,2), (2,2), (2,1), (3,1).>

.....

....... <. (x,f(y)) | (x,y) in INTLIST :- x>y .>

Сигнатуры операций:

^            :        T-list >< T-list -> T-list       concatenation

in           :        T >< T-list

len         :        T-list -> Nat

hd          :        T-list -~-> T

tl            :        T-list -~-> T-list

inds      :        T-list -> Nat-set

elems   :        T-list -> T-set

n        Диаграмма Гогена

Свойства операций

inds fl = {1..len fl}                             - для конечных списков

inds il = {idx | idx : Nat :- idx >= 1} - для бесконечных cписков

elems l = {l(idx) | idx : Nat :- idx isin inds l}

Texts and Character Lists

"abc"  = <.'a','b','c'.>

"" = <..>

Пример: A Queue

QUEUE =

  class

    type

      Element,

      Queue = Element-list

    value

      empty : Queue,

      put : Element >< Queue -> Queue,

      get : Queue -~-> Queue >< Element

    axiom forall e : Element, q : Queue

      empty is <..>,

      put (e,q) is q ^ <.e.>,

      get(q) is (tl q, hd q)

      pre q ~= empty

end

(Объяснить, что forall – это сокращенная запись, инструментом не поддерживается)

Следующий пример показывает, как строятся иерархии классов с расширениями (extend).

Вторая цель  примера – показать “хороший стиль”. Здесь мы не будем описывать алгоритмы. Мы описываем только свойства результата.

Пример: Sorting Integer Lists

LIST_PROPERTIES =

  class

    value

      is_permutation : Int-list >< Int-list -> Bool,

      is_sorted : Int-list -> Bool

    axiom forall l,l1,l2 ; Int-list :-

      is_permutation(l1,l2) is

        (all i : Int :-

           card {idx | idx : Nat :- idx isin l1 /\ l1(idx) = i} =

           card {idx | idx : Nat :- idx isin l2 /\ l2(idx) = i},

      is_sorted(l) is

        (all idx1,idx2 : Nat :-

          {idx1,idx2} <<= inds l /\ idx1 < idx2 =>

            l(idx1) <= l(idx2))

end

Ниже приведено расширение рассмотренного выше модуля

SORTING =

  extend LIST_PROPERTIES with

  class

    value

      sort : Int-list -> Int-list

    axiom forall l : Int-list :-

      sort(l) as l1 post is_permutation(l1,l2) /\ is_sorted(l1)

end


Более сложный пример. Цель примера: сравнить впоследствие спецификации Database в термина сорт-типов, множеств кортежей и списков записей.

Пример: A Database

KEY =

  class

    type

      Key

    value

      less_than : Key >< Key -> Bool

    axiom forall k,k1,k2,k3 : Key :-

      [anti_reflexive]

        ~less_than(k,k),

      [transitive]

        less_than(k1,k2) /\ less_than(k2,k3) => less_than(k1,k3),

      [total_order]

        less_than(k1,k2) \/ less_than(k2,k1) \/ k1=k2

end

DATA =

  class

    type

      Data

    value

      not_found : Data

end

RECORD =

  extend KEY with extend DATA with

  class

    type

      Record = Key >< Data

    value

      new_record : Key >< Data -> Record,

      key_of : Record -> Key,

      data_of : Record -> Data

    axiom forall k : Key, d : Data :-

      new_record(k,d) is (k,d),

      key_of(k,d) is k,

      data_of(k,d) is d

end

LIST_DATABASE =

  extend RECORD with

  class

    type

      Database = {| rl : record-list :- is_wf_Database(rl) |}

    value

      is_wf_Database : Record-list -> Bool,

      empty : Database,

      insert : Key >< Data >< Database -> Database,

      remove : Key >< Database -> Database,

      defined : Key >< Database -> Bool,

      lookup : Key >< Database -> Data

    axiom forall k : Key, d : Data, rl : record-list db : Database :-

      is_wf_Database(rl) is

        (all r1,r2 : Record, left,right : Record-list :-

          rl = left ^ <.r1,r2.> ^ right =>

            less_than(key_of(r1),key_of(r2))),

       empty is <..>,

       insert(k,d,db) as db1

       post elems db1 = (elems remove(k,db)) union {new_record(k,d)},

       remove(k,db) is <.r | r in db :- key_of(r) ~= k.>,

       defined(k,db) is

         if db = <..> \/ less_than(k,key_of(hd db)) then false

         else key_of(hd db) = k \/ defined(k,tl db)

         end,

       lookup(k,db) is

         if db = <..> \/ less_than(k,key_of(hd db)) then not_found

         elsif key_of(hd db) = k then data_of(hd db) then data_of(hd db)

         else lookup(k, tl db)

         end

end


Лекция 4-2. Отображения. Операции над отображениями

 

 

n        Свойства отображений:

- каждый ключ может встретиться только один раз

- порядок ключей не определен

Описание типа

type

MT12 = T1 -m-> T2

Литералы и агрегаты

[1 +> true, 3+>false, 2+>true]

[]

[“Petrov”+>”912-5317”, “Ivanov”+>”125-7652”

генерация отображения

[ n+>2*n | n : Nat :- n < 100 ]

Операции

dom

rng

m(k)   - “применение” - найти значение по ключу k в отображении m

!!  ()  - (dagger) добавить или переопределить значение ключа (override)

union  - добавить (но не переопределить)

#  (°)   - композиция

\ - убрать ключи из s

/ - оставить только ключи из s

Свойства операций

m \ s = [d +> m(d) | d : T1 :- d isin dom m /\ d ~isin s] /* restricted by */m / s = [d +> m(d) | d : T1 :- d isin dom m /\ d isin s]  /* restricted to */


n        Диаграмма Гогена

Пример с использованием MAP

LIBRARY_MAP =

  class

    type

       Books = Book-set,

       Log = Book -m-> Reader,

       Readers = Reader-set,

       Reader, Book

    value

        book_out : Reader >< Readers >< Book >< Books>< Log-~-> Log

........book_in : Book >< Books >< Log -~-> Log,

        register : Reader >< Readers -~-> Readers

        register : Book >< Books -~-> Books

......

end