So I have a couple of facts:
%bridge(Name,From,To).
bridge(a,1,2).
bridge(b,1,2).
bridge(c,2,3).
bridge(d,3,4).
Edit:changed to atoms
So this reads like "bridge A crosses from zone 1 to zone 2". This is simple. However, the inverse is also true. Bridge A crosses from zone 2 to zone 1. That's why I thought:
bridge(B,S,E):- bridge(B,E,S).
Thing is, this messes up my program because whenever swi-prolog can't find a match for a bridge, it will keep using the bridge rule to invert it's parameters over and over again. Is there any way to stop this? Or is there any other way to create a simple rule? My program works flawlessly if I add every other fact (bridge(A,2,1), bridge(C,3,2), etc).
First note that you seem to be using variables where you meant to use atoms to identify bridges.
As to your question: You can easily solve this by adding the additional required facts, for example:
bridge(a, 1, 2).
bridge(a, 2, 1).
bridge(b, 1, 2).
bridge(b, 2, 1).
etc.
However, as you already seem to have noticed intuitively, this is clearly redundant and you can refactor it with an auxiliary predicate, say for example bridge_/2
, that consists of two clauses:
bridge(B, X, Y) :- bridge_(B, X, Y).
brigde(B, X, Y) :- bridge_(B, Y, X).
bridge_(a, 1, 2).
bridge_(b, 2, 1).
bridge_(c, 2, 3).
etc.
Prolog offers a way to process each clause read, before asserting it, by means of term_expansion/2. Should work this way:
term_expansion(bridge(K,A,B), bridge(K,A,B)) :- assertz(bridge(K,B,A)).
That is, it 'returns' the unchanged term read, and add a term with swapped 'connections'.
Beware that could be difficult to get debug your transformed source with the graphical tracer...
edit my answer was a bit superficial, I'm trying to debug it...
edit thanks to Paulo hint, here is something working...
:- module(bridge, [bridge/3]).
term_expansion(bridge(K,A,B), [bridge(K,A,B),bridge(K,B,A)]).
bridge(a,1,2).
bridge(b,1,2).
bridge(c,2,3).
bridge(d,3,4).