输出路由并避免用户在prolog中输入的路由

时间:2013-07-18 11:22:26

标签: path prolog

输出prolog列表路径并避免用户在prolog中输入的某些路由。

嗨,我正在研究一个项目,一个建筑物包含区域,每个区域都有一个出口,我们想通过区域疏散人员退出,用户输入两个参数,第一个是“感染区域” ,另一个参数是“我们要疏散的人的区域”。 输出应该是从“我们想撤离的人员区域”到退出避开受感染区域的所有安全路线。

例如:  用户输入(z11, z12) //表示z11已被感染,我们要撤离的人员是z12。

输出:z12->z22->exit3. and z12->z21->exit2. and z12->elevators

事实是:

 path(z11,z12).
 path(z12,z11).
 path(z12,z22).
 path(z12,z21).
 path(z22,z12).
 path(z22,z21).
 path(z21,z22).
 path(z11,exit1).
 path(z12,elevators).
 path(z21,exit2).
 path(z22,exit3).

请帮我写代码。

1 个答案:

答案 0 :(得分:1)

您选择命名谓词path/2是不方便的,因为我们可能想要调用生成该名称退出路径的东西。首先,我要将您的所有事实从path/2重命名为connected/2。然后你会想要注释出口:

exit(exit1). exit(exit2).
exit(elevators).

否则你必须在其他地方对它们进行硬编码。

一件简单的事情是解决一般路径问题,然后检查以确保路径不包含受感染的站点。这看起来像这样:

path(Start, Path) :- path(Start, Path, []).

path(Start, [Exit], Seen) :-
    exit(Exit),
    connected(Start, Exit),
    \+ memberchk(Exit, Seen).
path(Start, [Next|Rest], Seen) :-
    connected(Start, Next),
    \+ memberchk(Next, Seen),
    path(Next, Rest, [Next|Seen]).

safe_path(Start, Avoid, Path) :-
    path(Start, Path),
    \+ memberchk(Avoid, Path).

这很容易推广处理避免区域集:

safe_path(Start, AvoidList, Path) :-
    path(Start, Path),
    forall(member(Avoid, AvoidList), \+ memberchk(Avoid, Path)).

Prolog中有趣和有趣的大部分内容都是通过生成/测试范例完成的。最简单和最直接的表述通常是你产生太多的(通常,你可能会说),并将所有限制放在测试中。一般来说,通过使生成器更加智能地生成可能性,您可以获得更好的性能 - 将代码从“测试”部分移动到“生成和测试”的“生成”部分。

通常,您面临的第一个问题是生成无限树。图表尤其如此。带有memberchk/2列表的path/3中的Seen用于防止循环,并且必须使路径集合有限。在exit/1的基本情况下使用path/3也有助于提高性能,因为我们不会生成中间路径。很高兴,根据您的具体情况,您可以逃脱这一点。

最后避免躲避糠..生成者不知道要避免这些节点,因此测试会生成并删除所有中毒路径。如果这种方式的性能不够,您可以直接将该代码移到path/2,对使用Seen列表完成的检查进行类似的检查。