- •Лабораторная работа №2.
- •Часть 1. Подготовка среды
- •Лабораторная работа №2.
- •Часть 2. Массивы.
- •Лабораторная работа №2.
- •Часть 3. Описание предикатов.
- •Лабораторная работа №2.
- •Часть 4. Обращение к разным состояниям переменных.
- •Лабораторная работа №2.
- •Часть 5. Описание функций, возвращающих значение. Леммы.
- •Лабораторная работа №2.
- •Часть 5. Призрачные переменные. Поведение функции.
- •Лабораторная работа №2.
- •Часть 6. Самостоятельное задание.
Лабораторная работа №2.
Часть 1. Подготовка среды
Откройте терминал (горячие клавиши Ctrl+Alt+T).
Введите команду
cd ~/
Так вы попадете в домашний каталог.
Создайте каталог, в котором будут храниться ваши рабочие файлы:
mkdir <ваша фамилия>
Например
mkdir Ivanov
Переместитесь в созданный каталог:
cd <название созданного каталога>
Например
cd Ivanov
Создайте каталог для первого задания:
mkdir Arrays
Переместитесь в каталог Arrays:
cd Arrays
Настроим верификатор на работу
why3 config –-detect
В терминале вы увидите похожий вывод:
Лабораторная работа №2.
Часть 2. Массивы.
Создайте файл исходного кода и откройте его в редакторе Gedit:
gedit Arrays.java
откроется окно текстового редактора Gedit.
Введите текст первой программы:
//@+ CheckArithOverflow = no
public class Arrays {
/*@ requires t != null && t.length >= 1;
@ ensures
@ 0 <= \result < t.length &&
@ \forall integer i; 0 <= i < t.length ==> t[i] <= t[\result];
@*/
public static int findMax(int[] t) {
int m = t[0];
int r = 0;
/*@ loop_invariant
@ 1 <= i && i <= t.length && 0 <= r && r < t.length &&
@ m == t[r] && \forall integer j; 0<=j && j<i ==> t[j]<=t[r];
@ loop_variant t.length−i;
@*/
for (int i = 1; i < t.length; i++) {
if (t[i] > m) {
r = i;
m = t[i];
}
}
return r;
}
}
Это простой пример программы нахождения максимума в массиве. Необходимо, чтобы массив был не пуст, т.к. это будет значить, что максимум существует. Также сразу отключена проверка на переполнение.
Сохраните файл.
Откройте еще один терминал (Часть 1, п. 1).
Переместитесь в каталог с файлом исходного кода программы:
cd ~/<ваша фамилия>/Arrays
Например
cd ~/<Ivanov>/Arrays
Запустите созданный файл для верификации
krakatoa Arrays.java
Убедитесь, что все выражения доказаны.
Лабораторная работа №2.
Часть 3. Описание предикатов.
В файл Arrays.java до описания класса введите следующий код:
/*@ predicate is_max{L}(int[] t,integer i,integer l) =
@ 0 <= i < l &&
@ \forall integer j; 0 <= j < l ==> t[j] <= t[i];
@*/
Предикаты описываются в конструкции /*@ predicate id{L}(t var, …) = e;*/, где id – имя предиката, t – тип переменной-параметра, var – имя переменной-параметра, e – логическое выражение, L – метка или своего рода параметр, с которым рассматривается предикат. L может принимать одно из четырех значений:
Here – берется значение предиката в текущей точке, т.е. с текущими значениями переменных.
Old – берется значение предиката со значением, которое было до входа в метод.
Pre – берется значение предиката, которое было в предыдущем состоянии.
Post – берется значение предиката из пост-состояния.
Вставьте еще один метод в класс:
/*@ requires t != null && t.length >= 1;
@ ensures is_max(t,\result,t.length);
@*/
public static int findMax2(int[] t) {
int m = t[0];
int r = 0;
/*@ loop_invariant
@ 1 <= i <= t.length && m == t[r] && is_max(t,r,i);
@ loop_variant t.length−i;
@*/
for (int i = 1; i < t.length; i++) {
if (t[i] > m) {
r = i;
m = t[i];
}
}
return r;
}
Этот метод также возвращает индекс максимального значения в массиве. Только теперь спецификация описана с помощью предиката. Как видно при обращении к предикату можно не указывать метку.
Заново откройте измененный фал для верификации и верифицируйте его.
Убедитесь, что все выражения доказаны.