Урок 8. Введение в редукцию графов
TRANSCRIPT
![Page 1: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/1.jpg)
1Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Глава 5. Системы исполнения функциональных программ5.3. Функциональные модели последовательных процессов
Рассмотрим простой язык императивного программирования без функций, переходов и сложных структур данных.
Выражения: Целые числа: 12 25 0
Простые переменные целого типа: x myInt
Унарные и бинарные операции с целыми результатами: (x+12) * (y-1)
Логические константы и выражения (но не переменные): not (x < 5)
Операторы:
Присваивание: x := x+1
Последовательное исполнение: begin s1; s2; ... end
Условный оператор: if b then s1 else s2
Пустой оператор: skip
Оператор цикла: while b do s
Программа начинает работу в состоянии, заданном совокупностью значений переменных(например, заданных оператором ввода данных), а результат программы – конечное состояние(например, выведенное в конце работы оператором вывода).
![Page 2: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/2.jpg)
2Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Рассмотрим программу вычисления факториала.
Пример программы.
begin f := 1; while n > 1 do begin f := f * n; n := n – 1 endend
В начальном состоянии существенно только значение переменной n; в конце работы результат определяется значением переменной f.
Прежде всего, переведем программу в вид, удобный для обработки.
data Expression = { представление выражений }data Operator = { представление операторов }data Context = { представление контекста переменных }
Два способа обработки и исполнения программы:
Интерпретация: interpret :: Operator -> Context -> Context Компиляция: compile :: Operator -> (Context -> Context)
На самом деле оба способа представлены одной и той же карринговой функцией!
![Page 3: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/3.jpg)
3Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Представление выражений и программ.
data Expression = Integral Int | Logical Bool | Variable String | Unary String Expression | Binary Expression String Expression
data Operator = Skip | Assignment String Expression | Sequence [Operator] | If Expression Operator Operator | While Expression Operator
type Context = [(String, Expression)]
interpret :: Operator -> Context -> Contexteval :: Expression -> Context -> Expression
eval v@(Integral n) _ = veval v@(Logical b) _ = veval (Variable x) ctx = assoc x ctxeval (Unary op ex) ctx = intrinsic op [eval ex ctx]eval (Binary e1 op e2) ctx = intrinsic op [eval e1 ctx, eval e2 ctx]
intrinsic "+" [(Integral a), (Integral b)] = Integral (a+b)intrinsic "-" [(Integral a)] = Integral (-a)intrinsic "and" [(Logical a), (Logical b)] = Logical (a && b)
intrinsic :: String -> [Expression] -> Expression
![Page 4: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/4.jpg)
4Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Исполнение операторов.
replace :: String -> Expression -> Context -> Context
replace x val = map (\(y,v) -> (y,if x == y then val else v))
replace "f" (Integral 20) [("n", (Integral 4)), ("f", (Integral 5))]
Например:
даст в результате [("n", (Integral 4)), ("f", (Integral 20))]
interpret :: Operator -> Context -> Context
interpret Skip ctx = ctxinterpret (Assignment x expr) ctx = replace x (eval expr ctx) ctxinterpret (Sequence []) ctx = ctxinterpret (Sequence (s:seq)) ctx = interpret (Sequence seq) (interpret s ctx)interpret (If expr s1 s2) ctx = case (eval expr ctx) of (Logical True) -> interpret s1 ctx (Logical False) -> interpret s2 ctxinterpret oper@(While expr s) ctx = case (eval expr ctx) of (Logical True) -> interpret oper (interpret s ctx) (Logical False) -> ctx
![Page 5: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/5.jpg)
5Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Пример компиляции и исполнения программы
begin f := 1; while n > 1 do begin f := f * n; n := n – 1 endend
program = Sequence [(Assignment "f" (Integral 1)), (While (Binary (Variable "n") ">" (Integral 1)) (Sequence [(Assignment "f" (Binary (Variable "f") "*" (Variable "n"))), (Assignment "n" (Binary (Variable "n") "-" (Integral 1)))])) ]
compile program - функция преобразования контекстов
interpret program [("f", (Integral 0)), ("n", (Integral 3))]
[("f", (Integral 6)), ("n", (Integral 0))]
![Page 6: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/6.jpg)
6Кубенский А.А. Функциональное программирование.
Глава 6. Введение в редукцию графов.
Глава 6. Введение в редукцию графов6.1. Представление лямбда-выражений в виде графов
Будем исходить из представления программ в виде структур данных расширенного лямбда-исчисления. Наша основная задача – корректно представить концепцию разделения переменных.
Константа c. c
Примитивная функция f. f
Лямбда-выражение λx.E.λ
x E
Применение функции E1 E2.@
E1 E2
Применение конструктора C x y z.C
x zy
![Page 7: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/7.jpg)
7Кубенский А.А. Функциональное программирование.
Особенности представления некоторых типов выражений.
Представление лямбда-выражений в виде графов (продолжение).
Глава 6. Введение в редукцию графов.
Частичное применений примитивных функций и конструкторов.
1+2 + 1 2 + 1
@
+ 1
@
2
@
+ 1
1 : lst : 1 lst
:
1 lst
: 1
@
: 1
или :
1 t
λ
t
![Page 8: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/8.jpg)
8Кубенский А.А. Функциональное программирование.
Представление лямбда-выражений в виде графов (продолжение).
Глава 6. Введение в редукцию графов.
Блоки let x = E1 in E2 и letrec x1 = E1;... xk = Ek in E.
let x = E1 in E2 (λx.E2) E1
E2
λ
x
@
E1
letrec x1 = E1;... xk = Ek in E – моделируется с помощью циклических графов.
![Page 9: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/9.jpg)
9Кубенский А.А. Функциональное программирование.
let twice = λf.λx.f (f x) in twice (λx.+ x 1) 2
Пример представления выражения в виде графа.
Глава 6. Введение в редукцию графов.
(λf.λx.f (f x)) (λx.+ x 1) 2
2
λ
x
λ
f
f
@
x
@
f
λ
@
@
x @
@
+ x
1
![Page 10: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/10.jpg)
10Кубенский А.А. Функциональное программирование.
• Нахождение самого левого из самых внешних редексов: проход по «левому гребню» графа.
Правила редукции графов.
Глава 6. Введение в редукцию графов.
2
x
x
@
succ
λ
@
• Копирование тела лямбда-выражения.
x
@
succ
• Подстановка аргумента вместо свободных вхождений переменной лямбда-выражения в тело.
• Замещение в дереве @-узла результатом «вычислений».
Некоторые особенности этой процедуры:• Тело лямбда-выражения копируется, чтобы его можно было переиспользовать; «мусор»
удаляется• Подстановка аргументов производится с помощью установки ссылок; тем самым
производится эффективное разделение переменных• Результат редукции замещает редуцируемое выражение, тем самым все ссылки на этот
результат будут иметь новое значение
![Page 11: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/11.jpg)
11Кубенский А.А. Функциональное программирование.
Пример редукции графов.
Глава 6. Введение в редукцию графов.
(λf.λx.f (f x)) (λx.+ x 1) 2
2
λ
x
λ
f
f
@
x
@
f
λ
@
@
x @
@
+ x
1
![Page 12: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/12.jpg)
12Кубенский А.А. Функциональное программирование.
Глава 6. Введение в редукцию графов.
2
λ
@
@
x @
@
+ x
1
Пример редукции графов.
(λf.λx.f (f x)) (λx.+ x 1) 2
@
@
+
1
3
4
![Page 13: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/13.jpg)
13Кубенский А.А. Функциональное программирование.
δ-редукция в графовом представлении
Глава 6. Введение в редукцию графов.
Если при проходе по левому гребню находим константу, то это – примитивная функция
2+
@
3
@
- сначала выполняем редукцию всех строгих аргументов;- потом формируем результат в соответствии с правилами этой примитивной функции;- результат замещает собой корень редекса.
@
@
*
612
![Page 14: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/14.jpg)
14Кубенский А.А. Функциональное программирование.
Общий алгоритм редукции графов (пока без учета рекурсии)
Глава 6. Введение в редукцию графов.
while (выражение не находится в СЗНФ) { спуск от корня по левому гребню до первой вершины, отличной от @-вершины; switch (тип вершины) { case (примитивная функция): if (число аргументов k > числа пройденных @-вершин) выражение находится в СЗНФ; else { редуцировать все строгие аргументы; сформировать результат согласно правилам примитивной функции; заменить k-ю @-вершину этим результатом; } break; case (λ-вершина): if (выше нет @-вершин) выражение находится в СЗНФ; else { создать копию тела с подстановкой (разделяемого) аргумента вместо свободных вхождений переменной λ-выражения; подставить результат вместо вершины редекса (первая @-вершина вверх по гребню); } break; default: // константа-значение или конструктор if (выше нет @-вершин) выражение находится в СЗНФ; else ошибка типа ! break; }}
![Page 15: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/15.jpg)
15Кубенский А.А. Функциональное программирование.
Использование вершин-синонимов
Глава 6. Введение в редукцию графов.
При выполнении редукций есть одна проблема, связанная с копированием: в теле функциипеременная может быть в корне. Тогда вместо подстановки ссылки на аргумент придется делатькопию вершины, представляющей аргумент.
+
@
λ@
x
1
2
x
@
x@
Можно вместо копирования вершины создавать «вершину-синоним» - «прозрачную» по ссылкам.
Θ
При прохождении вершины-синонима можно оптимизировать их количество, убирать двойные синонимы, заменять ссылки на синоним ссылками на саму вершину.
![Page 16: Урок 8. Введение в редукцию графов](https://reader036.vdocuments.pub/reader036/viewer/2022073119/55cb02b0bb61eb5d7a8b46e4/html5/thumbnails/16.jpg)
16Кубенский А.А. Функциональное программирование.
Использование вершин-синонимов (продолжение)
Глава 6. Введение в редукцию графов.
Аналогичная проблема возникает при применении примитивных функций-селекторов, которыене преобразуют, а просто выдают аргумент или его часть (например, head или tail).
head
head
@
@
:
:
1 nil
nil
head (cons (head (cons 1 nil)) nil)
Θ
Θ