Пролог точечного произведения с переменными (удовлетворение ограничений)
Я работаю над заданием на пролог, и в настоящее время я очень близок к решению. Таким образом, проблема представляет собой проблему удовлетворения ограничений, где я должен найти значения для набора переменных, чтобы определенные условия выполнялись. В частности, учитывая 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
,