3
votes

I'm writing a program about roads...

For example I have road(1, a, b, 2) (road no. 1 from a to b taking up 2 units of fuel). The point is if I have road(1, a, b, 2) I must also have road(1, b, a, 2) but if I use one I cannot use another, otherwise the program will loop.

What can I write so that if the program uses this one fact, it cannot use another?

3

3 Answers

1
votes

I'm not sure I understood you, but maybe -

    direct_road(1,a,b,2).
    direct_road(1,b,a,2).

    road(X,A,B,Y) :-
      direct_road(X,A,B,Y),
      direct_road(X,B,A,Y).
1
votes

You can use one rule to capture the symmetry, but put it after all other rules with same name and arity. If there exist any solutions for whatever your query is, they will be shown before getting into any sort of infinite loop.

road(R,A,B,F) :- road(R,B,A,F).

1
votes

You can keep a list of the visited points to avoid cycles if you want to keep your symetric facts (even though I don't get why). I coded a little example without the road number :

road(a, b, 2).
road(b, a, 3).
road(b, c, 5).
get_road(a, c, FuelConsumed) :-
    get_road(a, c, [a], 0, FuelConsumed).

We introduce two new parameters here, the third is a list of the visited points, the fourth is an accumulator to keep track of the consumed fuel.

get_road(Start, End, _Visited, TotalFuel, FuelConsumed) :-
    road(Start, End, Fuel),
    FuelConsumed is TotalFuel + Fuel.

If this step is the final step, we stop.

get_road(Start, End, Visited, TotalFuel, FuelConsumed) :-
    road(Start, Waypoint, Fuel),
    \+ member(Waypoint, Visited),
    NewTotalFuel is TotalFuel + Fuel,
    get_road(Waypoint, End, [Waypoint|Visited], NewTotalFuel, FuelConsumed).

Else, we pick a waypoint that we didn't already visit and go on.