2. Системы, способные упростить или заменить
работу специалиста-эксперта в какой-то
предметной области.
Примеры:
G2
MYCIN
PROSPECTOR
Яндекс-Гуру
3. Эксперт
База знаний
(множество
Пользователь
правил)
Механизм
логического Рабочая память
вывода Инженер по знаниям
В классической продукционной экспертной системе:
• База знаний представляет собой множество правил ЕСЛИ-ТО (продукций);
• Рабочая память представляет собой множество пар атрибут-значение (троек
объект-атрибут-значение), описывающих состояние решаемой задачи;
• Механизм логического вывода – это поиск в пространстве состояний
множества комбинаций рабочей памяти, переходы в котором задаются
правилами.
4.
5. • Дерево (связный ациклический граф) И-ИЛИ
• Каждая вершина дерева транслируется в
продукционное правило (пары <антецендент,
консеквент>)
• ЕСЛИ цвет - рыжевато-коричневый И узор –тёмные
пятна И класс – млекопитающее И отряд – хищник
ТО животное - обезьяна
• Листья дерева соответствуют элементарным
фактам, которые являются исходными для решения
задачи
6. Конфликтное Разрешение
множество конфликта
Отбор
применимых Применяемое
правил правило
Цель
получена? Применение
правила
Рабочая
База знаний
область
7. первое по тексту правило;
система приоритетов;
правило с максимальным (минимальным)
числом посылок;
правило с максимальным числом заключений;
…
8. Прямой вывод (управляемый фактами)
• Движение по дереву снизу вверх (от фактов)
• Необходимо знание начальных фактов
Обратный вывод (управляемый целями)
• Движение по дереву сверху вниз
• Выдвигаем гипотезу, пытаемся ее доказать
• Пользователю задаются вопросы для уточнения фактов
Комбинированный вывод
9. Естественное представление правил – правила
могут формулироваться даже экспертами
самостоятельно.
Возможность контроля непротиворечивости базы
знаний на этапе добавления правил.
Прозрачный и простой механизм логического
вывода.
Очевидный механизм объяснений.
10. 2 варианта реализации:
напрямую кодирование правил на Прологе;
создание «оболочки» экспертной системы со
специализированным языком представления
знаний.
19. Графом (точнее, направленным графом) называется пара
< U ,V > , где U— множество вершин, V ⊆ U × U — множество
дуг.
В отличие от конечных графов, которые могут быть заданы
матрицей смежности, мы будем рассматривать потенциально
бесконечные графы, задаваемые генератором вершин
move/2(in,out) G =< U ,V > a ∈U b ∈U
Путем в графе
{ xi } i =0n
из вершины , xi ⊂ U в вершинуa, xn = b
x0 =
называется>∈V
∀i < xi −1, xi последовательность , где
и
Задача поиска в графе ставится следующим образом: Пусть
имеется граф G, заданный предикатом move/2. Необходимо по
двум заданным вершинам a и b найти все пути (один путь,
кратчайший путь и т.д.) из a в b в графе G.
20.
21.
22.
23.
24. Функциональные языки:
Компактный синтаксис для списков, n-ок (tuples),
вариантных типов.
Логические языки:
Компактный синтаксис для списков, n-ок (tuples),
вариантных типов.
Возможность перебора и поиска различных
решений, заложенная в язык.
25. Запрос (целевое утверждение) сопоставляется
(унифицируется) с головами имеющихся в
программе правил и фактов.
Начиная с первого найденного правила, целевое
утверждение подменяется правой частью правила
(с учетом замены переменных).
Если встречается неуспех (правило не находится),
то происходит откат (backtracking).
26. [a] — очередь из одной исходной вершины
[a,b]
[a,b,c], [a,b,d]
[a,b,d], [a,b,c,d]
[a,b,c,d], [a,b,d,e], [a,b,d,f]
[a,b,d,e], [a,b,d,f], [a,b,c,d,e], [a,b,c,d,f]
[a,b,d,f], [a,b,c,d,e], [a,b,c,d,f] — тупиковый
путь [a,b,d,e] убирается из очереди
[a,b,c,d,e], [a,b,c,d,f], [a,b,d,f,g]
[a,b,c,d,f], [a,b,d,f,g] — тупиковый путь
[a,b,c,d,e] убирается из очереди
[a,b,d,f,g], [a,b,c,d,f,g]
[a,b,c,d,f,g] — получено первое решение
[a,b,d,f,g], убирается из очереди
[] — получено второе решение [a,b,c,d,f,g],
убирается из очереди
27. ?- findall(X, prolong([a,b],X), L).
L = [a,b,c],[a,b,d]
Если prolong([a,b],X) завершается неуспехом (тупик),
то findall также завершается неуспехом
28. path(X,Y,P):- bdth([[X]],Y,P).
bdth([[X|T]|_],X,[X|T]).
bdth([P|QI],X,R) :-
findall(Z,prolong(P,Z),T),
append(QI,T,QO),!,
bdth(QO,X,R).
bdth([_|T],Y,L) :- bdth(T,Y,L).
Первым находит кратчайший путь
Алгоритм выглядит менее естественно, требует явного
хранения путей в очереди и рассмотрения множественных вариантов
Низкая степень декларативности
Позволяет искать в путях с циклами
29.
30. В глубину В ширину
Память O(lmax) O(bl)
Время O(blmax) = O(1+b+b2+…+bl)
Только контуры без Может
петель использоваться
для нахождения путей
с
циклами
Порядок нахождения Первым находится
путей определён move/2 кратчайший путь
Даже если есть короткий Если известен
путь – поиск может уйти кратчайший путь – он
от него далеко находится быстро
32. Чтобы избежать зацикливания поиска в ширину,
ограничим глубину погружения параметром
DepthLimit
Если постепенно увеличивать этот параметр на 1,
то получим поиск, в котором находится первым
кратчайший путь
search_id(Start,Finish,Path,DepthLimit) :-
depth_id([Start],Finish,Path,DepthLimit).
depth_id([Finish|T],Finish,[Finish|T],_).
depth_id(Path,Finish,R,N) :- N>0,
prolong(Path,NewPath), N1 is N-1,
depth_id(NewPath,Finish,R,N1).
33. search_id(Start,Finish,Path):-
integer(Level),
search_id(Start,Finish,Path,Level).
integer(1).
integer(M) :- integer(N), M is N+1.
Сложность:
Для пути длины l поиск происходит l+1 раз
Первая вершина обходится (l+1) раз, второй уровень – l раз и т.д.
(l+1)*1 + l*b + (l-1)*b2 + … + 1*bl = O(bl)
Поиск в глубину по сложности не сильно превосходит поиск в ширину,
сохраняя все его положительные стороны и исключая требования к памяти.
34.
35. move(s(A,B,down,YN),s(C,B,down,YN)) :- vertex(C).
move(s(A,A,down,YN),s(B,B,down,YN)) :- vertex(B).
move(s(A,A,UD,YN),s(A,A,DU,YN)) :-
permute([DU,UD],[down,up]).
move(s(e,e,up,no),s(e,e,up,yes)).
Проследите за перемещением обезьяны!
Реальные перемещение не будут совпадать с
последовательностью вызовов move, поскольку будут откаты
В ширину vs. в глубину vs. погружение – ответ сразу не очевиден!
36.
37.
38. Алгоритмы поиска (в особенности поиск в глубину)
эффективно реализуются на языках логического
программирования
Базовые алгоритмы поиска обладают
взаимоисключающими достоинствами и
недостатками
Алгоритм поиска с заглублением сочетает в себе
достоинства обоих методов, хотя и производит
исключительно много ненужных вычислений
Чтобы решать реальные задачи, нужно иметь
методы поиска, использующие знания о
направлении поиска.
79. Парадигма программирования, которая
рассматривает выполнение программы как
вычисление математических функций
(выражений)
Неизменяемые данные, нет состояния среды
Стиль программирования, позволяющий
писать программы, свободные от ошибок
Язык программирования F# (и целое
семейство «странных» языков вместе с ним:
ML, Haskell, …)
80. Императивное – мы говорим компьютеру, как
решать задачу (что делать)
Основной акцент – манипулирование ячейками
памяти
◦ Оператор присваивания
Функции как способ декомпозиции задачи на
более простые
81. 0000 0A 12 1F 4B C3 E0 EE F1
0008 C3 1D 23 17 F2 00 0C 0D
0010 …
MOV AX, [ARG1]
ADD AX, [ARG2]
MOV [RES], AX
JMP NEXT
ARG1: DB 10
ARG2: DB 20
1954-57 г., Дж.Бэкус RES: DB 0
NEXT: …
• FORTRAN
S = 0
• язык ассемблера DO 10 I=1,10
S = S + I*I
• машинные коды 10 CONTINUE
• программирование переключателей
1950 1960 1970 1980 1990 2000 2010
Первый язык программирования высокого уровня – ФОРТРАН – был создан Дж.Бэкусом, чтобы
математики могли программировать на уровне формул.
82. Вычисление факториала:
function fact(x:integer):integer; let rec fact x =
var i, r : integer; if x=1 then 1
begin else x*fact(x-1);;
r:=1;
for i:=1 to x do r:=r*i; let rec fact = function
fact:=r 1 -> 1
end; | x -> x*fact(x-1);;
Pascal F#
83. Определение функции похоже на математическое определение
факториала
◦ Функциональное программирование имеет очень четкую
математическую основу
◦ Рассуждение о программах: доказательство корректности, …
Определение последовательности действий – рекурсивно
◦ При умелом программировании не ведет к падению
эффективности (компилятор сводит к итерации)
Отсутствует оператор присваивания
◦ let имеет другую семантику – связывание имен
◦ Будучи один раз связанным, имя не может менять свое
значение (в рамках области видимости)
◦ А это значит – нет побочных эффектов!
◦ Раз в императивной программе 90% - это операторы
присваивания, то функциональные программы на 90%
короче!
84. function fact(x:integer):integer;
begin
if x=1 then fact:=1
else fact:=x*fact(x-1)
end;
Это не «чистая» императивная программа.
В «чистых» императивных языках (ФОРТРАН) нет
рекурсии
Нет операторов присваивания
«:= » -это возврат результата из функции, а не
присваивание
85. Описание решения сложной задачи с
помощью множества простых шагов
Основная проблема – борьба со сложностью
Способы борьбы со сложностью:
◦ Декомпозиция («разделяй и властвуй»)
◦ Абстракция («не обращай внимание на мелочи»)
Как это воплощено в современных языках:
◦ Структурное программирование,
процедуры/функции
◦ Объектная ориентированность (наследование,
полиморфизм)
86. Какие способы комбинирования функций
доступны в традиционном
программировании?
function myexp(x:real):real;
var s : real;
i : integer;
begin
s:=0; Вызов
for i:=0 to 10 do
s:=s+taylor(x,i);
end;
function taylor(x : real, i:integer):real;
begin
taylor:=power(x,i)/fact(i); Композиция
end;
87. let rec iter f a b i =
f(f(f(…f(i,b),b-1)),…,a+1),a)
if a>b then i
else f (iter f (a+1) b i) a;;
let pow x n = iter (fun y i -> y*x) 1 n 1.0;;
let fact n = iter (fun y i -> y*(float i)) 1 n 1.0;;
let taylor x n = pow x n / fact n;;
let myexp x =
iter (fun y n -> y+taylor x n) 0 15 0.0;;
Более богатые возможности композиции за счет рассмотрения «функций-как-
данных»
iter – функциональная абстракция, лежащая в основе вычисления myexp, pow, fact
и др.
iter – может быть получено как частный случай абстракции
let iter f a b i = fold_left f i [a..b];;
88. fold_left
MyExp
iter
Taylor
Pow Fact
При этом:
◦ Технология мемоизации и ленивых вычислений могут увеличить
эффективность вычисления факториала и степени до линейной, за
счет запоминания предыдущих результатов вычислений
◦ Функционально-декомпозированный (более простой для человека)
алгоритм будет обладать такой же эффективностью, что и более
сложный алгоритм вычисления суммы в одном цикле (домножение
предыдущего слагаемого на фактор)
89. Сравните:
function sum_even(L:List):integer;
var s : integer;
begin
s:=0;
foreach (var x in L) do
if x mod 2 = 0 then s:=s+x;
sum_even:=s;
end;
let sum_even L = sum(filter (fun x->x%2==0) L);;
90. Императивный подход
На первый взгляд – большая эффективность по памяти (не
создается копия списка), по времени (один проход по списку)
Для определения суммы нечетных элементов придется
переписывать функцию
Функциональный подход
Высокий уровень абстракции -> суммирование нечетных
элементов получается автоматически
Проще для программиста
Пусть компилятор заботится об эффективности!
Большая эффективность при параллельных вычислениях
(возможность распараллеливания, поскольку sum и filter не
имеют зависимостей по данным)
При использовании ленивых вычислений – получаем
однопроходный алгоритм, эквивалентный итерационному!
91. Мы описываем функции, работающие над
данными – система программирования решает,
как их вычислять!
let rec fact = function
1 -> 1
| x -> x*fact(x-1);;
let sum_even L = sum(filter (fun x->x%2==0) L);;
var res = (from x in L where (x%2==0) select x^2).sum();
92. void quickSort (int a[], int l, int r)
{
int i = l;
int j = r;
int x = a[(l + r) / 2];
do {
while (a[i] < x) i++;
while (x < a[j]) j--;
if (i <= j)
{ int temp = a[i];
a[i++] = a[j];
a[j--] = temp; }
}
while (i <= j);
if (l < j) quickSort (a, l, j);
if (i < r) quickSort (a, i, r);
}
let rec quicksort = function
[] -> []
| h::t -> quicksort ([ for x in t when x<=h -> x])
@ [h] @ quicksort ([ for x in t when x>h -> x]);;
93.
94. flipH invert
flipV
stack
mirror
,
right glue
,
Какие функции можно получить композицией?
Какие свойства можно увидеть?
95. flipH
right right
mi
flipV
rro flipV
r
flipH
mirror = flipH flipV = flipV flipH
o o
flipH flipH = flipV flipV = Id
o o
flipH = right right o