先放中文wiki的代码,时间为2017年11月18日16:08:08。
|
|
基友猴哥告诉我,wiki上拓展子节点的时候,如果子节点出现在Close表中话,不做任何处理。而教材人工智能及其应用、算法艺术与信息学竞赛 中均对子节点的F值进行了计算,如果小于表中已有的,则必须更新(加入)到Open表中。而wiki上不论中英文版本均不做处理。那么有什么影响?
抽象的想,从起点S开始有p1、p2两条路径均可到达中间某节点A。假设从p1到达A之后,拓展A的子节点,此时A已加入到S表中,且A的子节点是在A的基础上计算的G值。那么如果路径p2到达A的代价值(G)比p1小,按照wiki的流程图,最终结果还是采用p1这条代价更大的走法,从而无法收敛到最优解(从p2到A)。
多说无益,下面我构造了个例子:
graph LR;
S{S 20}--12-->A{A 13};
S--10-->B{B 16};
B--1-->A;
A--15-->D{D 10};
起点是S,目标是X(未画出,在D之后)。节点内部的数字表示H估值,变上面的数字代表G代价。以下是按照wiki的流程:
格式为:A(G,H) 粗体表示最小F值节点。 斜体表示新加入节点。
| Step | Open | Close |
|---|---|---|
| 1 | A(12,13) B(10,16) | null |
| 2 | B(10,18) D(12+15,10) | A(12,13) |
| 3 | D(12+15,10) | A(12,13) |
到这里,拓展B的时候发现A已经在Close表中,就不采取任何操作,而D(F=37)和D之后节点的G值都是在A 12的基础上计算,明显比S→B→A(只需要11)大,故在这种情况下得到的不是最优解。
而采用更像放回Open表中的情况呢?
| Step | Open | Close |
|---|---|---|
| 1 | A(12,13) B(10,16) | null |
| 2 | B(10,18) D(12+15,10) | A(12,13) |
| 3 | D(12+5,10) A(10+1,13) | B(10,18) |
| 4 | D(10+1+15,10) | B(10,18) A(10+1,13) |
此时D的F值为26+10=36,路径是S→B→A→D,是最优路径。