как решить, когда количество переменных в цели / запросе меняется - Prolog Constrain Solver - PullRequest
0 голосов
/ 10 февраля 2012

Вот фрагмент классического решения крипто-арифметической задачи SENDMORY, использующего механизм решения ограничений пролога -

:- lib(ic).
sendmore(Digits) :-
Digits = [S,E,N,D,M,O,R,Y],
Digits :: [0..9],
alldifferent(Digits),
S #\= 0,
M #\= 0,
1000*S + 100*E + 10*N + D 
+ 1000*M + 100*O + 10*R + E
#= 10000*M + 1000*O + 100*N + 10*E + Y,
labeling(Digits).

Теперь, чтобы выполнить это, я бы отправил цель / запрос следующим образом:

?- sendmore(Digits).

И это вернуло бы мне возможные решения для цифр.

Теперь, мой вопрос, я не хочу сортировать «жесткий код» переменных (таких как S, E, N, ...) таким образом, но цель / запрос даст количество переменных.Например, если запрос, который я передаю, имеет следующий вид:

?- sendmore(S,E,N,D,M).

, он должен вычислить только значения SENDM и предположить, что другие переменные неприменимы, и, следовательно, присвоить 0 этим переменным, а затемприступить к вычислениям.И в следующий раз, когда я сделаю запрос, я могу передать другое количество переменных в запросе, например:

?- sendmore(S,N,D,M,O,Y).

, и программа должна выполнить аналогичные вычисления.

То, что я пытаюсь выполнитьФункция «достижение» является более обобщенным решением проблем для вышеуказанного сценария.Любые указания на это действительно приветствуются.Я довольно новичок в прологе, и я использую ECLIPSE решатель ограничений.Спасибо.

Ответы [ 2 ]

1 голос
/ 10 февраля 2012

Обычно переменные в цели и переменные в заголовке предложения сопоставляются по их позициям, а не по именам.Таким образом, вызов ?- sendmore0([S,E,N,D,M]). должен быть реализован следующим образом:

sendmore0([S,E,N,D,M]) :- sendmore([S,E,N,D,M,_,_,_]).

Однако это будет означать, что вам потребуется реализовать это для каждой возможной комбинации.Вы описываете, тогда вам нужно дать переменные стабильные имена.В ECLiPSe вы можете сделать это с библиотекой var_name.Хотя это довольно взломано ...

:- lib(var_name).

sendmore0(L) :-
   build_arg(["S","E","N","D","M',"O","R","Y"], L, A),
   sendmore(A).

build_arg([], _, []) :- !.
build_arg([H|T], L, [HA|HT]) :-
   match_arg(L, H, HA),
   build_arg(T, L, HT).

match_arg([], _, _). % or use 0 as last argument if you want
match_arg([H|T], Base, A) :-
   (
      get_var_name(H, S),
      split_string(S,"#","",[Base,_])
   ->
      A = H
   ;
      match_arg(T, Base, A)
   ).

Тогда вы можете вызвать sendmore0/1 с более коротким списком переменных.Не забудьте установить имена переменных!

?- set_var_name(S, "S"), set_var_name(E, "E"), sendmore0([S, E]).
S = 9
E = 5
Yes (0.00s cpu, solution 1, maybe more)

Отказ от ответственности : это , а не , для чего нужны стабильные имена.Они предназначены для отладки.Если Иоахим когда-нибудь увидит это, он даст мне острый зажим по ушам ...

1 голос
/ 10 февраля 2012

Вот 2 идеи:

  1. Вы можете определить sendmore () с различным количеством параметров, которое будет вызывать «реальную» версию с заполненными недостающими. Но вы не могли иметьразные версии с одинаковым КОЛИЧЕСТВОМ параметров, но РАЗЛИЧНЫМИ (поскольку Prolog сопоставляет аргументы с параметрами по позиции).
  2. Вы можете расширить / усложнить формат списка, чтобы указать параметры передаваемых вами параметров;что-то строка [(s,S),(e,E),(n,N),(d,D),(m,M)] для вашего среднего примера.Немного утомительно, но дает вам гибкость, которую вы, кажется, хотите.
...