I am very inexperienced with Prolog. I have a data set that contains elements and relations in graph that has circularity (quite a lot). There are rules to calculate the summary relation of a path. One of these is: one takes the path, then takes the weakest relation, and that is the one that holds between both ends.
With
Elements E1
, E2
, E3
and
Relations R1/R1c
, R2
, R3
(strength low to high) and
structure E1-R3-E2
, E1-R1-E2
, E2-R2-E3
, E3-R1-E2
I can make the following minimal example:
% weaker table
isWeaker( r1, r2).
isWeaker( r2, r3).
weaker( X, Y) :- isWeaker( X, Y).
weaker( X, Y) :-
isWeaker( X, Z),
weaker( Z, Y).
% 'weakest' is <= not <
weakest( X, X, Y) :- =(X,Y).
weakest( X, X, Y) :- weaker( X, Y).
% All direct relations
isADirectRelation( e1, r1, e2).
isADirectRelation( e1, r3, e2).
isADirectRelation( e2, r2, e3).
isADirectRelation( e3, r1, e2).
isADirectRelation( e1, r3, e4).
isADirectRelation( e4, r2, e3).
isADirectRelation( e1, r1, e4).
isADirectRelation( e3, r1, e4).
% derived relations calculations
% Structural Chains
isADerivedRelation( Source, Relation, Target, Visited) :-
\+ member( [Source,Relation,Target], Visited),
weakest( Relation, RelationOne, RelationTwo),
isARelation( Source, RelationOne, Intermediate, [[Source,Relation,Target]|Visited]),
isARelation( Intermediate, RelationTwo, Target, [[Source,Relation,Target]|Visited]).
% major workhorse with anti-circularity
isARelation( Source, Relation, Target, Visited) :-
(isADirectRelation( Source, Relation, Target);
isADerivedRelation( Source, Relation, Target, Visited)).
The result of isARelation( Source, Relation, Target, []).
is
e1,r1,e2
e1,r3,e2
e2,r2,e3
e3,r1,e2
e1,r3,e4
e4,r2,e3
e1,r1,e4
e3,r1,e4
e1,r1,e3
e3,r1,e3
e1,r1,e3 duplicate
e3,r1,e3 duplicate
Missing are
e4,r1,e4
e2,r2,e2
Is it at all possible to solve this in Prolog? Formally, yes, of course, but also with a decent performance?