Как вы проверяете элементы подматрицы в Prolog

Я пытаюсь написать решатель Shikaku в EclipsE Prolog. Мои ограничения определяются следующим образом:

solve(Problemname):-
writeln("Start shikaku."),
problem(Problemname, Width, Height, Hints),
shikaku(Width, Height, Hints).

shikaku(Width, Height, Hints):- 
length(Hints, HintCount),
array_list(HintsArray, Hints),

% Prepare the matrix and assign an ID to every Hint (from 1 to HintCount)
dim(Matrix, [Width, Height]),
Matrix[1..Width,1..Height] :: 1..HintCount,

%flatten_array(Matrix,FlattenedMatrix),
(for(ID,1,HintCount), foreach((HintX, HintY, HintNumber), Hints), param(Width, Height, Matrix, HintsArray) do
    (   
        occurrences(ID, Matrix, HintNumber),
        L :: 1..Width, R :: 1..Width,
        T :: 1..Height, B :: 1..Height,

        % Hint coordinates are inside the rectangle.
        L #=< HintX,
        R #>= HintX,
        T #=< HintY,
        B #>= HintY,
        DeltaX #= R-L+1,
        DeltaY #= B-T+1,
        HintNumber #= DeltaX * DeltaY,

        Matrix[L..R,T..B] :: ID..ID
        %writematrix(Submatrix, DeltaX, DeltaY, HintsArray),

        %flatten(Submatrix, FlatSubmatrix), 
        %array_list(FlatSubmatrixArray, FlatSubmatrix),

        % Cell count in rectangle must equal HintNumber
        %length(FlatSubmatrix, HintNumber),

        % All cells in rectangle must have ID as value
        %FlatSubmatrixArray[1..HintNumber] :: ID    

    )
),

% Start searching
labeling(Matrix),

writematrix(Matrix, Width, Height, HintsArray). 

writematrix(Matrix, Width, Height, HintsArray):-
writeln("Writing as classic view:"),
(for(I, 1, Height), param(Matrix, Width, HintsArray) do
    write("["),
    Row is Matrix[I],
    (for(J, 1, Width), param(Row, HintsArray) do
        ID is Row[J],
        (_,_,Val) is HintsArray[ID],
        write(" "),
        write(Val),
        write(" ")
    ),

    writeln("]")
).

Строка в комментариях должна проверять, содержит ли подматрица, идущая от L..R - T..B, только элементы, равные ID. Как это может быть сделано?

Выполнение этого дает "ошибку создания экземпляра в _3264 {1 .. 3} =‹ 3 "

edit1: полный код

edit2 Похоже, что eclipse не может уменьшить область переменных LR / TB для применения экземпляра. Это правильное предположение? Если да, то как это можно решить?


person JorenV    schedule 22.05.2016    source источник
comment
Ага, возможно, проблема заключается в том, что вы обращаетесь к Matrix для подмножества L..R, T..B, но эти переменные не всегда могут быть использованы при вводе строки кода. Вы не можете указать диапазоны для подмножеств массивов, имеющих домен. Существует возможность выполнить поиск после установки домена переменных LRTB, но до установки домена ID..ID для подмножества Matrix.   -  person SND    schedule 22.05.2016
comment
Как именно это сделать? :)   -  person JorenV    schedule 22.05.2016
comment
Использование встроенного поиска / 6 ECLiPSe, как вы это делаете при вызове метки / 1. Только вместо того, чтобы вызывать его после цикла, вызывайте его внутри цикла между экземплярами домена L..R и T..B, но перед строкой с Matrix [L..R, T..B] :: ID ..Я БЫ.   -  person SND    schedule 22.05.2016
comment
Ну запускается: D не возвращает решение хотя должно, но это что-то.   -  person JorenV    schedule 22.05.2016
comment
Отлично: D! Теперь, когда проблема обнаружена, вы можете адаптировать программу. Я предполагаю, что это сводится к следующему: либо вы заранее устанавливаете все ограничения для всех переменных LRTB, но еще не используете их для доступа к матрице внутри цикла, либо вы выполняете поиск внутри цикла, как сейчас, и можете сохранить Матрица звонит туда. Однако обратите внимание, что при вызове поиска внутри цикла потребуется создать разные точки выбора для разных решений, что может замедлить выполнение при работе с большими доменами. Всегда старайтесь ограничить вашу модель настолько сильно, насколько это возможно / необходимо, чтобы избежать ненужного поиска.   -  person SND    schedule 22.05.2016


Ответы (1)


Я не запускал ваш код, но смотрю документацию оператора :: для создания экземпляров доменов, мы видим, что он ожидает нижнюю и верхнюю границы диапазона доменов. В вашем примере, если вы просто хотите, чтобы каждое число в подмножестве массива было равно, скажем, 4, вы можете просто написать следующее:

Matrix[A..B,C..D] :: 4..4

ИЗМЕНИТЬ

Полученная вами ошибка не вызвана этой строкой кода. Это дает ошибку создания экземпляра при сравнении переменной домена с целым числом. Я предполагаю, что вы случайно написали = ‹вместо # =‹ где-то в коде, который не включен в этот вопрос, поскольку домен {1..3} на самом деле = ‹3 и не должен выдавать никаких ошибок. правильно использованы операторы ограничения.

Если вы не можете понять, какая строка кода вызывает ошибку, попробуйте выполнить трассировку - она ​​(почти) всегда выявляет причину. Если вы используете tkeclipse, доступен встроенный инструмент трассировки.

person SND    schedule 22.05.2016
comment
изменение :: ID на :: ID..ID возвращается с той же ошибкой - person JorenV; 22.05.2016
comment
Я изменил ответ. - person SND; 22.05.2016
comment
см. обновленный код. Трассировка завершается ошибкой при достижении строки Matrix :: ID..ID во второй раз. Кажется, что eclipse не может уменьшить область переменных LR / TB для применения экземпляра - person JorenV; 22.05.2016