【问题标题】:Prolog: Multiplying 2 lists with 1 of them not instantiated?Prolog:将 2 个列表与其中 1 个未实例化的列表相乘?
【发布时间】:2024-01-03 17:34:01
【问题描述】:

我正在尝试编写一个规则,该规则可以返回两个列表中每个元素的乘积之和(相同长度)。

这是我现在拥有的:

sum(0, _, []).
sum(Result, [H1|T1], [H2|T2]) :- 
    sum(Remaining,T1, T2),
    Remaining is Result - (H1*H2).

当列表之一未实例化时,它将不起作用。为了实现以下目标,我需要进行哪些更改?

sum([1,2],X,3).
X = [3,0].

谢谢。

【问题讨论】:

  • 我认为X = [1,1] 在您的示例中也是正确答案。你想让它产生所有的答案吗?还是您有其他限制?根据示例,我假设您只处理非负整数?你没说。这是作业吗?您可以使用 CLPFD 库吗?这将是处理这个问题的自然方法。
  • @lurker 是的,它应该产生所有带有非负整数输入的答案。它来自作业,因此我不能使用任何库。谢谢。

标签: recursion prolog dot-product


【解决方案1】:

您计算的内容通常称为dot product(也称为标量积或内积)。

您写的是不允许使用库。这肯定是指外部库——而不是作为 SWI Prolog 一部分的标准库,对吧?

以下谓词list_list_dotProduct/3 大致对应您实现的代码。它使用有限域约束(#>=)/2(#=)/2 来允许非单向整数运算:

:- use_module(library(clpfd)).

list_list_dotProduct([],[],0).
list_list_dotProduct([X|Xs],[Y|Ys],Sum) :-
    X   #>= 0,
    Y   #>= 0,
    Sum #=  X*Y + Sum0,
    list_list_dotProduct(Xs,Ys,Sum0).

考虑以下查询:

?- list_list_dotProduct([1,2],Xs,3), label(Xs).
Xs = [1, 1] ;
Xs = [3, 0].

另外,这是一个基于预定义谓词same_length/2ins/2scalar_product/4替代实现

list_list_dotProduct(Xs,Ys,Prod) :-
    same_length(Xs,Ys),
    Xs ins 0..sup,
    Ys ins 0..sup,
    scalar_product(Xs,Ys,#=,Prod).

【讨论】:

  • 很好的答案。在过去一周左右的时间里,这个问题出现了大量的变化。仍然不是很清楚谁给出了这个练习明确禁止使用像 clp(fd) 这样的库,或者学生是否误解了。班主任让学生们如此措手不及,也让人有些遗憾。
  • 您会惊讶于在一些高等教育机构中教授 Prolog 的程度有多么糟糕。太糟糕了,最好说“有一种叫做 Prolog 的语言,谷歌它”然后把它留在那里。教坏东西只会造成伤害。
  • 很好的解决方案,+1!请注意,尽管scalar_product/4 要求它的第一个参数是接地的,所以当它是包含变量的 first 参数时,list_list_dotProduct/3 的第二个版本将不起作用,例如:?- list_list_dotProduct([X,Y], [1,2], Prod). .在这种情况下,您的初始版本也可以按预期工作。对于这类问题,我也强烈推荐 CLP(FD) 约束。在我看来,要求在这种情况下不使用 CLP(FD) 的人要求“使用 Prolog 而不使用 Prolog”。
最近更新 更多