Скачать презентацию 20 11 13 Лекция 10 Предикатное программирование Скачать презентацию 20 11 13 Лекция 10 Предикатное программирование

lecture10.ppt

  • Количество слайдов: 38

 20. 11. 13 Лекция 10 Предикатное программирование 6. Система PVS. Блок доказательства (Prover) 20. 11. 13 Лекция 10 Предикатное программирование 6. Система PVS. Блок доказательства (Prover) 7. Технология предикатного программирования (прод) Разработка и верификация программ вычисления целочисленного квадратного корня, целой части вещественного числа и целочисленного двоичного логарифма 8. Язык, технология и методы верификации других классов программ Класс объектно-ориентированных программ

7. Технология предикатного программирования 7. 6. Разработка и верификация программ стандартных функций 7. Технология предикатного программирования 7. 6. Разработка и верификация программ стандартных функций

 Иллюстрация методов разработки и верификации Построение и верификация быстрых программ для стандартных функций: Иллюстрация методов разработки и верификации Построение и верификация быстрых программ для стандартных функций: • floor – целая часть плавающего числа, представленного в бинарном формате в соответствии со стандартом IEEE 754 -2008; • isqrt – целочисленный квадратный корень; • ilog 2 – целочисленный двоичный логарифм. Программы данных стандартных функций на языке C++ используются в отечественной системе спутниковой навигации “Навител Навигатор” для автомобилей (корпорация Центр Навигационных Технологий).

static const uint 32_t small_limit = 17; static const uint 32_t small_sqrts[small_limit] = // static const uint 32_t small_limit = 17; static const uint 32_t small_sqrts[small_limit] = // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 {0, 1, 1, 2, 2, 3, 3, 3, 4, 4}; #define sqrt. Bit(k) t = s + (1 UL << (k - 1)); t <<= k + 1; if (_n >= t) {_n -= t; s |= 1 UL << k; } uint 32_t os: : isqrt(uint 32_t _n) { if (_n < small_limit) return small_sqrts[_n]; uint 32_t s = 0 UL; if (_n >= 1 UL<<30) { _n -= 1 UL<<30; s = 1 UL<<15; } uint 32_t t; sqrt. Bit(14); sqrt. Bit(13); sqrt. Bit(12); sqrt. Bit(11); sqrt. Bit(10); sqrt. Bit(9); sqrt. Bit(8); sqrt. Bit(7); sqrt. Bit(6); sqrt. Bit(5); sqrt. Bit(4); sqrt. Bit(3); sqrt. Bit(2); sqrt. Bit(1); if (_n > s<<1) s |= 1 UL; return s; }

 Разработка программы вычисления целочисленного квадратного корня Спецификация isqrt : m = isqrt(x) = Разработка программы вычисления целочисленного квадратного корня Спецификация isqrt : m = isqrt(x) = floor(sqrt(x)) , где z = floor(t) – целая часть вещественного аргумента t со спецификацией t <= z < t+1. Спецификацией t = sqrt(x) является формула t^2 = x. Таким образом, функция isqrt имеет спецификацию: formula Isqrt(nat x, m) = m^2 <= x & x < (m + 1)^2; isqrt(nat x : nat m) post Isqrt(x, m); Спецификация для предиката isqrt(nat x : nat m) есть [ true , Isqrt(x, m)]

Построение (синтез) программы для предиката isqrt formula Isqrt(nat x, m) = m^2 <= x Построение (синтез) программы для предиката isqrt formula Isqrt(nat x, m) = m^2 <= x & x < (m + 1)^2; isqrt(nat x : nat m) post Isqrt(x, m); Синтезируем простейшую программу, вычисляющую результат m последовательным перебором с нуля. Применяется метод обобщения исходной задачи isqrt. Рассмотрим задачу sq 0, определяемую спецификацией: formula P_sq 0(nat x, k) = k^2 <= x sq 0(nat x, k: nat m) pre P_sq 0(x, k) post Isqrt(x, m); Задача isqrt(x : m) сводится к sq 0(x, 0: m) : isqrt(nat x : nat m) { sq 0(x, 0: m) } post Isqrt(x, m)

Построение программы для предиката sq 0 formula Isqrt(nat x, m) = m^2 <= x Построение программы для предиката sq 0 formula Isqrt(nat x, m) = m^2 <= x & x < (m + 1)^2; isqrt(nat x : nat m) { sq 0(x, 0: m) } post Isqrt(x, m) formula P_sq 0(nat x, k) = k^2 <= x sq 0(nat x, k: nat m) pre P_sq 0(x, k) post Isqrt(x, m); Построить программу S 1(x, k: m) для sq 0 и доказать формулу корректности: P_sq 0(x, k) & Isqrt(x, m) L(S 1(x, k: m)). Решение строится разбором случаев по условию x < (k + 1)^2. 1) истина – решение задачи: m = k. 2) ложь – решение сводится к sq 0(x, k + 1: m) для следующего значения k. formula e(nat x, k: nat) = (x<(k + 1)^2)? 0 : x – k^2; sq 0(nat x, k : nat m) pre P_sq 0(x, k) { if (x < (k + 1)^2) m = k else sq 0(x, k + 1: m) } post Isqrt(x, m) measure e(k, x);

 Более эффективная версия программы isqrt sq 0(nat x, k : nat m) pre Более эффективная версия программы isqrt sq 0(nat x, k : nat m) pre P_sq 0(x, k) { if (x < (k + 1)^2) m = k else sq 0(x, k + 1: m) } post Isqrt(x, m); Недостаток ─ вычисление квадрата в (k + 1)^2. (k + 1)^2=p =k^2 + 2* k + 1 Дополнительный параметра n = k^2. Параметр d = 2* k + 1 позволяет заменить умножение сложением. x < (k + 1)^2 эквивалентно x - k^2 < 2* k + 1 Вместо x и n можно перейти к одному параметру y = x - k^2. Соответствующее обобщение задачи sqrt есть предикат sq 1: formula P_sq 1(nat x, y, k, d) = k^2 <= x & d = 2 * k + 1 & y = x - k^2 ; sq 1(nat x, y, k, d: nat m) pre P_sq 1(x, y, k, d) post Isqrt(x, m); Результатом является программа: isqrt(nat x : nat m) { sq 1(x, x, 0, 1: m) } post Isqrt(x, m); sq 1(nat x, y, k, d: nat m) pre P_sq 1(x, y, k, d) { if (y < d) m = k else sq 1(x, y – d, k + 1, d + 2: m) } post Isqrt(x, m);

 Алгоритм вычисления целочисленного квадратного корня через двоичное разложение Спецификация: formula Isqrt(nat n, s) Алгоритм вычисления целочисленного квадратного корня через двоичное разложение Спецификация: formula Isqrt(nat n, s) = s^2 <= n & n < (s + 1)^2; formula P_sqp(nat n, p) = p > 0 & n < 2^(2*p); isqrt 1(nat n, p: nat s) pre P_sqp(n, p) post Isqrt(n, s); s состоит не более чем из p двоичных цифр !! Значение старшей цифры равно 0, если n < 2^(2*(p-1)) и 1 в противном случае. Алгоритм определяет цифры начиная со старшей и далее. Пусть q очередное приближение для результата s в виде старших двоичных цифр с номерами от p до k+1. Тогда должно выполняться условие q^2 <= n < (q + 2^k)^2. 2^(2*(p-1)) 0 2^(2*p) p k 1

 Спецификация обобщающей задачи: formula P_sq 2(nat n, p, k, q) = P_sqp(n, p) Спецификация обобщающей задачи: formula P_sq 2(nat n, p, k, q) = P_sqp(n, p) & k <= p & q^2 <= n & n < (q + 2^k)^2 ; sq 2(nat n, p, k, q : nat s) pre P_sq 2(n, p, k, q) post Isqrt(n, s); isqrt 1(nat n, p: nat s) pre P_sqp(n, p) { sq 2(n, p, p, 0: s) } post Isqrt(n, s);

formula P_sq 2(nat n, p, k, q) = P_sqp(n, p) & k <= p formula P_sq 2(nat n, p, k, q) = P_sqp(n, p) & k <= p & q^2 <= n & n < (q + 2^k)^2 ; sq 2(nat n, p, k, q : nat s) pre P_sq 2(n, p, k, q) post Isqrt(n, s); При k = 0 решением задачи sq 2 будет s = q. Если в s цифра с номером k есть 1, то следующим приближением для q будет q + 2^(k-1). Если n < (q + 2^(k-1))^2, то цифра с номером k есть 0, иначе 1. sq 2(nat n, p, q, k: nat s) pre P_sq 2(n, p, k, q) { if (k = 0) s = q else if ( n < (q + 2^(k-1))^2 ) sq 2(n, p, k - 1, q : s) else sq 2(n, p, k - 1, q + 2^(k-1) : s) } post Isqrt(n, s);

 Оптимизации программы предиката sq 2 В выражении q + 2^(k-1) заменим “+” побитовой Оптимизации программы предиката sq 2 В выражении q + 2^(k-1) заменим “+” побитовой операцией “or”. Чтобы обеспечить корректность такой замены, необходимо доказать лемму: or_eq_plus: lemma k > 0 & k < p & mod(q, 2^k) = 0 & q < 2^p (q or 2^(k - 1)) = q + 2^(k - 1) Необходимое условие mod(q, 2^k) = 0 проще обеспечить включением его в предусловие. Упростить вычисление n < (q + 2^(k-1))^2 (q + 2^(k-1))^2 = q^2 + 2^((k-1)*2) + q * 2^k Тогда условие n < (q + 2^(k-1))^2 эквивалентно: n - q^2 < 2^((k-1)*2) + q * 2^k Обозначим y = n - q^2.

 Синтез программы sq 3 Синтезируем программу с указанными оптимизациями sq 2: formula P_sq Синтез программы sq 3 Синтезируем программу с указанными оптимизациями sq 2: formula P_sq 3(nat n, p, k, q, y) = P_sq 2(n, p, k, q) & y = n - q^2 & mod(q, 2^k) = 0; isqrt 1(nat n, p: nat s) pre P_sqp(n, p) { sq 3(n, p, p, 0, n: s) } post Isqrt(n, s); sq 3(nat n, p, k, q, y: nat s) pre P_sq 3(n, p, k, q, y) { if (k = 0) s = q else { nat t = 2^((k-1)*2) + q * 2^k; if (y < t) sq 3(n, p, k - 1, q , y: s) else sq 3(n, p, k - 1, q or 2^(k-1), y – t : s) } } post Isqrt(n, s);

Трансформация программы isqrt 1 Этап 1. Склеивание переменных: sq 3: n y; s q; Трансформация программы isqrt 1 Этап 1. Склеивание переменных: sq 3: n y; s q; sq 3(nat n, p, k, s, n: nat s) { if (k = 0) s = s else { nat t = 2^((k-1)*2) + s * 2^k; if (n < t) sq 3(n, p, k – 1, s, n: s) else sq 3(n, p, k - 1, s or 2^(k-1), n – t : s) } } Этап 2. Замена хвостовой рекурсии циклом. sq 3(nat n, p, k, s, n: nat s) { M: if (k = 0) s = s else { nat t = 2^((k-1)*2) + s * 2^k; if (n < t) { |n, p, k, s, n| = |n, p, k – 1, s, n|; goto M } else {|n, p, k, s, n| = |n, p, k-1, s or 2^(k-1), n - t|; goto M}} }

Трансформация программы isqrt 1 (прод 1. ) Этап 2 a. Оформление цикла и раскрытие Трансформация программы isqrt 1 (прод 1. ) Этап 2 a. Оформление цикла и раскрытие мульти-присваиваний sq 3(nat n, p, k, s, n: s) {for (; ; ) { if (k = 0) break; nat t = 2^((k-1)*2) + s * 2^k; if (n < t) k = k – 1 else { s = s or 2^(k-1); k = k – 1; n = n – t } } } Этап 2 б. Оформление цикла и упрощения sq 3(nat n, p, k, s, n: s) { for ( ; k = 0; k = k – 1) { nat t = 2^((k-1)*2) + s * 2^k; if (n >= t) { n = n – t ; s = s or 2^(k-1); } } }

Трансформация программы isqrt 1 (прод 2. ) isqrt 1(nat n, p: nat s) { Трансформация программы isqrt 1 (прод 2. ) isqrt 1(nat n, p: nat s) { sq 3(n, p, p, 0, n: s) } Этап 3. Подстановка определения предиката на место вызова isqrt 1(nat n, p: nat s) { nat k; |n, p, k, s, n| = |n, p, p, 0, n|; for ( ; k = 0; k = k – 1) { nat t = 2^((k-1)*2) + s * 2^k; if (n >= t) { n = n – t ; s = s or 2^(k-1); } } } Программа на императивном расширении языка P nat n, p; nat s = 0; for (nat k = p ; k = 0; k = k – 1) { nat t = 2^((k-1)*2) + s * 2^k; if (n >= t) { n = n – t ; s = s or 2^(k-1); }

 Преобразования императивной программы nat n, p; nat s = 0; for (nat k Преобразования императивной программы nat n, p; nat s = 0; for (nat k = p; k = 0; k = k - 1) { nat t = 2^((k-1)*2) + s * 2^k; if (n >=t) { n = n – t; s = s or 2^(k-1); } } Введем макрос для тела цикла: sq(k) = { t = 2^((k-1)*2) + s * 2^k; if (n >=t) { n = n – t; s = s or 2^(k-1); } } Проведем развертку цикла. Получим: nat n, p; nat s = 0; sq(p); sq(p – 1); …; sq(2); sq(1) Проведем подстановку тела для sq(p) и sq(1). Получим программу, тождественную исходной: sq(k){ t = 2^((k-1)*2) + s * 2^k; if (n >=t) { n = n – t; s = s or 2^(k-1); } } nat n, p; nat s = 0; if (n >= 2^((p-1)*2)) { n = n – 2^((p-1)*2); s = 2^(p-1); } sq(p – 1); …; sq(2); if (n >= s * 2) s = s or 1

static const uint 32_t small_limit = 17; static const uint 32_t small_sqrts[small_limit] = // static const uint 32_t small_limit = 17; static const uint 32_t small_sqrts[small_limit] = // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 {0, 1, 1, 2, 2, 3, 3, 3, 4, 4}; #define sqrt. Bit(k) t = s + (1 UL << (k - 1)); t <<= k + 1; if (_n >= t) {_n -= t; s |= 1 UL << k; } uint 32_t os: : isqrt(uint 32_t _n) { if (_n < small_limit) return small_sqrts[_n]; uint 32_t s = 0 UL; if (_n >= 1 UL<<30) { _n -= 1 UL<<30; s = 1 UL<<15; } uint 32_t t; sqrt. Bit(14); sqrt. Bit(13); sqrt. Bit(12); sqrt. Bit(11); sqrt. Bit(10); sqrt. Bit(9); sqrt. Bit(8); sqrt. Bit(7); sqrt. Bit(6); sqrt. Bit(5); sqrt. Bit(4); sqrt. Bit(3); sqrt. Bit(2); sqrt. Bit(1); if (_n > s<<1) s |= 1 UL; return s; }

Доказательство формул корректности на PVS isqrt : THEORY BEGIN IMPORTING fl, reals@sqrt, reals@sq, bit_nat Доказательство формул корректности на PVS isqrt : THEORY BEGIN IMPORTING fl, reals@sqrt, reals@sq, bit_nat n, s, x, k, m: VAR nat Isqrt(n, s): bool = s = floor(sqrt(n)) Isqrt_eq: LEMMA Isqrt(n, s) IFF s^2 <= n & n < (s + 1)^2 Isqrt_uniq: LEMMA Isqrt(n, s) & Isqrt(n, m) IMPLIES s = m Isqrt_total: LEMMA EXISTS s: Isqrt(n, s) P_sq 0(x, k): bool = k^2 <= x Isqrt_fb 1: LEMMA Isqrt(x, s) IMPLIES P_sq 0(x, 0) & Isqrt(x, s) e(x, k): nat = IF x<(k + 1)^2 THEN 0 ELSE x - k^2 ENDIF sq 0_rec: LEMMA P_sq 0(x, k) & Isqrt(x, m) IMPLIES IF x < (k + 1)^2 THEN m = k ELSE e(x, k+1) < e(x, k) & P_sq 0(x, k+1) & Isqrt(x, m) ENDIF

Доказательство формул корректности (пр1) P_sq 1(x, y, k, d: nat): bool = k^2 <= Доказательство формул корректности (пр1) P_sq 1(x, y, k, d: nat): bool = k^2 <= x & d = 2 * k + 1 & y = x - k^2 Isqrt 1_fb 1: LEMMA Isqrt(x, s) IMPLIES P_sq 1(x, x, 0, 1) & Isqrt(x, s) sq 1_rec: LEMMA FORALL (x, y, k, d, m: nat): P_sq 1(x, y, k, d) & Isqrt(x, m) IMPLIES IF y < d THEN m = k ELSE e(x, k+1) < e(x, k) & P_sq 1(x, y - d, k + 1, d + 2) & Isqrt(x, m) ENDIF P_sqp(n, p: nat): bool = p > 0 & n < 2^(2*p) P_sq 2(n, p, k, q: nat): bool = P_sqp(n, p) & k <= p & q^2 <= n & n < (q + 2^k)^2 p: VAR nat Isqrt 2_fb 1: LEMMA P_sqp(n, p) & Isqrt(n, s) IMPLIES P_sq 2(n, p, p, 0) & Isqrt(n, s) e 2(k: nat): nat = k

Доказательство формул корректности (пр2) sq 2_rec: lemma FORALL (n, p, k, q, s: nat): Доказательство формул корректности (пр2) sq 2_rec: lemma FORALL (n, p, k, q, s: nat): P_sq 2(n, p, k, q) & Isqrt(n, s) IMPLIES IF k = 0 THEN s = q ELSIF n < (q + 2^(k-1))^2 THEN e 2(k-1) < e 2(k) & P_sq 2(n, p, k-1, q) & Isqrt(n, s) ELSE e 2(k-1) < e 2(k) & P_sq 2(n, p, k-1, q + 2^(k-1)) & Isqrt(n, s) ENDIF P_sq 3(n, p, k, q, y: nat): bool = P_sq 2(n, p, k, q) & y = n - q^2 & mod(q, 2^k) = 0 p_2_2: LEMMA (2^p)^2 = 2^(2*p) Isqrt 3_fb 1: LEMMA P_sqp(n, p) & Isqrt(n, s) IMPLIES P_sq 3(n, p, p, 0, n) & Isqrt(n, s)

Доказательство формул корректности (пр3) k 2_1: LEMMA k > 0 IMPLIES 2 * 2^(k-1) Доказательство формул корректности (пр3) k 2_1: LEMMA k > 0 IMPLIES 2 * 2^(k-1) = 2^k sq 3_rec: lemma FORALL (n, p, k, q, y, s, t: nat): P_sq 3(n, p, k, q, y) & Isqrt(n, s) IMPLIES IF k = 0 THEN s = q ELSE t = 2^((k-1)*2) + q * 2^k IMPLIES IF y < t THEN e 2(k-1) < e 2(k) & P_sq 3(n, p, k - 1, q , y) & Isqrt(n, s) ELSE e 2(k-1) < e 2(k) & P_sq 3(n, p, k - 1, bit_or(p, q, 2^(k-1)), y - t) & Isqrt(n, s) ENDIF END isqrt

Теория bit_nat: THEORY BEGIN IMPORTING bitvectors@bv_arith_concat, ints@mod_div_lems, ints@div_nat, bitvectors@bv_nat_rules, bitvectors@bv_bitwise_rules, fl bit_or(n: posnat, a, Теория bit_nat: THEORY BEGIN IMPORTING bitvectors@bv_arith_concat, ints@mod_div_lems, ints@div_nat, bitvectors@bv_nat_rules, bitvectors@bv_bitwise_rules, fl bit_or(n: posnat, a, b: below(exp 2(n))): below(exp 2(n)) = bv 2 nat[n](nat 2 bv[n](a) OR nat 2 bv[n](b)) concat_or: LEMMA FORALL (n, m: nat, x, z: bvec[n], y, t: bvec[m]): ((x o y) OR (z o t)) = ((x OR z) o (y OR t)) bvcomp: LEMMA FORALL (n, k: posnat, a: below(exp 2(n))): k <= n IMPLIES nat 2 bv[n](a) = nat 2 bv[n-k](div(a, exp 2(k))) o nat 2 bv[k](mod(a, exp 2(k))) bvcomp 2 e: LEMMA FORALL (n, k: posnat, a: below(exp 2(n))): k <= n & mod(a, exp 2(k)) = 0 IMPLIES nat 2 bv[n](a) = nat 2 bv[n-k](div(a, exp 2(k))) o fill[k](FALSE) bvcomp 1 e: LEMMA FORALL (n, k: posnat, b: below(exp 2(k))): k <= n IMPLIES nat 2 bv[n](b) = fill[n-k](FALSE) o nat 2 bv[k](b) or_eq_plus: LEMMA FORALL (n, k: posnat, a: below(exp 2(n)), b: below(exp 2(k))): k <= n & mod(a, exp 2(k)) = 0 IMPLIES bit_or(n, a, b) = a + b END bit_nat

Итоги В процессе верификации обнаружено 5 ошибок. Из них 4 чисто технические. Принципиальная ошибка: Итоги В процессе верификации обнаружено 5 ошибок. Из них 4 чисто технические. Принципиальная ошибка: результат функции floor не помещается в отведенные для него 32 бита. Затраты на доказательство формул корректности в системе PVS примерно в 5 раз больше времени обычного программирования. 30% – время доказательства собственно формул корректности 70% – время доказательства дополнительных лемм Среди более десятка работ по верификации и синтезу isqrt имеется лишь одна работа, в которой верифицируется алгоритм isqrt сравнимой эффективности. • • • Новая версия языка предикатного программирования языка P Учебное пособие по предикатному программированию для студентов НГУ Система предикатного программирования.

 Алгоритм вычисления целой части плавающего числа formula flp(real x, int i) = i Алгоритм вычисления целой части плавающего числа formula flp(real x, int i) = i <= x & x < i + 1; Спецификация функции floor: floor(real x: int y) post flp(x, y); для типов float, double и quad языка C++ Стандарт IEEE 754 -2008. Плавающее число представляется тройкой (S, E, T), где S = {0, 1} знак числа, E сдвинутая экспонента, а T мантисса в нормализованном представлении без старшего разряда (равного 1). В соответствии со стандартом, значение плавающего числа определяется по формуле: y = (-1)S 2 E-bias (1 + 21 -p T) Здесь bias сдвиг экспоненты, p число битов в представлении мантиссы, 1 E 2 w - 2, w число битов в представлении экспоненты. Значение E = 0 для кодирования нулей и ненормализованных малых значений; случай E = 2 w – 1 соответствует бесконечности и числу Na. N. Для формата 32 (float) значения bias = 127, w = 8 и p = 24. Для формата 64 (double) значения bias = 1023, w = 11 и p = 53.

const nat p, bias, w, m; const nat m = p + w; type const nat p, bias, w, m; const nat m = p + w; type bit = {nat a | a = 0 or a = 1}; type intm = {int x | - 2^(m-1) < x & x < 2^(m-1)}; formula val(bit S, nat E, T) = (-1)^S * 2^(E - bias) * (1 + 2^(1 - p) * T); floor(bit S, nat E, T: intm y) pre T < 2^(p-1) post flp(val(S, E , T), y); val(bit S, nat E, T) = (-1)^S * 2^(E – bias – p + 1) * (2^(p-1) + T) = sg 2^d z; sg= (-1)^S; sg = 1 or sg = -1 & d = E – bias – p + 1 & z = 2^(p-1) + T & z >= 2^(p-1) d = 0 => y = z * sg d > 0 => сдвиг вправо, однако d не может быть больше 7; сдвиг на 8 дает отрицательное целое. d < 0 => сдвиг влево, но не дальше, чем на 23, поскольку далее получим нулевое значение

const nat p, bias, w, m; const nat m = p + w; type const nat p, bias, w, m; const nat m = p + w; type bit = {nat a | a = 0 or a = 1}; type intm = {int x | - 2^(m-1) < x & x < 2^(m-1)}; floor(bit S, nat E, T: intm y) pre T < 2^(p-1) & E – bias – p + 1 < w { floor 1(S, E – bias – p + 1, 2^(p-1) + T: y) } post flp(val(S, E , T), y); val 1(bit S, nat d, z) = (-1)^S * 2^d z; floor 1(bit S, nat d, z: intm y) pre z >= 2^(p-1) & z < 2^p & d < w { if (S = 0) if (d >= 0) y = 2^d * z else y = div(z, 2^(-d)) else if (d >= 0) y = - 2^d * z else if (mod(z, 2^(-d)) = 0) y = - div(z, 2^(-d)) else y = - div(z, 2^(-d)) – 1 } post flp(val 1(S, d , z), y);

Представим теорию main для определения предиката floor. main: THEORY BEGIN IMPORTING fl p, bias, Представим теорию main для определения предиката floor. main: THEORY BEGIN IMPORTING fl p, bias, w, m: nat %constants m: nat = p + w nbit: TYPE = {n: nat | n = 0 OR n = 1} x: VAR real intm: TYPE = {x | - 2^(m-1) < x & x < 2^(m-1)} y: VAR intm S: VAR nbit E, T, d, z: VAR nat val(S, E, T) = (-1)^S * 2^(E - bias) * (1 + 2^(1 - p) * T) val 1(S, d, z) = (-1)^S * 2^d * z END main

floor_val: THEORY BEGIN IMPORTING main, floor 1 y: VAR intm E, T: VAR nat floor_val: THEORY BEGIN IMPORTING main, floor 1 y: VAR intm E, T: VAR nat S: VAR nbit P_floor(E, T): bool = T < 2^(p-1) & E – bias – p + 1 < w Q_floor(S, E, T, y): bool = flp(val(S, E , T), y) satisfy_spec: LEMMA P_floor(E, T) IMPLIES EXISTS y: Q_floor(S, E, T, y) Целью является доказательство истинности правила: P_floor(E, T) & Q_floor(S, E, T, y)├ LS(floor 1(S, E – bias – p + 1, 2^(p-1) + T)) В соответствии с правилом FB 1 генерируется лемма: FB 1: LEMMA P_floor(E, T) & Q_floor(S, E, T, y) IMPLIES P_floor 1(E – bias – p + 1, 2^(p-1) + T) & Q_floor 1(S, E – bias – p + 1, 2^(p-1) + T, y)

floor 1(bit S, nat d, z: intm y) pre z >= 2^(p-1) & z floor 1(bit S, nat d, z: intm y) pre z >= 2^(p-1) & z < 2^p & d < w { if (S = 0) if (d >= 0) y = 2^d * z else y = div(z, 2^(-d)) else if (d >= 0) y = - 2^d * z else if (mod(z, 2^(-d)) = 0) y = - div(z, 2^(-d)) else y = - div(z, 2^(-d)) – 1 } post flp(val 1(S, d , z), y); Представим начальную часть теории floor 1: THEORY BEGIN IMPORTING main y: VAR intm E, T, d, z: VAR nat S: VAR nbit P_floor 1(d, z): bool = z >= 2^(p-1) & z < 2^p & d < w Q_floor 1(S, d, z, y): bool = flp(val 1(S, d , z), y) satisfy_spec: LEMMA P_floor 1(d, z) IMPLIES EXISTS r: Q_floor 1(S, d, z, y) Целью является доказательство истинности правила:

 В соответствии с правилом FC 1 для первой альтернативы условного оператора генерируется цель: В соответствии с правилом FC 1 для первой альтернативы условного оператора генерируется цель: FC 1: P_floor 1(d, z) & Q_floor 1(S, d, z, y) & S = 0 ├ LS(<первый условный >) В соответствии с правилом FC 1 для первой альтернативы первого условного оператора генерируется лемма: FC 1: LEMMA P_floor 1(d, z) & Q_floor 1(S, d, z, y) & S = 0 & & d > 0 IMPLIES y = 2^d * z В соответствии с правилом FC 2 для второй альтернативы первого условного оператора генерируется лемма: FC 2: LEMMA P_floor 1(d, z) & Q_floor 1(S, d, z, y) & S = 0 & & NOT d > 0 IMPLIES y = div(z, 2^(-d))

 else if (d >= 0) y = - 2^d * z else if else if (d >= 0) y = - 2^d * z else if (mod(z, 2^(-d)) = 0) y = - div(z, 2^(-d)) else y = - div(z, 2^(-d)) – 1 В соответствии с правилом FC 2 для второй альтернативы условного оператора генерируется цель: FC 2: P_floor 1(d, z) & Q_floor 1(S, d, z, y) & NOT S = 0 ├ LS(<второй условный >) В соответствии с правилом FC 1 для первой альтернативы второго условного оператора генерируется лемма: FC 11: LEMMA P_floor 1(d, z) & Q_floor 1(S, d, z, y) & NOT S = 0 & d >= 0 IMPLIES y = - 2^d * z В соответствии с правилом FC 2 для второй альтернативы второго условного оператора генерируется цель: FC 2: P_floor 1(d, z) & Q_floor 1(S, d, z, y) & NOT S = 0 & NOT d > 0 ├ LS(<третий условный >)

 else if (mod(z, 2^(-d)) = 0) y = - div(z, 2^(-d)) else y else if (mod(z, 2^(-d)) = 0) y = - div(z, 2^(-d)) else y = - div(z, 2^(-d)) – 1 В соответствии с правилом FC 1 для первой альтернативы третьего условного оператора генерируется лемма: FC 12: LEMMA P_floor 1(d, z) & Q_floor 1(S, d, z, y) & NOT S = 0 & NOT d > 0 & mod(z, 2^(-d)) = 0 IMPLIES y = - div(z, 2^(-d)) В соответствии с правилом FC 2 для второй альтернативы третьего условного оператора генерируется лемма: FC 21: LEMMA P_floor 1(d, z) & Q_floor 1(S, d, z, y) & NOT S = 0 & NOT d >= 0 & NOT mod(z, 2^(-d)) = 0 IMPLIES y = - div(z, 2^(-d)) – 1

В программе, находящейся в файле fast_floor. cpp обнаружено две ошибки: 1. При E – В программе, находящейся в файле fast_floor. cpp обнаружено две ошибки: 1. При E – bias >= m – 2 (или d >= w) сдвигаемое влево значение выходит за пределы m – 1 битов. В частности, при d = w старшая единица попадает в позицию знака в представлении целого числа, в результате чего результат floor становится отрицательным. В реализации следовало бы запретить использовать функцию floor при d > 0, т. е. при E – bias – p + 1 > 0 из-за экспоненциально растущей погрешности. 2. Ненормализованное сверхмалое число обрабатывается также, как нормализованное (с добавление 1 в разряд p). Тем не менее, это не меняет значение функции floor из-за малости числа. Однако при вычислении других функций результат был бы ошибочным.

8. Язык, технология и методы верификации других классов программ 8. Язык, технология и методы верификации других классов программ

Классы программ 1. Программы-функции (преобразователи) Предикатное программирование Задачи дискретной и вычислительной математики 2. Программы-процессы Классы программ 1. Программы-функции (преобразователи) Предикатное программирование Задачи дискретной и вычислительной математики 2. Программы-процессы -- класс программ, для которого применяется Автоматное программирование ……. Языковые процессоры, Операционные системы Объектно-ориентированное расширение классов Параллелизм Разные классы требуют разных методов и технологий !

 Объектно-ориентированное расширение Язык. База – язык невзаимодействующих программ. Дополнительно - классы, инкапсуляция, наследование. Объектно-ориентированное расширение Язык. База – язык невзаимодействующих программ. Дополнительно - классы, инкапсуляция, наследование. class C(x) implements D(y) { invariant <инвариант класса> <поля и методы> < приватные поля и методы > } x и y – внешние параметры (типы, переменные) Объект – структура из доступных и приватных полей класса c. field Вызов метода: A(x, s: y, s’) s. A(x: y) Определение метода: A(x: y) pre P(x, s) {…} post Q(x, s, y, s’)

class D { invariant ID(s); A(x: y) pre PD(x, s) {…} post QD(x, s, class D { invariant ID(s); A(x: y) pre PD(x, s) {…} post QD(x, s, y, s’) … } class C implements D { invariant IC(s); A(x: y) pre PC(x, s) {…} post QC(x, s, y, s’)} IC(s) ID(s) PD(x, s) PC(x, s) QC(x, s, y, s’) QD(x, s, y, s’) Спецификация в виде предусловия и постусловия для методов, инвариант класса. Условия корректности. Формула тотальной корректности для методов. Выполнимость инварианта после вызова любого метода класса. Условия корректности, проверяющие для наследуемых методов ослабление предусловий и усиление постусловий. Проверка усиления инварианта наследуемого класса.