методичка по ТП

advertisement
Теоретическое программирование – математическая дисциплина,
изучающая синтаксические и семантические свойства программ, процессы
составления, преобразования и выполнения.
ПРОГРАММИРОВАНИЕ
искусство
ремесло
наука
Программирование как наука показывает как можно достичь множества
целей, применяя строго определенные правила построения к основным
конструктивным элементам.
Пример: х делим на y, r – остаток от деления.
r:= x; q:=0;
while r>y do
begin
r:=r-y; q:=q+1;
end;
write (‘yq+r’,yqr)
Организуем программу по-другому:
{y>0}
r:=x; q:=0;
while r>y do
begin
r:=r-y; q:=q+1;
end;
{x:= yq+r}
Однако, для того чтобы программа выполнялась для r  y, необходимо
откорректировать данную программу, добавив в нее условия:
{y>0 and x 0}
r:=x; q:=0;
while r>y do
begin
r:=r-y; q:=q+1;
end;
{x:= yq+r and 0 ry}
СПЕЦИФИКАЦИЯ ПРОГРАММ
Спецификация программ – выражение на определенном языке,
возможно естественном, который точно описывает что должно быть совершено
в результате выполнения программы.
Для составления спецификации программ целесообразно использовать язык
предикатов.
Спецификация программы на языке предикатов выглядит следующим образом:
{Q} S {R}, где Q – предусловие, S –программа, R – постусловие .
Если выполнение S началось в состоянии, удовлетворяющем Q, то имеется
гарантия, что оно завершится в R.
Пример1: записать в z произведение a и b, предполагается, что значения
a и b – положительные величины.
a).
{a  0 and b  0} S {z = a * b}
b).
Известно начальное значение переменных:
{a 0 and b  0 and a = A and b = B} S {z = a * b and a = A and b = B }
assert(a  0) – если программа “вылетает”, то выдается номер строчки и условие.
Пример2: сортировка.
a).
{n  0} S { i: 0  i < n-1: b[i]  b[i+1] }
b).
{n  0 and b = B} S { i: 0  i < n-1: b[i]  b[i+1] and b = перем.(B) }
где b является перемещением от B.
Пример3:обмен значениями переменных.
{x = X  y = Y} S {x = Y  y = X}
Пример4:найти максимальное значение переменных в массиве B,
который изменяется от 0 до n-1:
{n>0} S {(i: 0  i < n: b[i]  x)  ( i: : 0  i < n: x = b[i]) }
Пример5:придать x абсолютное значение x.
{x = X} S {(X  0  x = -X )  (X  0  x = X)}
или
{(x  0)  ( x = X  x = -X)}
Пример6:придать каждому значению массива b[0:n-1] значение суммы
элементов этого массива.
{n  0  b = B} S { i:0in:b[i] = j:0jn:B[j]}
Пример7:в массиве a[0:n-1] отсортирован список преподавателей
Политеха, в b[0:m-1] отсортирован список, получающих пособие по
безработице. Найти первого “жулика”, который преподает и получает пособие.
{n0  m>0} S {0  p<n  0q<m  a[p] = b[q]  (i,j:0 i p  0 j q:a[i] =
b[j]) = 1}
Задания для самостоятельной работы:
1).Найти место первого максимального значения в массиве.
2).Найти n-ое число Фиббоначи.
ПРЕОБРАЗОВАТЕЛЬ ПРЕДИКАТОВ WP.
Wp(S,R) – предикат, который определяет множество всех состояний, для
которого выполнение команды S закончится через некоторое конечное время в
состоянии, удовлетворяющем R. Предусловие является слабейшим для S по
отношению к R, так как оно определяет множество всех состояний, таких что
выполнение , начавшееся в любом из них заканчивается при истинном R.
Пример1:
wp(“i:=i+1”,i1)=i0
Пример2:
S: if x  y then z:=x else z:=y
R: z = max(x,y)
wp(S,R) = T
ЧАСТИЧНАЯ И ПОЛНАЯ КОРРЕКТНОСТЬ.
{Q} S {R}- полная корректность
В частичной корректности фразы “через конечное время” нет.
Q {S} R
Если выполнение команды S начинается в состоянии команды,
удовлетворяющем Q и если оно заканчиваеться, то конечное состояние бедет
удовлетворять R.
Пример:
T {while(1){}} - получили тавтологию, так как при частичной
коррекции нас не волнует закончится цикл или нет.
{T} while(1){} {T} - ложь, так как в полной корректности программа
закончится через конечное время, а, следовательно, противоречие получено.
НЕКОТОРЫЕ СВОЙСТВА WP.
1.) Закон “исключенного чуда”.
wp(S,F) = F
2.) Дистрибутивность конъюнкции.
wp(S,Q)  wp(S,R) = wp(S,Q  R)
3.) Закон монотонности.
Если из Q следует R, то из wp(S,Q) следует wp(S,R).
4.) Дистрибутивность дизъюнкции.
wp(S,Q)wp(S,R)wp(S,QR)
КОМАНДЫ SKIP И ABORT .
wp(skip,R)=R
wp(abort,R)=F-аварийное завершение
КОМПОЗИЦИЯ КОМАНД.
Последовательное соединение – один из способов составления больших
программных сегментов из меньших.
Определим последовательное соединение в термиах wp:
wp(s1;s2,R)=wp(s1,wp(s2,R)) – то есть постусловие выполнения команды
s1 должно быть предусловием того, что выполнение s2 даст R.
wp(“skip;skip”,R)=wp(“skip”,wp(“skip”,R))=wp(“skip”,R)=R
Пример1:
wp(“i:= i +1; j:= i -1”, i*j=0) = wp(“i:= i +1”,wp(“j:= i -1”, i*j=0)) =
wp(“i:= i +1”, i *( i -1)=0) = ((i+1)( i +1-1)=0) = ((i +1)* i =0)=( i =0, i =-1);
Пример2:
wp(“i:= i +1; j:=j-1”, i *j=0) = wp(“i:= i +1”,wp(“j:=j-1”, i*j=0)) =
wp(“i:= i +1”, i *( j -1)=0) = ((i+1)( j-1)=0) =( i =-1, j =1);
Пример3:
wp(“x:= 2+y; y:=x*y”, y+x=0) = wp(“x:= 2+y”,wp(“y:=x*y”, y+x=0)) =
wp(“x:= 2+y”, x*y+x=0) = ((2+y)*y+2+y)=0) =( y =-1, y =-2);
КОМАНДА ПРИСВАИВАНИЯ.
wp(“x:=e”,R)=domain(e) cand R
wp(“x:=e”,R)=R
wp(“x:=5”, x=5)=(x=5)=(5=5)=T
wp(“x:=5”, x5)=(x=5)=(5=5)=T
Выполнение присваивания может изменить лишь ту переменную,
которая стоит в левой части:
wp(“t:=x; x:=y; y:=t”,x=X  y=Y) = wp(“t:=x; x:=y; wp(“y:=t”,x=X
y=Y))=wp(“t:=x; x:=y”; x=X  t=Y) = wp(“t:=x”; y=X  t=Y) = (y=X  x=Y)
Задания для самостоятельной работы:
1.
1). wp(“i:=i+1”, i>0)
2). wp(“i:=i+2;j:=j-2”, i+j=0)
3). wp(“z:=z*j; i:=i-1”, z*ji=c)
4). wp(“i:=i+1;j:=i-1”,i*j=0)
2.
1). wp(skip, i>0)  wp(skip, i0)
2). wp(skip, i0)  wp(skip, i0)
3). wp(skip, i>0)  wp(skip, i<0)
4). wp(skip, i>0)  wp(abort, i<0)
5). wp(skip, i>0)  wp(abort, i>0)
3. Определить верно ли равенство wp(“s1;s2”,R) = wp(“s2;s1”,R) при следущих
значениях переменных:
1). s1: i:=i+1
s2: j:=j+1
R: i>j
2). s1: i:=j+1
s2: i:=i*2
R: i=j
3). s1: j:=i
s2: i:=i+1
R: i=j
КРАТНЫЕ ПРИСВАИВАНИЯ ПРОСТЫХ ПЕРЕМЕННЫХ.
x1,x2:=3,4
x1,x2, x3,...,xn:= e1,e2,e3,...,en
e1  v1
x1 v1
e2  v2
x2 v2
. . . . . . .
x := e
wp(“ x := e ”, R) = domain( e ) cand Rex
 i domain( e i )
wp(“x,y:=y,x”,x=X  y=Y) = (x=X  y=Y) xy,, yx =(y=X  x=Y)
ПОИСК РЕШЕНИЙ С ПОМОЩЬЮ WP.
Пример1:
В памяти имеется массив длиной p. Левую границу изменим, а правая
должна остаться на месте.
Спецификация программы:
{i+p=c} i,p:=m+1,x {i+p=c}
wp(“i,p:=m+1,x”,i+p=c)=m+1+x=c
С предусловием составим систему уравнений:
i  p  c

m  1  x  c
Следовательно, x=i+p-m-1
Пример2:
{T} a:=a+1; b:=x(a,b) {a=b}
wp(“s1;s2”,R) = wp(s1,wp(s2,R))
wp(“a:=a+1”, wp(“b:=x(a,b)”,a=b) = wp(“a:=a+1”,a=x(a,b))=(a+1=x(a+1,b))
т. е. x(a,b)=a – функция от двух аргументов возврвщает первый аргумент.
ПРИСВАИВАНИЕ ЭЛЕМЕНТУ МАССИВА.
b[i]:=e
b:=(b; i:e)- по i-ому элементу записано e.
(b;2:7)[2] = 7- во втором элементе записана цифра 7.
(b;1:4)[2] = 2 – на первом месте массива цифра 4.
Введем wp:
wp(“b[i]:=e”,R)=wp(“b:=(b;i:e)”,R)=domain(b;i:e) cand Rb(b;i:e)
где i – не должен выходить за границы массива e.
Пример1: wp(“b[i]:=5”,b[i]=5)=((b;i:5)[i]=5)=(5=5)=T
Пример2:
wp(“b[i]:=5”,b[i]=b[j])=((b;i:5)[i]=(b,i:5)[j])=(5=(b;i:5)[j])=(i=j5=5)(ij5
=b[j])=(i=j)( ij5=b[j])=(i=j ij)(i=j5=b[j])=(i=j5=b[j])
Пример3:
wp(“b[b[i]]:=i”,b[i]=i)=((b;b[i]:i)[i]=i)=(i=b[i]i=i)( ib[i]b[i]=i)=(i=b[i])
Задания для самостоятельной работы:
1.
1). wp(“z,x,y:=1,c,d”,z*xy=cd)
2). wp(“i,s:=1,b[0]”,1 i <n  s = b[0]+b[1]+…+b[i-1])
3). wp(“a,n:=0,1”,a2<n<(a+1)2n)
4). wp(“i,s:=i+1,s+b[i]”,0<i<n  s= b[0]+b[1]+…+b[i-1])
2. Найти x:
1) {T} a,b:=a+1;x {b=a+1}
2) {T} a:=a+1; b:=x {b=a+1}
3) {z+a*b=c} z,a:=z+b,x {z+a*b=c}
3.
1). wp(“b[i]:=i”,b[b[i]]=i)
2). wp(“b[i]:=5”, j:ij<n: b[i] b[j])
КОМАНДА ВЫБОРА.
if x<0 then x:=-x else x:=x
if
x  0  x:=-x
 x  0  x:=x
fi
Общий случай:
if
B1  S1
 B2  S2
 B3  S3
 B4  S4
…………
fi
где Bi – охрана; Si – охраняемая команда;
Введем wp: BB = B1B2B3…Bn
Если BB – ложно, значит ни одна из охран не пустила.
Определение: wp(IF,R)=domain(BB) cand BB cand
(B1wp(S1,R)
B2wp(S2,R)…
Bnwp(Sn,R))
wp(IF,R)=( i:1 i n:Bi)( i:1 i n:Bi wp(Si;R))
wp(IF,R)=BBB1wp(S1,R)B2wp(S2,R)
if
B1S1
 B2S2
fi
BB=B1B2
wp(“if x  0z:=-x  x  0z:=x ”,z=abs(x))=( x  0 x  0)
 x  0wp(“z:=-x”,z=abs(x))
 x  0 wp(“z:=x”,z=abs(x))=
=( x  0-x=abs(x))( x  0x=abs(x))=T
Пример: посчитать число положительных элементов в массиве.
if
b[i] > 0  i,p:=i+1,p+1
 b[i] < 0  i:=i+1
fi
{i<n  p=N j: 0j<i:b[j]>0}
wp(IF,R)=(b[i]0)  (b[i]0wp(“i,p:=i+1,p+1,R”))  (b[i]<0
wp(“i:=i+1,R”))=(b[i]0) 
 (b[i] 0i+1 n  p+1=N j:=0j<i+1:b[j]>0)
 (b[i] <0i+1 n  p=N j:=0j<i+1:b[j]>0)=
=(b[i]0)  (i<n  p=N j:0 j<i:b[j]>0) 
(i<n  p=N j:0 j<i:b[j]>0)=
=(b[i]0)  (i<n  p=N j:0 j<i:b[j]>0)
Задания для самостоятельной работы:
1). wp(“if x>y  x,y:=y,x  xy  skip fi ”,xy )
2). if
a>b  a:=a-b”
 b>a  b:=b-a
fi
R1: a>b  b>a
R2: a>0  b>0
ТЕОРЕМА О КОМАНДЕ ВЫБОРА.
Рассмотрим предикат Q:
1).QBB;
2).Q  Bi=wp(Si,R);
то Qwp(IF,R)
Пример: Поиск методом половинного деления
Ищем x в массиве b[0:n-1]
Q:ordered(b)  0 i  k  j<n  xb[i:j]
Постусловие: R:xb[i:j]
Программа:
if
b[k]  xi:=k
 b[k]  xj:=k
fi
Проверка теоремы:
1). Из QBB, т.е.
ordered(b)  0 i  k  j<n  xb[i:j]
b[k]  x  b[k]  x = T
т.е.первое условие выполнено.
2). Выполнение Si должно привести к R.
1 случай:
Q  b[k]  x  xb[k:j]
wp(i:=k,xb[i:j])
2 случай:
Q  b[k]  x  xb[k:j]
wp(i:=k,xb[i:j])
Задания для самостоятельной работы:
Проверить соответствие программ спецификации, используя теорему о команде
выбора:
1). {0<i<n  m=max(b[0: i-1])}
if
b[i]>m  m:=b[i]
 b[i]m  skip
fi
{0<i<n  m=max(b[0: i])}
2). {ordered(b[0:n]) 
0 i n  0 j n  ij }
if
i>j  i,j:=j,i
 i,j  skip
fi
{b[i]  b[j]}
3). {y>0  z+y*x=a*b}
if
неч(x)  z,x:=z+y,x-1
чет() skip
fi; y,x:=2*y, x/2
{y0  z+y*x=a*b}
КОМАНДА ПОВТОРЕНИЯ.
i:=0
while i<10
do
i:=i+1
done
Общий вид:
While B do S - пока условие выполняется делать команду.
do
B1S1
 B2S2
 B3S3
…………
od
т.е. в зависимости от того какая охрана пропускает происходит выполнение
соответствующей команды.
Введем команду повторения через слабейшее предусловие:
H0(R)=BB  R, где BB=B1B2B3…
Hk(R)=7 H0(R)wp(IF,Hk-1(R)), k>0
wp(DO,R)=k:0  k: Hk(R)
Сформулируем теорему для неслабейшего условия:
Программа ищет сумму элементов массива.
1.Начальная инициализация переменных.
i,s:=1,b[0]
do
i<11i,s:=i+1,s+b[i]
od
В цикле инициализация переменных присутствует почти всегда.
2.Рассмотрим некоторый предикат P:
{R:S=k:0 k 11:b[k]}
P:1 i 11S=k:0 k<i:b[k].
3.Ищем предусловие для цикла:
wp(“i,s:=1,b[0]”,P)=111b[0]= k:0 k<1:b[k]=Tb[0]=b[0]=T.
т.е. P можно использовать в качестве постусловия.
Если P истинно перед шагом цикла, то оно истинно и после него.
P называется инвариантом цикла.
Введем некоторую функцию t. Она показывает число шагов до конца цикла.
t:11-i
Такая функция называется ограничивающей функцией. В нашем случае она
четко говорит сколько шагов до конца цикла. Ограничивающая функция в
общем случае показывает верхнюю границу числа шагов до конца цикла.
В общем случае инвариант остается неизменен. Ограничивающая функция
изменяется с каждым шагом.
ТЕОРЕМА О ЦИКЛЕ, ЕГО ИНВАРИАНТЕ И
ОГРАНИЧИВАЮЩЕЙ ФУНКЦИИ.
1). PBiwp(Si,P) , 1 i n
Т.е. если выполняется инвариант и нас пустила i-ая охрана, то
выполнение i-ой команды составит истинность P.
2). PBB t >0
Т.е. если выполняется инвариант и BB, то ограничивающая функция
положительна.
3). С каждым шагом ограничивающая функция уменьшается.
PBiwp(“t1:=t; Si”, t<t1) ,1 i n
Т.е. если нас пустила i-ая охрана, то выполнение i-ой команды уменьшит
функцию.
Если 1), 2), 3) – выполняется, то P можно использовать в качестве
предусловия в команде повторения:
Pwp(DO,PBB);
АНОТИРОВАНИЕ ЦИКЛА.
{Q}
{inv P: инвариант}
{bound t: ограничивающая функция}
do
B1S1
 B2S2
 B3S3
…………
od
{R}
Список условий для проверки цикла:
1). P- истинно перед началом выполнения цикла;
2). P- инвариант: {PBi}Si{P}
3). Выполнение P и невыполнение BB должно дать R: (PBB)R
4). Если цикл еще не закончен, то ограничивающая функция
положительна: PBB t >0
5). С каждым шагом идет приближение к окончанию цикла:
{PBi} t1:=t; Si {t<t1}
Пример:
{b0}
x,y,z:=a,b,0;
{P:y 0  z+x*y=a*b}
{t:y}
do
y>0  четный(y)y; x:=y/2; x+x
 нечетный(y)y; z:=y-1; z+x
od
{z =a*b}
ПРОЦЕДУРЫ.
- используются для целей абстракции.
Построение процедуры – это рассмотрение языка путем включения
новой операции.
Если программу рассматривать как конструктивное дказательство, то
процедура будет леммой в таком доказательстве.
ОПИСАНИЕ ПРОЦЕДУРЫ.
{Pre: P}
{Post: Q}
proc <идентификатор>(<специф. параметра>;…);
<тело>
<специф. параметра>:
value <список идент.>: тип – изменения параметров не передаются в
основную программу.
result <список идент.>: тип
value result <список идент.>: тип - изменения параметров передаются в
основную программу; значение в процедуру не передается, а только из
процедуры.
Есть ограничение на тело: в теле могут лишь передаваться параметры
процедуры и идентификаторы, описанные в самом теле, т.е. нельзя
использовать глобальные переменные.
В P используются параметры с атрибутами value и value result. В Q – со
словом result.
ПОИСК ЭЛЕМЕНТОВ В МАССИВЕ.
{Pre: n=Nx=Xb=BXB[0:N-1]}
{Post:0 i NB[i]=X}
proc search(value n,x:integer; value b:array of integer; result i:integer);
i:=0
{Inv: 0 i NXB[0:N-1]}
{Огранич. функция: N-i}
do b[i]xi:=i+1
od
Выносим за скоби типы и делаем обобщение:
proc p(value x; value result y ; result z); - передаются формальные параметры.
Где x={x1, x2,…,xn}
Вызов процедуры: формальные параметры заменяются фактическими.
P( a, b, c ); где а – могут быть выражениями; b,c – только переменные.
АЛГОРИТМ ВЫПОЛНЕНИЯ ПРОЦЕДУРЫ.
1). Определяются значения аргументов a и b и записываются в параметры x и y:
x,y:=a,b
2). Определяются переменные, описывающие b,c(под них резервируется память
и т.д.).
3). Выполняется тело.
4). Значения выходных параметров y и z записываются в выходные аргументы b
и c:
b,c:=y,z
ФОРМАЛЬНОЕ ОПРЕДЕЛЕНИЕ ПРОЦЕДУРЫ.
x,y:=a,b; B; b,c:=y,z
Через wp(“p(a,b,c)”,R) = wp(“x,y:=a,b; B; b,c:=y,z”,R)
ТЕОРЕМА О ВЫЗОВЕ ПРОЦЕДУРЫ.
{P} B {Q}
{PR: P(u,v: QR)}
P(a,b,c)
{R}
Предусловие:
PRwp(p(a,b,c),R)
Описание:
Proc swap(value result y1,y2);
{P:y1=X  y2=Y}
B
{Q:y1=Y  y2=X}
Вызов:
{a=X  b=Y}
swap(a,b)
{R:a=Y b=X}
Ищем предусловие того, что после выполнения swap у нас все будет нормально:
PR= a=X  b=Y u1, u2: u1=Y  u2=X u1=Y  u2=X = a=X  b=Y  T = (a=X 
b=Y)
Для других аргументов:
{i=I  (k: b[k]=B[k])}
swap(i,b[i])
{i=B[I]  b[I]=I 
(k:Ik:b[k]=B[k])}
swap(value result y1,y2)
{y1=I  y2=B[I]}
B
{y1=B[I]  y2=I}
По доказанной теореме, по постусловию вызова, мы получили условие и оно
должно совпасть с тем, что задано:
PR=i=Ib[i]=B[I]u1,u2:u1=B[I]u2=Iu1=B[I](b;i:u2)[I]k:kI:(b;i:u2)[k]=
=B[k] =
= i=Ib[i]=B[I]B[I]=B[I](b;i=I)[I]=Ik:kI(b;i:I)[k]=B[k] 
 i=Ib[i]=B[I]I= Ik:kI:b[k]=B[k] 
 i=Ik:kI:b[k]=B[k] 
 вызов был сделан правильно, спецификация выполнилась.
Задания для самостоятельной работы:
1). proc p(value x; result z1,z2);
{P:x=X}
z1,z2:=x,x
{Q:z1=z2=X}
PR: {a=X}p(a,c1,c2){c1=c2=X}
2). Proc m(value x1,x2; result z);
{P:x1=X1x2=X2}
if
x1>x2  z:=x1
 x2  x1  z:=x2
fi {Q:z=max(X1,X2)}
PR={a=b=A}m (a,b,c) {R:c=A}
Download