% CPSC 312
% Author: Steven Wolfman, based on work by David Poole
% Released into the public domain

% connected_to(X, Y) is true when X is electrically 
% connected to (i.e., capable of drawing power *from*)
% Y. X and Y should be wiring network elements.
%
% Let's order these carefully to learn more about them.
% We'll intersperse the order of facts, which lets us
% see more about how the order Prolog tries them impacts
% its solution order. w_X_Y_Z will be a wire X steps away
% from outside and number Y in order in our list. Lastly,
% Z will just be the order it appears on the left in a
% connected_to rule.
connected_to(w_d2_i1_c1, w_d1_i1_c2).
connected_to(w_d1_i1_c2, outside).
connected_to(w_d1_i2_c3, outside).
connected_to(w_d2_i2_c4, w_d1_i1_c2).
connected_to(w_d1_i3_c5, outside).
connected_to(w_d2_i3_c6, w_d1_i1_c2).

% live_both_rev(X) has exactly the same meaning as live
% but reverses the order of the recursive rule's body
% and of the base and recursive rules.
live_both_rev(X) :- live_both_rev(Y), connected_to(X, Y).
live_both_rev(outside).

% live(X) is true if X is live: has power flowing to it.
% outside is always live. Otherwise, an element is live
% if it's connected to a live element. X should be a 
% wiring network element.
live(outside).
live(X) :- connected_to(X, Y), live(Y).

% live_body_rev(X) has exactly the same meaning as live
% but reverses the order of the recursive rule's body.
live_body_rev(outside).
live_body_rev(X) :- live_body_rev(Y), connected_to(X, Y).

% live_rule_rev(X) has exactly the same meaning as live
% but reverses the order of the base and recursive rules.
live_rule_rev(X) :- connected_to(X, Y), live_rule_rev(Y).
live_rule_rev(outside).



% Let's carefully trace trees for each of these calls:
% :- live(X).
% :- live_body_rev(X).
% :- live_rule_rev(X).
% :- live_both_rev(X).
%
% We'll need to keep track of the variable numbers
% Prolog uses for calls to live...() during the trace
% so we can "hang" nodes in the right place!