Проектирование цикла при помощи инварианта
В предыдущем параграфе мы уже познакомились с техникой проектирования цикла при помощи инварианта, позволяющей значительно упростить написание программ. Вопросы нахождения инвариантов циклов и доказательства правильности получающихся программ — основная тематика данного параграфа.
Условия правильности цикла
Теоремой, на которой базируется схема проектирования цикла при помощи инварианта, является следующее утверждение, которое мы примем без доказательства. Его истинность может быть выведена из свойств преобразователя предикатов и определения оператора цикла 6.12.
Теорема 8.1. Если
- ,
- ,
- ,
- и
- ,
то спецификация программы является тавтологией.
Докажем с помощью этой теоремы правильность некоторых программ, построенных в предыдущем параграфе.
Текст программы
public class MulI { public static void main(String[] args) throws Exception { int a = Xterm.inputInt("a -> "); int b = Xterm.inputInt("b -> "); int x = a, y = b, z = 0; while (y > 0) { if ((y&1) == 0) { y >>>= 1; x += x; } else { y -= 1; z += x; } } Xterm.println("a * b = " + z); } }
- Для того чтобы проверить, что предикат
является тавтологией, вычислим предварительно .
Далее имеем
-
Получившийся предикат представляет собой дизъюнкцию четырех членов и, очевидно, истинен, если истинны первый или второй из этих членов. В противном случае , и предикат принимает вид . Таким образом, — тавтология.
- .
-
Для проверки последнего условия найдем
Тогда имеем
что завершает доказательство правильности написанной программы.
Докажем частично правильность еще одной построенной в предыдущем параграфе программы.
Текст программы
public class Gcd { public static void main(String[] args) throws Exception { int x = Xterm.inputInt("x -> "); int y = Xterm.inputInt("y -> "); Xterm.print("gcd(" + x + "," + y + ") ="); while ( (x != 0) && (y != 0) ) { if (x >= y) x -= y; else y -= x; } Xterm.println(" " + (x+y)); } }
Если в качестве ограничивающей функции взять , то правильность полученной программы легко может быть доказана. Обозначим через и начальные значения переменных и , удовлетворяющих предусловию . Заметим также, что постусловие программы в целом может быть записано в виде предиката ( напечатан ), а постусловием цикла является предикат .
- .
- Сохранение инварианта после выполнения тела цикла следует из -инвариантности . Формальную проверку проведите самостоятельно.
-
- Формальное доказательство проведите самостоятельно.
- Формальное доказательство проведите самостоятельно.
- Для завершения доказательства правильности программы необходимо еще показать, что является тавтологией . Так как формального определения операторов печати мы не рассматривали, будем считать, что предикат , а имеет вид .
Полученная дизъюнкция истинна, если ложно условие . В противном случае один из аргументов функции равен нулю и по соответствующему свойству наименьшего общего делителя истинным является второй дизъюнктивный член, что завершает доказательство правильности программы.