/* 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].