Encouraged by the knowledge I've gained from the answer to my previous post, I aim to generate Gray-codes of given length. The procedure hamming seems to work correctly, however, the Picat system finds no solution. Where's the mistake here?
import cp.
main => gray(2).
gray(CodeLen) =>
CodeNr is 2**CodeLen,
Codes = new_array(CodeNr, CodeLen),
Codes :: 0..1,
foreach(CodeNr1 in 1..CodeNr)
CodeNr2 = cond(CodeNr1 == CodeNr, 1, CodeNr1 + 1),
hamming(Codes[CodeNr1], Codes[CodeNr2], 0, H),
H #= 1
% the Hamming distance between 2 consecutive codes is 1
end,
solve(Codes),
printf("%w\n", Codes).
hamming([], [], A, H) ?=> H #= A.
hamming([H1|T1], [H2|T2], A, H) ?=>
H1 #!= H2,
A1 #= A + 1,
hamming(T1, T2, A1, H).
hamming([H1|T1], [H2|T2], A, H) ?=>
H1 #= H2,
A1 #= A + 0,
hamming(T1, T2, A1, H).
The reason that the model don't print anything is that you are using list constructs (
[H|T]) on the array matrixCodewhich is not allowed. You have to convert the rows of the matrix (which are arrays) to lists. This can be done in two ways:Codematrix to a list matrix witharray_matrix_to_list_matrix()(requires that theutilpackage is loaded):hamming/4to lists with theto_list()function. E.g.:Update.
Here's a constraint model that solves the problem of generating different rows that was indicated in the comment. It uses a simpler version of
hamming_distanceby just counting the number of different bits withsum.Also, for symmetry, I require that the first and last row also have a Hamming distance of 1.(This was in the original code.)To require different rows, the constraint
to_num/3is used to converts a number to digits in an array (given a base, here 2). These numbers (which must be distinct) are in theCodesNumlist.It solves N=4 in 0s:
The model solves N=2..7 (first solution) quite fast, but it struggles with N=8, and I don't have the time to test different search heuristics to make it faster.
Here's some another approach for solving the gray code but without constraint modelling and it's much faster: http://hakank.org/picat/gray_code.pi
Update2 Here's a much faster version of
hamming/4. It use a reification (boolean) variableBto check ifH1andH2are different and can then be used as the value to add toA0.