自定义子集不回溯



我刚开始学prolog,我一直在做一些作业。在我代码的某些部分,我必须在回溯时生成给定集合的子集。这意味着,代码应该尝试一个子集,当它无法满足下一个条件时,再尝试下一个子集。我已经做了一些研究,默认函数子集不会回溯,因为正如在这个问题中解释的那样,两个参数都是输入参数。所以我做了一个定制的,它仍然不能回溯。你能给我提示一下我做错了什么吗?下面是我的代码:<>之前numNutrients(8)。产品(牛奶、[2,4,6])。产品(猪排,[1,8])。产品(酸奶、(3,1))。产品(亲爱的,[5、7])。产品(塑料、[3、5、2])。产品(魔法,[5、7、8])。

nutrientlist(N,L):-findall(I,between(1,N,I),L). subset2([],[]):-!. subset2([X|T],[X|T2]):- subset2(T,T2). subset2([_|T],[T2]):- subset2(T,T2). shopping(K,L):- numNutrients(J), nutrientlist(J,N), findall(P,product(P,_),Z), subset2(X,Z), length(X,T), T =< K, covers(X,N), L = X. covers(_,[]):-!. covers([X|L],N):- product(X,M), subset2(M,N), subtract(N,M,T), covers(L,T). main:- shopping(5,L), write(L). 之前

问题是关于谓词购物(K,L)的。当它到达谓词subset2时,它给出长度为6(而不是5)的整个集合,然后失败并且不返回。因为所有之前的谓词都不能回溯,所以它就失败了。

那么,为什么subset2不回溯呢?

感谢您的宝贵时间。

主要焦点:subset2/2

首先,让我们只关注显示与您期望的属性不同的谓词。

在您的情况下,这是只有 subset2/2,由您定义为:

<>之前Subset2 ([], []):- !subset2([X|T], [X|T2]):-subset2 (T, T2)。subset2([_|T], [T2]):-subset2 (T, T2)。之前我现在将使用声明式调试来定位问题的原因。

要应用此方法,我删除!/0 ,因为声明式调试在单调逻辑程序上效果最好。有关更多信息,请参阅逻辑纯度。因此,我们将处理:

<>之前subset2([][])。subset2([X|T], [X|T2]):-subset2 (T, T2)。subset2([_|T], [T2]):-subset2 (T, T2)。之前<标题> 测试用例

让我们首先构造一个测试用例,产生非预期的答案。例如:

<>之前?- subset2([a], [a,b])。假。之前

显然不是的本意。我们可以概括测试用例吗?是的:

<>之前- subset2([a], [a,b] |_])。假。之前

所以,我们现在有一个无限的例子族,产生错误的结果。

练习:是否也存在程序过于一般化的情况,也就是说,测试用例成功,尽管它们应该失败?

<标题> 定位错误

为什么在上述情况下会出现意外失败?为了找出这些错误,让我们概括程序。

例如:

<>之前subset2 ( _ ,[])。subset2([_|T], [_|T2]):-subset2 (T, T2)。subset2(_, [T2]):-subset2 (T, T2)。之前

即使有了这个大量的概括,我们仍然有:

<>之前- subset2([a], [a,b] |_])。假。之前

也就是说,在很多情况下,我们期望查询成功,但是失败。这意味着剩余的程序,即使它是原始程序的大量泛化,仍然是太特定

纠正程序

要使所示的案例成功,我们必须:

  • 添加子句,描述我们需要的情况
  • 更改现有条款,使涵盖这些情况<nbsp;>
例如,一种解决方法是添加到数据库中: <>之前subset2 ([], [a, b | _])。之前

我们甚至可以归纳为:

<>之前subset2([],[| _))。之前

在程序中添加其中一个或两个子句将使查询成功:

<>之前- subset2([a], [a,b] |_])。之前然而,这当然不是我们正在寻找的subset2/2的一般定义,因为它仍然会失败,例如: <>之前?- subset2([x], [x,y|_])。假。之前因此,让我们使用另一个选项,并且更正现有的定义。特别地,让我们考虑一般化程序的最后一个子句: <>之前subset2(_, [T2]):-subset2 (T, T2)。之前

注意,这个只有当第二个参数是一个只有一个元素的列表进一步约束时,才成立。这似乎太特殊了!

因此,我建议您从更改此子句开始,以便它至少使到目前为止收集的所有测试用例都成功。然后,添加必要的专门化,以使它能够精确地用于预期的情况。

最新更新