- •07.11.12 Лекция 8
- •7. Технология предикатного программирования 7.4. Гиперфункции
- •Структурное
- •Неудобные ситуации
- •Пример. Решение системы линейных уравнений
- •Определение гиперфункции :
- •elemTwo(list (int) s : int e : )
- •Пример 7.4. Определим гиперфункцию Comp следующей спецификацией:
- •Если оператор продолжения ветви содержит только оператор перехода, то оператор перехода переносится в
- •Свойства гиперфункций
- •Пример. Сумма чисел в строке
- •Обобщение исходной задачи :
- •Отметим, что можно было бы использовать гиперфункцию вида: перваяЦифра1(string s: : string r),
- •Сумма(string s, nat m : nat n)
- •Чтобы получить хвостовую рекурсию для предиката числоВстроке необходимо ввести накопитель для вычисления значения
- •взятьЧисло(string r, nat p: nat v, string t)
- •Сумма:
- •числоВстроке(char e, string s: nat v, string s) { взятьЧисло(s, val(e): v, s)
- •перваяЦифра(string s:
- •Подставим определения предикатов взятьЧисло и перваяЦифра на место вызовов. Проведем очевидные упрощения.
- •Поскольку внутренний цикл в теле предиката Сумма не имеет нормального выхода, можно заменить
- •Кодирование строк
- •Имеется недостаток программы (7.39): если строка s завершается цифрой, то проверка исчерпания строки
- •Система линейных уравнений
- •diagEl(nat n, MATR(n) a, VEC(n) b, nat k:
- •perm(nat n, MATR(n) a, VEC(n) b, nat k, m:
- •norm(nat n, k, MATR(n) a, VEC(n) b: MATR(n) a’, VEC(n) b’) pre 1
- •subtrCol(nat n, MATR(n) a, VEC(n) b, nat k:
- •На втором этапе реализуется замена хвостовой рекурсии циклами. Результатом проведения двух этапов трансформации
- •Jord(nat n, MATR(n) a, VEC(n) b, nat k: MATR(n) a, VEC(n) b :
- •perm(nat n, MATR(n) a, VEC(n) b, nat k, m: MATR(n) a, VEC(n) b
- •subtrLines(nat n, k, MATR(n) a, VEC(n) b: MATR(n) a, VEC(n) b)
- •На третьем этапе проведем подстановку следующую серию подстановок тел определений на место вызовов:
- •Lin(nat n, MATR(n) a, VEC(n) b: VEC(n) b : )
- •Lin(nat n, MATR(n) a, VEC(n) b: VEC(n) b : )
- •Нетривиальным является устранение неиспользуемых вычислений : Lin(nat n, MATR(n) a, VEC(n) b: VEC(n)
diagEl(nat n, MATR(n) a, VEC(n) b, nat k:
MATR(n) a’, VEC(n) b’ : )
pre 1 k n & triaCol(n, k, a) pre 1: det(a) != 0
{if (a[k, k] != 0) {a’ = a || b’ = b #1}
else perm(n, a, b, k, k+1: a’, b’ #1 | #2) } post 1: a’[k, k] != 0 & postLin(n, a, b, a’, b’)
perm(nat n, MATR(n) a, VEC(n) b, nat k, m:
MATR(n) a’, VEC(n) b’ : )
pre 1 k n & k<m n+1 &
i = k..m-1. a[i, k] = 0 & triaCol(n, k, a) pre 1: det(a) != 0
{ if (m>n) #2 else
if (a[m, k] != 0)
{
b’ = b for (j) {case k: b[m] case m: b[k]};
a’ = a for (i, j) {case (k, k..n): a[m, j] case (m, k..n): a[k, j]}
#1
}
else perm(n, a, b, k, m + 1: a’, b’ #1 : #2) } post 1: a’[k, k] != 0 & postLin(n, a, b, a’, b’)
norm(nat n, k, MATR(n) a, VEC(n) b: MATR(n) a’, VEC(n) b’) pre 1 k n & a[k, k] != 0 & triaCol(n, k, a)
{ b’ = b for (j) {case k: b[k] / a[k, k] };
a' = a for (i, j) {case (k, k..n): a[k, j] / a[k, k]} } post a’[k, k] = 1 & postLin(n, a, b, a’, b’)
subtrLines(nat n, k, MATR(n) a, VEC(n) b: MATR(n) a’, VEC(n) b’)
pre 1 k n & a[k, k] = 1 & triaCol(n, k, a)
{
b’ = b for (i) {case k+1..n: b[i] - b[k] a[i, k]};
a' = a for (i, j) {case (k+1..n, k..n): a[i, j] - a[k, j] a[i, k] }
} post triaCol(n, k+1, a) & postLin(n, a, b, a’, b’)
Solution(nat n, MATR(n) a, VEC(n) b: VEC(n) x ) pre n > 0 & triangle(n, a)
{ uniMat(n, a, b, n: VEC(n) x ) } post LinEq(n, a, b, x)
formula nulColl(nat n, k, MATR(n) a) =
j=k+1..n. i=1..j-1. a[i, j] = 0 uniMat(nat n, MATR(n) a, VEC(n) b, nat k: VEC(n) x ) pre n > 0 & triangle(n, a) & nulCol(n, k, a)
{ if (k = 1) x = b
else { subtrCol(n, a, b, k : MATR(n) c, VEC(n) d); uniMat(n, c, d, k-1: VEC(n) x )
}
} post LinEq(n, a, b, x)
subtrCol(nat n, MATR(n) a, VEC(n) b, nat k:
MATR(n) a’, VEC(n) b’) pre n > 0 & triangle(n, a) & nulCol(n, k, a)
{ b’ = b for (i) {case 1..k-1: b[i] - b[k] a[i, k]}; a' = a for (i, j) {case (1..k-1, k): 0 }
} post nulCol(n, k-1, a) & postLin(n, a, b, a’, b’)
На первом этапе трансформации реализуется склеивания.
Lin: a <- c; b <- d, x; TriangleMatr: a <- a’; b <- b’;
Jord: a <- c, e, g, a’; b <- d, f, h, b’; diagEl: a <- a’; b <- b’;
perm: a <- a’; b <- b’; norm: a <- a’; b <- b’; subtrLines: a <- a’; b <- b’; Solution: b <- x;
uniMat: a <- c; b <- d, x; subtrCol: a <- a’; b <- b’;
На втором этапе реализуется замена хвостовой рекурсии циклами. Результатом проведения двух этапов трансформации является следующая программа:
Lin(nat n, MATR(n) a, VEC(n) b: VEC(n) b : )
{ TriangleMatr(n, a, b: MATR(n) a, VEC(n) b : #2); Solution(n, a, b: VEC(n) b ) #1
}
TriangleMatr(nat n, MATR(n) a, VEC(n) b:
MATR(n) a, VEC(n) b : ); { Jord(n, a, b, 1: MATR(n) a, VEC(n) b : ) }
Jord(nat n, MATR(n) a, VEC(n) b, nat k: MATR(n) a, VEC(n) b : ) { for(;;) {
diagEl(n, a, b, k: MATR(n) a, VEC(n) b : #2); norm(n, k, a, b: MATR(n) a, VEC(n) b); subtrLines(n, k, a, b: MATR(n) a, VEC(n) b); if (k = n) #1
else k = k + 1
}
}
diagEl(nat n, MATR(n) a, VEC(n) b, nat k:
MATR(n) a, VEC(n) b : )
{ if (a[k, k] != 0) #1
else perm(n, a, b, k, k+1: a, b #1 | #2)
}
perm(nat n, MATR(n) a, VEC(n) b, nat k, m: MATR(n) a, VEC(n) b : )
{ for(;;) {
if (m>n) #2 else
if (a[m, k] != 0) {
b = b for (j) {case k: b[m] case m: b[k]};
a = a for (i, j) {case (k, k..n): a[m, j] case (m, k..n): a[k, j]} #1
}
else m = m + 1
}
}
norm(nat n, k, MATR(n) a, VEC(n) b: MATR(n) a, VEC(n) b)
{b = b for (j) {case k: b[k] / c[k, k] };
a = a for (i, j) {case (k, k..n): a[k, j] / a[k, k]}
}
subtrLines(nat n, k, MATR(n) a, VEC(n) b: MATR(n) a, VEC(n) b)
{b = b for (i) {case k+1..n: b[i] - b[k] a[i, k]};
a = a for (i, j) {case (k+1..n, k..n): a[i, j] - a[k, j] a[i, k] }
}
Solution(nat n, MATR(n) a, VEC(n) b: VEC(n) b ) { uniMat(n, a, b, n: VEC(n) b ) }
uniMat(nat n, MATR(n) a, VEC(n) b, nat k: VEC(n) b ) { for(;;) {
if (k = 1) return;
subtrCol(n, a, b, k : MATR(n) a, VEC(n) b); k = k - 1
}
}
subtrCol(nat n, MATR(n) a, VEC(n) b, nat k: MATR(n) a, VEC(n) b)
{b = b for (i) {case 1..k-1: b[i] - b[k] a[i, k]}; a = a for (i, j) {case (1..k-1, k): 0 }
}
На третьем этапе проведем подстановку следующую серию подстановок тел определений на место вызовов:
perm -> diagEl;
subtrLines, norm, diagEl -> Jord -> TriangleMatr -> Lin; subtrCol -> uniMat -> Solution -> Lin;
