Вы уточнили свой вопрос после моего первого сообщения, но под ним уже есть обсуждение. Чтобы избежать путаницы, я не буду редактировать его, но написать второй один:
Есть две причины, почему вы не можете непосредственно запишите вашу проблему как пролог программы:
- вы хотите разрешить без запроса
- вы хотите увидеть резольвенту (одного) вывода этапе
Поэтому мы закодировать базу данных в операторе предиката mi_clause, который имеет два аргумента: голова и список с телом. Предикат clause_clause_resolvent имеет 6 аргументов: head и body для каждого предложения, а также для резольвенты. Здесь резольвента является результатом разрешения над главой второго предложения с первым элементом тела первого предложения. Выполнение этого также будет работать.
mi_clause(m(_P,X), [m(_Q,X), m(_R,X)]). % your original clause, anonymous variables are prefixed with _ for compiler reasons
clause_clause_resolvent(Head1, Body1, Head2, Body2, RHead, RBody) :-
copy_term(clause(Head1,Body1), clause(H1,B1)), % create a variant of the first clause
copy_term(clause(Head2,Body2), clause(H2,B2)), % same for second clause
B1 = [H2|Rest1], % the prolog execution order always uses the first literal
H1 = RHead, % head of resolvent is the same (is only resolved with the query)
append(Rest1, B2, RBody). % create the new body
Комментарии должны быть более или менее понятны: В copy_terms создать варианты пункта ввода, в противном случае вы можете потерять резольвенты. Затем вы выбираете первый элемент тела второй статьи и пытаетесь унифицировать. На самом деле, этого объединения достаточно, чтобы правильно создать оба предложения. Теперь мы создаем наше предложение резольвент: глава пункта 1 переносится (по модулю подстановкой унификатора), тело резольвент - это тело 1-го пункта без разрешенного литерала, добавленного к телу тела второго предложения.
Теперь попробуйте предикат, например, в SWI Prolog:
?- mi_clause(H1,B1), mi_clause(H2,B2), clause_clause_resolvent(H1,B1,H2,B2,RH,RB).
H1 = m(_G1028, _G1029),
B1 = [m(_G1034, _G1029), m(_G1040, _G1029)],
H2 = m(_G1043, _G1044),
B2 = [m(_G1049, _G1044), m(_G1055, _G1044)],
RH = m(_G1068, _G1069),
RB = [m(_G1080, _G1069), m(_G1099, _G1069), m(_G1105, _G1069)].
Как вы можете видеть, H1 и H2 варианты вашего п головы, содержащие свежие переменные anonoymous. Тем не менее все элементы RB имеют вид m (_, _G1069), получая вариант предложения, который вы ожидали.
Если вы хотите, чтобы проверить общий шаг разрешения, замените строки B1 = [H2 | Rest1] с member_of_rest (H2, B1, Rest1) и определить это как:
member_of_rest(X, [X|Xs], Xs).
member_of_rest(X, [H|Xs], [H|Ys]) :-
member_of_rest(X, Xs, Ys).
В хорошем упражнении может расширить программу путем дедуктивного закрытия clause_clause_resolvent, чтобы увидеть произвольные последовательности разрешений (вы можете быть уверены в порядке цепочки или запускать бесконечные рекурсии).
Удачи!
Благодарим вас за ответ, но он не затрагивает вопрос, как показать, что вы можете разрешить 'C3' из саморазрешающегося' C1'. – S0rin
Prolog не делает шаги с одним разрешением, вы не можете запускать без запроса. Самостоятельное разрешение содержится в деривации, показанной выше, но первый шаг - с запросом, поэтому отсутствует литерал: –
(Q):: - m (Q, Y). и (5): m (P, X): - m (Q, X), m (R, X). будет решено к новой цели (6): - m (Q, A), m (R, A). Теперь пролог попробует самосогласование с помощью (5), снова получив (6) - это подпункт предлагаемого вами предложения C3. Подача этого интерпретатора пролога даст вам бесконечный цикл, который снова и снова создает предложение (6), поэтому вы не получите никакого вывода вообще. Более того, интерпретатор будет возвращать ответную подстановку для вашего запроса, а не доказательство разрешения, которое он получил. (Вы можете написать так называемый метациркуляр-интерпретатор для отслеживания шагов, но обычно вы их не получаете) –