Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/optimiser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (hide annotations) (download) (as text)
Sun Jan 4 17:51:24 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 18236 byte(s)
Changed the node, way and segment functions and data types.
Removed 'alloced', shortened the prototype array.
Remove the automatic sorting of the data.
Added assert statements.

1 amb 2 /***************************************
2 amb 8 $Header: /home/amb/CVS/routino/src/optimiser.c,v 1.5 2009-01-04 17:51:23 amb Exp $
3 amb 2
4     Routing optimiser.
5     ******************/ /******************
6     Written by Andrew M. Bishop
7    
8 amb 3 This file Copyright 2008,2009 Andrew M. Bishop
9 amb 2 It may be distributed under the GNU Public License, version 2, or
10     any higher version. See section COPYING of the GNU Public license
11     for conditions under which this file may be redistributed.
12     ***************************************/
13    
14    
15     #include <string.h>
16     #include <stdlib.h>
17    
18     #include "functions.h"
19     #include "types.h"
20    
21     #define INCREMENT 10*1024
22     #define NBINS 64
23    
24     /*+ One item in the results. +*/
25     typedef struct _Result
26     {
27     node_t node; /*+ The end node. +*/
28     Node *Node; /*+ The end Node. +*/
29     Node *shortest_Prev; /*+ The previous Node following the shortest path. +*/
30     distance_t shortest_distance; /*+ The distance travelled to the node following the shortest path. +*/
31     duration_t shortest_duration; /*+ The time taken to the node following the shortest path. +*/
32     Node *quickest_Prev; /*+ The previous Node following the quickest path. +*/
33     distance_t quickest_distance; /*+ The distance travelled to the node following the quickest path. +*/
34     duration_t quickest_duration; /*+ The time taken to the node following the quickest path. +*/
35     }
36     Result;
37    
38     /*+ A list of results. +*/
39     typedef struct _Results
40     {
41     uint32_t alloced; /*+ The amount of space allocated for results in the array +*/
42     uint32_t number[NBINS]; /*+ The number of occupied results in the array +*/
43     Result **results[NBINS]; /*+ An array of pointers to arrays of results +*/
44     }
45     Results;
46    
47    
48     /*+ A queue results. +*/
49     typedef struct _Queue
50     {
51     uint32_t alloced; /*+ The amount of space allocated for results in the array +*/
52     uint32_t number; /*+ The number of occupied results in the array +*/
53     Result *queue[1024]; /*+ An array of results whose size is not
54     necessarily limited to 1024 (i.e. may
55     overflow the end of this structure). +*/
56     }
57     Queue;
58    
59    
60     /*+ The queue of nodes. +*/
61     Queue *OSMQueue=NULL;
62    
63     /*+ The list of results. +*/
64     Results *OSMResults=NULL;
65    
66     /* Functions */
67    
68     static void insert_in_queue(Result *result);
69     static Result *find_insert_result(node_t node);
70     static Result *find_result(node_t node);
71    
72    
73     /*++++++++++++++++++++++++++++++++++++++
74     Find the optimum route between two nodes.
75    
76     node_t start The start node.
77    
78     node_t finish The finish node.
79     ++++++++++++++++++++++++++++++++++++++*/
80    
81     void FindRoute(node_t start,node_t finish)
82     {
83     Node *Start,*Finish;
84     node_t node1,node2;
85     Node *Node1,*Node2;
86     distance_t shortest_distance1,shortest_distance2=0;
87     duration_t shortest_duration1,shortest_duration2=0;
88     distance_t quickest_distance1,quickest_distance2=0;
89     duration_t quickest_duration1,quickest_duration2=0;
90 amb 5 distance_short_t deltadistance;
91     duration_short_t deltaduration;
92 amb 2 distance_t totalcrow,crow;
93     distance_t shortest_distancefinish=~0,quickest_distancefinish=~0;
94     duration_t shortest_durationfinish=~0,quickest_durationfinish=~0;
95     Result *result1,*result2;
96     Segment *segment;
97     int nresults=0;
98    
99     /* Work out the distance as the crow flies */
100    
101     Start=FindNode(start);
102     Finish=FindNode(finish);
103    
104 amb 8 totalcrow=Distance(Start,Finish);
105 amb 2
106     /* Insert the first node into the queue */
107    
108     result1=find_insert_result(start);
109    
110     result1->node=start;
111     result1->Node=Start;
112     result1->shortest_Prev=NULL;
113     result1->shortest_distance=0;
114     result1->shortest_duration=0;
115     result1->quickest_Prev=NULL;
116     result1->quickest_distance=0;
117     result1->quickest_duration=0;
118    
119     insert_in_queue(result1);
120    
121     /* Loop across all nodes in the queue */
122    
123     while(OSMQueue->number>0)
124     {
125     result1=OSMQueue->queue[--OSMQueue->number];
126     node1=result1->node;
127     Node1=result1->Node;
128     shortest_distance1=result1->shortest_distance;
129     shortest_duration1=result1->shortest_duration;
130     quickest_distance1=result1->quickest_distance;
131     quickest_duration1=result1->quickest_duration;
132    
133     segment=FindFirstSegment(node1);
134    
135     while(segment)
136     {
137     node2=segment->node2;
138    
139     deltadistance=segment->distance;
140     deltaduration=segment->duration;
141    
142     shortest_distance2=shortest_distance1+deltadistance;
143     shortest_duration2=shortest_duration1+deltaduration;
144     quickest_distance2=quickest_distance1+deltadistance;
145     quickest_duration2=quickest_duration1+deltaduration;
146    
147     result2=find_result(node2);
148     if(result2)
149     Node2=result2->Node;
150     else
151     Node2=FindNode(node2);
152    
153 amb 8 crow=Distance(Node2,Finish);
154 amb 2
155 amb 5 if((crow+shortest_distance2)>(km_to_distance(10)+1.4*totalcrow))
156 amb 2 goto endloop;
157    
158 amb 3 if(shortest_distance2>shortest_distancefinish && quickest_duration2>quickest_durationfinish)
159 amb 2 goto endloop;
160    
161     if(!result2) /* New end node */
162     {
163     result2=find_insert_result(node2);
164     result2->node=node2;
165     result2->Node=Node2;
166     result2->shortest_Prev=Node1;
167     result2->shortest_distance=shortest_distance2;
168     result2->shortest_duration=shortest_duration2;
169     result2->quickest_Prev=Node1;
170     result2->quickest_distance=quickest_distance2;
171     result2->quickest_duration=quickest_duration2;
172    
173     nresults++;
174    
175     if(node2==finish)
176     {
177     shortest_distancefinish=shortest_distance2;
178     shortest_durationfinish=shortest_duration2;
179     quickest_distancefinish=quickest_distance2;
180     quickest_durationfinish=quickest_duration2;
181     }
182     else
183     insert_in_queue(result2);
184     }
185     else
186     {
187     if(shortest_distance2<result2->shortest_distance ||
188     (shortest_distance2==result2->shortest_distance &&
189     shortest_duration2<result2->shortest_duration)) /* New end node is shorter */
190     {
191     result2->shortest_Prev=Node1;
192     result2->shortest_distance=shortest_distance2;
193     result2->shortest_duration=shortest_duration2;
194    
195     if(node2==finish)
196     {
197     shortest_distancefinish=shortest_distance2;
198     shortest_durationfinish=shortest_duration2;
199     }
200     else
201     insert_in_queue(result2);
202     }
203    
204     if(quickest_duration2<result2->quickest_duration ||
205     (quickest_duration2==result2->quickest_duration &&
206     quickest_distance2<result2->quickest_distance)) /* New end node is quicker */
207     {
208     result2->quickest_Prev=Node1;
209     result2->quickest_distance=quickest_distance2;
210     result2->quickest_duration=quickest_duration2;
211    
212     if(node2==finish)
213     {
214     quickest_distancefinish=quickest_distance2;
215     quickest_durationfinish=quickest_duration2;
216     }
217     else
218     insert_in_queue(result2);
219     }
220     }
221    
222     endloop:
223    
224     segment=FindNextSegment(segment);
225     }
226    
227     if(!(nresults%1000))
228     {
229     printf("\rRouting: End Nodes=%d Queue=%d Journey=%.1fkm,%.0fmin ",nresults,OSMQueue->number,
230 amb 5 distance_to_km(shortest_distance2),duration_to_minutes(quickest_duration2));
231 amb 2 fflush(stdout);
232     }
233     }
234    
235     printf("\rRouted: End Nodes=%d Shortest=%.1fkm,%.0fmin Quickest=%.1fkm,%.0fmin\n",nresults,
236 amb 5 distance_to_km(shortest_distancefinish),duration_to_minutes(shortest_durationfinish),
237     distance_to_km(quickest_distancefinish),duration_to_minutes(quickest_durationfinish));
238 amb 2 fflush(stdout);
239     }
240    
241    
242     /*++++++++++++++++++++++++++++++++++++++
243     Print the optimum route between two nodes.
244    
245     node_t start The start node.
246    
247     node_t finish The finish node.
248     ++++++++++++++++++++++++++++++++++++++*/
249    
250     void PrintRoute(node_t start,node_t finish)
251     {
252     FILE *file;
253     Result *result;
254 amb 3 // int i,j;
255 amb 2
256     /* Print the result for the shortest route */
257    
258     file=fopen("shortest.txt","w");
259    
260     result=find_result(finish);
261    
262     do
263     {
264     if(result->shortest_Prev)
265     {
266 amb 6 Segment *segment;
267     Way *way;
268 amb 2
269 amb 6 segment=FindFirstSegment(result->shortest_Prev->id);
270 amb 2 while(segment->node2!=result->Node->id)
271     segment=FindNextSegment(segment);
272    
273 amb 6 way=FindWay(segment->way);
274    
275     fprintf(file,"%9.5f %9.5f %9d %5.3f %5.2f %3.0f %s\n",result->Node->latitude,result->Node->longitude,result->node,
276 amb 5 distance_to_km(segment->distance),duration_to_minutes(segment->duration),
277 amb 6 distance_to_km(segment->distance)/duration_to_hours(segment->duration),
278     WayName(way));
279 amb 2
280     result=find_result(result->shortest_Prev->id);
281     }
282     else
283     {
284     fprintf(file,"%9.5f %9.5f %9d\n",result->Node->latitude,result->Node->longitude,result->node);
285    
286     result=NULL;
287     }
288     }
289     while(result);
290    
291     fclose(file);
292    
293     /* Print the result for the quickest route */
294    
295     file=fopen("quickest.txt","w");
296    
297     result=find_result(finish);
298    
299     do
300     {
301     if(result->quickest_Prev)
302     {
303 amb 6 Segment *segment;
304     Way *way;
305 amb 2
306 amb 6 segment=FindFirstSegment(result->quickest_Prev->id);
307 amb 2 while(segment->node2!=result->Node->id)
308     segment=FindNextSegment(segment);
309    
310 amb 6 way=FindWay(segment->way);
311    
312     fprintf(file,"%9.5f %9.5f %9d %5.3f %5.2f %3.0f %s\n",result->Node->latitude,result->Node->longitude,result->node,
313 amb 5 distance_to_km(segment->distance),duration_to_minutes(segment->duration),
314 amb 6 distance_to_km(segment->distance)/duration_to_hours(segment->duration),
315     WayName(way));
316 amb 2
317     result=find_result(result->quickest_Prev->id);
318     }
319     else
320     {
321     fprintf(file,"%9.5f %9.5f %9d\n",result->Node->latitude,result->Node->longitude,result->node);
322    
323     result=NULL;
324     }
325     }
326     while(result);
327    
328 amb 3 /* Print all the distance results. */
329    
330     // file=fopen("distance.txt","w");
331     //
332     // for(i=0;i<NBINS;i++)
333     // for(j=0;j<OSMResults->number[i];j++)
334     // {
335     // result=OSMResults->results[i][j];
336     //
337     // fprintf(file,"%9.5f %9.5f 0 %5.3f\n",result->Node->latitude,result->Node->longitude,
338 amb 5 // distance_to_km(result->shortest_distance));
339 amb 3 // }
340     //
341     // fclose(file);
342    
343     /* Print all the duration results. */
344    
345     // file=fopen("duration.txt","w");
346     //
347     // for(i=0;i<NBINS;i++)
348     // for(j=0;j<OSMResults->number[i];j++)
349     // {
350     // result=OSMResults->results[i][j];
351     //
352     // fprintf(file,"%9.5f %9.5f 0 %5.3f\n",result->Node->latitude,result->Node->longitude,
353 amb 5 // duration_to_minutes(result->quickest_duration));
354 amb 3 // }
355     //
356     // fclose(file);
357 amb 2 }
358    
359    
360     /*++++++++++++++++++++++++++++++++++++++
361     Insert an item into the queue in the right order.
362    
363     Result *result The result to insert into the queue.
364     ++++++++++++++++++++++++++++++++++++++*/
365    
366     static void insert_in_queue(Result *result)
367     {
368     int start;
369     int end;
370     int mid;
371     int insert=-1;
372    
373     /* Check that the whole thing is allocated. */
374    
375     if(!OSMQueue)
376     {
377     OSMQueue=(Queue*)calloc(1,sizeof(Queue));
378     OSMQueue->alloced=sizeof(OSMQueue->queue)/sizeof(OSMQueue->queue[0]);
379     }
380    
381     /* Check that the arrays have enough space. */
382    
383     if(OSMQueue->number==OSMQueue->alloced)
384     {
385     OSMQueue=(Queue*)realloc((void*)OSMQueue,sizeof(Queue)-sizeof(OSMQueue->queue)+(OSMQueue->alloced+INCREMENT)*sizeof(Result*));
386    
387     OSMQueue->alloced+=INCREMENT;
388     }
389    
390     /* Binary search - search key may not match, new insertion point required
391     *
392     * # <- start | Check mid and move start or end if it doesn't match
393     * # |
394     * # | Since there may not be an exact match we must set end=mid
395     * # <- mid | or start=mid because we know that mid doesn't match.
396     * # |
397     * # | Eventually end=start+1 and the insertion point is before
398     * # <- end | end (since it cannot be before the initial start or end).
399     */
400    
401     start=0;
402     end=OSMQueue->number-1;
403    
404     if(OSMQueue->number==0) /* There is nothing in the queue */
405     insert=start;
406     else if(result->shortest_distance>OSMQueue->queue[start]->shortest_distance) /* Check key is not before start */
407     insert=start;
408     else if(result->shortest_distance<OSMQueue->queue[end]->shortest_distance) /* Check key is not after end */
409     insert=end+1;
410     else
411     {
412     do
413     {
414     mid=(start+end)/2; /* Choose mid point */
415    
416     if(OSMQueue->queue[mid]->shortest_distance>result->shortest_distance) /* Mid point is too low */
417     start=mid;
418     else if(OSMQueue->queue[mid]->shortest_distance<result->shortest_distance) /* Mid point is too high */
419     end=mid;
420     else /* Mid point is correct */
421     {
422     if(OSMQueue->queue[mid]==result)
423     return;
424    
425     insert=mid;
426     break;
427     }
428     }
429     while((end-start)>1);
430    
431     if(insert==-1)
432     insert=end;
433     }
434    
435     /* Shuffle the array up */
436    
437     if(insert!=OSMQueue->number)
438     memmove(&OSMQueue->queue[insert+1],&OSMQueue->queue[insert],(OSMQueue->number-insert)*sizeof(Result*));
439    
440     /* Insert the new entry */
441    
442     OSMQueue->queue[insert]=result;
443    
444     OSMQueue->number++;
445     }
446    
447    
448     /*++++++++++++++++++++++++++++++++++++++
449     Find an existing result or insert a new one into the results in the right order.
450    
451     node_t node The node that is to be inserted into the results.
452     ++++++++++++++++++++++++++++++++++++++*/
453    
454     static Result *find_insert_result(node_t node)
455     {
456     int start;
457     int end;
458     int mid;
459     int insert=-1,found=-1;
460     int bin=node%NBINS;
461    
462     /* Check that the whole thing is allocated. */
463    
464     if(!OSMResults)
465     {
466     int i;
467    
468     OSMResults=(Results*)calloc(1,sizeof(Results));
469     OSMResults->alloced=INCREMENT;
470    
471     for(i=0;i<NBINS;i++)
472     OSMResults->results[i]=(Result**)malloc(OSMResults->alloced*sizeof(Result*));
473     }
474    
475     /* Check that the arrays have enough space. */
476    
477     if(OSMResults->number[bin]==OSMResults->alloced)
478     {
479     int i;
480    
481     OSMResults->alloced+=INCREMENT;
482    
483     for(i=0;i<NBINS;i++)
484     OSMResults->results[i]=(Result**)realloc((void*)OSMResults->results[i],OSMResults->alloced*sizeof(Result*));
485     }
486    
487     /* Binary search - search key may not match, if not then insertion point required
488     *
489     * # <- start | Check mid and move start or end if it doesn't match
490     * # |
491     * # | Since there may not be an exact match we must set end=mid
492     * # <- mid | or start=mid because we know that mid doesn't match.
493     * # |
494     * # | Eventually end=start+1 and the insertion point is before
495     * # <- end | end (since it cannot be before the initial start or end).
496     */
497    
498     start=0;
499     end=OSMResults->number[bin]-1;
500    
501     if(OSMResults->number[bin]==0) /* There are no results */
502     insert=start;
503     else if(node<OSMResults->results[bin][start]->node) /* Check key is not before start */
504     insert=start;
505     else if(node>OSMResults->results[bin][end]->node) /* Check key is not after end */
506     insert=end+1;
507     else
508     {
509     do
510     {
511     mid=(start+end)/2; /* Choose mid point */
512    
513     if(OSMResults->results[bin][mid]->node<node) /* Mid point is too low */
514     start=mid;
515     else if(OSMResults->results[bin][mid]->node>node) /* Mid point is too high */
516     end=mid;
517     else /* Mid point is correct */
518     {
519     found=mid;
520     break;
521     }
522     }
523     while((end-start)>1);
524    
525     if(found==-1)
526     {
527     if(OSMResults->results[bin][start]->node==node) /* Start is correct */
528     found=start;
529     else if(OSMResults->results[bin][end]->node==node)/* End is correct */
530     found=end;
531     else
532     insert=end;
533     }
534     }
535    
536     /* Shuffle the array up */
537    
538     if(insert!=-1 && insert!=OSMResults->number[bin])
539     memmove(&OSMResults->results[bin][insert+1],&OSMResults->results[bin][insert],(OSMResults->number[bin]-insert)*sizeof(Result*));
540    
541     if(insert!=-1)
542     found=insert;
543    
544     /* Insert the insert entry */
545    
546     if(insert!=-1)
547     {
548     OSMResults->number[bin]++;
549    
550     OSMResults->results[bin][found]=(Result*)malloc(sizeof(Result));
551     }
552    
553     return(OSMResults->results[bin][found]);
554     }
555    
556    
557     /*++++++++++++++++++++++++++++++++++++++
558     Find a result, ordered by node.
559    
560     node_t node The node that is to be found.
561     ++++++++++++++++++++++++++++++++++++++*/
562    
563     static Result *find_result(node_t node)
564     {
565     int start;
566     int end;
567     int mid;
568     int bin=node%NBINS;
569    
570     /* Binary search - search key exact match only is required.
571     *
572     * # <- start | Check mid and move start or end if it doesn't match
573     * # |
574     * # | Since an exact match is wanted we can set end=mid-1
575     * # <- mid | or start=mid+1 because we know that mid doesn't match.
576     * # |
577     * # | Eventually either end=start or end=start+1 and one of
578     * # <- end | start or end is the wanted one.
579     */
580    
581     start=0;
582     end=OSMResults->number[bin]-1;
583    
584     if(OSMResults->number[bin]==0) /* There are no results */
585     return(NULL);
586     else if(node<OSMResults->results[bin][start]->node) /* Check key is not before start */
587     return(NULL);
588     else if(node>OSMResults->results[bin][end]->node) /* Check key is not after end */
589     return(NULL);
590     else
591     {
592     do
593     {
594     mid=(start+end)/2; /* Choose mid point */
595    
596     if(OSMResults->results[bin][mid]->node<node) /* Mid point is too low */
597     start=mid+1;
598     else if(OSMResults->results[bin][mid]->node>node) /* Mid point is too high */
599     end=mid-1;
600     else /* Mid point is correct */
601     return(OSMResults->results[bin][mid]);
602     }
603     while((end-start)>1);
604    
605     if(OSMResults->results[bin][start]->node==node) /* Start is correct */
606     return(OSMResults->results[bin][start]);
607    
608     if(OSMResults->results[bin][end]->node==node) /* End is correct */
609     return(OSMResults->results[bin][end]);
610     }
611    
612     return(NULL);
613     }

Properties

Name Value
cvs:description Route optimiser.