【问题标题】:how to solve when the number of variables in the goal/query varies - Prolog Constrain Solver当目标/查询中的变量数量变化时如何解决 - Prolog Constrain Solver
【发布时间】:2012-02-10 14:31:08
【问题描述】:

这是一个关于经典 SENDMORY 密码算术问题解决方案的 sn-p 使用 prolog 约束求解机制-

:- 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).

程序应该同样计算。

我想要实现的是针对上述场景的更通用的问题解决方案。对此的任何指示都非常感谢。我对 prolog 很陌生,并且正在使用 ECLIPSE 约束求解器。 谢谢。

【问题讨论】:

  • 我很难掌握可用的工具,并将它们应用到非常简单的问题上,你是在概括求解器之后。祝你好运!

标签: prolog logic clpfd cryptarithmetic-puzzle


【解决方案1】:

这里有两个想法:

  1. 您可以使用不同数量的参数定义 sendmore(),这将调用填充缺失参数的“真实”版本。但是您不能拥有具有相同数量参数但不同参数的不同版本(自 Prolog按位置将 args 与参数匹配)。
  2. 您可以扩展/复杂化您的列表格式,以允许指定您要传递的参数;某行[(s,S),(e,E),(n,N),(d,D),(m,M)] 用于您的中间示例。有点乏味,但可以为您提供所需的灵活性。

【讨论】:

    【解决方案2】:

    通常,目标中的变量和子句头部中的变量通过它们的位置而不是它们的名称来匹配。所以调用?- sendmore0([S,E,N,D,M]). 应该实现为:

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

    但是,这意味着您需要为每个可能的组合实现此功能。

    如果你真的想实现你所描述的,那么你需要给变量稳定的名字。在 ECLiPSe 中,您可以使用库 var_name 执行此操作。不过,这确实是一个 hack……

    :- 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)
    

    免责声明:这不是稳定名称的用途。它们用于调试目的。如果约阿希姆看到这个,他会给我一个尖锐的耳夹...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-25
      相关资源
      最近更新 更多