ЛОГИЧЕСКОЕ ПРОГРАММИРОВАНИЕ Игорь Александрович Бессмертный +7 921 9563154 igor_bessmertny@hotmail.com 1 Поиск доказательств в пропозициональной логике и логике первого порядка • Логическое программирование – это декларативный стиль программирования, где программист говорит, что он хочет вычислить, но не указывает явно, как это вычислить. • Задача интерпретатора (или компилятора) – самостоятельно построить требуемые вычисления. • Процедурный стиль программирования означает, что программист явно описывает все шаги вычислений 2 Простая логическая программа volkhov → windy kronstadt → windy kronstadt → petersburg petersburg → rainy rainy ˄ windy → umbrella_useless kronstadt 3 Простая логическая программа Действительно ли зонтик бесполезен? 4 Простая логическая программа Текст программы на Прологе: windy :- volkhov. windy :- kronstadt. petersburg :- kronstadt. rainy :- petersburg. umbrella_useless :- windy, rainy. kronstadt. 5 Простая логическая программа (модифицированная) Текст программы на Прологе: windy :- volkhov. windy :- kronstadt. petersburg :- kronstadt. rainy :- petersburg. umbrella_useless :- windy, rainy. kronstadt. volkhov :- fail. Запрос : ?- umbrella_useless. yes 6 Задача логического программирования Почему этот ответ верный? (логическое следствие) Как Пролог вычисляет ответ? (поиск доказательства) 7 Поиск доказательства J 1 ,..., J n R J Если J1 и…и Jn , то J, если правило R верно. n n n a +b ≠c при n>2 = 357 лет напряженной работы! 8 Логическая последовательность Формула F истинна в интерпретации T T F тогда и только тогда, когда вытекает из стандартных таблиц истинности Формула G – логическое следствие формул F1 , F2 , , Fn если T F1 и …и T G Fn то T G 9 ПРИМЕР Логическое следствие: poor happy, happy poor (всего 4 интерпретации, для всех формулы слева и справа верны) Логически не следует: poor happy, poor happy (если poor=false, а happy=true, левая часть истинна, а правая ложна) 10 ИДЕЯ ЛОГИЧЕСКОЙ ПРОГРАММЫ Логическая программа – список формул F1, F2, …, Fn Цель – формула G. Задача машины вывода – определить F1 , F2 , , Fn G Если это истина, то система отвечает yes, иначе – no 11 СЕМАНТИЧЕСКАЯ ПРОВЕРКА ЛОГИЧЕСКОГО СЛЕДСТВИЯ Таблица истинности Интерпретация 1 … Интерпретация 2n n – число атомов в программе и запросе Экспоненциальный рост сложности => задача нерешаема 12 ПУТЬ К РАЗРЕШИМОСТИ ПРОБЛЕМЫ • Ограничить формулы в программах определенными дизъюнктами (definite clauses) • Использовать поиск доказательства для определения логической последовательности (использовать синтаксические методы вместо семантических методов проверки таблиц истинности) 13 ОПРЕДЕЛЕННЫЙ ДИЗЪЮНКТ q p1 ˄…˄ pk → q (в Прологе факт q.) (в Прологе правило q :- p1,…, pk.), где p1,…, pk – атомы (атомарные утверждения). Логическая программа – это список F1, F2, …, Fn определенных дизъюнктов. Цель – это список g1,…, gm атомов Задача системы логического вывода - доказать F1, F2, …, Fn g1,…, gm 14 СИСТЕМА ЛОГИЧЕСКОГО ВЫВОДА F1, . . . , Fn – аксиомы Правило: p1 p2 ... pk p1 p2 ... pk q (Backchain) q Доказательство цели g – дерево цепочек обратного вывода, где каждый лист – определенный дизъюнкт Fi, а цель g – корень. 15 ПРИМЕР ВЫВОДА kronst piter rainy kronst windy piter windy rainy umb _ useless windy rainy umbrella _ useless 16 ТО ЖЕ В ЛИНЕЙНОЙ ФОРМЕ 1. 2. 3. 4. 5. 6. 7. 8. 9. kronstadt аксиома kronstadt windy аксиома windy обратный вывод из 1,2 kronstadt petersburg аксиома petersburg обратный вывод из 1,4 petersburg rainy аксиома rainy обратный вывод из 5,6 windy ˄ rainy → umbrella_useless аксиома umbrella_useless обратный вывод из 3,7,8 17 ПОСТРОЕНИЕ ДОКАЗАТЕЛЬСТВА • Снизу вверх: Чтобы доказать g, начинаем с аксиом и применяем все правила, пока не достигнем цели g (прямой вывод) • Сверху вниз: Чтобы доказать g, применяем правила в обратном направлении, пока не найдем необходимый набор аксиом (обратный вывод) – используется в Прологе («верх» и «низ» относятся к проблеме, на бумаге все наоборот) 18 ПРИМЕР ВЫВОДА В ПРОЛОГЕ Текущая цель: [umbrella_useless]. Это не аксиома, но есть правило: windy ˄ rainy → umbrella_useless Заменяем текущую цель на [windy, rainy] 19 ПРИМЕР ВЫВОДА В ПРОЛОГЕ Текущая цель: [windy, rainy]. Первый атом цели не аксиома, но есть правила: volkhov → windy kronstadt → windy Применяем первое правило и заменяем текущую цель на [volkhov, rainy] 20 ПРИМЕР ВЫВОДА В ПРОЛОГЕ Текущая цель: [volkhov, rainy]. Первый атом цели не аксиома, и нет правила. Используем бэктрекинг и восстанавливаем текущую цель [windy, rainy] 21 ПРИМЕР ВЫВОДА В ПРОЛОГЕ Текущая цель: [windy, rainy]. Первый атом цели не аксиома, и мы уже знаем, что правило volkhov→ windy не порождает решения windy. Применяем второе правило kronstadt → windy Заменяем текущую цель на [kronstadt , rainy] 22 ПРИМЕР ВЫВОДА В ПРОЛОГЕ Текущая цель: [kronstadt , rainy]. Первый атом цели – аксиома. Удаляем kronstadt из списка цели. Заменяем текущую цель на [rainy] 23 ПРИМЕР ВЫВОДА В ПРОЛОГЕ Аналогичным образом получаем: Текущая цель: [rainy] Текущая цель: [petersburg] Текущая цель: [kronstadt] Текущая цель: [] Пустой список означает, что цель достигнута, и первоначальная цели umbrella_useless истинна 24 ОСНОВНЫЕ ПОНЯТИЯ • • • • • Пропозициональная логика Логическое следствие Определенный дизъюнкт Система (машина) логического вывода Пропозициональное правило обратного вывода • Процедура доказательства в Прологе 25 ЛОГИЧЕСКОЕ ПРОГРАММИРОВАНИЕ (НЕ)ПОЛНОТА ПРОПОЗИЦИОНАЛЬНОГО ПРОЛОГА 26 ОПРЕДЕЛЕННЫЙ ДИЗЪЮНКТ (вспоминаем…) q (в Прологе факт q.) p1 ˄…˄ pk → q (в Прологе правило q :- p1,…, pk.), где p1,…, pk – атомы (атомарные утверждения). Логическая программа – это список F1, F2, …, Fn определенных дизъюнктов. Цель – это список g1,…, gm атомов Задача системы логического вывода - доказать F1, F2, …, Fn g1,…, gm 27 СИСТЕМА ЛОГИЧЕСКОГО ВЫВОДА F1, . . . , Fn – аксиомы Правило: p1 p2 ... pk p1 p2 ... pk q (Backchain) q Доказательство цели g – дерево цепочек обратного вывода, где каждый лист – определенный дизъюнкт Fi, а цель g – корень. 28 ПРИМЕР ЛОГИЧЕСКОЙ ПРОГРАММЫ hotterSun → warmerClimate carbonIncrease → warmerClimate warmerClimate → iceMelts iceMelts → albedoDecrease albedoDecrease → warmerClimate carbonIncrease 29 ВЫВОД ЦЕЛИ iceMelts carbonIncrease carbonIncrease warmerClimate warmerClimate iceMelts warmerClimate iceMelts 30 ПОИСК ДОКАЗАТЕЛЬСТВА СВЕРХУ ВНИЗ Список [g1,…, gm] – текущая цель 1. Если g1 – аксиома, то g1 удаляется из списка. 2. Иначе найти в программе правило вида h1 ˄…˄ hk → g1 Заменить g1 на h1, …, hk . Новая цель: [h1, …, hk,g1,…, gm] Таким образом порождается дерево поиска. Цель доказательства – найти ветвь, лист которой заканчивается пустым списком []. 31 ДЕРЕВО ПОИСКА ДЛЯ ЦЕЛИ [iceMelts] [iM] [wC] [hS] [cI] [aD] [] [iM] [wC] [hS] [cI] [aD] [] . . . 32 ПОИСК ДОКАЗАТЕЛЬСТВА В ПРОЛОГЕ Пролог использует поиск сначала в глубину: • Поиск всегда идет на еще не посещенный дочерний узел, если таковой есть. • Если такого узла нет, происходит возврат на последний посещенный узел, у которого есть еще не посещенный дочерний узел. Узлы посещаются в порядке их следования в программе. 33 ДЕРЕВО ПОИСКА ДЛЯ ЦЕЛИ [iceMelts] [iM] (1) [wC] (2) [hS] (3) [cI] (4) [aD] [ ] (5) [iM] [wC] [hS] [cI] [aD] [] . . . 34 ПЕРЕУПОРЯДОЧЕНИЕ ПРОГРАММЫ МОЖЕТ ПОВЫСИТЬ ЭФФЕКТИВНОСТЬ… carbonIncrease → hotterSun → warmerClimate → iceMelts → albedoDecrease → warmerClimate warmerClimate iceMelts albedoDecrease warmerClimate carbonIncrease 35 НОВОЕ ДЕРЕВО ПОИСКА ДЛЯ ЦЕЛИ [iceMelts] [iM] (1) [wC] (2) [cI] (3) [hS] [aD] [ ] (4) [iM] [wC] [cI] [hS] [aD] [] . . . 36 … ИЛИ ПОНИЗИТЬ ЭФФЕКТИВНОСТЬ … hotterSun → albedoDecrease → carbonIncrease → warmerClimate → iceMelts → warmerClimate warmerClimate warmerClimate iceMelts albedoDecrease carbonIncrease 37 … КАТАСТРОФИЧЕСКИ ! [iM] (1) [wC] (2) [hS] (3) [ aD] (4) [cI] [ iM] (5) [] [wC] (6) [hS] (7) [ aD] (8) [cI] . . (∞) . [] 38 В ПРОЛОГЕ Программа: warmerClimate :- hotterSun. warmerClimate :- albedoDecrease. warmerClimate :- carbonIncrease. iceMelts :- warmerClimate. albedoDecrease :- iceMelts. carbonIncrease. hotterSun :- false. Запрос: | ?- iceMelts. ! Resource error: insufficient memory 39 НЕПОЛНОТА ВЫВОДА В ПРОЛОГЕ Правильный ответ на запрос iceMelts – yes, потому что имеется соответствующая логическая последовательность (независимо от порядка следования аксиом). Первоначальный вариант программы давал верный ответ. Процедура поиска решений в Прологе не обладает полнотой: она не всегда производит решение, даже если оно есть 40 Нотация Пролога Пусть F1, F2, …, Fn – определенные дизъюнкты (аксиомы в программе) • Атом g это логическое следствие из F1, F2, …, Fn F1, F2, …, Fn g • Атом g выводѝм из F1, F2, …, Fn F1, F2, …, Fn ├ g • Атом g выводѝм на Прологе из F1, F2, …, Fn F1, F2, …, Fn ├ Prolog g Следовательно, вывод Пролога успешный 41 ФУНДАМЕНТАЛЬНЫЕ СВОЙСТВА Корректность поиска в Прологе F1, F2, …, Fn ├ Prolog g следует F1, …, Fn ├ g Явность системы вывода из F1, F2, …, Fn ├ g следует F1, …, Fn g Полнота системы вывода из F1, F2, …, Fn g следует F1, …, Fn ├ g Неполнота системы вывода Пролога из F1, F2, …, Fn g не следует F1, …, Fn ├ Prolog g 42 ФУНДАМЕНТАЛЬНЫЕ СВОЙСТВА Корректность поиска в Прологе (докажем в третью очередь) из F1, F2, …, Fn ├ Prolog g следует F1, …, Fn ├ g Явность системы вывода (докажем в первую очередь) из F1, F2, …, Fn ├ g следует F1, …, Fn g Полнота системы вывода (докажем во вторую очередь) из F1, F2, …, Fn g следует F1, …, Fn ├ g Неполнота системы вывода Пролога (уже доказана) F1, F2, …, Fn g не следует F1, …, Fn ├ Prolog g 43 ДОКАЗАТЕЛЬСТВО ЯВНОСТИ Следует доказать, что из F1, F2, …, Fn ├ g следует F1, …, Fn g Пусть F1, …, Fn ├ g. Пусть Т – интерпретация, для которой Т F1 и … и Т Требуется доказать, что Т Fn g. Предположим, что П – дерево вывода для g. На следующем слайде покажем, что для каждого атома q, встречающегося в П, выполняется T q 44 ДОКАЗАТЕЛЬСТВО ЯВНОСТИ (продолжение) Покажем, что для каждого атома q, встречающегося в П, выполняется T q Исходя из листьев (аксиом) в П сверху вниз, распространяем свойство T q. • Если q - аксиома (одна из F1, …, Fn ), T q безусловно. • В противном случае p1 ... pk p1 ... pk q q где p1˄ … ˄ pk → q это аксиома. Распространяя это по дереву, T p1 и … и T pk . Поскольку p1˄ … ˄ pk → q – аксиома, T p1 ˄ … ˄ pk → q Следовательно, T q. 45 ОСНОВНЫЕ ПОНЯТИЯ • • • • • • Дерево поиска для доказательства сверху вниз Стратегия поиска в Прологе сначала вглубь Неполнота стратегии поиска Пролога Корректность поиска в Прологе Явность поиска доказательств Полнота системы вывода 46 ЛОГИЧЕСКОЕ ПРОГРАММИРОВАНИЕ СТРУКТУРЫ ДАННЫХ В ПРОЛОГЕ 47 СПИСКИ Два конструктора: nil и cons Список a,b,c = cons(a, cons(b, cons(c, nil))) В нотации Пролога nil = []; cons = [h|t] [a,b,c] = [a | [b | [c | [] ]]] или [a,b | [c, []]] list([]). list([X | Xs]) :- list(Xs). 48 ЧЛЕНСТВО В СПИСКЕ member ( X , cons( X , Ys ) member ( X , Ys ) member ( X , cons(Y , Ys )) В синтаксисе Пролога это выглядит следующим образом: member(X, [X | Ys]). member(X, [Y | Ys]) :- member(X, Ys). 49 НЕРАВЕНСТВО ?- member(a, [a, b, a, c]). завершится успехом дважды → возможно непредсказуемое поведение программы. Найти первое вхождение: member ( X , cons( X , Ys ) X Y member ( X , Ys ) member ( X , cons(Y , Ys )) 50 НЕРАВЕНСТВО member1(X, [X | Ys]). member1(X, [Y | Ys]) :- X \= Y, member1(X, Ys). Может проблемой, если хотя бы одна переменная не определена. Решение: 1. Не допускать неравенства, если хотя бы один операнд – свободная переменная. 2. Откладывать проверку до тех пор, пока переменные не получат значения (требует продвинутой операционной семантики). 51 ПРЕДИКАТЫ ДЛЯ ОБРАБОТКИ СПИСКОВ Префикс prefix([], Ys). prefix([X | Xs], [X|Ys]) :- prefix(Xs, Ys). Суффикс suffix(Xs, Xs). suffix(Xs, [Y | Ys]) :- suffix(Xs, Ys). 52 ПРЕДИКАТЫ ДЛЯ ОБРАБОТКИ СПИСКОВ Префикс prefix([], Ys). prefix([X | Xs], [X|Ys]) :- prefix(Xs, Ys). ?Xs Xs Xs Xs Xs prefix(Xs,[a,b,c,d]). = []; = [a]; = [a,b]; = [a,b,c]; = [a,b,c,d]. 53 ПРЕДИКАТЫ ДЛЯ ОБРАБОТКИ СПИСКОВ Объединение списков append([], Ys, Ys). append([X|Xs],Ys,[X|Zs]):- append(Xs,Ys,Zs). Префикс и суффикс – частные случаи объединения prefix2(Xs, Ys) :- append(Xs, _, Ys). suffix2(Xs, Ys) :- append(_, Xs, Ys). 54 СОРТИРОВКА Быстрая сортировка quicksort([], []). quicksort([X0|Xs], Ys) :partition(Xs, X0, Ls, Gs), quicksort(Ls, Ys1), quicksort(Gs, Ys2), append(Ys1, [X0|Ys2], Ys). 55 СОРТИРОВКА (продолжение) partition([], _, [], []). partition([X|Xs], X0, [X|Ls], Gs) :X =< X0, partition(Xs, X0, Ls, Gs). partition([X|Xs], X0, Ls, [X|Gs]) :X > X0, partition(Xs, X0, Ls, Gs). Сравнение X > X0 лишнее? Без него В случае бэктрекинга результат может быть непредсказуем: ?- quicksort([2,1,3], Ys) ошибочно возвратит Ys=[2,1,3] в качестве альтернативного решения 56 УСЛОВНЫЕ УТВЕРЖДЕНИЯ Рассмотрим minimum(X, Y, X) :- X =< Y. minimum(X, Y, Y) :- X > Y. Можно использовать следующую конструкцию: A -> B ; C Если цель А успешна, выполняется B, иначе C minimum(X, Y, Z) :- X =< Y -> Z = X ; Z = Y. Сокращенная форма A -> B эквивалентна A -> B ; fail 57 ОТСЕЧЕНИЕ Рассмотрим minimum(X, Y, Z) :- X =< Y, !, Z = X. minimum(X, Y, Y). Если первый предикат успешен, второй выполняться не будет. Если сравнение в первом предикате завершится неудачей, очередь до отсечения (!) не дойдет. Выполнится второй предикат. 58 ОТСЕЧЕНИЕ Действие отсечений может быть неочевидным и становиться источником многих ошибок, поскольку их интерпретация зависит скорее от операционного поведения программы, чем от логического прочтения программы. 59 КРАСНОЕ И ЗЕЛЕНОЕ ОТСЕЧЕНИЯ minimum(X, Y, Z) :- X =< Y, !, Z = X. minimum(X, Y, Y) :- X > Y. - Это зеленое отсечение. Логика программы не меняется. minimum(X, Y, Z) :- X =< Y, !, Z = X. minimum(X, Y, Y). - Это красное отсечение. Логика программы меняется, если отсечение убрать. 60 А ЭТО НЕКОРРЕКТНЫЙ КОД minimum(X, Y, X) :- X =< Y, !. minimum(X, Y, Y). ?- minimum(5,10,10). Yes (унификация с первым утверждением заканчивается неудачей и срабатывает второе утверждение) 61 ОТРИЦАНИЕ КАК НЕУДАЧА (NEGATION AS FAILURE) Реализация отрицания: \+(A) :- A, !, fail. \+(A). Если A=истина, то ⌐ A=ложь Если A=ложь, второе утверждение истинно (без проверки). 62 ОТРИЦАНИЕ КАК НЕУДАЧА (NEGATION AS FAILURE) Проблема: Режим использования переменных в цели ?- \+(X = a). no (не существует терма, который бы не был равен константе a) В то время как ?- \+(b = a). yes 63 АРИФМЕТИКА В ПРОЛОГЕ length([], 0). length([X|Xs], N) :length(Xs, N1), N is N1+1. factorial(0,1). factorial(N,F) :- N1 is N-1, factorial(N1,F1), F is F1*N. (проблема: нехвостовая рекурсия) 64 ОСНОВНЫЕ ПОНЯТИЯ • • • • • Список Неравенство Отсечение Красное и зеленое отсечения Отрицание как неудача 65