- •Лекции по
- •(Те что я нашел)
- •Информация и данные.
- •Анализ программ, не содержащих ветвлений
- •Если p{ а }q и q{ b }r, то выполняется p{ a;b }r.
- •Проектирование цикла с помощью инварианта Задача 1. Найти сумму величин 1/iот 1 до тех пор, пока она не станет больше некоторого наперед заданного числаa.
- •Будем искать решение нашей задачи в виде цикла, имеющего следующий вид:
- •Линейные структуры данных.
- •Операции над линейной структурой данных
- •Виды линейных структур данных.
- •4)Стек на базе массива
- •Тема: Анализ создаваемых абстракций
- •Полнота
- •Аназиз типов данных
- •Операции egual, similar и copy
- •Функция абстракции
- •Функция абстракции есть
Анализ программ, не содержащих ветвлений
Для доказательства правильности программ мы будем использовать формулы полной корректности. Каждая такая формула включает в себя два предиката – предусловие и постусловие, а также сегмент программы. Областью предикатов является набор всевозможных состояний переменных программы, получаемых в ходе вычислений.
Формула полной корректности имеет вид
{P} S1;S2;…Sn {Q}
и утверждает , что если состояние процесса вычислений перед выполнением операторов S1;S2;…Sn удовлетворяет предусловию P, то выполнение операторов S1;S2;…Sn гарантирует выполнение постусловия {Q}. Разумеется, если в начальном состоянии предусловие ложно, то вся формула истинна. Это аналогично правилу логики, утверждающему , что
(FALSE P) TRUE.
Видно, что пара предикатов в этих формулах очень напоминает тело спецификации процедуры: предусловие похоже на Requires, а постусловие – на Effects.
Например.
{TRUE}
X:=0; Y:=1;
{Y > X}
Как это доказать? Используя смысл операции присваивания, видно, что выполнение двух операторов присваивания даст значения переменным Y=1 и X=0. Из теории целых чисел известно, что 1 > 0, ч.т.д.
Что мы использовали:
порядок вычислений в программе (управляющий поток);
смысл оператора присваивания (:=);
значение операции > для целых чисел.
Основной прием доказательства можно сформулировать следующим образом:
Локализация всех путей между двумя предикатами.
Для каждого пути выполняется проход назад от конечного предиката до обнаружения производного предиката P, который должен быть истинен по отношению к первому оператору в данном пути, если при этом был истинен конечный предикат.
Информация о типах значений переменных, входящих в предикаты, используется для установления того факта, что предусловие для каждого пути включает производный предикат P.
Это доказательство можно расписать более подробно. Проход назад через второе присваивание с исходной посылкой Y > X упрощает данный фрагмент программы до следующего
{ TRUE }
X:=0;
{1 > X },
а дальнейший проход дает
TRUE 1 > 0,
которое упрощается до TRUE, следуя правилам логики целых чисел.
В построении этого доказательства мы воспользовались следующим правилом (аксиомой) присваивания:
Пусть Р есть любой предикат, а E - есть выражение свободное от побочных эффектов: тогда если Р истинен после присваивания X := E, то Р с E, подставленным во все свободные вхождения X (т.е. вхождения не связанные квантором) перед этим присваиванием, должен быть истинен.
Или другими словами:
Для того, чтобы P было верным после выполнения X:=E (где E – выражение) достаточно, чтобы P[E X] (т.е. свойство P после замены всех вхождений X на E) было верно изначально или кратко
{ P[E X]} X:=E {P}.
Это означает, что предикат P, в котором E подставлено во все свободные вхождения X, есть самое слабое предусловие, обеспечивающее истинность P после присваивания X:=P.
Кажется несколько странным выполнение прохода назад по программе. Но преимущество этого способа заключается в том, что таким образом мы последовательно достигаем поставленной цели: на каждом шаге, зная, что мы хотим удостовериться в правильном выполнении каждого фрагмента программы, мы вычисляем то, что должно быть истинным по отношению к данному шагу. По достижении начала программы мы получаем самое слабое условие, выполнение которого достаточно для подтверждения истинности постусловия (“самое слабое” в том смысле, что его включает в себя любое другое достаточное предусловие). Мы завершаем доказательство, показывая, что исходное предусловие включает в себя полученное нами самое слабое предусловие.
Если двигаться вперед, то необходимо начать с того, что предполагается истинным в начале выполнения программы, и вычислить то, что должно быть истинным по завершении данной части. Достигнув, таким образом, конца программы, мы будем иметь самое сильное постусловие, вытекающее из исходного предусловия (“самое сильное” в том смысле, что оно предполагает выполнение любых других значимых постусловий). В этом случае мы завершаем доказательство, если покажем, что это самое строгое постусловие включает в себя необходимое постусловие.
Проблема здесь заключается в том, что при просмотре программы вперед у на отсутствует метод последовательного исключения незначимой информации. Это приводит к накоплению множества утверждений, являющихся истинными, но не имеющими никакого отношения к доказательству.
Эти два метода доказательства можно проиллюстрировать с помощью следующих рисунков:
Достаточное предусловие (P)
Необходимое
постусловие (Q)
S1; S2; … Sn
Самое слабое предусловие
Рис. 1 . Проход назад.
Достаточное предусловие (P) Самое сильное постусловие
S1; S2; … Sn
Необходимое
постусловие (Q)
Рис. 2. Проход вперед.
Мы видим, что предусловие и постусловие аналогичны предложениям Requires и Effects в спецификациях процедур. Но между ними есть существенное различие. В спецификациях процедуры предикат Effects имеет дело с двумя состояниями: до и после обращения. Когда мы ссылаемся на значение формального параметра, то рассматриваем его (порой неявно) как имеющий префикс пре- и пост-. В формуле полной корректности каждый предикат относится только к одному состоянию. Это порождает небольшую проблему, возникающую при необходимости установления связи между начальными и конечными значенгиями.
Например, рассмотрим формулу полной корректности, утверждающую, что оператор X:=X+1 приводит к увеличению X на 1. Необходимо, чтобы постусловие ссылалось как к начальному, так и к конечному значению X. Для этого введем в предусловие новую переменную X0 и считая, что она имеет такое же значение как и X. Запишем
{ X0=X } X:=X+1 {X>X0 }
Для доказательства продвинем предикат X > X0 через оператор присваивания:
X+1>X0.
Учтем, что X0=X, получим
X0+1>X0 или 1>0,
что упрощается до TRUE.
Рассмотрим несколько примеров доказательства.
Пример 1. Необходимо доказать формулу полной корректности
{ X>n } X:=X+1 {X>n+1 } (1)
Доказательство. Продвинем предикат {X>n+1 } через оператор присваивания. Получим самое слабое предусловие {X+1>n+1 } или {X>n }. Как видим самое слабое предусловие не шире (в точности совпадает) достаточного предусловия. Формула доказана.
Пример 2. Доказать
{0<X<1} X:=1/X+Y {X>Y+1}. (2)
Доказательство. Продвинем предикат {X>Y+1} через оператор присваивания. Получим самое слабое предусловие {1/X+Y>Y+1}. Теперь докажем, что достаточное предуслове включает (из него следует) самое слабое предусловие. Т.е. нам надо доказать тождественную истинность формулы
(0<X<1) (1/X+Y>Y+1)
Заметим, что (0<X<1) (1/X>1).
Добавив к обеим частям неравенства по Y, получим
(0<X<1) (1/X>1) (1/X+Y>Y+1)
ч.т.д.
Аксиома последовательного выполнения.