- •21.11.12 Лекция 10
- •7. Технология предикатного программирования 7.6. Разработка и верификация программ стандартных функций
- •Иллюстрация методов разработки и верификации
- •Разработка программы вычисления целочисленного квадратного корня
- •Построение (синтез) программы для предиката isqrt
- •Построение программы для предиката sq0
- •Более эффективная версия программы isqrt
- •Алгоритм вычисления целочисленного квадратного корня через двоичное разложение
- •Спецификация обобщающей задачи:
- •Оптимизации программы предиката sq2
- •Синтез программы sq3
- •Трансформация программы isqrt1
- •Трансформация программы isqrt1 (прод1.)
- •Трансформация программы isqrt1 (прод2.)
- •Преобразования императивной программы
- •Доказательство формул корректности на PVS
- •Доказательство формул корректности (пр1)
- •Доказательство формул корректности (пр2)
- •Доказательство формул корректности (пр3)
- •Теория bit_nat
- •Итоги
- •Алгоритм вычисления целой части плавающего числа
- •Представим теорию main для определения предиката floor.
- •floor_val: THEORY BEGIN
- •В соответствии с правилом FC1 для первой альтернативы условного оператора генерируется цель:
- •В программе, находящейся в файле fast_floor.cpp обнаружено две ошибки:
- •8.Язык, технология
- •8.1. Класс объектно-ориентированных программ.
- •class D { invariant ID(s);
- •3. Класс простых процессов.
- •Языковые средства описания процесса
- •Декомпозиция процессов
- •Декомпозиция с одним внутренним состоянием:
- •stop
- •Декомпозиция без внутренних состояний:
- •Пример 1. Гадание на кофейных зернах
- •2.Электронные часы с будильником
- •class Часы { nat hours; nat minutes;
21.11.12 Лекция 10
Предикатное программирование
7. Технология предикатного программирования (прод)
Разработка и верификация программ вычисления целочисленного квадратного корня, целой части вещественного числа и целочисленного двоичного логарифма
8. Язык, технология и методы верификации других классов программ
Класс объектно-ориентированных программ Класс простых процессов.
Примеры. Гадание на кофейных зернах. Электронные часы с будильником
Класс реактивных систем
7. Технология предикатного программирования 7.6. Разработка и верификация программ стандартных функций
Иллюстрация методов разработки и верификации
Построение и верификация быстрых программ для стандартных функций:
•floor – целая часть плавающего числа, представленного в бинарном формате в соответствии со стандартом IEEE 754-2008;
•isqrt – целочисленный квадратный корень;
•ilog2 – целочисленный двоичный логарифм.
Программы данных стандартных функций на языке C++ используются в отечественной системе спутниковой навигации “Навител Навигатор” для автомобилей (корпорация Центр Навигационных Технологий).
static const uint32_t small_limit = 17;
static const uint32_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, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4}; |
|||||||||||
#define sqrtBit(k) |
|
|
\ |
|
|
||||||
|
t = s + (1UL << (k - 1)); |
|
|
t <<= k + 1;
if (_n >= t) {_n -= t; s |= 1UL << k;}
uint32_t os::isqrt(uint32_t _n) { if (_n < small_limit)
return small_sqrts[_n]; uint32_t s = 0UL;
if (_n >= 1UL<<30) { _n -= 1UL<<30; s = 1UL<<15; } uint32_t t;
sqrtBit(14); sqrtBit(13); sqrtBit(12); sqrtBit(11); sqrtBit(10); sqrtBit(9); sqrtBit(8); sqrtBit(7); sqrtBit(6); sqrtBit(5);
sqrtBit(4); sqrtBit(3); sqrtBit(2); sqrtBit(1); if (_n > s<<1)
s |= 1UL; return s;
}
Разработка программы вычисления целочисленного квадратного корня
Спецификация 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 & x < (m + 1)^2; isqrt(nat x : nat m) post Isqrt(x, m);
Синтезируем простейшую программу, вычисляющую результат m последовательным перебором с нуля.
Применяется метод обобщения исходной задачи isqrt. Рассмотрим задачу sq0, определяемую спецификацией: formula P_sq0(nat x, k) = k^2 <= x
sq0(nat x, k: nat m) pre P_sq0(x, k) post Isqrt(x, m);
Задача isqrt(x : m) сводится к sq0(x, 0: m) : isqrt(nat x : nat m) { sq0(x, 0: m) } post Isqrt(x, m)
Построение программы для предиката sq0
formula Isqrt(nat x, m) = m^2 <= x & x < (m + 1)^2; isqrt(nat x : nat m) { sq0(x, 0: m) } post Isqrt(x, m) formula P_sq0(nat x, k) = k^2 <= x
sq0(nat x, k: nat m) pre P_sq0(x, k) post Isqrt(x, m);
Построить программу S1(x, k: m) для sq0 и доказать формулу корректности: P_sq0(x, k) & Isqrt(x, m) LS(S1(x, k: m)).
Решение строится разбором случаев по условию x < (k + 1)^2.
1)истина – решение задачи: m = k.
2)ложь – решение сводится к sq0(x, k + 1: m) для следующего значения k.
formula e(nat x, k: nat) = (x<(k + 1)^2)? 0 : x – k^2; sq0(nat x, k : nat m) pre P_sq0(x, k)
{ if (x < (k + 1)^2) m = k else sq0(x, k + 1: m) } post Isqrt(x, m) measure e(k, x);
Более эффективная версия программы isqrt
sq0(nat x, k : nat m) pre P_sq0(x, k)
{ if (x < (k + 1)^2) m = k else sq0(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 есть предикат sq1: formula P_sq1(nat x, y, k, d) = k^2 <= x & d = 2 * k + 1 & y = x - k^2 ; sq1(nat x, y, k, d: nat m) pre P_sq1(x, y, k, d) post Isqrt(x, m);
Результатом является программа:
isqrt(nat x : nat m) { sq1(x, x, 0, 1: m) } post Isqrt(x, m); sq1(nat x, y, k, d: nat m) pre P_sq1(x, y, k, d)
{ if (y < d) m = k else sq1(x, y – d, k + 1, d + 2: m) } post Isqrt(x, m);
Алгоритм вычисления целочисленного квадратного корня через двоичное разложение
Спецификация:
formula Isqrt(nat n, s) = s^2 <= n & n < (s + 1)^2; formula P_sqp(nat n, p) = p > 0 & n < 2^(2*p); isqrt1(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_sq2(nat n, p, k, q) =
P_sqp(n, p) & k <= p & q^2 <= n & n < (q + 2^k)^2 ; sq2(nat n, p, k, q : nat s) pre P_sq2(n, p, k, q) post Isqrt(n, s);
isqrt1(nat n, p: nat s) pre P_sqp(n, p) { sq2(n, p, p, 0: s) } post Isqrt(n, s);
formula P_sq2(nat n, p, k, q) =
P_sqp(n, p) & k <= p & q^2 <= n & n < (q + 2^k)^2 ; sq2(nat n, p, k, q : nat s) pre P_sq2(n, p, k, q) post Isqrt(n, s);
При k = 0 решением задачи sq2 будет s = q. Если в s цифра с номером k есть 1, то следующим приближением для q будет q + 2^(k-1). Если n < (q + 2^(k-1))^2, то цифра с номером k есть 0, иначе 1.
sq2(nat n, p, q, k: nat s) pre P_sq2(n, p, k, q) { if (k = 0) s = q
else if ( n < (q + 2^(k-1))^2 ) sq2(n, p, k - 1, q : s) else sq2(n, p, k - 1, q + 2^(k-1) : s)
} post Isqrt(n, s);