最短路径算法之AStar算法(四) 可变H函数

前面的文章已经讨论过,当H函数可变时,前面给出的AStar算法伪过程存在问题,并且通过实际的例子证明了问题的存在。现在,让我们具体分析一下问题究竟出现在什么地方。

 

我们回顾一下AStar算法的证明过程,其中一个关键的过程在于结论2的得出。结论2的得出依靠引理3。如果H函数可变,那么引理3是不成立的。对于某个节点node而言,F(node)=G(node)+H(node)。如果H值不变,则当G值最小时F值最小。如果H函数可变,则当函数G函数最小时,对于当前的H值来说是最小的F值。可是如果后面H值变了,则对于某个稍大的G值而言,所得的F值可能会小于之前那个F值。
我们来看看注意点7的过程和图2。

                      图2

 

开始的H值为:H(A)=-100,H(C)=40,H(end)=0。先扩展start节点然后是A节点。此时从start节点到A节点的路径值G(A)=100,F(A)=0,此时A的F值并不是最小值。如果H函数值不变,则扩展C节点时会再次计算A节点的F值,因为G(A)=30,则F(A)=-70,此时根据引理3,该G(A)为最小值,对应的F值是最小值。可是H函数值可变,当G(A)达到最小值时,H(A)变成了20远大于之前的H值-100,使得尽管G值达到最小,但是对应的F值并没有达到最小,根据AStar算法,不会进行更新,使得从start到A的路径没有更新成从start到C到A。


我们现在对算法作出修改,在原始的算法中,注意注释中的程序注意点1和程序注意点2,比较都是基于F值进行比较,现在我们对这两处作出修改,比较基于G值进行。


作出了修改以后,引理3就不存在了。因为比较基于G值进行比较,G(S1)= Pstp (start-S1)是最小值,设定此时的F值为F1,根据修改过的AStar算法,此时节点S1的F值不会改变。并且因为H(S1)<=β(S1),F1<= Pstp (start-S1)<=N<M。至此,结论1仍然成立。
现在我们假设节点Sm以最小的G值进行了扩展,1<=m<=k,G(Sm)= Pstp(start-Sm),此时对应的F值是Fm。下面看看节点Sm+1。如果m=k,那么Sm+1就是end节点。
扩展Sm节点时,因为Sm+1节点是其后继节点,则计算Sm+1节点的F值为F(Sm+1)=G(Sm+1)+H(Sm+1)=G(Sm)+w(Sm,Sm+1)+ H(Sm+1)。因为G(Sm)= Pstp(start-Sm)。因为Sm节点以及Sm+1节点都是最短路径stp上的节点,很显然,Pstp(start-Sm)+w(Sm,Sm+1)= Pstp(start-Sm+1)。因此,F(Sm+1)= Pstp(start-Sm+1)+ H(Sm+1)<=N<M。令此时的F值为Fm+1。至此结论2仍然成立。
结论1和结论2仍然成立。和上面的证明相同的过程,可以得出算法的正确性。
现在将修改过的算法伪过程列出来:

 

struct Node{
    int g;   //该节点的g值
    int h;   //该节点的h值
    int f;   //该节点的f值
    Node* pre;  //该节点的前驱节点
};


AStar_Search(){
    struct  Node  start_node;
    start_node.g = 0;
    start_node.h = H(start);
    start_node.f = start_node.h;
    start_node.pre = NULL;

 

    OPEN链表 = [start_node]; CLOSE链表 = [];

 

    while ( OPEN链表非空 ) {

        如果H函数发生了变化,更新OPEN链表中的Node结构的h和f属性


        从OPEN链表中取得F值最小的Node,称之为x_node,对应的节点称之为为x;
        从OPEN链表中删除x_node;

 

        if (x是end节点){
            根据每个节点对应的node结构的pre指针,返回路径;
        }

 

        for (x的每一个后继节点y){
            struct  Node  y_node;
            y_node.g = x_node.g+w(x,y);
            y_node.h = H(y);
            y_node.f = y_node.g+y_node.h;
            y.pre = x_node;

 

            if( y不在OPEN表 and 不在CLOSE表中){
                把y_node放到OPEN表中;
            }else  if( y在OPEN表中){
                取出OPEN表中的y节点对应的Node结构,称之为y_open;

 

                if( y_node.g小于y_open.g) {               //程序注意点1
                    y_open.g=y_node.g;
                    y_open.h=y_node.h;
                    y_open.f =y_node.f;
                    y_open.pre = y_node.pre;
                }
            }else{              //y在CLOSE表中
                取出CLOSE表中的y节点对应的Node结构,称之为y_close;


                if(y_node.g小于y_close.g){              //程序注意点2
                    将y_close从CLOSE链表中删除
                    把y_node放到OPEN表中;
                }
            }
        }  //end  for

 

        将x_node放入到CLOSE表中;


    }    //end  while
}    // end  AStar_Search

  

H函数毕竟是一个估计函数,随着算法的进行,有可能对节点的H值进行更新以更准确的反映出节点到终点的最短路径值。因此,这里对算法的修改会具有某些实际意义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值