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

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

Часть 4. Обращение к разным состояниям переменных.

  1. Вставьте еще один метод в класс:

/*@ requires t != null;

@ ensures

@ \forall integer i; 0 < i < t.length ==> t[i] == \old(t[i−1]);

@*/

public static void shift(int[] t) {

/*@ loop_invariant

@ j < t.length &&

@ (\forall integer i; 0 <= i <= j ==> t[i] == \at(t[i],Pre)) &&

@ (\forall integer i;

@ j < i < t.length ==> t[i] == \at(t[i−1],Pre));

@ loop_variant j;

@*/

for (int j = t.length - 1; j > 0; j--) {

t[j] = t[j - 1];

}

}

Здесь присутствуют конструкции:

  • \old(…) – возвращает значение переменной до вызова метода. Может быть использована только в описании постусловия.

  • \at(…, Pre) – возвращает значение переменной на предыдущей итерации. Вместо Pre может быть использована метка Here, аналогично предикатам с соответствующим смыслом.

  1. Заново откройте измененный фал для верификации и верифицируйте его.

  2. Убедитесь, что все выражения доказаны.

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

Часть 5. Описание функций, возвращающих значение. Леммы.

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

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

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

mkdir Muller

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

cd Muller

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

Gedit Muller.java

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

//@+ SeparationPolicy = Regions

/*@ axiomatic NumOfPos {

@ logic integer num_of_pos{L}(integer i,integer j,int t[]);

@ axiom num_of_pos_empty{L} :

@ \forall integer i j, int t[];

@ i >= j ==> num_of_pos(i,j,t) == 0;

@ axiom num_of_pos_true_case{L} :

@ \forall integer i j k, int t[];

@ i < j && t[j-1] > 0 ==>

@ num_of_pos(i,j,t) == num_of_pos(i,j-1,t) + 1;

@ axiom num_of_pos_false_case{L} :

@ \forall integer i j k, int t[];

@ i < j && ! (t[j-1] > 0) ==>

@ num_of_pos(i,j,t) == num_of_pos(i,j-1,t);

@ }

@*/

/*@ lemma num_of_pos_non_negative{L} :

@ \forall integer i j, int t[]; 0 <= num_of_pos(i,j,t);

@*/

/*@ lemma num_of_pos_additive{L} :

@ \forall integer i j k, int t[]; i <= j <= k ==>

@ num_of_pos(i,k,t) == num_of_pos(i,j,t) + num_of_pos(j,k,t);

@*/

/*@ lemma num_of_pos_increasing{L} :

@ \forall integer i j k, int t[];

@ j <= k ==> num_of_pos(i,j,t) <= num_of_pos(i,k,t);

@*/

/*@ lemma num_of_pos_strictly_increasing{L} :

@ \forall integer i n, int t[];

@ 0 <= i < n && t[i] > 0 ==>

@ num_of_pos(0,i,t) < num_of_pos(0,n,t);

@*/

public class Muller {

/*@ requires t != null;

@*/

public static int[] m(int t[]) {

int count = 0;

/*@ loop_invariant

@ 0 <= i <= t.length &&

@ 0 <= count <= i &&

@ count == num_of_pos(0,i,t) ;

@ loop_variant t.length - i;

@*/

for (int i = 0; i < t.length; i++) {

if (t[i] > 0) {

count++;

}

}

int u[] = new int[count];

count = 0;

/*@ loop_invariant

@ 0 <= i <= t.length &&

@ 0 <= count <= i &&

@ count == num_of_pos(0,i,t);

@ loop_variant t.length - i;

@*/

for (int i = 0; i < t.length; i++) {

if (t[i] > 0) {

u[count++] = t[i];

}

}

return u;

}

}

Это программа, которая из входного массива переписывает все положительные элементы в новый массив в том же порядке и возвращает этот массив.

Здесь используется директива

//@+ SeparationPolicy = Regions

Так верификатор проверяет, что память, выделенная под массивы, не пересекается.

Также демонстрируется работа с описанием в спецификации функций, возвращающих значение, за это отвечает конструкция /*@ logic t1 id{L}(t2 var, …) = e;*/, где t1 – возвращаемый тип, id – имя функции, L – метка, аналогично предикатам, t2 – тип переменной-параметра, var – имя переменной-параметра, e – выражение. В данном примере выражение e отсутствует – это не ошибка, это другой способ описания функции, т.к. необходимая нам функция нетривиальна.

Здесь описывается функция, возвращающая число положительных элементов в массиве t начина с индекса i до индекса j. Для этого описана сама функция: ее имя, список параметров – и правила, по которым происходит вычисления. Эти правила описываются после ключевого слова /*@ axiom …;*/. Все вместе это группируется в блоке /*@ axiomatic id {}*/.

Также в этом примете используются леммы. Леммы помогают верификатору работать с выражениями, доказывать их. При верификации в графической среде леммы также будут отображаться и их также можно попытаться доказать, но неизвестно корректная реакция верификатора на леммы. Они могут быть и не верифицированы, но тем не менее они помогают верификатору. Сами леммы оформляются в конструкции /*@ lemma id{L}: e;*/, где id – имя леммы, L – метка, аналогично предикатам, e – выражение.

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

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

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

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