Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lectures / lecture10.ppt
Скачиваний:
34
Добавлен:
06.06.2015
Размер:
402.94 Кб
Скачать

Оптимизации программы предиката sq2

Ввыражении 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.

Синтез программы sq3

Синтезируем программу с указанными оптимизациями sq2: formula P_sq3(nat n, p, k, q, y) =

P_sq2(n, p, k, q) & y = n - q^2 & mod(q, 2^k) = 0; isqrt1(nat n, p: nat s) pre P_sqp(n, p)

{ sq3(n, p, p, 0, n: s) } post Isqrt(n, s);

sq3(nat n, p, k, q, y: nat s) pre P_sq3(n, p, k, q, y) { if (k = 0) s = q

else { nat t = 2^((k-1)*2) + q * 2^k;

if (y < t) sq3(n, p, k - 1, q , y: s)

else sq3(n, p, k - 1, q or 2^(k-1), y – t : s)

}

} post Isqrt(n, s);

Трансформация программы isqrt1

Этап 1. Склеивание переменных: sq3: n y; s q; sq3(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) sq3(n, p, k – 1, s, n: s)

else sq3(n, p, k - 1, s or 2^(k-1), n – t : s) }

}

Этап 2. Замена хвостовой рекурсии циклом. sq3(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}}

}

Трансформация программы isqrt1 (прод1.)

Этап 2a. Оформление цикла и раскрытие мульти-присваиваний

sq3(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б. Оформление цикла и упрощения sq3(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); }

}

}

Трансформация программы isqrt1 (прод2.)

isqrt1(nat n, p: nat s) { sq3(n, p, p, 0, n: s) }

Этап 3. Подстановка определения предиката на место вызова isqrt1(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 = 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 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;

}

Доказательство формул корректности на 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_sq0(x, k): bool = k^2 <= x

Isqrt_fb1: LEMMA Isqrt(x, s) IMPLIES P_sq0(x, 0) & Isqrt(x, s)

e(x, k): nat = IF x<(k + 1)^2 THEN 0 ELSE x - k^2 ENDIF sq0_rec: LEMMA P_sq0(x, k) & Isqrt(x, m) IMPLIES

IF x < (k + 1)^2 THEN m = k

ELSE e(x, k+1) < e(x, k) & P_sq0(x, k+1) & Isqrt(x, m) ENDIF

Доказательство формул корректности (пр1)

P_sq1(x, y, k, d: nat): bool = k^2 <= x & d = 2 * k + 1 & y = x - k^2

Isqrt1_fb1: LEMMA Isqrt(x, s) IMPLIES P_sq1(x, x, 0, 1) & Isqrt(x, s) sq1_rec: LEMMA FORALL (x, y, k, d, m: nat):

P_sq1(x, y, k, d) & Isqrt(x, m) IMPLIES IF y < d THEN m = k

ELSE e(x, k+1) < e(x, k) &

P_sq1(x, y - d, k + 1, d + 2) & Isqrt(x, m) ENDIF

P_sqp(n, p: nat): bool = p > 0 & n < 2^(2*p)

P_sq2(n, p, k, q: nat): bool =

P_sqp(n, p) & k <= p & q^2 <= n & n < (q + 2^k)^2

p: VAR nat

Isqrt2_fb1: LEMMA P_sqp(n, p) & Isqrt(n, s) IMPLIES P_sq2(n, p, p, 0) & Isqrt(n, s)

e2(k: nat): nat = k

Доказательство формул корректности (пр2)

sq2_rec: lemma FORALL (n, p, k, q, s: nat): P_sq2(n, p, k, q) & Isqrt(n, s) IMPLIES

IF k = 0 THEN s = q

ELSIF n < (q + 2^(k-1))^2 THEN

e2(k-1) < e2(k) & P_sq2(n, p, k-1, q) & Isqrt(n, s) ELSE e2(k-1) < e2(k) & P_sq2(n, p, k-1, q + 2^(k-1)) & Isqrt(n, s) ENDIF

P_sq3(n, p, k, q, y: nat): bool =

P_sq2(n, p, k, q) & y = n - q^2 & mod(q, 2^k) = 0

p_2_2: LEMMA (2^p)^2 = 2^(2*p)

Isqrt3_fb1: LEMMA P_sqp(n, p) & Isqrt(n, s) IMPLIES

P_sq3(n, p, p, 0, n) & Isqrt(n, s)

Соседние файлы в папке lectures