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

Трансформация кодирования рекурсивных структур

Пример. Программа суммирования sum(s: c) эл-тов посл-ти s.

type seqR = list (real); formula SUM(seqR s, real c) =

s = nil ? c = 0 : exists real a. SUM(s.cdr, a) & c = s.car + a;

sum(seqR s: real c)

 

{ switch (s){ case nil:

c = 0

case cons(h, t): c = h + sum(t) }

} post SUM(s, c);

 

sum(seqR s: real c)

nil?(s) or cons?(s) = true

{ if (nil?(s)) c = 0

 

else {{h = s.car || t = s.cdr}; c = h + sum(t)} } post SUM(s, c);

sum(seqR s: real c) { if (s = nil) c = 0

else c = s.car + sum(s.cdr) } post SUM(s, c);

type seqR = list (real); formula SUM(seqR s, real c) =

s = nil ? c = 0 : exists real a. SUM(s.cdr, a) & c = s.car + a; sum(seqR s: real c)

{ if (s = nil) c = 0 else c = s.car + sum(s.cdr) } post SUM(s, c);

Обобщение задачи SUM

formula SUMG(seqR s, real d, c) = e. SUM(s, e) & c = e + d; sumG(seqR s, real d: real c) post SUMG(s, d, c);

sum(seqR s: real c)

{ sumG(s, 0: c) } post SUM(s, c);

sumG(seqR s, real d: real c)

{ if (s = nil ) c = d else sumG(s.cdr, d + s.car : c) } post SUMG(s, d, c) measure len(s);

SUMG(s, d, c)
len(s);

sumG(seqR s, real d: real c)

{ if (s = nil ) c = d else sumG(s.cdr, d + s.car : c) } post measure

Склеивание c d. sumG(seqR s, real с: c)

{ if (s = nil ) c = c else sumG(s.cdr, c + s.car : c) }

Замена хвостовой рекурсии циклом. При раскрытии

группового оператора меняется порядок присваивания параметрам s и с.

sumG(seqR s, real с: real c)

{ for (; s != nil; ) { с = с + s.car; s = s.cdr }

Подстановка определения на место вызова

real c = 0; for (; s != nil; ) { с = с + s.car; s = s.cdr }

Кодирование списка вырезкой массива

Кодирование начального и текущего состояния списка S

type SEQR = array (real, M..N); Начальное S[m..n], текущее S[j..n]. SEQR S;

int j = m;

Значения границ M и N должны быть достаточными, т.е. M ≤ m, n, j ≤ N.

Кодирование операций:

s = nil

j > n

s != nil

j <= n

s.car

S[j]

s = s.cdr

j = j + 1

Итоговая программа

real c = 0; for (int j = m; j <= n; ) { c = с + S[j]; j = j + 1 }

real c = 0; for (; s != nil; ) { c = с + s.car; s = s.cdr }

Кодирование списка через указатели

type LISTP = struct (real car, LISTP *cdr);

LISTP *S;

 

 

s

S

Кодирование операций:

s = nil

S = null

s != nil

S != null

s.car

S->car

s = s.cdr

S = S->cdr

Итоговая программа

real c = 0; for ( ; S != null; ) { c = с + S->car; S = S->cdr }

real c = 0; for (; s != nil; ) { c = с + s.car; s = s.cdr }

Пример. Обращение списка

a1

a2

a3

an

Результат обращения списка:

a1 a2 a3 an

type T; type LT = list(T);

formula reverse(LT s: LT) = (s = nil)? s : reverse(s.cdr) + s.car; reverseIn(LT s: LT s’) pre s nil

{ reverseG([s.car], s.cdr: s’) } post s’ = reverse(s);

reverseG(LT s, u: LT s’) post s’ = reverse(reverse(s) + u);

reverseIn(LT s: LT s’) pre s nil

{ reverseG([s.car], s.cdr: s’) } post s’ = reverse(s);

reverseG(LT s, u: LT s’){ if (u = nil) s’ = s

else reverseG(u.car + s, u.cdr: s’) } post s’ = reverse(reverse(s) + u);

Склеивание и замена хвостовой рекурсии циклом: reverseIn(LT s: LT s){ reverseG([s.car], s.cdr: s) };

reverseG(LT s, u: LT s){ М: if (u = nil) s = s

else |s, u| = |u.car + s, u.cdr|; goto M

};

Оформление цикла и подстановка на место вызова: reverseIn(LT s: LT s){

LT u; |s, u| = |[s.car], s.cdr|;

while (u != nil) { s = u.car + s; u = u.cdr }

}; Раскрытие мультиприсваивания:

reverseIn(LT s: LT s){

LT u = s.cdr; s = [s.car];

while (u != nil) { s = u.car + s; u = u.cdr }

};

type LTP = struct (T car, LTP *cdr);

LTP *S;

s

→ S; u → U

Кодирование операций:

u != nil

U != null

s = [s.car]

S->cdr := null

u = s.cdr

U = S->cdr

reverseIn(LT s: LT s){ LT u = s.cdr; s = [s.car];

 

 

while (u != nil) { s = u.car + s; u = u.cdr }};

type LTP = struct (T car, LTP *cdr);

LTP *S; s

S; u → U

Кодирование операций:

u != nil

U != null

s = [s.car]

S->cdr := null; u = s.cdr → U = S->cdr

u = u.cdr

U = U->cdr;

s = u.car + s → U.cdr = s; S = U // портится U

s = u.car + s; u = u.cdr → LTP* a = U; U = U->cdr; a->cdr = S; S = a

reverseIn(LTP* S) {

LTP* U = S->cdr; S->cdr = null;

while (U != null) {LTP* a = U; U = U->cdr; a->cdr = S; S = a }

};

method ReverseInPlace ( ) returns ( reverse : Node)

requires Val id ( ) ; modifies f o o t p r i n t ; ensures reverse 6= nul l ^ reverse . Val id ( ) ;

ensures fresh ( reverse . f o o t p r i n t .. old ( f o o t p r i n t ) ) ; ensures | reverse . l i s t | = | old ( l i s t ) | ; ensures (8 i : int ¤ 0 i ^ i < | old ( l i s t ) | =) old ( l i s t ) [ i ] = reverse . l i s t [ | old ( l i s t )|..1.. i ] ) ;

{

var current : Node ; current := next ; reverse := this ; reverse . next := null ; reverse . f o o t p r i n t := { reverse } ; reverse . l i s t := [ data ] ;

while ( cur rent 6= nul l )

invar iant reverse 6= nul l ^ reverse . Val id ( ) ; invar iant reverse . f o o t p r i n t old ( f o o t p r i n t ) ; invar iant cur rent = nul l =) | old ( l i s t ) | = | reverse . l i s t | ; invar iant cur rent 6= nul l =)

cur rent . Val id ( ) ^ cur rent 2 old ( f o o t p r i n t ) ^ cur rent . f o o t p r i n t old ( f o o t p r i n t ) ^

cur rent . f o o t p r i n t , reverse . f o o t p r i n t ^ | old ( l i s t ) | = | reverse . l i s t | + | cur rent . l i s t | ^ (8 i : int ¤ 0 i ^ i < | cur rent . l i s t | =) cur rent . l i s t [ i ] = old ( l i s t ) [ | reverse . l i s t |+ i ] ) ;

invar iant (8 i : int ¤ 0 i ^ i < | reverse . l i s t | =) old ( l i s t ) [ i ] = reverse . l i s t [ | reverse . l i s t |..1.. i ] ) ;

{

var nx : Node ;

nx := current . next ;

assert nx 6= nul l =) (8 i : int ¤ 0 i ^ i < | nx . l i s t | =) cur rent . l i s t [1+ i ] = nx . l i s t [ i ] ) ;

/ / The s ta t e looks l i k e : . . . , reverse , cur rent , nx , . . .

assert cur rent . data = cur rent . l i s t [ 0 ] ; current . next := reverse ;

cur rent . f o o t p r i n t := { cur rent } [ reverse . f o o t p r i n t ; cur rent . l i s t := [ cur rent . data ] + reverse . l i s t ;

reverse := current ; current := nx ;

}

}

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