
- •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)
Lin(nat n, MATR(n) a, VEC(n) b: VEC(n) b : )
{for(nat k = 1; ; k=k+1) {
if (a[k, k] != 0) #M1; nat m;
for(m = k +1;;m = m + 1) {
|
if (m>n) #2; |
|
if (a[m, k] != 0) break |
|
} |
|
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]} |
M1: |
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]} |
|
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] } |
|
if (k = n) break |
}
for(nat k = n; k != 1; k = k - 1) {
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 }
}
#1
}
Lin(nat n, MATR(n) a, VEC(n) b: VEC(n) b : )
{for(nat k = 1; ; k=k+1) {
if (a[k, k] != 0) #M1; nat m;
for(m = k +1;;m = m + 1) {
if (m>n) #2;
if (a[m, k] != 0) break
}
real t = b[k]; b[k] = b[m]; b[m] = t;
for (nat j=k; k<=n; k=k+1) { t = a[k, j]; a[k, j] = a[m, j]; a[m, j] = t } M1: b[k] = b[k] / c[k, k];
for (nat j=k; j<=n; j=j+1) a[k, j] = a[k, j] / a[k, k]; for (nat i=k+1; i<=n; i=i+1) b[i] = b[i] - b[k] a[i, k];
for (nat i=k+1; i<=n; i=i+1) for (nat j=k; j<=n; j=j+1)
a[i, j] = a[i, j] - a[k, j] a[i, k]; if (k = n) break
|
} |
|
for(nat k = n; k != 1; k = k - 1) { |
|
for (nat i=1; i<k; i=i+1) b[i] = b[i] - b[k] a[i, k]; |
|
for (nat i=1; i<k; i=i+1) a[i, k] = 0 |
|
} |
} |
#1 |
На четвертом этапе раскроем операции с массивами |
Нетривиальным является устранение неиспользуемых вычислений : Lin(nat n, MATR(n) a, VEC(n) b: VEC(n) b : )
{for(nat k = 1; ; k=k+1) {
if (a[k, k] != 0) #M1; nat m;
for(m = k +1;;m = m + 1) {
if (m>n) #2;
if (a[m, k] != 0) break
}
real t = b[k]; b[k] = b[m]; b[m] = t;
for (nat j=k; k<=n; k=k+1) { t = a[k, j]; a[k, j] = a[m, j]; a[m, j] = t } M1: b[k] = b[k] / c[k, k];
for (nat j=k+1; j<=n; j=j+1) a[k, j] = a[k, j] / a[k, k]; for (nat i=k+1; i<=n; i=i+1) b[i] = b[i] - b[k] a[i, k];
for (nat i=k+1; i<=n; i=i+1) for (nat j=k+1; j<=n; j=j+1)
a[i, j] = a[i, j] - a[k, j] a[i, k]; if (k = n) break
}
for(nat k = n; k != 1; k = k - 1) for (nat i=1; i<k; i=i+1) b[i] = b[i] - b[k] a[i, k];
#1
}