【问题标题】:Prolog Calling predicates within predicates correctlyProlog 在谓词中正确调用谓词
【发布时间】:2014-03-03 19:23:16
【问题描述】:

我在 Prolog 中有两个谓词,第一个确实返回两​​个列表(带 w/e 的向量)的正确点积……第二个是当您将列表乘以列表(矩阵)列表时,它将返回一个列表。当我尝试传递诸如([1,2],[[3,4],[5,6],[7,8]], X) 之类的东西时,第二个失败了。任何精通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).

【问题讨论】:

  • 你有两个问题。一个是N is getDotProd...,你的意思是getDotProd(List, MH, N)。另一个是getDotProd 的两个规则没有相同的数量:第一个有四个参数,第二个有三个。
  • 是的,我修好了,我的笨蛋哈哈。感谢您的输入,所以就像我在第二个谓词中调用 getDotProd 时一样,我只是传递一个 N 而不是将 N 设置为谓词?我已经不太喜欢 prolog 了:/ .
  • Prolog 是为符号计算而设计的。如果您尝试实现symbolic differentiation 而不是线性代数,我保证您会获得更多乐趣。如果这里的目标是享受 Prolog 的乐趣,我会选择一个不同的问题;如果这里的目标是做矩阵数学,我会选择另一种语言——可能是OctaveJulia
  • 知道了,是的,到目前为止所做的更改在 vecTimesMatrix 的第一个谓词中添加了 [] 而不是 _ 并将另一行固定为 getDotProd(List,MH,N) .. 仍在跟踪中它似乎接受了第一个电话然后爬行一次并在下一次失败。不过,我今天会继续玩它。如果我有选择的话,我会用 C 或 C++ 来做这件事。
  • @user3376151 Prolog 的新手不喜欢该语言的主要原因是他们认为它应该像他们熟悉的其他语言一样,但只是有自己的曲折。然而,在使用 Prolog 时,最好检查一下你所知道的关于其他语言如何工作的所有信息,并了解 Prolog 作为一种关系语言是如何工作的。然后你就可以更有效地把它应用到你的线性代数问题上,正如丹尼尔所说,真的很喜欢它擅长的那些问题。

标签: list vector matrix prolog


【解决方案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 的查询实例化为向量List 和向量MH 的点积。从逻辑上讲,递归调用应该是说ListMtail 的向量乘积是最终乘积的尾部
  3. 基本情况假设第一个参数减少到[],但事实并非如此。 List 在整个递归过程中始终保持原样。因此,您应该使用 _ 而不是 [](它将保持其价值,但在基本情况下您不关心它)。
  4. 基本情况有第二个参数[[]],但这不是空列表的正确形式。这实际上是一个由一个元素组成的列表,该元素是空列表。实际上,即使第二个参数是“列表列表”,空列表仍然是[]

将它们放在一起(并根据 de facto 约定使用下划线而不是驼峰式大小写来重命名谓词):

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

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

一旦您学会思考 prolog 的思考方式(相关性),您会发现它更有趣。 :)

【讨论】:

  • 哇,感谢您如此深入,我想在阅读您的回答后,我现在明白了!好人。
  • 我希望我能给你+10。
【解决方案2】:

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

getDotProd([], [], 0).

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

N is getDotProd(List, MH, _)

您不能在标准 Prolog 上定义自己的函数。您需要将该目标替换为:

getDotProd(List, MH, N)

还有其他问题,但这应该可以帮助您进步。

【讨论】:

  • 啊,这应该是 0.0 并且在我的实际代码中是正确的,因为它是一个返回的浮点数,在另一台计算机上快速输入我的代码我打错了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多