使用序言程序创建一个新变量

Creating a new variable withing prolog program

我对在程序中创建的变量有疑问。 假设我有一个函数(?- 不确定这里的措辞),它是 /2,有没有办法将它更改为 /1?

:- use_module(library(clpfd)).
solve(N, L):-
        L = [A,B,C,D],
        L ins 1..sup,
        N #= A * B * C * D,
        all_distinct(L),
        A #< B, B #< C, C #< D,
        labeling([],L),nl,
        Z #= A+B+C+D,
        write(A+B+C+D=Z).

是否有可能实际解决 (N),其中 L 是在 运行 上创建的。 尝试同时使用,

L is [A,B,C,D],

L = [],
L is [A,B,C,D]

但现在运气不好。

程序是这样工作的:->

 ?- solve(30,Elements).

1+2+3+5=11
Elements = [1, 2, 3, 5].

?-     solve(60, Elements).

1+2+3+10=16
Elements = [1, 2, 3, 10] ;

1+2+5+6=14
Elements = [1, 2, 5, 6] ;

1+3+4+5=13
Elements = [1, 3, 4, 5] ;
false.

是的,但是你会得到例如:

?- solve(30).

1+2+3+5=11
true.

?- solve(60).

1+2+3+10=16
true ;

1+2+5+6=14
true ;

1+3+4+5=13
true ;
false.

如果这是您要查找的内容,只需写 solve(N) 而不是 solve(N, L):

:- use_module(library(clpfd)).
solve(N):-
        L = [A,B,C,D],
        L ins 1..sup,
        N #= A * B * C * D,
        all_distinct(L),
        A #< B, B #< C, C #< D,
        labeling([],L),nl,
        Z #= A+B+C+D,
        write(A+B+C+D=Z).

请记住 L is [A,B,C,D] 无效,因为 is/1 用于算术表达式而不是合一。您需要使用 =/2 将 L 与四元素列表统一起来。

如果你想打印列表,你可以这样写:

:- use_module(library(clpfd)).
solve(N):-
        L = [A,B,C,D],
        L ins 1..sup,
        N #= A * B * C * D,
        all_distinct(L),
        A #< B, B #< C, C #< D,
        labeling([],L),nl,
        Z #= A+B+C+D,

        writeln(A+B+C+D=Z),
        write("Elements="),
        write(L).

示例:

?- solve(30).

1+2+3+5=11
Elements=[1,2,3,5]
true.

您可以尝试 "hide" 输出变量,并像您已经在做的那样自己编写:只需从谓词定义的头部删除第二个参数:

solve(N) :-
    % rest unchanged

然后:

?- solve(30).

1+2+3+5=11
true.

但这真的适得其反。 "Prolog" 方式是只使用顶层进行打印。例如,我将从您的定义中完全删除手动编写:

:- use_module(library(clpfd)).
solve(N, Z-L):-
        L = [A,B,C,D],
        L ins 1..sup,
        N #= A * B * C * D,
        all_distinct(L),
        A #< B, B #< C, C #< D,
        Z #= A+B+C+D,
        labeling([],L).

然后:

?- solve(30, Solution).
Solution = 11-[1, 2, 3, 5].

然而,即使这样也不是最理想的。最好将标签留在构成约束的谓词之外:

solve(N, Z-L):-
        L = [A,B,C,D],
        L ins 1..sup,
        N #= A * B * C * D,
        all_distinct(L),
        A #< B, B #< C, C #< D,
        Z #= A+B+C+D.

如果没有残差约束,你仍然可以立即得到解:

?- solve(30, Solution).
Solution = 11-[1, 2, 3, 5].

(我们不再调用 labeling/2!)

如果你特别喜欢A + B + ... = Sum格式的方案,还是可以让顶层帮你打印。只需将谓词的头部更改为:

solve(N, A+B+C+D=Z) :-
    % rest as in the last example

然后:

?- solve(30, Solution).
Solution =  (1+2+3+5=11).