Вопрос довольно широкий. Чтобы ответить на него в разумном месте, я сделаю много упрощений.
Давайте договоримся о терминологии. Программа верна, если подразумевает ее спецификацию. Это расплывчатое утверждение уточняется во многих отношениях, определяя, что именно является программой, а что является спецификацией. Например, при проверке модели программа представляет собой структуру Крипке, а спецификация часто является формулой LTL . Или программа может быть списком команд PowerPC, а спецификация может быть набором утверждений Хоара-Флойда, написанных, скажем, в логике первого порядка, Есть очень много возможных вариантов. Заманчиво сделать вывод, что в одном случае (структура Крипке) мы не проверяем реальную программу, а во втором случае (список инструкций PowerPC) мы это делаем. Однако важно понимать, что мы действительно смотрим на математические модели в обоих случаях, и это прекрасно. (Ситуация очень похожа на физику, где, например, классическая механика является математической моделью реальности.)
Большинство формализаций различают синтаксис и семантику программы; то есть, как это представлено и что это значит. Семантика программы - это то, что считается с точки зрения верификации программы. Но, конечно, важно иметь четкий способ присвоения значений (синтаксическим представлениям) программ. Два популярных способа следующие:
- (маленький шаг) операционная семантика : Это очень похоже на определение языка программирования путем написания для него интерпретатора. Для этого вам нужно сказать, что такое состояние , и на него влияет каждое утверждение на языке. (Вы можете спросить, на каком языке вы пишете переводчик, но я буду притворяться, что вы нет.)
- аксиоматическая семантика : здесь каждый тип оператора поставляется со схемой аксиомы. Таким образом, грубо говоря, всякий раз, когда используется конкретное утверждение этого типа, оно означает возможность использования определенных аксиом. Например, присваивание поставляется со схемой { P [ x / e ] }х : = е ; конкретное назначение x : = x + 1 идет с аксиомой { x + 1 = 1 }{ P[ x / e ] }х : = е{ P}х : = х + 1 если мы создаем схему с помощью P = ( x = 1 ) .{ x + 1 = 1 }х : = х + 1{ x = 1 }п= ( х = 1 )
(Есть и другие. Я чувствую себя особенно плохо из-за того, что опускаю денотационную семантику, но этот ответ уже длинный.) Машинный код плюс операционная семантика довольно близки к тому, что большинство людей назвали бы «настоящей программой». Вот оригинальный документ, в котором используется операционная семантика для подмножества машинного кода DEC Alpha:
Зачем вам когда-нибудь использовать высокоуровневую семантику, например аксиоматическую? Когда вы не хотите, чтобы ваши доказательства правильности зависели от оборудования, на котором вы работаете. Подход заключается в том, чтобы доказать правильность алгоритма относительно некоторой удобной семантики высокого уровня, а затем доказать, что семантика звучит относительно семантики более низкого уровня, которая ближе к фактическим машинам.
Таким образом, я мог бы подумать о трех причинах, которые привели к вашему вопросу:
- Вы видели только семантику высокого уровня, которая не похожа на то, что вы называете программой, и вам интересно, есть ли она низкоуровневая. Ответ - да.
- Вы удивляетесь, как вы доказываете, что модель соответствует реальности. Как в физике, вы не делаете. Вы просто придумываете лучшие модели и сравниваете их с реальностью.
- Вы не видели различий между синтаксисом и семантикой, а также различными способами присвоения значений программам. Два предыдущих вопроса содержат список некоторых книг.
Этот ответ просто пытается определить три различных способа, которыми я понял вопрос. Углубление в любую из этих точек потребовало бы много места.