Newsgroups: comp.ai.games
Path: cantaloupe.srv.cs.cmu.edu!rochester!cornellcs!newsstand.cit.cornell.edu!portc01.blue.aol.com!news-res.gsl.net!news.gsl.net!news.mathworks.com!newsfeed.internetmci.com!torn!watserv3.uwaterloo.ca!cnts2p28.uwaterloo.ca!user
From: smmcdowe@undergrad.math.uwaterloo.ca (Sean McDowell)
Subject: Re: Anybody experienced with the A* algorithm?  -  alg.txt [1/1]  -  alg.txt [1/1]
Message-ID: <smmcdowe-2008961649380001@cnts2p28.uwaterloo.ca>
Sender: news@watserv3.uwaterloo.ca
Nntp-Posting-Host: cnts2p28.uwaterloo.ca
Organization: University of Waterloo
X-Newsreader: Value-Added NewsWatcher 2.0b24.0+
References: <4v1gos$qf5@willow.cc.kcl.ac.uk> <01bb8b81$0679aca0$2fee60ce@speedy.imagicgames.com>
Date: Tue, 20 Aug 1996 20:51:19 GMT
Lines: 194

In article <01bb8b81$0679aca0$2fee60ce@speedy.imagicgames.com>, "Jeff Kiel" <jkiel@imagicgames.com> wrote:

> If you have a known graph (and of suck a limited number) it may be just as
> easy to perform a minimum spanning tree calculation.  Basically, that sorts
> the arcs by weight/distance, and adds one arc at a time until all nodes are
> connected.  This arc subset represents the minimum cost from one node to
> another.
> 
> Sounds good, at least :-)
> 
I think you are confusing minimum weight spanning trees with breadth first search trees. It's easy to create a graph with a minimum-weight spanning tree where the path from node A to B is not minimal, e.g.,

A---3---B
|       |
1       2
|       |
C---2---D

Using Kruskal's algorithm like you describe gives the minimum-weight spanning tree A-C-D-B but the weight of the path from A to B is then 5, not 3.

The algorithm you're looking for is based on the theorem, "The length of the shortest path from u to v in a graph G is equal to the level of v in any breadth first search tree of G with u as the root" (my intro to graph theory text). The algorithm for doing this is a variation of Prim's algorithm which is another algorithm to find a minimum-weight spanning tree. All you need to implement it is a stack. However, the algorithm requires the ability to detect when a cycle would be created, so you'd need a cycl

e detection mechanism.

You could also use Dijkstra's algorithm which can be done with arrays. Since your problem is so small maybe this is an option. Make sure you understand priority queues to figure out this code! It's from an assignment I recently finished...it finds the shortest path from node h to all other nodes in the graph. Hope this is useful! Anyone who wants to use this code for anything is welcome to.

Sean 

#ifndef DIJKSTRA_H
#define DIJKSTRA_H

///--------------------------------------------------------------------------------------
//  Preprocessor declarations
///--------------------------------------------------------------------------------------
#include <String.h>
#include <limits.h>

class Dijkstra {
public:
    Dijkstra( int **, int, int );                                       // constructor  
    void Solve( void );                                                 // solves shortest path problem
private:
    void DownHeap( int [], unsigned int[], int, int );                  // move entry down heap
    void UpHeap( int [], unsigned int [], int );                        // move entry up heap
    const int   n;                                                      // matrix size
    const int   h;                                                      // from this vertex
    int **weights;                                                      // cost matrix
}; // Dijkstra

#endif


///--------------------------------------------------------------------------------------
//  Preprocessor declarations
///--------------------------------------------------------------------------------------
#undef NDEBUG                                                       // enables assertions

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <String.h>
#include "Dijkstra.h"


///-Dijkstra::Dijkstra-------------------------------------------------------------------
//
//  Purpose:  The constructor initializes the Dijkstra object's global variables   
//
//  Requires: weights != NULL (weights is a matrix of edge weights, where INT_MAX (or a
//            number larger than any possible edge weight) represents no edge)
//
//  Ensures:  global variables are initialized
///--------------------------------------------------------------------------------------
Dijkstra::Dijkstra(
   int **weights,
   int n,
   int h 
) : weights( weights ), n( n ), h( h - 1 ) { // modify h for zero-based array addressing
    
} // Dijkstra::Dijkstra


///-Dijkstra::Solve----------------------------------------------------------------------
//
//  Purpose:  Computes the shortest path length from vertex h to all others  
//
//  Ensures:  The distance array holds the shortest path lengths
//
//  Credits:  Adapted frmo H.R. Lewis & L. Denenberg, Data Structures & Their Algorithms 
//            (New York: HarperCollins, 1991) 449.
///--------------------------------------------------------------------------------------
void Dijkstra::Solve( void )
{
    unsigned int distance[ n ]; // distance from h to each vertex
    int unknown[ n ];           // priority queue, indexes distance

    distance[ h ] = 0;          // node h distance 0 to itself  
    unknown[ 0 ] = h;           // place node h at top of heap
    for ( int i = 0; i < h; i++ ) { // initialize priority queue
        distance[ i ] = INT_MAX;    // initialize distance to "infinity"
        unknown[ i + 1 ] = i;
    } // for
    for ( i = h + 1; i < n; i++ ) { // initialize priority queue
        distance[ i ] = INT_MAX;    // initialize distance to "infinity"
        unknown[ i ] = i;
    } // for
    
    int minVertex;
    for ( i = n - 1 ; i >= 1; i-- ) { // i represents heap size after deletion
        minVertex = unknown[ 0 ];     // minimum at top of heap
        unknown[ 0 ] = unknown[ i ];  // delete minimumVertex                              
        DownHeap( unknown, distance, 0, i ); // repair heap condition
        for ( int j = 0; j < i; j++ ) {
            if ( weights[ minVertex ][ unknown[ j ] ] < INT_MAX ) { // unknown[ j ] a neighbour of minvertex?
                unsigned int maybeSmaller = distance[ minVertex ] + weights[ minVertex ][ unknown[ j ] ];
                if ( distance[ unknown[ j ] ] > maybeSmaller ) {
                    distance[ unknown[ j ] ] = maybeSmaller; // it was smaller
                    UpHeap( unknown, distance, j );          // repair heap condition
                } // if 
            } // if         
        } // for
    } // for
    
    // distance array now holds the results, do what you want with it...
    
} // Dijkstra::Solve


///-Dijkstra::DownHeap------------------------------------------------------------------
//
//  Purpose:    Ensures the heap condition is maintained, where the heap is ordered so
//              that the parent node is smaller than its children.
//
//  Requires:   0 <= index < heapSize
//
//  Ensures:    For all nodes in the heap, any children of a node have probabilities not
//              less than that node.
//
//  Credits:    Adapted from R. Sedgewick, "Algorithms in C" (Don Mills: Addison-Wesley,
//              1990), 152.
///--------------------------------------------------------------------------------------
void Dijkstra::DownHeap( int heap[], unsigned int distance[], int index, int heapSize )
{
    assert( 0 <= index && index < heapSize );
        
    int update = heap[ index ];                       // holds node to place in heap
    unsigned int priority = distance[ heap[ index ] ];
    int childIndex;
    
    while ( index < heapSize/2 ) {                    // while a node might have children...
        childIndex = index + index + 1;
        if ( childIndex < ( heapSize - 1 )
                && distance[ heap[ childIndex ] ] > distance[ heap[ childIndex + 1 ] ] ) {
            childIndex += 1;                          // right child smaller
        } // if
        if ( priority <= distance[ heap[ childIndex ] ] ) { // heap condition okay
    break;
        } // if
        heap[ index ] = heap[ childIndex ]; // swap child & parent
        index = childIndex;
    } // while
    heap[ index ] = update; // put node at new location
    
} // Dijkstra::DownHeap


///-Dijkstra::UpHeap--------------------------------------------------------------------
//
//  Purpose: Ensures the heap condition is retained.
//
//  Requires:   0 <= index < heapSize
//
//  Ensures:    For all nodes in the heap, any children of a node have probabilities not
//              less than that node.
//
//  Credits:    Adapted from R. Sedgewick, "Algorithms in C" (Don Mills: Addison-Wesley,
//              1990), 150.
///--------------------------------------------------------------------------------------
void Dijkstra::UpHeap( int heap[], unsigned int distance[], int index )
{
    int update = heap[ index ];
    unsigned int priority = distance[ heap[ index ] ];
    
    while ( index != 0 && distance[ heap[ index / 2 ] ] >= priority ) {
        heap[ index ] = heap[ index / 2 ];
        index /= 2;
    } // while
    heap[ index ] = update;
    
} // Dijkstra::UpHeap
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Sean McDowell                  "We should not let ourselves be burnt for
4N CS, U of Waterloo            our opinions: we are not that sure of them.
smmcdowell@undergrad.math.      But perhaps for this: that we may have and
uwaterloo.ca                    change our opinions." -- Nietzsche
