输出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).
请帮我写代码。
答案 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
列表完成的检查进行类似的检查。