Download
:- use_module(library(clpfd)).
% Costas Array (CSPLib prob076)
% A permutation Xs of 1..N where all differences within each level of the difference triangle are distinct.
% Level L contains differences X(i+L) - X(i) for all valid i.
% costas(+N, ?Xs): Xs is a Costas Array of size N
costas(N, Xs) :-
length(Xs, N), % Xs= [_,_,_, ... ,_] with N variables
Xs ins 1..N, % each value is a row position 1..N
all_distinct(Xs), % one mark per row (permutation)
N1 is N - 1,
findall(L, between(1, N1, L), Levels), % Levels = [1, 2, 3, ..., N-1] of the difference triangle
maplist(level_all_distinct(Xs), Levels), % each level must have distinct differences
label(Xs).
% level_all_distinct(+Xs, +L): differences at level L must all be distinct
level_all_distinct(Xs, L) :-
level_diffs(Xs, L, Diffs), % compute differences X(i+L) - X(i) for all valid i
all_distinct(Diffs).
% level_diffs(+Xs, +L, -Diffs): collect differences at level L
level_diffs(Xs, Lev, Diffs) :-
length(Drop, Lev), % Drop = [_,_, .. ,_ ] with Length = Lev
append(Drop, Shifted, Xs), % Shifted = elements from position L+1 onwards in Xs
length(Shifted, LenDiff), % LenDiff= How many differences there will be
length(Base, LenDiff), % Base = [_,_, ... ,_] with length of LenDiff
append(Base, _, Xs), % Base = first LenDiff elements of Xs
maplist(diff, Base, Shifted, Diffs). % D = X(i+L) - X(i)
% diff(+A, +B, -D): D is the difference B - A
diff(A, B, D) :- D #= B - A.