【发布时间】:2013-05-08 14:52:43
【问题描述】:
我的逻辑课程有一个家庭作业,但或多或少不知道如何解决它... 像
这样的查询 ?- find(a,[r(a,[b,d]),r(b,[a,c,e]),r(c,[b]),r(d,[a,e]),
r(e,[b,d,f]),r(f,[e,g]),r(g,[f])],Path).
Prolog 应该返回给定图中所有可能的路径。术语 r(X,List) 定义了图,意味着可以从节点 X 到达 List 中的节点。在这种情况下,输出将是:
Path = [a,b,c] ;
Path = [a,b,e,d] ;
Path = [a,b,e,f,g] ;
Path = [a,d,e,b,c] ;
Path = [a,d,e,f,g] ;
false.
虽然我已经掌握了 SE 和 Web 上针对类似问题的众多解决方案的窍门,但我不知何故太笨了,无法弄清楚如何在此作业中使用图形的定义。
我认为 find(Start,...) 应该使用 r(Start,List) 中列表的所有成员递归调用,但作为 Prolog 的新手(我们只是做了标准的家谱.. .) 我不知道该怎么做。
任何帮助将不胜感激。我知道我没有太多可以开始的事实,但我已经花了半个晚上试图弄清楚一些事情,直到现在我没有任何线索。
/编辑:
对于初学者,我想我需要某种基本情况来中止递归。 我觉得应该是
find([],_,_).
因为我猜最后一个递归调用不会有任何开始,或者
find(_,[],_).
假设当程序完成处理时,定义相邻节点的术语列表应该是空的。
现在是实际调用。大概是这样的
find(Start,[r(Start,[Adjacent|Restadj])|Rest],Path):-
find(???).
我的问题如下:
-如何让程序使用 r(...) 术语中的列表成员作为下一个开始?
-如何检查节点是否已被“访问”/如何从 r 中的特定列表中删除节点
-如何将找到的节点放入路径列表?简单地追加?还是使用 [Path|Start] 之类的东西执行递归调用?
如您所见,这并不多。一些暗示性的问题会很好,因为 Prolog 看起来很有趣,因此学习起来很有趣......
在使用了简洁的 PDT-Eclipse 跟踪工具一段时间后,我想我理解了该程序在做什么。我现在不明白为什么最后一个节点总是丢失。回溯失败后,例如因为 r(c,[b]) 是下一个找到的术语,而 memberchk(b,[b]) 因否定而失败(这就是我的事情 + 所做的)并且没有其他术语与 r(c ,X) 可以找到,它开始寻找从节点 b 出发的其他可能性,节点 b 在 r(b,[...]) 中留下了相邻的节点。但是为什么程序忘记将节点 c 放入 Path 列表中呢?是否有可能做某种 if-then-else 以防万一
member(r(Node, Adjacent), Graph),
member(AdjNode, Adjacent),
\+ memberchk(AdjNode, Seen),
失败,仍然将最后一个节点附加到路径?
【问题讨论】:
-
向我们展示您的想法。我们了解它是否不完整或不正确,但有助于了解您的尝试。
-
为什么投反对票?这不像 OP 只是在这里放弃了作业(就像关于数独的其他问题一样);他清楚地表明他试图解决它/考虑它。
-
是的,我知道在写考试的时候不会有人帮我做我的工作,所以仅仅寻求解决方案是愚蠢的。
标签: path prolog find graph-theory