Модификация алгоритма Дейкстры для реализации A*

Я нахожусь в процессе создания имитации лабиринта мыши, бегущей по лабиринту. Алгоритм Дейкстры великолепен и все такое, но он не особенно влияет, когда участвуют кошки, поэтому я пытаюсь изменить мою существующую реализацию Дейкстры на поиск A * с эвристикой для избегания кошек, которые перемещаются по лабиринту.

Проблема, с которой я сталкиваюсь, когда просматриваю какой-то псевдокод, заключается в том, что я не уверен, какие структуры эквивалентны или что мне нужно будет ввести, чтобы это заработало. Может ли кто-нибудь дать какие-либо советы или подтолкнуть в правильном направлении?

struct path_node *shortestPath(float A[GsizeSqr][GsizeSqr], int xi, int yi, int xf, int yf)
{
    /*
    Solves for the shortest path between grid point (xi,yi) and (xf,yf)
    on the graph encoded by A using Dijkstra's shortest path method.

    The shortest path is returned as a linked list of nodes to be visited.

    Keep track of visited nodes, and the predecessor
    for each node that has been explored while computing the shortest path.*/

    if (xi<0||xi>=Gsize&&yi<0&&yi>=Gsize||xf<0||xf>=Gsize||yf<0||yf>=Gsize)
    {
        fprintf(stderr,"shortestPath(): Endpoint(s) outside of the graph!\n");
        return(NULL);
    }

    int i, j, pCount, findN, row, col, icnt, stNode, finNode, xcnt, ycnt;
    finNode = yf * ceil(sqrt(GsizeSqr)) + xf; //index of start node given its row and col value
    stNode = yi * ceil(sqrt(GsizeSqr)) + xi; //index of finish node given its row and col value

    int p[GsizeSqr]; //predecessors
    int d[GsizeSqr]; //distance from source
    int flags[GsizeSqr]; //(0, 1) for unvisited, visited)

    int g_score[GsizeSqr];
    int f_score[GsizeSqr];

    PriorityQueue Q; //Initialize priority queue that stores (priority, key) values
    Q = init_heap(GsizeSqr);    

    path_node *start; //Maintain a pointer to the starting node
    start = newPathNode(xi, yi);
    start->next = NULL;

    //Initialize p and d with infinity and NULL values (note: -1 means null and 1000000 means inf)
    for(i=0; i < GsizeSqr; i++){
        p[i] = -1;
        d[i] = 10000000;
        flags[i] = 0;
    }

    for(i=0; i < GsizeSqr; i++){
        node in;
        in = create_node(10000000, i);
        enqueue(Q, in);
    }

    //(Note: PQ uses 0 as a sentinel node to make calculating left, right, and parents easier, elements begin at 1)
    decrease_priority(Q, stNode+1, 0); //setting start node in PQ.
    d[stNode] = 0;

    g_score[stNode] = 0;
    //For my heuristic, I'm thinking just using manhattan distances between mouse and cat agents
    f_score[stNode] = g_score[stNode] + heuristic(xi, yi, xf, yf);

    while(Q->heap_size != 1){ //while Q not empty
        node u;
        u = dequeue(Q);
        flags[u.key] = 1;

        //For each adjacent node A[u.key][i]
        for(i=0; i < GsizeSqr; i++){
            if(A[u.key][i] != 0){
                findN = find_node(Q, i);
                if(flags[i] == 0){ //If it is unvisited and new path distance is shorter
                    if(findN != 0 && (d[i] >= A[u.key][i] + d[u.key])){ //reset values and update PQ and mark visited
                        d[i] = A[u.key][i] + d[u.key];
                        p[i] = u.key;                       
                        flags[i] = 1;
                        decrease_priority(Q, findN, d[i]);
                    }
                }
            }
        }
    }

    // Begin selectively filling our LL with values from p[]
    icnt = finNode;
    appendLL(start, xf, yf);
    while(icnt != stNode){
        icnt = p[icnt];
        xcnt = icnt % (int)ceil(sqrt(GsizeSqr));
        ycnt = icnt / (int)ceil(sqrt(GsizeSqr));
        appendLL(start, xcnt, ycnt);
    }

    clean_heap(Q);
    return reverseLL(start);
}

person Community    schedule 04.08.2012    source источник
comment
У вас есть актуальный, более конкретный вопрос?   -  person BlueRaja - Danny Pflughoeft    schedule 04.08.2012
comment
В частности, мне интересно, есть ли способ преобразовать алгоритм Дейкстры в A *, не переписывая все это?   -  person    schedule 05.08.2012
comment
нет необходимости переписывать. например вам понадобится широта, долгота каждой точки и функция расстояния. Дейкстра — это просто алгоритм с предполагаемым расстоянием до цели == 0. Посмотрите: github.com/karussell/GraphHopper/blob/master/core/src/main/java/   -  person Karussell    schedule 10.08.2012


Ответы (1)


Возможно, вы уже это знаете, но единственное теоретическое различие между алгоритмом A* и алгоритмом Дейкстры с точки зрения поиска наилучших результатов — это функция стоимости f(n). Алгоритм Дейкстры — f(n) = g(n), а A* — f(n) = g(n) + h(n). Подробнее читайте на AIMA.

С точки зрения вашего кода, в настоящее время он хранит g(n) = A[u.key][i] + d[u.key] в d[i], поэтому вам нужно изменить его для хранения g (n) + h (n). Вам не нужны эти новые переменные g_score и f_score, просто добавьте эвристику в конец этой строки и инициализацию d[stNode].

person Jeremy W. Murphy    schedule 04.02.2013