Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
38
Добавлен:
23.03.2015
Размер:
792.06 Кб
Скачать

224 Глава ID

Дополнительная литература

Bj0rner, Dines, and Cliff B. Jones, 1982. Formal Specification & Software] Development. Englewood Cliffs, N. J.: Prentice-Hall International.

Guttag, John V,, James J. Homing, and Jeannette M. Wing, 1985. Larch: in five easy pieces. Technical report 5, Digital Equipment Corporation Systems' research Center.

I

Щ. Краткий обзор процесса ^верификации программ

Упражнения

10.1. Рассмотрим спецификацию абстракции bag, приведенную на рис. 10.6. Покажите, что каждый свободный по переменным терм с оператором на самом верхнем уровне IS. IN равен терму, в котором нет ни одной функции, определен­ной в области INBAG.

10.2. Добавьте к спецификации на рис. 10.6 подходящий partitioned by. 10.3. Добавьте к спецификации на рис. 10.6 функцию COUNT. Она должна иметь структуру: COUNT: INTBAG, INT -^ INT и возвращать число вхождений в bag целых чисел.

10.4. Модифицируйте спецификацию на рис. 10.6 таким образом, чтобы операция DELETE удаляла все вхождения удаленного элемента.

10.5. Напишите полную спецификацию абстракции table, которая отобра-экает строки в целые числа. Она должна иметь операции для создания пустой таблицы, добавления в таблицу строки и связанного^ этой строкой целого числа, удаления из таблицы строки и соответствующего целого числа, поиска строки в таблице и операцию, определяющую число отображений в таблице. Таблицы должны быть изменяемыми. (Указание: используйте сорт STRING-TABLE, рассмотренный в разд. 10.1.1 и 10.1.2.)

10.6. Напишите полную спецификацию типа, представляющего ограничен­ный стек. Она должна иметь процедуры со следующими заголовками:

new == proc (i: int) returns (s: stack)

signals (non_ positive-Size)

push = proc (s: stack, i: int) signals (overflow, duplicate) pep = proc (s: stack) returns (i: int) signals (empty)

Целое число, передаваемое процедуре ne\v, есть максимальный размер стека size. Если оно не больше нуля, то процедура new сигнализирует о возникновении исключительной ситуации non_ positive- Size. Процедура push выдает сигнал о пе­реполнении overflow, если запись в стек передаваемого ей целого числа вызывает ув5личен1:е стека до недопустимых размеров. Она выдает сигнал duplicate, если передаваемое ей целое число уже имеется в стеке. Процедура pop возвращает последний размещенный в стеке элемент и удаляет его из стека. (Указание: вос­пользуйтесь сортом INTST-ACK, рассмотренным в разд. 10.1.5, модифицировав его соответствующим образом.)

10.7. Напишите спецификацию на естественном языке, которая содержит информацию о всех ваших ответах на упражнения 5 или 6. Не кажется ли вам, что подобная спецификация была бы такой же полной, если бы вы не написали сначала формальную спецификацию?

10.8. Напишите формальную спецификацию для процедуры poly (рис. 4.3). В процессе составления этой спецификации вам понадобится трейт с соответ­ствующими функциями для связанного с ним сорта.

10.9. Напишиге спецификацию для очереди, организованной по принципу д^че? «первый поступивший удаляется первым». В процессе составления этой специфи- ДЖЙ; кгцни вам понадобится трейт с соответствующими функциями для связанного г ним сорта.

Эта глава представляет собой краткий обзор относительно сложной темы. Мы попытаемся дать представление о процессе верификации без углубления в мириады подробностей, пред­полагающих составление строгих доказательств, относящихся к свойствам программы. Мы убеждены, что понимание того, что подразумевается под формальной верификацией программ, яв­ляется ценным качеством для их неформального анализа; при этом самым ценным, что можно было бы вынести из данной главы, является понимание сущности основных методов, используемых в формальных рассуждениях. Важна структура" Правил доказа-Тедьств, а также сами доказательства. Подробности несуще­ственны.

Верификация программы предполагает анализ ее текста. Это отличает верификацию от тестирования, при котором всегда производится наблюдение за вычислениями. В процессе верифи­кации мы анализируем текст программы и делаем выводы по Поводу описываемого программой набора вычислений. Мы часто выдаемся к этому набору для подтверждения правильности наших рассуждений, однако никогда не создаем этот набор или его часть.-Начнем с рассмотрения базовой задачи верификации и анализа текста программы, не содержащего ветвлений. Затем рассмотрим операторы ifи циклы while,коснемся процесса доказательства соответствия процедур своим спецификациям и рассмотрим про­граммы, вызывающие процедуры. Наконец, проведем анализ программ, содержащих кластеры.

Для большей иллюстративности примеров мы сознательно будем избегать точных определений. Более того, мы не будем рассматривать все выражения и операторы языка CLU,а будем составлять программы таким образом, чтобы в них использовались только уже рассмотренные конструкции. Также не будем рассма­тривать алиасы, рекурсивные процедуры, итераторы и исключи­тельные ситуации.

° Лисков Б., 1'атэ1 Дж.

226 Глава II

11.1. Анализ программ, не содержащих ветвлений

Для доказательств мы будем использовать формулы полной корректности.Каждая такая формула включает в себя два пре­диката —предусловиеипостусловие,а также сегмент программы. Областью предикатов является набор всех возможных состояний вычислений. Формула полной корректности имеет вид

Р^ ... S,} Q

В ней утверждается, что если состояние процесса вычислений перед выполнением операторов 8152... S„удовлетворяет пред­условию Р, то мы хотим, чтобы 5182 ••• S„выполнились, а состо­яние, предшествующее последующим вычислениям, удовлетворяло бы условию Q.Разумеется, если в начальном состоянии предусло­вие ложно, то вся формула истинна. Это аналогично правилу логики, утверждающему, что

(FALSE^ Р) = TRUE

Здесь мы придерживаемся соглашения, по которому идентифика­торы, не использующиеся в программах (подобные TRUEиFALSE),обозначаются заглавными буквами. Отметим, что пара предикатов в этих формулах очень напоминает тело спецификации процедуры. Предусловие сходно с предложением requires,а пост­условие —с предложением effects. Рассмотрим пример

TRUE {х:=о

у:=1} у>х

Как мы можем убедиться в истинности этой формулы? То есть откуда мы знаем, что данный фрагмент программы завершился и после этого значение у больше значения х? Для начала мы отме­тим, что выполняются в точности два оператора. После выполне­ния второго оператора значение у есть 1,а значение х соответ­ствует тому, каким оно стало после выполнения первого опера­тора, т. е. 0.Завершая наши рассуждения, отметим, что 1 > 0. В приведенной аргументации мы рассуждали об 1)управляющем потоке сквозь программу, 2)значении оператора присваивания и 3)значении операции >для целых чисел.

Основной прием, который мы будем использовать в наших рассуждениях, касающихся программ, можно сформулировать следую1Ц);?.1 образом:

1. Локализация всех путей между двумя предикатами.

2.Для каждого пути выполняется проход назад от конечного предиката до обнаружения производного предиката R,который

ий обзор процесса верификации программ

должен быть истинен по отношению к первому оператору в данном пути, если при этом истинен конечный предикат.

3.Информация о типах значений переменных, входящих предикаты, используется для установления того факта, что пред-•словие для каждого пути включает производный предикат R. ^ Только что рассмотренное простое доказательство может быть 1переформулировано более аккуратно. Проход назад через второе Присваивание с исходной посылкой у >х упрощает данный 1'фрагмент программы до следующего:

itrue{x:=o}i>x

а дальнейший проход назад через оставшееся присваивание с 1 >х в качестве исходной посылки дает

. TRUE =» 1 >О

которое упрощается до TRUE,следуя правилам логики для целых чисел. В построении этого доказательства для продвижения предикатов назад через операторы присваивания мы воспользо­вались следующим правилом присваивания: Пусть Р есть любой предикат, а е есть любое выражение, свободное от побочных эффектов: если Р истинен после при­своения х s =е, то Р с е, подставленным во все свободные вхождения х (т. е. вхождения, не связанные квантором), перед этим присваиванием должен быть истинен. Это означает, ^ что предикат Р, в котором е подставлено во все свободные ' вхождения х, есть самое слабое_ предисловие, обеспечивающее ^ истинность Р после присваивания х :==е. ' "• На первый взгляд выполнение прохода назад по программе может показаться несколько странным. Преимущество такого способа заключается в том, что таким образом мы последовательно достигаем поставленной цели: на каждом шаге, зная, что мы хотим удостовериться в правильном выполнении каждого фрагмента программы, мы вычисляем то, что должно быть истинным по отно­шению к данному шагу. По достижении начала программы мы получаем самое слабое условие, выполнения которого достаточно для подтверждения истинности постусловия («самое слабое» в том смысле, что его включает в себя любое другое достаточное пред­условие). Мы завершаем доказательство, показывая, что данное предусловие включает в себя самое слабое предусловие.

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

228 Глава II

мы завершим ддк^атед^тво, если покажем, что-то самое строгоепocтуcлoвиe^включaeт\вГceбя^имeю^eecl,Jlocтуcл^)Jвиe.''Boзникa-ющая"прй' таком подходе проблема заключается в том, что при просмотре программы вперед у нас отсутствует метод последова­тельного исключения незначимой информации. Это приводит к накоплению множества утверждений, являющихся истинными, но не имеющих никакого отношения к доказательству.

Как мы уже видели, два предиката в формуле полной коррект­ности аналогичны предложениям requiresи effectsв специфика­циях процедур. Однако между ними имеется ^щественное^раз-личие. В спецификации процедуры предикат ltfectsимеет дело ^Гд5умя состоя ни ями: до и после обращения. Когда мы ссылаемся к значению формального параметра, то рассматриваем этот пара­метр (порой неявно) как имеющий префикс пре- или пост-. В фор­муле полной корректности каждый предикат относится только к одному состоянию. Это порождает небольшую проблему, возни­кающую при необходимости установления связи между началь­ными и конечными значениями.

В качестве примера рассмотрим формулу полной корректности, утверждающую, что оператор х :==х+1приводит к увеличению х на 1.Необходимо, чтобы постусловие ссылалось как к началь­ному, так и к конечному значению х. Для этого мы воспользуемся приемом, введя в предусловиеновую переменнуюх() и считая, что она имеет то же значение, что и х. Она является «новой» в том смысле, что еще ни разу не встречалась ни в программе, ни в пост-или предусловии. Для подтверждения того, что х :== х + 1, запишем

Хо == х )х :== х+Ц х > Хо

Для проверки данной формулы мы продвинем предикат х >х через оператор присваивания: -

(Хо ==х) ^ (х+1 >Хо)

Подставляя в правую часть Хд вместо х, получаем Хо + 1 >Хц, что, считая, что х имеет тип целое, упрощается до TRUE.

11.2. Анализ программ с ветвлениями

До сих пор мы рассматривали программы без ветвлений. Теперь рассмотрим программу g двумя ветвями, например

ifх == I thenу :== 0 elseу :==х end

В ней имеется один путь для предложения thenи один —для предложения else.Рассматривая предложение then,мы можем считать, что предикат в условии истинен, а предикат для else — ложен. В общем случае при разборе программ с операторами if

аткий обзор процесса верификации программ

_используем следующее правило анализа условного выражения: !£сли вычисление bне имеет побочных эффектов, то доказательство

р \it b then si else s2\ Q

эквивалентно доказательству пары Р & b {811и Р &~b {52} Q. 1Более кратко правило вывода может быть записано следующим 1образом:

^без-побочных-эффектов (b), Р & b \&\\ Q, Р & ^b \s2\ Q "—Р b then si else s2\ Q—~~

В этом представлении находящиеся поверх горизонтальной черты и разделенные запятой предложения называются гипотезой. Утверждение, расположенное под чертой, называется заключе­нием. Это правило может быть рассмотрено как утверждение, говорящее о том, что истинности всех гипотез достаточно для до­казательства истинности заключения.

Правило анализа условных выражений является первым в ряду правил, которые мы будем использовать для сведения доказа­тельства сложных формул общей корректности к набору более простых формул или условий истинности. Например, для дока­зательства

(х = 1) 1 (х-0)

{if х = I then у ;= 0 else х := у end) (у =0)

нам необходимо доказать три условия истинности:

1)без-побочных-эффектов (х = 1)

2) ((х = 1)1 (х-0)) &(x = 1) iy :- 0\ у = О

3)((х = 1) 1(х =0))&~ (х-1){у := xlу ==О Истинность второго и третьего условий может быть заказана при помощи правила о присваивании. Истинность третьего усло­вия истинности следует из того факта, что единственная проце­дура, вызываемая данным выражением, есть mt$equal,а она ничего не модифицирует.

Рассмотренный выше способ анализа условных конструкций приложим к любому сегменту программы с относительно неболь­шим числом ветвлений. К сожалению, как это уже отмечалось в гл. 9,степень ветвления большинства программ довольно ве­лика. Рассмотрим, например

х>0 & у == О

{vAiile —(у == х) do у := у + I end} у- х

В данном фрагменте программы имеется бесконечное количество путей, по одному для каждого возможного значения х. Если

232

Глава II

множество переменных программы на некоторый хорошо упоря-^ Л^енный набор. (Набор называется полностью упорядоченным,! ^^И каждый его член можно сравнить с любым другим его членом. •"• ^^ностью упорядоченный набор называется хорошо упорядочен­ным, если любое его непустое подмножество имеет последний ^^Мент.) Неотрицательные и положительные целые числа яв-•1я(о1.^д хорошо упорядоченными. Множество всех целых чисел ^^овым не является, поскольку в нем отсутствует последний -^•^Мент. Набор неотрицательных рациональных чисел также не является хорошо упорядоченным, поскольку в нем имеются ""Аг^ножества, не содержащие последнего элемента, например все положительные рациональные числа. В данной главе мы будем "Пользовать неотрицательные числа в качестве области измене-"^ наших функций декремента.

Функция декремента должна удовлетворять двум условиям:1.Мы должны показать, что каждая итерация цикла умень-шз^-fзначение, в которое отображается функция декремента.

2.Мы должны также показать, что конъюнкция инварианта ^^ла и логического выражения, принимающего значение true ^^Ом случае, если функция декремента отображается в последний ^^Мент хорошо упорядоченного набора, имплицирует отрицание "Р^Диката управления циклом. Другими словами, что цикл будет з^ершен.

^^и мы можем представить функцию декремента с данными свойствами, то и можем из этого заключить, что цикл завершается. ^^ следует из того факта, что каждый раз при прохожденииi^^-лафункция декремента должна отображаться в меньшее ^^Чение (условие 1);имеется только конечное число значений ^^Нду начальным значением функции декремента и последним элементом в области ее изменения (свойство хорошо упорядо-^^»шх наборов); при достижении программой состояния, в ко-^Ром функции декремента отображаются в последний элемент, "Р^исходит выход из цикла (условие 2).Полученный результат ^"^.погичен правилу инварианта цикла:даже если через программу имеется бесконечное число маршрутов, мы можем говорить о воз-мо^сности завершения программы, анализируя только конечное чис^о маршрутов.

В нашем примере подходящей функцией декремента может ^У>кить (х —у). Для доказательства того, что цикл

х^о&у=0 {% инвариант х^у

% декремент выражения (х—у) в диапазоне неотрицательных целых % чисел

^•hile ~ (у = х) do у :== у+ I end} У х

^^1"да завершается, мы должны показать, что

обзор процесса верификации программ *ч«»

1.функция декремента уменьшается в теле цикла ^у) = do &~ (у-х) &х >у {у :=у +Ц (х— у) < do

1.функция декремента не увеличивается в процессе проверки 1)вия выполнения цикла

»-у) == do1~(х ==у); (х— у) < do

S.При достижении функцией декремента значения 0цикл вршается

„-у) = 0 &(х >у) ^ ~ (~(у =х))f' ^ эти выражения легко упрощаются до значения TRUE.

1Мы начали с наблюдения, что основная проблема, связанная задачей, содержащей цикл, заключается в невозможности про-меровать все проходы через программу. Из этого следуют два вода.

1.Доказательство утверждения о том, что цикл завершается, является более тривиальным^

2.Сразу не очевидно, как ограничить число шагов, касаю­тся описания поведения программы, до конечного числа. у1Ы рассмотрели две эти проблемы отдельно друг от друга. Сна-1&ла мы доказали, что если цикл завершится, то он завершится Состоянием, удовлетворяющим постусловию. Это называется аргу­ментомчастичной корректности,и в данном случае критическим указывается отыскание подходящего инварианта цикла. Затем 1{ы анализировали условия завершения цикла. В этом случае 1важно было отыскать соответствующую функцию декремента. [•Комбинация частичной корректности и условия завершения на-1аываетсяполной корректностью.

1^ Студенты часто испытывают затруднения при изучении инва­риантов циклов. К счастью, нахождение подходящего инварианта ,не представляет труда. Если вариант неподходящий, то по край­ней мере один шаг в проверке не даст положительного результата. В большинстве случаев исследование ситуации о ошибочным инвариантом позволяет быстро решить проблему.

11.3. Разбор процедур

Введение процедур усложняет систему доказательств, необхо­димую для анализа программ, однако это также уменьшает слож­ность доказательств в этой системе, что аналогично введению про­цедур, которые усложняют определение языка программирова­ния, однако упрощает написание программ на этом языке. Гра­мотное использование процедур облегчает понимание программы и применение по отношению к ней формальных доказательств. Мы будем отделять корректность реализации процедуры от тех

252 Глава II

ий обзор процесса верификации программ

зации. В противном случае мы не смогли бы показать, что удал^ ние одной копии элемента будет достаточным для удаления егс»1 из набора.

11.5. Несколько замечаний по поводу формального анализа

Из вышесказанного очевидно, что формальные рассуждения ' о программах предполагают большой объем утомительных мани­пуляций с символами. Этот процесс не относится к легким или приятным. Очевидно, что это —идеальная работа для вычисли­тельной машины. Человек должен предоставить 1)спецификацию проверяемой программы; 2)предполагаемую реализацию этой программы; 3)спецификации процедур и типов, используемых в реализации; 4)инвариант цикла и функцию декремента для каждого из циклов и 5)инвариант представителя и функцию абстракции для каждого кластера.

Не следует полагать, что эта информация получается как следствие проверочной стадии. Весь рассмотренный подход к про­граммированию базируется на построении спецификаций в про­цессе создания программы. Инварианты, функции декремента и функции абстракций должны быть включены как часть програм­мной документации.

Располагая рассмотренной информацией, вторая стадия вери­фикации программы — создание проверочных условий — под­чиняется алгоритмизации и, следовательно, может быть получена программно. Большинство манипуляций с формулами предпола­гает генерацию проверочных условий.

Окончательная стадия проверки — упрощение проверочных условий — может быть частично автоматизирована. Большая часть проделанных в данной главе упрощений производилась при помощи программ, доказывающих теоремы. Однако в общем слу­чае все может складываться не столь удачно. Программа про­верки может оказаться не в состоянии доказать, что некоторая программа соответствует своей спецификации, при следующих условиях:

1.Дедуктивные возможности проверочной программы не поз­воляют ей получить из теоремы необходимый предикат. Имеется ряд любопытных областей, в которых невозможно написать до­казывающие теоремы программы, отвечающие на все необходимые вопросы.

2.Проверяемая программа соответствует своей спецификации, однако спецификации внутренних процедур являются слишком слабыми, чтобы доказать это.

3. Проверяемая программа соответствует своей спецификации, однако инварианты цикла, функции декремента, инварианты пред-

двления или функции абстракции являются неудовлетвори-дьными.

4.Корректность программы зависит от некоторого факта, ст­оящегося к области ее применения. В идеальном случае информа-^я такого рода должна быть включена в спецификацию или дру-ую документацию.

' 5.Программа не удовлетворяет своей спецификации. В этом дучае «неправильной» может быть спецификация, программа или;обе одновременно.

Первая из описанных причин неудач представляет собой серьез-ю проблему в задаче верифицирования программ. Ее обычно 1жно обойти, снабдив проверочную программу соответству-„.цими леммами. К сожалению, ввод необходимых лемм часто Оказывается затруднительным и не соответствует принципам до­казательств, используемым проверяющей программой. Во-вто­рых, третий и четвертый случаи часто являются следствием ^ошибок в программе или документации. Обнаружение таких оши-'бок существенно облегчает проверку программы. Не существует 'способа, позволяющего a prioriопределить, является ли программа -или спецификация «неправильной». Выявление таких проблем яв­ляется первоочередной задачей процесса верификации программы. ^

^1.6. Заключение

В этой главе мы рассматривали программы как некоторый текст и анализировали его с этой же точки зрения. Мы связывали с языком программирования набор правил доказательства, кото­рый позволял сократить формулу общей корректности вида

Предусловие ^текст программы} Постусловие

до предиката, значение которого не зависело от языка программи­рования. Для того чтобы это стало возможным, мы ввели в текст программы различную вспомогательную информацию.

Для работы с циклами был введен инвариант цикла и функция декремента. Функции декремента используются для доказатель­ства возможности завершения цикла. Инварианты цикла сокра­щают анализ произвольно большого числа проходов через содер­жащую цикл программу до относительно небольшого числа.

При работе с процедурами основной акцент делался на специ­фикациях. Хотя правила доказательства для процедур довольно сложны (были рассмотрены упрощенные правила), они играют важную роль в организации структурного анализа программ. Главной особенностью является тот факт, что анализ реализации процедуры не зависит от анализаобращений^ней.'Спецификации также играют существенную роль при анализе типов. А типы, аналогично процедурам, помогают структуриро-

254 Глава II

Краткий обзор процесса верификации программ

вать анализ. Доказательство того, что реализация типа удовле­творяет его спецификации, полностью независимо от доказательств для тех частей программы, которые используют данный тип. Функция абстракции и инвариант представления играют суще­ственные роли в анализе корректности реализации типа. Функ­ция абстракции является связующим звеном между абстрактными объектами, на которые осуществляется ссылка в спецификациях типа, и конкретными объектами в реализации. Инвариант пред­ставления отражает взаимосвязь между реализациями операций типа. Это позволяет нам анализировать реализацию каждой опе­рации отдельно от других.

Польза от инвариантов цикла, функций декремента, инва­риантов представления и функций абстракции не ограничивается формальной верификацией. Они полезны и для самого процесса реализации, поскольку содержат утверждения, от которых за­висит эта реализация. Их удобно использовать в процессе тестиро­вания как источник различных проверочных случаев, а также в процессе отладки как свидетельство об ошибках. Они также снабжают программу комментариями, полезными для тех, кто впоследствии пытается разобраться в программе.

Понимание программы предполагает неформальный анализ ее смысла. Неформальный анализ во многом напоминает формальный. Он проходит те же стадии и использует ту же информацию. Не удивительно, что разработанные для формального анализа кон­цепции полезны для понимания программ. И возможно, что са­мым важным результатом процесса формальной верификации явилось идентифицирование и определение этих концепций.

элемент в этом массиве. Напишите спецификацию процедуры max. array, которая принимает в качестве аргументов два непустых целочисленных массива и воз­вращает тот массив, который содержит максимальный элемент. (Примечание; вам не требуется реализовывать процедуру max-elem.)

11.4. Напишите спецификацию процедуры, которая изменяет порядок сле­дования элементов в массиве целых чисел на обратный. Напишите процедуру, удовлетворяющую этой спецификации, а затем докажите полную корректность • вашей процедуры.

11.5. Напишите спецификацию для типа стек, не являющегося ограничен­ным. Он должен иметь операции со следующими заголовками:

new = proc ( ) returns (s: stack) push = proc (s: stack, i: int) pop == proc (s: stack) returns (i: int)

Приведите реализацию для этого типа, включая инвариант представления и функцию абстракции. Докажите, что ваша реализация удовлетворяет специ­фикации.

11.6. Проанализируйте взаимосвязь между верификацией программы и про-цессом отбора данных для тестирования, приведенным в разд. 9,1.

Дополнительная литература

Cries, David) 1981. The Science of Programming. New York: Springer-Verlag. Hoare, C. R., An axiomatic basis for computer programming. Communications of the ACM 12 (10): 576—583. Reprinted in Programming Methodology, A Collec­tion of Articles by Members of IFIP WG2.3, edited by David Gries (New York: Springer-Verlag, 1978).

Jones, Cliff B., 1980. Software Development, A Rigorous Approach. Engle-wood Cliffs, N. J.: Prentice-Hall International.

London, Ralph L., Mary Shaw, and William A. Wulf, 1981. Abstraction and verification in Alphard: a symbol table example. In Alphard: Form and Content, edited by Mary Shaw (New York: Springer-Verlag), pp. 161—190.

Упражнения

11.1. Приведите инвариант цикла для процедуры sum.positive, приведенной на^ис. 11.2. Докажите корректность данной реализации.

11.2. Завершите проверку реализации целочисленного набора intset доказа­тельством значимости каждой из формул, приведенных на рис. 11.7.

11.3. Напишите спецификацию процедуры max-elem, которая принимает в качестве аргумента непустой массив целых чисел и возвращает наибольший

Предварительные

замечания о процессе разработки программ

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