Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 如何防止循环一次后的递归_Loops_Recursion_Prolog_Prolog Cut - Fatal编程技术网

Loops 如何防止循环一次后的递归

Loops 如何防止循环一次后的递归,loops,recursion,prolog,prolog-cut,Loops,Recursion,Prolog,Prolog Cut,我才意识到这是个愚蠢的问题。很好奇是否还有人能找到漏洞 源代码: married(trump,obama). married(trump,goat). married(pepee,pepper). married(X,Y) :- married(Y,X),!. % not awesome because of infinite recursion Goal: ex. married(trump, putin). trace( first base case fails. second base

我才意识到这是个愚蠢的问题。很好奇是否还有人能找到漏洞

源代码:

married(trump,obama).
married(trump,goat).
married(pepee,pepper).
married(X,Y) :- married(Y,X),!. % not awesome because of infinite recursion

Goal: ex. married(trump, putin).
trace(
first base case fails.
second base case fails.
third base case fails.
married(trump,putin) = married(putin,trump),!.
我想要它做的是再次尝试结婚(普京、特朗普),但所有早期的基本案例都将再次失败。我们以前尝试过切换参数,但失败了。所以不要重复。只要返回false

我得到一个堆栈错误,因为直到结婚(普京,特朗普)或其他方式之前!不会返回true或false,因此无法触发剪切

更简单、更理智的方法是重写代码以防止递归。我很好奇是否有一种方法可以尝试切换args一次,如果失败则返回fail。如果你有一个很长的事实列表,如果你可以尝试arg1,arg2,反之亦然,那么你可以将这个长列表减少一半。如果我们得到疯狂的排列场景,可能会有更大的指数增长


任何洞察都将非常棒,谢谢。

您的“切换参数一次,如果失败则返回失败”的做法是正确的,尽管这是非常必要的,并没有涵盖我们期望从这种关系中获得的所有模式

要使其工作,需要将其分成两个谓词。很容易看出,使用给定接口的单个谓词是不够的

首先,辅助谓词

married_(a, b). married_(c, d). etc. 已婚者(a,b)。 已婚(c,d)。 等 然后,主谓词,基本上如您所建议:

married(X, Y) :- married_(X, Y). married(X, Y) :- married_(Y, X). 已婚(X,Y):-已婚(X,Y)。 已婚(X,Y):-已婚(Y,X)。 向解决方案中添加杂质会使情况变得更糟:几乎总是会破坏关系的一般性,从而提出一个问题:为什么要使用声明性语言atall

查询示例:

?- married(X, Y). X = a, Y = b ; X = c, Y = d ; X = b, Y = a ; X = d, Y = c. ?- married(_, X, Y). X = a, Y = b ; X = c, Y = d ; X = b, Y = a ; X = d, Y = c. -已婚(X,Y)。 X=a, Y=b; X=c, Y=d; X=b, Y=a; X=d, Y=c。
严格地说,您当然也可以只使用一个单个谓词来执行此操作,但如果这样做,您需要携带额外的信息

例如:

married(_, a, b). married(_, c, d). married(first, X, Y) :- married(second, Y, X). 已婚的。 已婚的。 已婚(第一,X,Y):-已婚(第二,Y,X)。 查询示例:

?- married(X, Y). X = a, Y = b ; X = c, Y = d ; X = b, Y = a ; X = d, Y = c. ?- married(_, X, Y). X = a, Y = b ; X = c, Y = d ; X = b, Y = a ; X = d, Y = c. -已婚(ux,Y)。 X=a, Y=b; X=c, Y=d; X=b, Y=a; X=d, Y=c。
这与您描述的方法非常相似:“我们以前尝试过切换参数,所以不要再这样做了。”

您使用“切换参数一次,如果失败则返回失败”的方法是正确的,尽管这是非常必要的,并且没有涵盖我们期望从这种关系中获得的所有模式

要使其工作,需要将其分成两个谓词。很容易看出,使用给定接口的单个谓词是不够的

首先,辅助谓词

married_(a, b). married_(c, d). etc. 已婚者(a,b)。 已婚(c,d)。 等 然后,主谓词,基本上如您所建议:

married(X, Y) :- married_(X, Y). married(X, Y) :- married_(Y, X). 已婚(X,Y):-已婚(X,Y)。 已婚(X,Y):-已婚(Y,X)。 向解决方案中添加杂质会使情况变得更糟:几乎总是会破坏关系的一般性,从而提出一个问题:为什么要使用声明性语言atall

查询示例:

?- married(X, Y). X = a, Y = b ; X = c, Y = d ; X = b, Y = a ; X = d, Y = c. ?- married(_, X, Y). X = a, Y = b ; X = c, Y = d ; X = b, Y = a ; X = d, Y = c. -已婚(X,Y)。 X=a, Y=b; X=c, Y=d; X=b, Y=a; X=d, Y=c。
严格地说,您当然也可以只使用一个单个谓词来执行此操作,但如果这样做,您需要携带额外的信息

例如:

married(_, a, b). married(_, c, d). married(first, X, Y) :- married(second, Y, X). 已婚的。 已婚的。 已婚(第一,X,Y):-已婚(第二,Y,X)。 查询示例:

?- married(X, Y). X = a, Y = b ; X = c, Y = d ; X = b, Y = a ; X = d, Y = c. ?- married(_, X, Y). X = a, Y = b ; X = c, Y = d ; X = b, Y = a ; X = d, Y = c. -已婚(ux,Y)。 X=a, Y=b; X=c, Y=d; X=b, Y=a; X=d, Y=c。
这与您描述的方法非常相似:“我们以前尝试过切换参数。所以不要再这样做。”

这些是替代事实吗?这些是替代事实吗?谢谢您的评论,mat。这就是我最后做的。我在触发这个具有剪切特性的族函数之前放置了另一个辅助函数,以防止在给定非族成员对的情况下触发这个函数。这是一个强盗式的解决方案,因为它不能解决这种关系的根本缺陷,但它已经足够了。另一个更好的方法是不使用递归,因为让我们面对它,执行一次递归的递归就像告诉奥运冠军只需一步就可以跑得很快。marriageCheck(X,Y):-(已婚(X,Y);已婚(Y,X))。您显示的最后一个版本与我发布的第一个版本相当:我使用了两个子句来表示替代项,您使用的是
(';)/2
,它也表示逻辑替代项,可以用作子句的替代项。请注意,这个谓词非常通用(这很好!),不仅可以用于检查,还可以用于生成和完成解决方案。因此,
marriageCheck
是一个用词不当的术语,在混合病例中必须这样说。我想知道(不能运行prolog atm)查询完成后会发生什么。似乎所有以前的事实都必须重写(因为已婚函数需要两个arg,而ur已婚函数需要3个arg)。但我们假设这不是问题。跟我在这里追踪。。尝试所有事实,然后我们点击已婚(第一,X,Y):-已婚(第二,Y,X)。它用(秒,Y,X)再次扫描所有事实。如果同样失败,我们会遇到已婚(第二,Y,X)V:-已婚(第二,Y,X)。这里会发生什么?我无法在脑海中追踪;。他们是一样的,所以。。到此为止?在以下情况出现之前,一切都是正确的:“…我们遇到了
已婚(第二,Y,X)
”。没有这样的条款!请注意,子句头的第一个参数是
first
。第二次尝试时,目标的第一个参数有意识地指定为
second
。因此,该条款不再适用,因为
dif(第一,第二)
。因此,该条款不再适用。为了简化,发布以下查询:
?-marred(second,X,Y)。
并查看最后一个子句是否不适用。我是我