Prolog 对于length/2如何添加人类可读的变量名

Prolog 对于length/2如何添加人类可读的变量名,prolog,prolog-toplevel,Prolog,Prolog Toplevel,如何为系统生成的变量名显示人类可读的变量名 举个简单的例子: ?- length(Ls,N). Ls = [], N = 0 ; Ls = [_5112], N = 1 ; Ls = [_5112, _5118], N = 2 ; Ls = [_5112, _5118, _5124], N = 3 不如 ?- length(Ls,N). Ls = [], N = 0 ; Ls = [a], N = 1 ; Ls = [a, b], N = 2 ; Ls = [a, b, c], N = 3

如何为系统生成的变量名显示人类可读的变量名

举个简单的例子:

?- length(Ls,N).
Ls = [],
N = 0 ;
Ls = [_5112],
N = 1 ;
Ls = [_5112, _5118],
N = 2 ;
Ls = [_5112, _5118, _5124],
N = 3
不如

?- length(Ls,N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1 ;
Ls = [a, b],
N = 2 ;
Ls = [a, b, c],
N = 3 
映射

_5112 = a
_5118 = b
_5124 = c

详细信息

我发现的最接近的解决方案使用了
variable\u names(Vars)
选项,但我的问题不是使用
read\u term
从控制台获取术语

如果这是一个副本,让我知道;我找不到


真正的问题是基于生成测试用例数据:

?- length(Ls,N),list_partitionedNU(Ls,Ps).
Ls = Ps, Ps = [],
N = 0 ;
Ls = [_5242],
N = 1,
Ps = [[_5242]] ;
Ls = [_5242, _5248],
N = 2,
Ps = [[_5242], [_5248]] ;
Ls = [_5242, _5248],
N = 2,
Ps = [[_5242, _5248]] ;
Ls = [_5242, _5248, _5254],
...
有关
列表,\u partitionedNU/2
,请参见和


在回答后跟进

基于威廉

partitions(Ps) :-
  length(Ls,N),
  assign(Ls),
  list_partitionedNU(Ls,Ps).

?- partitions(Ps).
Ps = [] ;
Ps = [[a]] ;
Ps = [[a], [b]] ;
Ps = [[a, b]] ;
Ps = [[a], [b], [c]] ;
Ps = [[a], [b, c]] ;
Ps = [[a, b], [c]] ;
Ps = [[a, c], [b]] ;
Ps = [[a, b, c]] ;
Ps = [[a], [b], [c], [d]] ;
Ps = [[a], [b], [c, d]] ;
Ps = [[a], [b, c], [d]] ;
Ps = [[a], [b, d], [c]] ;
Ps = [[a], [b, c, d]] ;
Ps = [[a, b], [c], [d]] ;
Ps = [[a, c], [b], [d]] ;
Ps = [[a, d], [b], [c]] ;
Ps = [[a, b], [c, d]] ;
Ps = [[a, c], [b, d]] ;
Ps = [[a, d], [b, c]] ;
Ps = [[a, b, c], [d]] ;
Ps = [[a, b, d], [c]] ;
Ps = [[a, c, d], [b]] ;
Ps = [[a, b, c, d]] ;
...
基于卡佩罗

partitions(Ps) :-
    length(Ls,N),
    numbervars(Ls,0,N),
    list_partitionedNU(Ls,Ps).

?- partitions(Ps).
Ps = [] ;
Ps = [[A]] ;
Ps = [[A], [B]] ;
Ps = [[A, B]] ;
Ps = [[A], [B], [C]] ;
Ps = [[A], [B, C]] ;
Ps = [[A, B], [C]] ;
Ps = [[A, C], [B]] ;
Ps = [[A, B, C]] ;
Ps = [[A], [B], [C], [D]] ;
Ps = [[A], [B], [C, D]] ;
Ps = [[A], [B, C], [D]] ;
Ps = [[A], [B, D], [C]] ;
Ps = [[A], [B, C, D]] ;
Ps = [[A, B], [C], [D]] ;
Ps = [[A, C], [B], [D]] ;
Ps = [[A, D], [B], [C]] ;
Ps = [[A, B], [C, D]] ;
Ps = [[A, C], [B, D]] ;
Ps = [[A, D], [B, C]] ;
Ps = [[A, B, C], [D]] ;
Ps = [[A, B, D], [C]] ;
Ps = [[A, C, D], [B]] ;
Ps = [[A, B, C, D]] ;
...

我们可以构造一个谓词,以递归的方式将值“赋值”给函子中的变量,并使用一个累加器跟踪最新赋值的“名称”

例如:

assign(Term) :-
    assign(Term, 97, _).

assign(X, N, N1) :-
    var(X),
    !,
    char_code(X, N),
    N1 is N+1.
assign(F, N, N1) :-
    F =.. [_|A],
    assign_list(A, N, N1).

assign_list([], N, N).
assign_list([H|T], N, NT) :-
    assign(H, N, N1),
    assign_list(T, N1, NT).
?- length(L, _), assign(L).
L = [] ;
L = [a] ;
L = [a, b] ;
L = [a, b, c] ;
L = [a, b, c, d] ;
L = [a, b, c, d, e] ;
L = [a, b, c, d, e, f] .
?- Q = [L, [_, _]], length(L, _), assign(Q).
Q = [[], [a, b]],
L = [] ;
Q = [[a], [b, c]],
L = [a] ;
Q = [[a, b], [c, d]],
L = [a, b] ;
Q = [[a, b, c], [d, e]],
L = [a, b, c] .
例如:

assign(Term) :-
    assign(Term, 97, _).

assign(X, N, N1) :-
    var(X),
    !,
    char_code(X, N),
    N1 is N+1.
assign(F, N, N1) :-
    F =.. [_|A],
    assign_list(A, N, N1).

assign_list([], N, N).
assign_list([H|T], N, NT) :-
    assign(H, N, N1),
    assign_list(T, N1, NT).
?- length(L, _), assign(L).
L = [] ;
L = [a] ;
L = [a, b] ;
L = [a, b, c] ;
L = [a, b, c, d] ;
L = [a, b, c, d, e] ;
L = [a, b, c, d, e, f] .
?- Q = [L, [_, _]], length(L, _), assign(Q).
Q = [[], [a, b]],
L = [] ;
Q = [[a], [b, c]],
L = [a] ;
Q = [[a, b], [c, d]],
L = [a, b] ;
Q = [[a, b, c], [d, e]],
L = [a, b, c] .
因此,我们在树中“漫游”并为变量赋值。对于上述实现,我们不考虑现有常量。因此,我们可以将已经存在的值分配给变量。此外,我们只是不断增加字符代码,所以最终我们将获得符号、控制字符和字符

但是,通过首先检查函子并获得要跳过的常量列表,可以“解决”上述缺点。此外,当然可以改进术语生成器,例如,在
z
之后生成
aa

@DanielLyons指出谓词,它可以大大简化
assign/1
谓词,如:

assign(Term) :-
    term_variables(Term, Vars),
    assign_list(Vars, 97).

assign_list([], _).
assign_list([H|T], N) :-
    char_code(H, N),
    N1 is N+1,
    assign_list(T, N1).
当然,这仍然不能解决上述缺点,尽管如前所述,我们可以通过使用除字符代码以外的其他方法来获得常量名称,并首先通过wak查找正在使用的常量来解决这些缺点。

旧的goldie已经被重新审视:

?- length(L,5),numbervars(L,0,N).
L = [A, B, C, D, E],
N = 5.
不确定它是否真的有用,但探索它很好

?- length(L,5),numbervars(L,0'a,N).
L = [T3, U3, V3, W3, X3],
N = 102.

我们不要忘记一个显而易见的选择:一个不同的Prolog处理器

使用SICStus Prolog 4.5.0():

|?-Xs=[_C,f(_E)|长度(Xs,N)。 N=2,Xs=[_C,f(_E)]; N=3,Xs=[_C,f(_E),_A]; N=4,Xs=[_C,f(_E),_A,_B]; N=5,Xs=[_C,f(_E),_A,_B,_D]; N=6,Xs=[_C,f(_E),_A,_B,_D,_f]; N=7,Xs=[[u C,f(_E),[u A,[u B,[u D,[u f,[u G]。。。
你可以“遍历”这个函子,每次分配变量时,你都会得到你存储在累加器中的下一个“名称”。小心约束!您正在统一可能连接到约束的实际变量。对于你的例子,考虑<代码>长度(XS,5),CPLFD:ALLUXY不同(XS)< /代码>。我们可以结合使用它来让它以任意的术语工作。在代码< No.BulvARS/3 > @ false:究竟是什么已经被重新访问了:IRC又是一个类似“$var”(n)的模式。但我不太确定,让我知道。。。无论如何,我暗示,即使我们得到这样的模式,也可以应用映射列表来理解数据。(你所说的IRC是什么意思…?)
numbervars/3
'$VAR'/1
一样定义terms@CapelliC在SWI中,尝试
length(L,5),numbervars(L,0,N);正确。
。当显示
,按“w”。)(要撤消,请重复,然后按“p”。)LOL
?-aggregate\u all(计数、字符类型(\u、alpha)、计数)。Count=811138。
值得注意的是,SICStus如何避免已经使用的变量名
\u C
\u E
@false。真聪明。为什么没有可移植的“最佳”顶级?这需要编写