Посмотрите, сможете ли вы получить "Программу пролога для искусственного интеллекта" Ивана Братко.
Он объясняет процесс, которым следует Пролог, чтобы очень хорошо достигать целей.
Я постараюсь ответить на ваши вопросы индивидуально:
clause 1: evenN(X):- (X mod 2) =:= 0.
clause 2: sumEven([], 0).
clause 3: sumEven([H|T], X):- evenN(H), sumEven(T,Y), X is Y+H.
clause 4: sumEven([H|T], X):- \+evenN(H), sumEven(T,X).
ВОПРОСЫ:
1) Когда я закомментирую второе правило (последнюю строку), оно дает мне ошибку в качестве ответа, потому что 1 не является четным числом, а весь sumEven () терпит неудачу, потому что evenN () терпит неудачу, что я понимаю. Мой вопрос: что происходит потом? Вернется ли он к началу и попробует факт sumEven ([], 0) или? Я просто хочу знать, что происходит.
A: Вы комментируете пункт 4. Пролог пытается достичь цели, сначала пытаясь выполнить предложение 2, которое не выполняется, поскольку список не пуст, затем он пытается выполнить предложение 3, которое не выполняется по правилу 1 когда Н странно. Теперь он попытается найти другой пункт, следующий за пунктом 3 (он не будет возвращаться к предыдущему пункту 3), который потерпит неудачу, поскольку вы его закомментировали, и поэтому цель не достигнута.
2) Когда включается последняя строка (второе правило), и первое правило не выполняется, когда оно возвращается назад, ищет ли оно другое sumEven (), следующее за ним (подобно тому, как второе правило следует первому правилу, которое не выполняется) ) или он возвращается к началу и проверяет факт sumEven ([], 0) и запускает его оттуда?
A: Нет, он не возвращается, когда пункт 3 не выполняется, но переходит к следующему пункту (4).
Мне нужно понять, как он возвращается, когда правила используются в прологе, особенно в рекурсивных ситуациях, подобных этой.
A : Если правило evenN(H)
выполнено успешно, sumEven (T, Y) снова запускает весь процесс из пункта 2, используя T и Y. Если sumEven (T, Y) завершается неудачей по какой-то причине , пункт три завершится неудачно, а Prolog вернется назад и попытается использовать пункт 4. Если текущим вызовом является sumEven ([2,3, ...], X) и по какой-то причине происходит сбой sumEven ([3, ...], Y), Пролог откатится назад и попытается найти другое предложение sumEven ([2,3, ...], X), следующее за пунктом 3.
3) Я нашел следующий код (рекурсивный) в сети. Он делит список на положительные и отрицательные списки.
clause 1: split([],[],[]).
clause 2: split([X|L],[X|L1],L2):- X>= 0, !, split(L,L1,L2).
clause 3: split([X|L],L1,[X|L2]):- split(L,L1,L2).
Может кто-нибудь помочь мне понять, как это работает, чтобы найти решение? Я имею в виду, я хочу понять шаг за шагом, как это выполняется, чтобы найти решение.
A : я буду использовать более короткое разделение целей (numlist, PosList, NegList) с numlist = [1, -1,2, -2]. Очень грубо это работает следующим образом (на самом деле он использует стек для размещения совпадающих значений и создает переменные только тогда, когда его цель наконец достигает успеха, когда разворачивает этот стек - подробности см. В книге Братко):
Пункт 1 не выполняется, поскольку numlist не пуст.
Пункт 2 применяется с: split ([1 | -1,2, -2], [1 | L1], [Y | L2]) - поскольку 1> = 0 PosList теперь будет [1], и split будет применен к хвосту numlist = [- 1,2, -2].
Пункт 1 снова не выполняется. Пункт 2 применяется с разделением ([- 1 | 2, -2], [- 1 | L1], [Y | L2]) - он завершается неудачей, поскольку -1 <0, и Пролог применит раздел 3 с разделением ([- 1 | 2, -2], [1], [-1 | L2] - NegList теперь будет [-1], и снова разделение будет применено к хвосту numlist = [2, -2]. </p>
Пункт 1 не выполняется; предложение 2 успешно выполняется, PosList становится [1,2], а split применяется к numlist = [- 2].
Пункты 1 и 2 не выполнены; пункт 3 завершается успешно, а NegList становится [-1, -2]. хвост numlist пуст, предложение 1 успешно выполнено, и PosList = [1,2] и NegList [-1, -2] возвращаются.