Graphviz  2.29.20120524.0446
lib/pathplan/shortestpth.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 
00015 #include "vis.h"
00016 
00017 #ifdef DMALLOC
00018 #include "dmalloc.h"
00019 #endif
00020 
00021 static COORD unseen = (double) INT_MAX;
00022 
00023 /* shortestPath:
00024  * Given a VxV weighted adjacency matrix, compute the shortest
00025  * path vector from root to target. The returned vector (dad) encodes the
00026  * shorted path from target to the root. That path is given by
00027  * i, dad[i], dad[dad[i]], ..., root
00028  * We have dad[root] = -1.
00029  *
00030  * Based on Dijkstra's algorithm (Sedgewick, 2nd. ed., p. 466).
00031  *
00032  * This implementation only uses the lower left triangle of the
00033  * adjacency matrix, i.e., the values a[i][j] where i >= j.
00034  */
00035 int *shortestPath(int root, int target, int V, array2 wadj)
00036 {
00037     int *dad;
00038     COORD *vl;
00039     COORD *val;
00040     int min;
00041     int k, t;
00042 
00043     /* allocate arrays */
00044     dad = (int *) malloc(V * sizeof(int));
00045     vl = (COORD *) malloc((V + 1) * sizeof(COORD));     /* One extra for sentinel */
00046     val = vl + 1;
00047 
00048     /* initialize arrays */
00049     for (k = 0; k < V; k++) {
00050         dad[k] = -1;
00051         val[k] = -unseen;
00052     }
00053     val[-1] = -(unseen + (COORD) 1);    /* Set sentinel */
00054     min = root;
00055 
00056     /* use (min >= 0) to fill entire tree */
00057     while (min != target) {
00058         k = min;
00059         val[k] *= -1;
00060         min = -1;
00061         if (val[k] == unseen)
00062             val[k] = 0;
00063 
00064         for (t = 0; t < V; t++) {
00065             if (val[t] < 0) {
00066                 COORD newpri;
00067                 COORD wkt;
00068 
00069                 /* Use lower triangle */
00070                 if (k >= t)
00071                     wkt = wadj[k][t];
00072                 else
00073                     wkt = wadj[t][k];
00074 
00075                 newpri = -(val[k] + wkt);
00076                 if ((wkt != 0) && (val[t] < newpri)) {
00077                     val[t] = newpri;
00078                     dad[t] = k;
00079                 }
00080                 if (val[t] > val[min])
00081                     min = t;
00082             }
00083         }
00084     }
00085 
00086     free(vl);
00087     return dad;
00088 }
00089 
00090 /* makePath:
00091  * Given two points p and q in two polygons pp and qp of a vconfig_t conf, 
00092  * and the visibility vectors of p and q relative to conf, 
00093  * compute the shortest path from p to q.
00094  * If dad is the returned array and V is the number of polygon vertices in
00095  * conf, then the path is V(==q), dad[V], dad[dad[V]], ..., V+1(==p).
00096  * NB: This is the only path that is guaranteed to be valid.
00097  * We have dad[V+1] = -1.
00098  * 
00099  */
00100 int *makePath(Ppoint_t p, int pp, COORD * pvis,
00101               Ppoint_t q, int qp, COORD * qvis, vconfig_t * conf)
00102 {
00103     int V = conf->N;
00104 
00105     if (directVis(p, pp, q, qp, conf)) {
00106         int *dad = (int *) malloc(sizeof(int) * (V + 2));
00107         dad[V] = V + 1;
00108         dad[V + 1] = -1;
00109         return dad;
00110     } else {
00111         array2 wadj = conf->vis;
00112         wadj[V] = qvis;
00113         wadj[V + 1] = pvis;
00114         return (shortestPath(V + 1, V, V + 2, wadj));
00115     }
00116 }