Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
23-05-2015_23-29-55 / ЛР2.docx
Скачиваний:
6
Добавлен:
22.03.2016
Размер:
70.7 Кб
Скачать

Лабораторная работа №2.

Часть 5. Призрачные переменные. Поведение функции.

  1. Закройте редактор Gedit и терминал, в котором он был запущен.

  2. Проделайте пункты 1, 2, 4 части 1. Вы должны оказаться в каталоге с вашей фамилией.

  3. Создайте каталог для следующего примера:

mkdir GCD

  1. Перейдите в этот катлог:

cd GCD

  1. Создайте файл исходного кода и откройте его в редакторе Gedit:

Gedit GCD.java

  1. Вставьте в файл следующий текст программы:

//@+ CheckArithOverflow = no

/* complements for non-linear integer arithmetic */

/*@ lemma distr_right:

@ \forall integer x y z; x*(y+z) == (x*y)+(x*z);

@*/

/*@ lemma distr_left:

@ \forall integer x y z; (x+y)*z == (x*z)+(y*z);

@*/

/*@ lemma distr_right_minus:

@ \forall integer x y z; x*(y-z) == (x*y)-(x*z);

@*/

/*@ lemma distr_left_minus:

@ \forall integer x y z; (x-y)*z == (x*z)-(y*z);

@*/

/*@ lemma mul_comm:

@ \forall integer x y; x*y == y*x;

@*/

/*@ lemma mul_assoc:

@ \forall integer x y z; x*(y*z) == (x*y)*z;

@*/

/*@ predicate divides(integer x, integer y) =

@ \exists integer q; y == q*x ;

@*/

/*@ lemma div_mod_property:

@ \forall integer x y;

@ x >=0 && y > 0 ==> x%y == x - y*(x/y);

@*/

/*@ lemma mod_property:

@ \forall integer x y;

@ x >=0 && y > 0 ==> 0 <= x%y && x%y < y;

@*/

/*@ predicate isGcd(integer a, integer b, integer d) =

@ divides(d,a) && divides(d,b) &&

@ \forall integer z;

@ divides(z,a) && divides(z,b) ==> divides(z,d) ;

@*/

/*@ lemma gcd_zero :

@ \forall integer a; isGcd(a,0,a) ;

@*/

/*@ lemma gcd_property :

@ \forall integer a b d q;

@ b > 0 && isGcd(b,a % b,d) ==> isGcd(a,b,d) ;

@*/

class Gcd {

/*@ requires x >= 0 && y >= 0;

@ behavior resultIsGcd:

@ ensures isGcd(x,y,\result) ;

@ behavior bezoutProperty:

@ ensures \exists integer a b; a*x+b*y == \result;

@*/

static int gcd(int x, int y) {

//@ ghost integer a = 1, b = 0, c = 0, d = 1;

/*@ loop_invariant

@ x >= 0 && y >= 0 &&

@ (\forall integer d ; isGcd(x,y,d) ==>

@ \at(isGcd(x,y,d),Pre)) &&

@ a*\at(x,Pre)+b*\at(y,Pre) == x &&

@ c*\at(x,Pre)+d*\at(y,Pre) == y ;

@ loop_variant y;

@*/

while (y > 0) {

int r = x % y;

//@ ghost integer q = x / y;

x = y;

y = r;

//@ ghost integer ta = a, tb = b;

//@ ghost a = c;

//@ ghost b = d;

//@ ghost c = ta - c * q;

//@ ghost d = tb - d * q;

}

return x;

}

}

Здесь вычисляется НОД двух чисел. Известно, что существует разложение НОД(x, y) = x*a + y*b. В примере выполняется проверка этого разложения. Но, т.к. сама постановка задачи не требует нахождения разложения НОД(x, y), то, чтобы не вмешиваться в код программы используются призрачные переменные. Такие переменные и все действия над ними видны только для верификатора. Для применения этого инструмента используется блок /*@ ghost d;*/, где d – это объявление переменной или какое-либо присваивание с использованием выражений, см. пример.

Также в этом примере в постусловии используется конструкция /*@ behavior id: requires e1; ensures e2;*/. Такая конструкция применяется, когда есть ветвление в возвращаемых результатах. Например: функция возвращает значение, или функция выбрасывает исключение. В данном примере это ветвление не такое явное, но все-таки реализовано таким способом. Также в данном примере в блоке behavior пропущено предусловие. Но в общем случае оно может присутствовать, и тогда оно будет являться дополнительным предусловием к конструкции requires метода. Тоже самое касается постусловия ensures в блоке behavior. Оно будет являть дополнительным постусловием к постусловию функции.

  1. Сохраните файл.

  2. Откройте его для верификации.

  3. Убедитесь, что утверждения доказаны (леммы не обязательно будут доказаны).

Соседние файлы в папке 23-05-2015_23-29-55