00001
00002
00003
00004
00005 #include "common.h"
00006 #include "diGraph.h"
00007
00008 static char const rcsid[] = "$Id: dgRange.c,v 1.3 2003/05/06 07:33:42 kate Exp $";
00009
00010 struct bfEdge
00011
00012 {
00013 struct bfEdge *next;
00014 int distance;
00015 struct bfVertex *in;
00016 struct bfVertex *out;
00017 };
00018
00019 struct bfVertex
00020
00021 {
00022 int position;
00023 struct bfEdge *waysOut;
00024 };
00025
00026 struct bfGraph
00027
00028 {
00029 int vertexCount;
00030 struct bfVertex *vertices;
00031 int edgeCount;
00032 struct bfEdge *edges;
00033 };
00034
00035 struct bfRange
00036
00037 {
00038 int minDist, maxDist;
00039 };
00040
00041 static void bfGraphFree(struct bfGraph **pGraph)
00042
00043 {
00044 struct bfGraph *graph = *pGraph;
00045 if (graph != NULL)
00046 {
00047 freeMem(graph->vertices);
00048 freeMem(graph->edges);
00049 freez(pGraph);
00050 }
00051 }
00052
00053 static struct bfGraph *bfGraphFromRangeGraph(struct diGraph *rangeGraph,
00054 boolean (*findEdgeRange)(struct dgEdge *edge, int *retMin, int *retMax),
00055 struct dgNode *a, struct dgNode *b, int abMin, int abMax)
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 {
00078 struct bfGraph *bfGraph;
00079 struct bfVertex *vertices, *freeVertex, *newSource, *newDest, *zeroVertex;
00080 struct bfEdge *edges, *newEdge, *freeEdge;
00081 struct dgNode *oldSource, *oldDest, *oldNode;
00082 int oldEdgeCount = dlCount(rangeGraph->edgeList);
00083 int oldVertexCount = 0;
00084
00085
00086
00087
00088 for (oldNode = rangeGraph->nodeList; oldNode != NULL; oldNode = oldNode->next)
00089 oldNode->topoOrder = ++oldVertexCount;
00090
00091
00092 AllocVar(bfGraph);
00093 bfGraph->vertexCount = oldVertexCount + 1;
00094 bfGraph->vertices = freeVertex = AllocArray(vertices, bfGraph->vertexCount);
00095 bfGraph->edgeCount = 2*oldEdgeCount + oldVertexCount;
00096 if (a != NULL)
00097 bfGraph->edgeCount += 2;
00098 bfGraph->edges = freeEdge = AllocArray(edges, bfGraph->edgeCount);
00099
00100
00101 zeroVertex = freeVertex++;
00102
00103
00104 for (oldSource = rangeGraph->nodeList; oldSource != NULL;
00105 oldSource = oldSource->next)
00106 {
00107 struct dgConnection *dgConn;
00108 int rangeMin, rangeMax;
00109
00110
00111 newSource = freeVertex++;
00112
00113
00114 newEdge = freeEdge++;
00115 newEdge->distance = 0;
00116 newEdge->in = zeroVertex;
00117 newEdge->out = newSource;
00118 slAddHead(&zeroVertex->waysOut, newEdge);
00119
00120
00121 for (dgConn = oldSource->nextList; dgConn != NULL; dgConn = dgConn->next)
00122 {
00123
00124 if ((*findEdgeRange)(dgConn->edgeOnList->val, &rangeMin, &rangeMax))
00125 {
00126 oldDest = dgConn->node;
00127 newDest = &vertices[oldDest->topoOrder];
00128
00129
00130 newEdge = freeEdge++;
00131 newEdge->distance = rangeMax;
00132 newEdge->in = newSource;
00133 newEdge->out = newDest;
00134 slAddHead(&newSource->waysOut, newEdge);
00135 newEdge = freeEdge++;
00136 newEdge->distance = -rangeMin;
00137 newEdge->in = newDest;
00138 newEdge->out = newSource;
00139 slAddHead(&newDest->waysOut, newEdge);
00140 }
00141 }
00142 }
00143
00144 if (a != NULL)
00145 {
00146 newSource = &vertices[a->topoOrder];
00147 newDest = &vertices[b->topoOrder];
00148 newEdge = freeEdge++;
00149 newEdge->distance = abMax;
00150 newEdge->in = newSource;
00151 newEdge->out = newDest;
00152 slAddHead(&newSource->waysOut, newEdge);
00153 newEdge = freeEdge++;
00154 newEdge->distance = -abMin;
00155 newEdge->in = newDest;
00156 newEdge->out = newSource;
00157 slAddHead(&newDest->waysOut, newEdge);
00158 }
00159 bfGraph->edgeCount = freeEdge - bfGraph->edges;
00160 return bfGraph;
00161 }
00162
00163 static boolean bfCheckGraph(struct bfGraph *graph)
00164
00165 {
00166 struct bfVertex *vertices = graph->vertices, *in, *out;
00167 int vertexCount = graph->vertexCount;
00168 int edgeCount = graph->edgeCount;
00169 struct bfEdge *edges = graph->edges, *edge;
00170 int i, edgeIx;
00171 int maxIterations = vertexCount - 1;
00172 boolean anyChange = FALSE;
00173 int newPos;
00174
00175 for (i=0; i<vertexCount; ++i)
00176 vertices[i].position = 0x3fffffff;
00177 for (i=0; i<maxIterations; ++i)
00178 {
00179 anyChange = FALSE;
00180 for (edgeIx = 0, edge = edges; edgeIx < edgeCount; ++edgeIx, ++edge)
00181 {
00182 in = edge->in;
00183 out = edge->out;
00184 newPos = in->position + edge->distance;
00185 if (newPos < out->position)
00186 {
00187 out->position = newPos;
00188 anyChange = TRUE;
00189 }
00190 }
00191 if (!anyChange)
00192 break;
00193 }
00194 return !anyChange;
00195 }
00196
00197 boolean dgAddedRangeConsistent(struct diGraph *rangeGraph,
00198 struct dgNode *a, struct dgNode *b, int abMin, int abMax,
00199 boolean (*findEdgeRange)(struct dgEdge *edge, int *retMin, int *retMax) )
00200
00201
00202
00203 {
00204 struct bfGraph *bfGraph;
00205 boolean ok;
00206
00207 bfGraph = bfGraphFromRangeGraph(rangeGraph, findEdgeRange, a, b, abMin, abMax);
00208 ok = bfCheckGraph(bfGraph);
00209 bfGraphFree(&bfGraph);
00210 return ok;
00211 }
00212
00213 boolean dgRangesConsistent(struct diGraph *rangeGraph,
00214 boolean (*findEdgeRange)(struct dgEdge *edge, int *retMin, int *retMax) )
00215
00216
00217 {
00218 return dgAddedRangeConsistent(rangeGraph, NULL, NULL, 0, 0, findEdgeRange);
00219 }
00220