forked from gonum/graph
/
graph_test.go
142 lines (119 loc) · 4.55 KB
/
graph_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package graph_test
import (
"github.com/nathankerr/graph"
"math"
"testing"
)
func TestTileGraph(t *testing.T) {
tg := graph.NewTileGraph(4, 4, false)
if tg == nil || tg.String() != "▀▀▀▀\n▀▀▀▀\n▀▀▀▀\n▀▀▀▀" {
t.Fatal("Tile graph not generated correctly")
}
tg.SetPassability(0, 1, true)
if tg == nil || tg.String() != "▀ ▀▀\n▀▀▀▀\n▀▀▀▀\n▀▀▀▀" {
t.Fatal("Passability set incorrectly")
}
tg.SetPassability(0, 1, false)
if tg == nil || tg.String() != "▀▀▀▀\n▀▀▀▀\n▀▀▀▀\n▀▀▀▀" {
t.Fatal("Passability set incorrectly")
}
tg.SetPassability(0, 1, true)
if tg == nil || tg.String() != "▀ ▀▀\n▀▀▀▀\n▀▀▀▀\n▀▀▀▀" {
t.Fatal("Passability set incorrectly")
}
tg.SetPassability(0, 2, true)
if tg == nil || tg.String() != "▀ ▀\n▀▀▀▀\n▀▀▀▀\n▀▀▀▀" {
t.Fatal("Passability set incorrectly")
}
tg.SetPassability(1, 2, true)
if tg == nil || tg.String() != "▀ ▀\n▀▀ ▀\n▀▀▀▀\n▀▀▀▀" {
t.Fatal("Passability set incorrectly")
}
tg.SetPassability(2, 2, true)
if tg == nil || tg.String() != "▀ ▀\n▀▀ ▀\n▀▀ ▀\n▀▀▀▀" {
t.Fatal("Passability set incorrectly")
}
tg.SetPassability(3, 2, true)
if tg == nil || tg.String() != "▀ ▀\n▀▀ ▀\n▀▀ ▀\n▀▀ ▀" {
t.Fatal("Passability set incorrectly")
}
if tg2, err := graph.GenerateTileGraph("▀ ▀\n▀▀ ▀\n▀▀ ▀\n▀▀ ▀"); err != nil {
t.Error("Tile graph errored on interpreting valid template string\n▀ ▀\n▀▀ ▀\n▀▀ ▀\n▀▀ ▀")
} else if tg2.String() != "▀ ▀\n▀▀ ▀\n▀▀ ▀\n▀▀ ▀" {
t.Error("Tile graph failed to generate properly with input string\n▀ ▀\n▀▀ ▀\n▀▀ ▀\n▀▀ ▀")
}
if tg.CoordsToID(0, 0) != 0 {
t.Error("Coords to ID fails on 0,0")
} else if tg.CoordsToID(3, 3) != 15 {
t.Error("Coords to ID fails on 3,3")
} else if tg.CoordsToID(0, 3) != 3 {
t.Error("Coords to ID fails on 0,3")
} else if tg.CoordsToID(3, 0) != 12 {
t.Error("Coords to ID fails on 3,0")
}
if r, c := tg.IDToCoords(0); r != 0 || c != 0 {
t.Error("ID to Coords fails on 0,0")
} else if r, c := tg.IDToCoords(15); r != 3 || c != 3 {
t.Error("ID to Coords fails on 3,3")
} else if r, c := tg.IDToCoords(3); r != 0 || c != 3 {
t.Error("ID to Coords fails on 0,3")
} else if r, c := tg.IDToCoords(12); r != 3 || c != 0 {
t.Error("ID to Coords fails on 3,0")
}
if succ := tg.Successors(graph.GonumNode(0)); succ != nil || len(succ) != 0 {
t.Error("Successors for impassable tile not 0")
}
if succ := tg.Successors(graph.GonumNode(2)); succ == nil || len(succ) != 2 {
t.Error("Incorrect number of successors for (0,2)")
} else {
for _, s := range succ {
if s.ID() != 1 && s.ID() != 6 {
t.Error("Successor for (0,2) neither (0,1) nor (1,2)")
}
}
}
if tg.Degree(graph.GonumNode(2)) != 4 {
t.Error("Degree returns incorrect number for (0,2)")
}
if tg.Degree(graph.GonumNode(1)) != 2 {
t.Error("Degree returns incorrect number for (0,2)")
}
if tg.Degree(graph.GonumNode(0)) != 0 {
t.Error("Degree returns incorrect number for impassable tile (0,0)")
}
}
func TestSimpleAStar(t *testing.T) {
tg, err := graph.GenerateTileGraph("▀ ▀\n▀▀ ▀\n▀▀ ▀\n▀▀ ▀")
if err != nil {
t.Fatal("Couldn't generate tilegraph")
}
path, cost, _ := graph.AStar(graph.GonumNode(1), graph.GonumNode(14), tg, nil, nil)
if math.Abs(cost-4.0) > .00001 {
t.Errorf("A* reports incorrect cost for simple tilegraph search")
}
if path == nil {
t.Fatalf("A* fails to find path for for simple tilegraph search")
} else {
correctPath := []int{1, 2, 6, 10, 14}
if len(path) != len(correctPath) {
t.Fatalf("Astar returns wrong length path for simple tilegraph search")
}
for i, node := range path {
if node.ID() != correctPath[i] {
t.Errorf("Astar returns wrong path at step", i, "got:", node, "actual:", correctPath[i])
}
}
}
}
func TestHarderAStar(t *testing.T) {
tg := graph.NewTileGraph(3, 3, true)
path, cost, _ := graph.AStar(graph.GonumNode(0), graph.GonumNode(8), tg, nil, nil)
if math.Abs(cost-4.0) > .00001 || !graph.IsPath(path, tg) {
t.Error("Non-optimal or impossible path found for 3x3 grid")
}
tg = graph.NewTileGraph(1000, 1000, true)
path, cost, _ = graph.AStar(graph.GonumNode(00), graph.GonumNode(999*1000+999), tg, nil, nil)
if !graph.IsPath(path, tg) || cost != 1998.0 {
t.Error("Non-optimal or impossible path found for 100x100 grid; cost:", cost, "path:\n"+tg.PathString(path))
}
}