Печать пути в Прологе

Я хочу напечатать путь узлов в ориентированном графе. Этот код работает правильно для ребра, но не работает для всего пути. Он возвращает ложь, когда дело доходит до пути. Вот мой код, но он работает только для края, а не для всего пути. Пожалуйста, помогите мне.

Вот мой код:

path(Node1, Node2, X) :-
  edge(Node1, Node2),
  append([Node1], [Node2], X).
path(Node1, Node2, X, N) :-
  edge(Node1, SomeNode),
  append([Node1], [SomeNode], X),
  path(SomeNode, Node2, X, N),
  append([], [Node2], X).

X это список.

2 ответа

В то время как @WouterBeek уже определил ваши проблемы, заявление Wouter

Без выполнения этого кода вы уже можете заметить, что второе предложение всегда будет неудачным, поскольку список длины 2 не может быть объединен со списком длины 1

заслуживает некоторой разработки. Для опытного программиста Пролога такие проблемы легко обнаружить. Но что могут сделать новички? Они могут применять следующую технику: обобщить вашу программу, и если обобщенная программа все еще слишком специализирована, в оставшейся части должна быть ошибка.

Обобщение чистой программы Пролог

Есть несколько способов обобщить программу на чистом Прологе: либо удалить цели, либо удалить подтермы в аргументах головы или цели. Чтобы удалить цели, я добавлю * перед целью, используя:

: - op (920, фу, *).

*_.

путь (Node1, Node2, X): -
  * край (Node1, Node2),
  добавить ([Node1], [Node2], X).
путь (Node1, Node2, X): -
  * edge (Node1, SomeNode),
  добавить ([Node1], [SomeNode], X),
  * путь (SomeNode, Node2, X),
  добавить ([], [Node2], X).

Теперь мы можем задать наиболее общий запрос этого нового предиката:

| ?- path(N1, N2, P).
P = [N1,N2] ? ;
no

Поэтому: хотя это определение в настоящее время является (чрезмерно) обобщением, оно все же допускает только пути длины 2. Проблема полностью независима от определения edge/3, только оставшаяся часть несет ответственность. Итак, посмотрите на оставшуюся часть, чтобы решить проблему!

Во втором предложении у вас есть следующие два утверждения:

append([Node1], [SomeNode], X),
append([], [Node2], X).

Обратите внимание на эту переменную X происходит в обоих операторах, и это должно быть создано в одном и том же списке. Это означает, что [Node1]+[SomeNode] = []+[Node2] или же [Node1,SomeNode]=[Node2],

Без выполнения этого кода вы уже можете заметить, что второе предложение всегда будет неудачным, поскольку список длины 2 не может быть объединен как список длины 1.

Еще один момент: эти два предложения не принадлежат одному и тому же предикату, так как первый имеет арность 3, а последний имеет арность 4. Как правило, для вычисления путей или произвольной глубины вам нужен предикат, который состоит из двух предложений, которые принадлежат друг другу: базовый случай и рекурсивный случай. В рекурсивном случае обычной практикой является использование обозначения head/tail для построения пути: [FromNode,ToNode|RestOfPath],

Надеюсь это поможет!

Другие вопросы по тегам