Решение 1. Использование библиотеки
Это легко сделать, если вы используете библиотеку теории графов. Сначала я перепишу ваш график, используя S-представление:
[1-[2],2-[1,3],3-[2],4-[5],5-[4]]
Затем я буду использовать библиотеку ugraph
, включенную в SWI-Prolog (спасибо Ричарду О' Киф и Витор Сантос Коста):
?- use_module(library(ugraph)).
?- G = [1-[2],2-[1,3],3-[2],4-[5],5-[4]], vertices(G, Vs), member(V, Vs), reachable(V, G, Ws).
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 1,
Ws = [1, 2, 3] ;
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 2,
Ws = [1, 2, 3] ;
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 3,
Ws = [1, 2, 3] ;
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 4,
Ws = [4, 5] ;
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 5,
Ws = [4, 5].
Решение 2: «Сделай сам»
Вместо того, чтобы полагаться на существующие библиотеки, вы также можете реализовать это самостоятельно различными способами (настоятельно рекомендуется, если вы хотите стать лучшим программистом!). Один из способов реализовать эту форму с нуля — использовать closure0/3, который реализует рефлексивный -транзитивное замыкание над бинарным предикатом (созданный пользователем SO false).
Если вы добавите соответствующие ребра в свою базу данных:
edge(1,2).
edge(2,1).
edge(2,3).
edge(3,2).
edge(4,5).
edge(5,4).
... теперь вы можете запросить:
?- member(V, [1,2,3,4,5]), findall(W, closure0(edge, V, W), Ws).
V = 1,
Ws = [1, 2, 3] ;
V = 2,
Ws = [2, 1, 3] ;
V = 3,
Ws = [3, 2, 1] ;
V = 4,
Ws = [4, 5] ;
V = 5,
Ws = [5, 4].
person
Wouter Beek
schedule
17.11.2014