Пролог точечного произведения с переменными (удовлетворение ограничений)

Я работаю над заданием на пролог, и в настоящее время я очень близок к решению. Таким образом, проблема представляет собой проблему удовлетворения ограничений, где я должен найти значения для набора переменных, чтобы определенные условия выполнялись. В частности, учитывая 3 слова (W1,W2,W3), присвойте их переменные так, чтобы W1+W2=W3. Примером этого может быть SEND+MORE=MONEY или IT+IS=ME.

Ограничения: (1) они должны сложиться правильно, (2) начальная буква не может быть 0 (3), и все переменные должны быть различны. И это должно работать для общей проблемы со словом. Моя проблема возникает, когда я пытаюсь убедиться, что они правильно складываются (я выполнил другие условия и понимаю проблему). С точки зрения второй проблемы слова мы должны иметь:

 10*I + 1*T
+10*I + 1*S
___________
 10*M + 1*E

Итак, я сделал функцию, которая составляет списки степеней 10 определенной длины, например:

powlist(1,L) :-
    append([1.0],[],L). 
powlist(N,L) :-
    N1 is N-1,
    X is 10**N1,
    powlist(N1,L1),
    append([X],L1,L),
    !.

У меня также есть фактический список букв, скажем, [I,T,I,S,M,E]. Затем я создал список коэффициентов (я объясню эту часть позже) из списка рассылки, поэтому у нас есть что-то вроде следующего: [10,1,10,1,-10,-1]. Я сделал это так, если бы мы взяли скалярное произведение между этим списком коэффициентов и списком букв, и оно равнялось нулю, ограничение было бы выполнено. Но я не могу заставить эту теорию точечного продукта работать. В настоящее время у меня есть строка, которая говорит:

   scalar_product(Coefficients, Letters, #=, 0)

Но это дает мне следующую ошибку:

! Ошибка инстанции в аргументе 2 is / 2
! цель: _102 - это 0+10,0*_109

Я не уверен, как определить точечное произведение, чтобы оно могло работать с переменными (а не только с атомами). Весь остальной код работает отлично (и я не хочу его здесь приводить, потому что это очень распространенный вопрос для вводных курсов по прологу, и я не хочу давать ответы для ленивых людей). Что вы, ребята, предлагаете?

1 ответ

Ваша стратегия действительно разумна и работает, по крайней мере, с SWI-Prolog CLP(FD) с использованием встроенного scalar_product/4, Я не знаком с определением этого предиката в SICStus, но его интерфейс выглядит так же, как в SWI-Prolog.

Я могу сделать пару предложений. Во-первых, возможно, какой-то аспект написанного вами кода генерирует точки выбора, которые при выполнении в режиме обратного отслеживания (например, для поиска альтернативных решений, например, через label/1), переводчик выполняет подцель _102 is 0+10.0*_109 где _109 непреднамеренно не связан. Вы написали предикат, который содержит такую ​​строку? Даже если нет, я рекомендую дважды проверить ваш код, чтобы убедиться, что они не генерируют ненужные точки выбора, такие как ваше определение powlist/2, Я рекомендую вам попробовать следующее:

powlist(1, [1]) :- !.
powlist(N, [F|Fs]) :-
    N > 1,
    N1 is N - 1,
    F is 10 ** N1,
    powlist(N1, Fs).

Эта версия не оставляет точек выбора для интерпретатора Пролога, к которому можно вернуться, что может решить проблему (хотя, не видя больше кода, я просто не могу сказать).

В противном случае, если вы правы и ошибка действительно исходит из определения scalar_product/4 (хотя я был бы удивлен), тогда, возможно, вы могли бы сгенерировать термин ограничения скалярного продукта и добавить его в магазин самостоятельно, вручную. Например, рассмотрим:

my_scalar_product([V|Vs], [C|Cs], Op, Value) :-
    construct_constraint(Vs, Cs, (V * C), Constr),
    Constraint =.. [Op, Constr, Value],
    Constraint.

construct_constraint([], [], Acc, Acc).
construct_constraint([V|Vs], [F|Fs], Acc, Res) :-
    construct_constraint(Vs, Fs, '+'(Acc, (V * F)), Res).

Эта версия (my_scalar_product/4) предполагает тот же интерфейс, что и встроенный scalar_product/4, но он добавляет ограничение в хранилище вместо того, чтобы пытаться выполнить его, используя is/2,

Другие вопросы по тегам