Программирование на языке Пролог для искусственного интеллекта
Шрифт:
Эта процедура "нумерует" переменные, содержащиеся в
Терм
, заменяя каждую из них на некоторый специальный новый терм таким образом, чтобы эти "нумерующие" термы соответствовали числам от N до M–1, Например, пусть эти термы имеют вид пер/0, пер/1, пер/2, ...
тогда в результате обращения к системе
?- Терм = f( X, t( a,Y, X) ), нумпер( Терм, 5, М).
мы получим
Терм = f( пер/5, t( а, пер/6, пер/5) )
М = 7
% Процедура
%
%
ответпольз( Цель, Трасса, Ответ)
%
% порождает, используя механизм возвратов, все решения
% для целевого утверждения Цель, которые указал пользователь.
% Трасса - это цепочка целей-предков и правил,
% используемая для объяснения типа "почему".
ответпольз( Цель, Трасса, Ответ) :-
можно_спросить( Цель, _ ), % Можно спросить?
копия( Цель, Копия), % Переименование переменных
ответпольз( Цель, Копия, Трасса, Ответ, 1).
% Не спрашивать второй раз относительно конкретизированной цели
ответпольз( Цель, _, _, _, N) :-
N > 1, % Повторный вопрос?
конкретный( Цель), !, % Больше не спрашивать
fail.
% Известен ли ответ для всех конкретизации утверждения Цель?
ответпольз( Цель, Копия, _, Ответ, _ ) :-
сказано( Копия, Ответ, _ ),
конкретизация( Копия, Цель), !. % Ответ известен
% Найти все известные решения для Цель с индексами, начиная с N
ответпольз( Цель, _, _, правда, N) :-
сказано( Цель, правда, М),
М >= N.
% Все уже сказано об утверждении Цель?
ответпольз( Цель, Копия, _, Ответ, _) :-
конец_ответов( Копия),
конкретизация( Копия, Цель), !, % Уже все сказано
fail.
% Попросить пользователя дать (еще) решения
ответпольз( Цель, _, Трасса, Ответ, N) :-
спросить_польз( Цель, Трасса, Ответ, N).
спросить_польз( Цель, Трасса, Ответ, N) :-
можно спросить( Цель, ВнешФормат),
формат( Цель, ВнешФормат, Вопрос, [], Перем),
% Получить формат вопроса
спросить( Цель, Вопрос, Перем, Трасса, Ответ, N).
спросить( Цель, Вопрос, Перем, Трасса, Ответ, N) :-
nl,
( Перем = [], !, % Сформулировать вопрос
write( 'Это правда: ');
write( 'Есть (еще) решения для :' )),
write(
Вопрос), write( '?'),
принять( Ответ1), !, % Ответ1 - да/нет/почему
обработать( Ответ1, Цель, Вопрос, Перем,
Трасса, Ответ, N).
обработать( почему, Цель, Вопрос, Перем,
Трасса, Ответ, N):-
выд_трассу( Трасса),
спросить( Цель, Вопрос, Перем, Трасса, Ответ, N).
обработать( да, Цель,_, Перем, Трасса, правда, N) :-
след_индекс( Инд),
% Получить новый индекс для "сказано"
Инд1 is Инд + 1,
( запрос_перем( Перем),
assertz( сказано( Цель, правда, Инд) );
% Запись решения
копия( Цель, Копия), % Копирование цели
ответпольз( Цель, Копия, Трасса, Ответ, Инд1) ).
% Есть еще решения?
обработать( нет, Цель, _, _, _, ложь, N) :-
копия( Цель, Копия),
сказано( Копия, правда, _), !,
% 'нет' означает, больше нет решений
assertz( конец_ответов( Цель) ),
% Отметить конец ответов
fail;
след_индекс( Инд),
% Следующий свободный индекс для "сказано"
assertz( сказано( Цель, ложь, Инд) ).
% 'нет' означает нет ни одного решения
формат( Пер, Имя, Имя, Перем, [Пер/Имя | Перем]) :-
var( Пер), !.
формат( Атом, Имя, Атом, Перем, Перем) :-
atomic( Атом), !,
atomic( Имя).
формат( Цель, Форм, Вопрос, Перем0, Перем) :-
Цель =.. [Функтор | Apг1],
Форм =.. [Функтор | Форм1],
формвсе( Apг1, Форм1, Арг2, Перем0, Перем),
Вопрос =.. [Функтор | Арг2].
формвсе( [], [], [], Перем, Перем).
формвсе( [X | СпХ], [Ф | СпФ], [В | СпВ], Перем0, Перем) :-
формвсе( СпХ, СпФ, СпВ, Перем0, Перем1),
формат( X, Ф, В, Перем1, Перем).
запрос_перем( []).
запрос_перем( [Переменная/Имя | Переменные]) :-
nl, write( Имя), write( '='),
read( Переменная),
запрос_перем( Переменные).
выд_трассу( []) :-
nl, write( 'Это был ваш вопрос'), nl.
выд_трассу( [Цель по Прав | Трасса] ) :-
Поделиться с друзьями: