Prolog正确地在谓词中调用谓词

时间:2014-03-03 19:23:17

标签: list vector matrix prolog

我在Prolog中有两个谓词,第一个确实返回两​​个列表的正确点积(向量w / e)...第二个是当你列出一个列表列表(矩阵)时将返回一个列表。当我尝试传递诸如([1,2],[[3,4],[5,6],[7,8]], X)之类的任何内容时,第二个失败。任何精通Prolog的人都会看到我的错误?我有点卡住,因为跟踪和prolog本身只是一直返回失败。

getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
    getDotProd(T1,T2,N1),
    N is N1 + (H1 * H2).



vecTimesMatrix(_,[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
    N is getDotProd(List, MH, _),
    vecTimesMatrix(List, Mtail, N).

目前为止更新了代码:

getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
    getDotProd(T1,T2,N1),
    N is N1 + (H1 * H2).



vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
    getDotProd(List, MH, N),
    vecTimesMatrix(List, Mtail, N).

2 个答案:

答案 0 :(得分:1)

您的代码中存在几个问题。首先,您定义getDotProd/4getDotProd/3谓词。第一个是拼写错误。即getDotProd/3谓词的基本情况有一个重复的参数,它应该是:

getDotProd([], [], 0).

其次,在第二个谓词vecTimesMatrix/3中,您有一个目标,即对内置谓词is/2的调用,这将导致异常:

N is getDotProd(List, MH, _)

您无法在标准Prolog上定义自己的功能。您需要用以下内容替换该目标:

getDotProd(List, MH, N)

还有其他问题,但这可以帮助您取得进展。

答案 1 :(得分:1)

您剩下的问题出在vecTimesMatrix谓语中:

vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
    getDotProd(List, MH, N),
    vecTimesMatrix(List, Mtail, N).

的问题:

  1. 在第二个子句中,第一个参数以[List]给出,这意味着单个元素(List)的列表。在条款中对getDotProdvecTimesMatrix的后续调用表明这应该只是List
  2. 在第二个子句中,第三个参数仅显示为一个参数的列表:[N]。所以第三个参数永远不会“构建”一个列表。此外,对vecTimesMatrix的递归调用具有N作为其第三个参数,并且该参数已经被先前查询实例化为getDotProd作为向量{{1}的点积。和vectory List。从逻辑上讲,递归调用应该说 MH的矢量积List是最终产品的尾部
  3. 基本情况假设第一个参数减少到Mtail,但事实并非如此。在整个递归过程中,[]始终保持原样。因此,List代替[]而不是_(它将保留其值,但在基本情况下你并不关心它。)
  4. 基本案例有第二个参数[[]],但这不是空列表的正确形式。这实际上是一个由一个元素组成的列表,该元素是空列表。实际上,即使第二个参数是“列表列表”,空列表仍然是[]
  5. 将所有内容放在一起(并使用下划线而不是驼峰的情况重命名每个事实上的约定的谓词):

    get_dot_prod([], [], 0.0).            % Dot product of empty vectors is 0.0
                                          %   (Dot prod of vectors of unequal length
                                          %   is not defined and will fail)
    get_dot_prod([H1|T1], [H2|T2], N) :-  % N is dot product of [H1|T1] [H2|T2] if...
        get_dot_prod(T1, T2, N1),         % N1 is dot product of T1 T2, and
        N is N1 + (H1 * H2).              % N is N1 + (H1*H2) [evaluated]
    
    vec_times_matrix(_, [], []).          % Product of any vector with
                                          %   empty matrix is empty
    vec_times_matrix(List, [MH|Mtail], [N|Ntail]):-
                                          % [N|Ntail] is List x [MH|Mtail] if...
        get_dot_prod(List, MH, N),        % N is dot product of List and MH, and
        vec_times_matrix(List, Mtail, Ntail). % Ntail is List x Mtail
    

    这将产生:

    | ?- vec_times_matrix([1,2],[[1,0],[0,1]], M).
    
    M = [1.0,2.0] ? a
    
    no
    | ?- vec_times_matrix([1,2],[[1,0],[0,1],[1,1]], M).
    
    M = [1.0,2.0,3.0] ? a
    
    (1 ms) no
    

    我在上面的代码中添加了注释,以简单的方式说明如何考虑prolog谓词逻辑,这有助于定义它们。正如已经指出的那样,序言“谓词”并不充当“功能”。它描述了成功或失败的实体之间的逻辑关系。

    一旦你学会思考prolog如何思考(关系),你会发现它更有乐趣。 :)