Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lectures / lecture8.ppt
Скачиваний:
8
Добавлен:
06.06.2015
Размер:
327.68 Кб
Скачать

07.11.12 Лекция 8

Предикатное программирование

7. Технология предикатного программирования

7.4. Гиперфункции

Неудобные ситуации в программировании Гиперфункция и оператор продолжения ветвей Свойства гиперфункций Пример. Вычисление суммы чисел в строке

Пример. Решение системы линейных уравнений

7. Технология предикатного программирования 7.4. Гиперфункции

Структурное

программирование

Эдвард Дейкстра

begin <оператор1> ; <оператор2> end

if <условие> then <оператор1> else <оператор2> end while <условие> do <оператор> end

Неудобные ситуации

elemTwo(list(int) s: int e, bool exists ) { if (s = nil s.cdr = nil) exsts = false

else { e = s.cdr.car || exists = true }

} post exists = (s nil & s.cdr nil) & (exists e = s.cdr.car)

elemTwo(s: e, exists); if (exists) B(e…) else D(…)

(7.13)

if ( s = nil s.cdr =

nil )

(7.14)

{ exist = false; if (exist) B(e…) else D(…) }

 

else {{e = s.cdr.car

|| exist = true }; if (exist) B(e…) else D(…)}

if (s = nil s.cdr = nil) D(…) else { e = s.cdr.car; B(e…) }

Пример. Решение системы линейных уравнений

n

aijxj bj, j 1..n LinEq(a, x, b)

i 1

type VEC(nat k) = array (real, 1..k);

type MATRICE(nat k) = array(real, 1..k, 1..k); Lin(nat n, MATRICE(n) a, VEC(n) b: VEC(n) x)

pre det(n, a) 0

// >

post LinEq(n, a, x, b);

Иногда требуется решить более общую задачу:

Lin1(nat n, MATRICE(n) a, VEC(n) b: bool c; VEC(n) x) post c = (det(n, a) 0) & (c LinEq(n, a, x, b));

Lin1(n, a, b: c; x); if (c) B(x…) else D(…)

P(x) { A(x: y, z, c) } c = C(x) Q(x, y, z); x, y и z возможно пустые

Q(x, y, z) (C(x) S(x, y)) ( C(x) R(x, z))

(7.16)

Предикаты S(x, y) и R(x, z) функции S: x y и R: x z.

 

C(x) истинно

Q(x, y, z) совпадает с S: x y

 

C(x) ложно

Q(x, y, z) совпадает с R: x z.

 

Q(x, y, z) результат склеивания функций S: x y и R: x z. В Q(x, y, z) не определено значение набора z, если C(x) истинно. Аналогично, не определено значение y при ложном C(x).

Лемма 7.10. Если предикат S(x, y) тотален в области P(x) & C(x), а R(x, z) в области P(x) & C(x), то

спецификация предиката A(x: y, z, c) является тотальной.

Лемма 7.11. Если предикат S(x, y) является однозначным в области P(x) & C(x), а R(x, z) в области P(x) & C(x), то спецификация предиката A(x: y, z, c) является однозначной.

P(x) { A(x: y, z, c) } c = C(x) Q(x, y, z)

 

Q(x, y, z) (C(x) S(x, y)) ( C(x) R(x, z))

(7.16)

Пусть вызов A используется во фрагменте вида:

 

A(x: y, z, c); if (c) B(y: u) else D(z: u)

(7.17)

Построим оператор A’(x: y, z) модификацией A(x: y, z). Всякий оператор c = true заменим на #1, а c = false на #2.

#1 и #2 обозначают операторы goto 1 и goto 2.

A’(x: y, z); if (c) 1: B(y: u) else 2: D(z: u)

(7.18)

A’(x: y, z); 1: B(y: u); goto 3; 2: D(z: u); 3:

(7.19)

Предикат A’(x: y, z) будем записывать в виде A(x: y #1: z #2) и называть гиперфункцией с двумя ветвями. Метки 1 и 2 являются метками ветвей.

A(x: y #1: z #2) case 1: B(y: u) case 2: D(z: u)

(7.20)

Допускается более компактная запись:

 

A(x: y : z) case B(y: u) case D(z: u)

(7.21)

Определение гиперфункции :

 

A(x: y #1: z #2) pre P(x); pre 1: C(x)

(7.22)

{ A’(x: y, z) } post 1: S(x, y); post 2: R(x, z);

Блок A’(x: y, z) тело гиперфункции, P(x) общее предусловие, C(x) предусловие первой ветви

гиперфункции, S(x, y) постусловие первой ветви, R(x, z)

постусловие второй ветви.

Метки ветвей в определении предиката можно опустить:

A(x: y: z ) pre P(x); pre 1: C(x) { … } …

(7.23)

A(x: y #1: z #2) case 1: B(y: u) case 2: D(z: u)

(7.20)

case 1: B(y: u) и case 2: D(z: u) операторы продолжения ветви, а вместе обработчик ветвей. Обработчику

ветвей предшествует оператор, содержащий операторы перехода. Если предшествующий оператор нормально завершается (не оператором перехода), то обработчик ветвей пропускается.

elemTwo(list (int) s : int e : )

pre 1: s nil & s.cdr nil

 

{ if (s = nil

s.cdr = nil)

#2

else

{ e = s.cdr.car

#1 }

} post 1: e = s.cdr.car;

elemTwo(list (int) s : int e #1 : #2)

elemTwo(s: e: ) case B(e…) case D(…)

elemTwo B(e…)

D(…)

Пример 7.4. Определим гиперфункцию Comp следующей спецификацией:

Comp(list (int) s: : int d, list (int) r) pre 1: s = nil

post 2: d = s.car & r = s.cdr;

Построим определение предиката elemTwo через гиперфункцию Comp без полей car, cdr и конструктора nil.

elemTwo(list (int) s: int e #1: #2) pre 1: s != nil & s.cdr != nil

{int e1; list (int) s1, s2; Comp(s: : e1, s1) case #2

case {

Comp(s1: : e, s2) case #2

case #1

}

} post 1: e = s.cdr.car;

Соседние файлы в папке lectures