Skip to content

Commit

Permalink
First stab at A*
Browse files Browse the repository at this point in the history
  • Loading branch information
tcsc committed Dec 19, 2019
1 parent 0e5972a commit 1d8b518
Show file tree
Hide file tree
Showing 16 changed files with 963 additions and 292 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ script:
- dub test
- (cd "examples/Connected Components" && dub build)
- (cd "examples/Dijkstra" && dub build)
- (cd "examples/Astar Cities" && dub build)
6 changes: 6 additions & 0 deletions examples/Astar Cities/dub.sdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name "astar-cities"
description "An example illustrating an A* search."
copyright "Copyright © 2016, Trent Clarke"
license "BSL-1.0"
authors "Trent Clarke"
dependency "anansi" version="master" path="../../"
123 changes: 123 additions & 0 deletions examples/Astar Cities/source/app.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* An example using the anansi A* search algorithm. Ported from the
* boost graph library's example.
*/
import anansi,
anansi.algorithms.astar;
import std.math : sqrt;
import std.algorithm : reverse;
import std.stdio : write, writeln;
import std.container;

/**
* The city data associated wth a given vertex.
*/
struct City {
this(string n, real latitude, real longitude) {
name = n;
lat = latitude;
lng = longitude;
}

string name;
real lat;
real lng;
}

alias Graph = AdjacencyList!(VecS, VecS, DirectedS, City, real);
alias Vertex = Graph.VertexDescriptor;

/**
* An exception type that signals that a path through the graph has been found.
*/
class FoundTarget : Throwable {
this() { super("found it"); }
}

struct AStarGoalVisitor {
mixin NullAstarVisitor!Graph;

Vertex _target;

this(Vertex target) {
_target = target;
}

void examineVertex(ref const(Graph) g, Vertex v) {
if (v == _target) {
throw new FoundTarget;
}
}
}


void main() {
Graph g;

auto troy = g.addVertex(City("Troy", 42.73, 73.68));
auto lake_placid = g.addVertex(City("Lake Placid", 44.28, 73.99));
auto plattsborough = g.addVertex(City("Plattsborough", 44.70, 73.46));
auto massena = g.addVertex(City("Massena", 44.93, 74.89));
auto watertown = g.addVertex(City("Watertown", 43.97, 75.91));
auto utica = g.addVertex(City("Utica", 43.10, 75.23));
auto syracuse = g.addVertex(City("Syracuse", 43.04, 76.14));
auto rochester = g.addVertex(City("Rochester", 43.17, 77.61));
auto buffalo = g.addVertex(City("Buffalo", 42.89, 78.86));
auto ithaca = g.addVertex(City("Ithaca", 42.44, 76.50));
auto binghamton = g.addVertex(City("Binghamon", 42.10, 75.91));
auto woodstock = g.addVertex(City("Woodstock", 42.04, 74.11));
auto new_york = g.addVertex(City("New York", 40.67, 73.94));

g.addEdge(troy, utica, 93);
g.addEdge(troy, lake_placid, 134);
g.addEdge(troy, plattsborough, 143);
g.addEdge(lake_placid, plattsborough, 65);
g.addEdge(plattsborough, massena, 115);
g.addEdge(lake_placid, massena, 113);
g.addEdge(massena, watertown, 117);
g.addEdge(watertown, utica, 116);
g.addEdge(watertown, syracuse, 74);
g.addEdge(utica, syracuse, 56);
g.addEdge(syracuse, rochester, 84);
g.addEdge(rochester, buffalo, 73);
g.addEdge(syracuse, ithaca, 69);
g.addEdge(ithaca, binghamton, 70);
g.addEdge(ithaca, rochester, 116);
g.addEdge(binghamton, troy, 147);
g.addEdge(binghamton, woodstock, 173);
g.addEdge(binghamton, new_york, 183);
g.addEdge(syracuse, binghamton, 74);
g.addEdge(woodstock, troy, 71);
g.addEdge(woodstock, new_york, 124);

auto src = woodstock;
auto target = watertown;

real heuristic(Vertex v) {
auto dx = g[target].lng - g[v].lng;
auto dy = g[target].lat - g[v].lat;
return sqrt(dx * dx + dy * dy);
}

auto predecessor = new Graph.VertexDescriptor[g.vertexCount];

try {
aStarSearch(g,
src,
&heuristic,
g,
predecessor,
AStarGoalVisitor(target));
}
catch(FoundTarget) {
writeln("Found a path");
auto path = extractPath(predecessor, target);

write(g[path[0]].name);
foreach (n; path[1..$]) {
write(" -> ", g[n].name);
}

writeln("");
}
}
4 changes: 2 additions & 2 deletions examples/Connected Components/source/app.d
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* An example using the anansi connected compomemt finder. Ported from the
* An example using the anansi connected compomemt finder. Ported from the
* boost graph library's example.
*/

Expand All @@ -20,7 +20,7 @@ void main() {
graph.addEdge(b, e);
graph.addEdge(e, a);
graph.addEdge(c, f);

size_t[6] componentMap;
auto nComponents = connectedComponents(graph, componentMap);

Expand Down
10 changes: 5 additions & 5 deletions examples/Dijkstra/source/app.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

/**
* Copyright 2014 Trent Clarke.
*
*
* Distributed under the Boost Software License, Version 1.0. (See
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
Expand All @@ -12,7 +12,7 @@ import std.stdio;
void main()
{
alias Graph = AdjacencyList!(VecS, VecS, DirectedS, char, string);

Graph graph;
auto a = graph.addVertex('a');
auto b = graph.addVertex('b');
Expand All @@ -35,13 +35,13 @@ void main()
auto colourMap = new Colour[graph.vertexCount];
auto distance = new real[graph.vertexCount];
auto predecessor = new Graph.VertexDescriptor[graph.vertexCount];
dijkstraShortestPaths(graph, a, weight, predecessor,
NullDijkstraVisitor!Graph(),
dijkstraShortestPaths(graph, a, weight, predecessor,
NullDijkstraVisitor!Graph(),
colourMap,
distance);

foreach(v; graph.vertices) {
writeln(graph[v], " - Distance: ", distance[v],
writeln(graph[v], " - Distance: ", distance[v],
", Predecessor: ", graph[predecessor[v]]);
}
}
4 changes: 2 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This first pass will probably be a pretty simple translation of (bits of) the BG

**Q**: Why another graph handling library?

**A**: Because the only available graph handling library in the Dub package registry was GPL licensed, and I thought it might be nice to have a graph library that people can use in commercial code. Don't get me wrong; [the dgraph library](http://code.dlang.org/packages/dgraph) is awesome, and got me out of a hole in a personal project. It is also a hell of a lot simpler to use than this. I just wanted the option.
**A**: Because the only available graph handling library in the Dub package registry was GPL licensed, and I thought it might be nice to have a graph library that people can use in commercial code. Don't get me wrong; [the dgraph library](http://code.dlang.org/packages/dgraph) is awesome, and got me out of a hole in a personal project. It is also a hell of a lot simpler to use than this. I just wanted the option.

**Q**: Why "Anansi"?

Expand All @@ -34,7 +34,7 @@ void fn() {
auto a = g.addVertex('a');
auto b = g.addVertex('b');
g.addEdge(a, b, "a -> b");
// now dow something interesting with your graph
for(v; g.vertices) {
writeln("Hi from vertex ", g[v]);
Expand Down
Loading

0 comments on commit 1d8b518

Please sign in to comment.