Download
/*

  Traffic lights problem in Picat.

  CSPLib problem 16
  http://www.csplib.org/Problems/prob016
  """
  Specification:
  Consider a four way traffic junction with eight traffic lights. Four of the traffic 
  lights are for the vehicles and can be represented by the variables V1 to V4 with domains 
  {r,ry,g,y} (for red, red-yellow, green and yellow). The other four traffic lights are 
  for the pedestrians and can be represented by the variables P1 to P4 with domains {r,g}.
  
  The constraints on these variables can be modelled by quaternary constraints on 
  (Vi, Pi, Vj, Pj ) for 1<=i<=4, j=(1+i)mod 4 which allow just the tuples 
  {(r,r,g,g), (ry,r,y,r), (g,g,r,r), (y,r,ry,r)}.
 
  It would be interesting to consider other types of junction (e.g. five roads 
  intersecting) as well as modelling the evolution over time of the traffic light sequence. 
  ...
 
  Results
  Only 2^2 out of the 2^12 possible assignments are solutions.
  
  (V1,P1,V2,P2,V3,P3,V4,P4) = 
     {(r,r,g,g,r,r,g,g), (ry,r,y,r,ry,r,y,r), (g,g,r,r,g,g,r,r), (y,r,ry,r,y,r,ry,r)}
     [(1,1,3,3,1,1,3,3), ( 2,1,4,1, 2,1,4,1), (3,3,1,1,3,3,1,1), (4,1, 2,1,4,1, 2,1)}
 
 
  The problem has relative few constraints, but each is very tight. Local propagation 
  appears to be rather ineffective on this problem.   
  """

  Model created by Hakan Kjellerstrand, hakank@gmail.com
  See also my Picat page: http://www.hakank.org/picat/

*/

% Licenced under CC-BY-4.0 : http://creativecommons.org/licenses/by/4.0/

import cp.

main => go.

go => 
    L = findall([V,P], $traffic_lights(V,P)),
    writeln(L),
    print_results(L),
    nl,

    writef("Using table constraint:\n"),
    L2 = findall([V2,P2], $traffic_lights_table(V2,P2)),
    print_results(L2),
    nl.


print_results(L) =>
    foreach([V,P] in L)
       foreach(I in 1..4)
          tr(VC,V[I]),
          tr(PC,P[I]),
          writef("%w %w ",VC,PC)
       end,
       nl
    end.

traffic_lights(V, P) =>
    N  = 4,

    V = new_list(N),
    V :: 1..N,
    P = new_list(N), 
    P :: 1..N,
    Allowed = [[r,r,g,g],
               [ry,r,y,r],
               [g,g,r,r],
               [y,r,ry,r]],

    foreach(I in 1..N, J in 1..N) 
       JJ = (1+I) mod N,
       if J == JJ then
          check_allowed(V[I], P[I], V[J], P[J])
          % check_allowed2(V[I], P[I], V[J], P[J], Allowed)
       end
    end,

    Vars = V ++ P,
    solve(Vars),
    writeln(vars=Vars).


check_allowed(VI, PI, VJ, PJ) ?=>
    L1 = [],
    foreach(El in [VI, PI, VJ, PJ])
      if tr(C,El) then 
         L1 := L1 ++ [C] 
      end
    end,
    L = L1,

    allowed(L).


check_allowed2(VI, PI, VJ, PJ, Allowed) ?=>
    L1 = [],
    foreach(El in [VI, PI, VJ, PJ])
      writeln(el=El),
      if tr(C,El) then 
         L1 := L1 ++ [C] 
      end
    end,
    L = L1,
    writeln(l=L),
    writef("before element\n"),
    element(C,Allowed,L),
    writef("after element\n"),
    allowed(L).


%
% Using table Allowed
%
traffic_lights_table(V, P) =>
    N  = 4,

    % allowed/1 as a table (translated)
    Allowed = [(1,1,3,3),
               (2,1,4,1),
               (3,3,1,1),
               (4,1,2,1)],
   
    V = new_list(N),
    V :: 1..N,
    P = new_list(N), 
    P :: 1..N,
    foreach(I in 1..N, J in 1..N)
        JJ = (1+I) mod N,
        if J #= JJ then
             VI = V[I], PI = P[I],
             VJ = V[J], PJ = P[J],
             % Table constraint
             table_in((VI, PI, VJ, PJ), Allowed)
        end
    end,

    Vars = V ++ P,
    solve(Vars).

% Note: I'm not sure this is the best 
%       representation...
tr(L,A) ?=> L=r,  A=1.
tr(L,A) ?=> L=ry, A=2.
tr(L,A) ?=> L=g,  A=3.
tr(L,A)  => L=y,  A=4.

% The allowed combinations
allowed(A) ?=> A = [r,r,g,g].
allowed(A) ?=> A = [ry,r,y,r]. 
allowed(A) ?=> A = [g,g,r,r].
allowed(A)  => A = [y,r,ry,r].