Пролог точечного произведения с переменными (удовлетворение ограничения) - PullRequest
2 голосов
/ 12 апреля 2011

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

1 голос
/ 12 апреля 2011

Ваша стратегия действительно разумна и работает, по крайней мере, с 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.

...