:- use_module(library(lists),[member/2, select/3, last/2]). bicentered(Term,Centers) :- findall(Edge,is_edge(Term,Edge),Edges), setof(Node,is_node(Node,Edges),Nodes), two_centers(Edges,Nodes,Centers). is_edge(Term,Edge) :- Term =.. [ParentName|Children], member(Child,Children), ( Child =.. [ChildName|_], Edge = ParentName-ChildName ; is_edge(Child,Edge) ). is_node(Node,Edges) :- member(Node-_,Edges) ; member(_-Node,Edges). two_centers(Edges,Nodes,[Center1,Center2]) :- setof(Ecc-Node,eccentricity(Edges,Nodes,Ecc,Node),EccNodes), EccNodes = [Ecc-Center1,Ecc-Center2|Rest], ( Rest = [] ; Rest = [Ecc2 - _|_], Ecc2 > Ecc ). eccentricity(Edges,Nodes,Ecc,Node) :- member(Node,Nodes), setof(Dist,distance(Node,Nodes,Edges,Dist),Dists), last(Dists,Ecc). distance(Node,Nodes,Edges,NegDist) :- member(Node1,Nodes), path(Node,Node1,Edges,0,NegDist). path(Node,Node,_,DistIn,DistOut) :- !, DistIn = DistOut. path(Node,Node2,Edges,DistIn,DistOut) :- (select(Node-Node1,Edges,Edges1) ; select(Node1-Node,Edges,Edges1)), DistIn1 is DistIn + 1, path(Node1,Node2,Edges1,DistIn1,DistOut).