Лекция 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