%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% AGOSTINO DOVIER
%%% August 29, 2012
%%% Tested in BProlog
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%% Just call :- consistency(L).

consistency(Labels) :-
   findall(X,node(X),Nodes),
   length(Nodes,N),
   length(Labels,N),
   set_domains(Labels),
   initial_assignment(Nodes,Labels),
   constraint(Nodes,Labels),
   labeling([],Labels).

set_domains([]).
set_domains([L|Labels]) :-
    domain([L],-1,1), L #\= 0, %%% L in {-1,1},
    set_domains(Labels).   
      
initial_assignment([],[]).
initial_assignment([N|Nodes],[L|Labels]) :-
    (partial(N,L),!;true), %%% if N is labeled by a partial assignment, use that label 
    initial_assignment(Nodes,Labels).

constraint(Nodes,Labels) :-
    constraint(Nodes,Labels,Nodes,Labels).

constraint([],_,_,_).
constraint([N|Odes],[_|Abels],Nodes,Labels) :-
       input(N),!, 
       constraint(Odes,Abels, Nodes,Labels).
constraint([N|Odes],[L|Abels], Nodes,Labels) :-
       findall([A,Sign],edge(A,N,Sign),EdgeList), %%% A1->N, ..., An -> N edges   
       product_list(EdgeList,Nodes,Labels,PLIST), %%% L in [A1 S1, A2 S2, ... , AnSn] 
       element(_,PLIST,L),
       constraint(Odes,Abels, Nodes,Labels).

product_list([],_,_,[]).
product_list([[A,Sign]|EdgeList],Nodes,Labels,[P|LIST]) :-
       nth1(I,Nodes,A),nth1(I,Labels,L), 
       P #= Sign*L,
       product_list(EdgeList,Nodes,Labels,LIST).
              
printlab([])    :- nl.
printlab([1|L]) :- print(' 1 ||'),printlab(L).
printlab([-1|L]) :- print('-1 ||'),printlab(L).
    
% Graph (Veber example)

input(1).    input(3).

%
node(1).    node(2).    node(3).   node(4).
node(5).    node(6).    node(7).   node(8).

%
edge(1,2,1).
edge(2,3,1).
edge(3,8,-1).
edge(4,1,-1).
edge(4,2,1).
edge(5,2,-1).
edge(5,3,1).
edge(5,7,1).
edge(6,4,-1).
edge(6,5,-1).
edge(7,6,-1).
edge(8,5,1).
edge(8,4,1).
%
partial(1,1).
partial(2,-1).
%partial(3,1).
%partial(4,1).
%partial(5,1).
%partial(6,1).
%partial(7,1).
partial(8,1).

