Давайте попробуем разобраться в положениях, которые вы написали. В первом разделе allnodes([]).
в основном говорится: «нет узлов». Это, очевидно, не так, если только никаких границ не существует.
Второе предложение может интерпретироваться по строкам «все узлы состоят из X и Y, если есть ребро от X до Y, плюс все узлы». См. Рекурсию здесь? Список содержит себя как хвост! Вот почему вы получаете одни и те же узлы снова и снова.
Что вы на самом деле хотите, это набор всех узлов, которые встречаются как начальный или конечный узел для ребра.
Для того, чтобы облегчить для себя, давайте сначала перевести Prolog, что это значит для чего-то, чтобы быть узлом:
node(N) :- edge(N, _).
node(N) :- edge(_, N).
просто. Что-то есть узел, если там начинается какой-то край, или какой-то край заканчивается там.
Теперь все, что нам нужно сделать, это найти все, что удовлетворяет вышеуказанному предикату.
allnodes(Nodes) :- setof(N, node(N), Nodes).
Обратите внимание, что я использую setof/3
, а не findall/3
для удаления дубликатов, как указано выше, определение node/2
будет успешным один раз для каждого вхождения узла в кромке, например, он будет успешным дважды для n1 и n2.
Это дает результат, который вы ищете:
?- allnodes(N).
N = [n1, n2, n3, n4]
Hm. Мне, видимо, нужно больше изучить множество предикатов/3 (и пролог больше в любом случае). –