在Prolog中计算多维数据集列表

时间:2012-08-13 00:44:00

标签: prolog clpfd

所以我在SWI-Prolog做一些Prolog,我遇到了一些障碍。在给定输入列表的情况下,我必须创建一个立方体列表。我目前的代码是

cubes([Head|Tail],Cubes) :-
    cubes([Head|Tail],Cubes,[]).
cubes([Head|Tail],Cubes,ActualCubes) :-
    X is Head^3,
    append(ActualCubes,[X],NewCubes),
    cubes(Tail,Cubes,NewCubes).
cubes([Tail],Cubes,ActualCubes) :-
    X is Tail^3,
    append(ActualCubes,[X],NewCubes),
    Cubes is NewCubes.

当我运行它时会出错,具体而言......

ERROR: '.'/2: Type error: `[]' expected, found `[8]' ("x" must hold one character)
   Exception: (7) cbList([1, 2], _G296, []) ? creep

我不完全确定为什么会出现这种错误,但它似乎发生在最后一行,Cubes是NewCubes。任何帮助表示赞赏:)

3 个答案:

答案 0 :(得分:5)

我认为您正在尝试使用称为 accumulator 的模式,使用包含中间结果的添加的参数重写二元关系。

除了语法错误之外,你应该注意一个累加器在这里没用,因为列表中的每个元素只与关联与另一个列表的对应元素。

图书馆(apply)有maplist / 3这种常见情况:

cube(N, C) :-
    C is N^3.
cubes(Ns, Cs) :-
    maplist(cube, Ns, Cs).

和库(clpfd)具有有趣的功能,允许(在整数域中)更好的关系处理算术。用

替换上面的多维数据集
:- [library(clpfd)].

cube(N, C) :-
    N ^ 3 #= C.

你可以写

?- cubes(X,[1,8,27]).
X = [1, 2, 3].

答案 1 :(得分:1)

首先,您使用不同数量的参数创建不同的cubes谓词。这必然会导致概念和语法问题,所以在这一点上,重新思考你在做什么。在这种情况下,尝试扩展模式匹配和递归的方式:

cubes([],[]).
cubes([H|T], [Y|Z]):-
        Y is H*H*H,
        cubes(T,Z).


betterCubes([],[]).
betterCubes([H|T], [Y|Z]):-
        ( 
          var(Y) , nonvar(H)    -> Y is H*H*H
        ; nonvar(Y) , var(H)    -> H is Y**(1.0/3.0) 
        ; nonvar(Y) , nonvar(H) -> H*H*H =:= Y
        ),
        betterCubes(T,Z).

答案 2 :(得分:-1)

在这种情况下,还可以使用差异列表来实现所需目标:

cubes( [] , [] ) .
cubes( [X|Xs] , [Y|Ys] ) :-
  Y is X*X*X ,
  cubes( Xs , Ys )
  .

输出列表是在遍历源列表时生成的,递归。最终目标cubes([],[])将空列表[]与输出列表的尾部统一起来,使其成为正确的列表。

另一种方法是使用累加器,它以相反的顺序构建输出,然后反转它:

cubes(Xs,Ys) :-
  cubes(Xs,[],T) ,
  reverse(T,Ys)
  .

cubes( [] , Ys, Ys ).
cubes( [X|Xs] , Ts , Ys ) :-
  T is X*X*X ,
  cubes( Xs , [T|Ts] , Ys )
  .

两者都是(我们应该)正确的尾递归。

相关问题