Skip to content

Commit dcfb6e1

Browse files
authored
Initial commit
1 parent bd248eb commit dcfb6e1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+6697
-0
lines changed

bfs.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package graph
2+
3+
// BFS traverses g in breadth-first order starting at v.
4+
// When the algorithm follows an edge (v, w) and finds a previously
5+
// unvisited vertex w, it calls do(v, w, c) with c equal to
6+
// the cost of the edge (v, w).
7+
func BFS(g Iterator, v int, do func(v, w int, c int64)) {
8+
visited := make([]bool, g.Order())
9+
visited[v] = true
10+
for queue := []int{v}; len(queue) > 0; {
11+
v := queue[0]
12+
queue = queue[1:]
13+
g.Visit(v, func(w int, c int64) (skip bool) {
14+
if visited[w] {
15+
return
16+
}
17+
do(v, w, c)
18+
visited[w] = true
19+
queue = append(queue, w)
20+
return
21+
})
22+
}
23+
}

bfs_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package graph
2+
3+
import (
4+
"strconv"
5+
"testing"
6+
)
7+
8+
func TestBFS(t *testing.T) {
9+
gm := New(10)
10+
for _, e := range []struct {
11+
v, w int
12+
}{
13+
{0, 1}, {0, 4}, {0, 7}, {0, 9},
14+
{4, 2}, {7, 5}, {7, 8},
15+
{2, 3}, {5, 6},
16+
{3, 6}, {8, 9}, {4, 4},
17+
} {
18+
gm.AddBoth(e.v, e.w)
19+
}
20+
g := Sort(gm)
21+
exp := "0147925836"
22+
res := "0"
23+
BFS(g, 0, func(v, w int, c int64) {
24+
res += strconv.Itoa(w)
25+
})
26+
if mess, diff := diff(res, exp); diff {
27+
t.Errorf("BFS: %s", mess)
28+
}
29+
}

bipart.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package graph
2+
3+
// Bipartition returns a subset U of g's vertices with the property
4+
// that every edge of g connects a vertex in U to one outside of U.
5+
// If g isn't bipartite, it returns an empty slice and sets ok to false.
6+
func Bipartition(g Iterator) (part []int, ok bool) {
7+
type color byte
8+
const (
9+
none color = iota
10+
white
11+
black
12+
)
13+
colors := make([]color, g.Order())
14+
whiteCount := 0
15+
for v := range colors {
16+
if colors[v] != none {
17+
continue
18+
}
19+
colors[v] = white
20+
whiteCount++
21+
for queue := []int{v}; len(queue) > 0; {
22+
v, queue = queue[0], queue[1:]
23+
if g.Visit(v, func(w int, _ int64) (skip bool) {
24+
switch {
25+
case colors[w] != none:
26+
if colors[v] == colors[w] {
27+
skip = true
28+
}
29+
return
30+
case colors[v] == white:
31+
colors[w] = black
32+
default:
33+
colors[w] = white
34+
whiteCount++
35+
}
36+
queue = append(queue, w)
37+
return
38+
}) {
39+
return []int{}, false
40+
}
41+
}
42+
}
43+
part = make([]int, 0, whiteCount)
44+
for v, color := range colors {
45+
if color == white {
46+
part = append(part, v)
47+
}
48+
}
49+
return part, true
50+
}

bipart_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package graph
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestBipartition(t *testing.T) {
8+
g := New(0)
9+
part, ok := Bipartition(g)
10+
if mess, diff := diff(part, []int{}); diff {
11+
t.Errorf("Bipartition: %s", mess)
12+
}
13+
if mess, diff := diff(ok, true); diff {
14+
t.Errorf("Bipartition: %s", mess)
15+
}
16+
17+
g = New(1)
18+
part, ok = Bipartition(g)
19+
if mess, diff := diff(part, []int{0}); diff {
20+
t.Errorf("Bipartition: %s", mess)
21+
}
22+
if mess, diff := diff(ok, true); diff {
23+
t.Errorf("Bipartition: %s", mess)
24+
}
25+
26+
g.Add(0, 0)
27+
part, ok = Bipartition(g)
28+
if mess, diff := diff(part, []int{}); diff {
29+
t.Errorf("Bipartition: %s", mess)
30+
}
31+
if mess, diff := diff(ok, false); diff {
32+
t.Errorf("Bipartition: %s", mess)
33+
}
34+
35+
g = New(2)
36+
part, ok = Bipartition(g)
37+
if mess, diff := diff(part, []int{0, 1}); diff {
38+
t.Errorf("Bipartition: %s", mess)
39+
}
40+
if mess, diff := diff(ok, true); diff {
41+
t.Errorf("Bipartition: %s", mess)
42+
}
43+
44+
g.AddBoth(0, 1)
45+
part, ok = Bipartition(g)
46+
if mess, diff := diff(part, []int{0}); diff {
47+
t.Errorf("Bipartition: %s", mess)
48+
}
49+
if mess, diff := diff(ok, true); diff {
50+
t.Errorf("Bipartition: %s", mess)
51+
}
52+
53+
g.Add(0, 0)
54+
part, ok = Bipartition(g)
55+
if mess, diff := diff(part, []int{}); diff {
56+
t.Errorf("Bipartition: %s", mess)
57+
}
58+
if mess, diff := diff(ok, false); diff {
59+
t.Errorf("Bipartition: %s", mess)
60+
}
61+
62+
g = New(5)
63+
g.Add(0, 1)
64+
g.Add(0, 2)
65+
g.Add(0, 3)
66+
part, ok = Bipartition(g)
67+
if mess, diff := diff(part, []int{0, 4}); diff {
68+
t.Errorf("Bipartition: %s", mess)
69+
}
70+
if mess, diff := diff(ok, true); diff {
71+
t.Errorf("Bipartition: %s", mess)
72+
}
73+
74+
g.Add(2, 3)
75+
part, ok = Bipartition(g)
76+
if mess, diff := diff(part, []int{}); diff {
77+
t.Errorf("Bipartition: %s", mess)
78+
}
79+
if mess, diff := diff(ok, false); diff {
80+
t.Errorf("Bipartition: %s", mess)
81+
}
82+
83+
g = New(5)
84+
g.AddBoth(0, 1)
85+
g.AddBoth(1, 2)
86+
g.AddBoth(2, 3)
87+
g.AddBoth(3, 0)
88+
part, ok = Bipartition(g)
89+
if mess, diff := diff(part, []int{0, 2, 4}); diff {
90+
t.Errorf("Bipartition: %s", mess)
91+
}
92+
if mess, diff := diff(ok, true); diff {
93+
t.Errorf("Bipartition: %s", mess)
94+
}
95+
}

build/bench_test.go

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package build
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func BenchmarkKn(b *testing.B) {
8+
g := Kn(100)
9+
for i := 0; i < b.N; i++ {
10+
g.Visit(0, func(w int, c int64) (skip bool) {
11+
return
12+
})
13+
}
14+
}
15+
16+
func BenchmarkComplement(b *testing.B) {
17+
g := Empty(100).Complement()
18+
for i := 0; i < b.N; i++ {
19+
g.Visit(0, func(w int, c int64) (skip bool) {
20+
return
21+
})
22+
}
23+
}
24+
25+
func BenchmarkSubgraph(b *testing.B) {
26+
g := Kn(1000).Subgraph(Range(0, 100))
27+
for i := 0; i < b.N; i++ {
28+
g.Visit(0, func(w int, c int64) (skip bool) {
29+
return
30+
})
31+
}
32+
}
33+
34+
func BenchmarkConnect(b *testing.B) {
35+
g := Kn(50).Connect(0, Kn(50))
36+
for i := 0; i < b.N; i++ {
37+
g.Visit(0, func(w int, c int64) (skip bool) {
38+
return
39+
})
40+
}
41+
}
42+
43+
func BenchmarkJoin(b *testing.B) {
44+
g := Kn(1).Join(Kn(100), AllEdges())
45+
for i := 0; i < b.N; i++ {
46+
g.Visit(0, func(w int, c int64) (skip bool) {
47+
return
48+
})
49+
}
50+
}
51+
52+
func BenchmarkCost(b *testing.B) {
53+
g := Kn(100).AddCost(8)
54+
for i := 0; i < b.N; i++ {
55+
g.Visit(0, func(w int, c int64) (skip bool) {
56+
return
57+
})
58+
}
59+
}
60+
61+
func BenchmarkCostFunc(b *testing.B) {
62+
g := Kn(100).AddCostFunc(Cost(8))
63+
for i := 0; i < b.N; i++ {
64+
g.Visit(0, func(w int, c int64) (skip bool) {
65+
return
66+
})
67+
}
68+
}
69+
70+
func BenchmarkDeleteNone(b *testing.B) {
71+
g := Kn(100).Delete(NoEdges())
72+
for i := 0; i < b.N; i++ {
73+
g.Visit(0, func(w int, c int64) (skip bool) {
74+
return
75+
})
76+
}
77+
}
78+
79+
func BenchmarkDeleteOne(b *testing.B) {
80+
g := Kn(100).Delete(Edge(3, 8))
81+
for i := 0; i < b.N; i++ {
82+
g.Visit(0, func(w int, c int64) (skip bool) {
83+
return
84+
})
85+
}
86+
}
87+
88+
func BenchmarkDeleteAll(b *testing.B) {
89+
g := Kn(100).Delete(AllEdges())
90+
for i := 0; i < b.N; i++ {
91+
g.Visit(0, func(w int, c int64) (skip bool) {
92+
return
93+
})
94+
}
95+
}
96+
97+
func BenchmarkAddNone(b *testing.B) {
98+
g := Kn(100).Add(NoEdges())
99+
for i := 0; i < b.N; i++ {
100+
g.Visit(0, func(w int, c int64) (skip bool) {
101+
return
102+
})
103+
}
104+
}
105+
106+
func BenchmarkAddOne(b *testing.B) {
107+
g := Kn(100).Add(Edge(3, 8))
108+
for i := 0; i < b.N; i++ {
109+
g.Visit(0, func(w int, c int64) (skip bool) {
110+
return
111+
})
112+
}
113+
}
114+
115+
func BenchmarkAddAll(b *testing.B) {
116+
g := Kn(100).Add(AllEdges())
117+
for i := 0; i < b.N; i++ {
118+
g.Visit(0, func(w int, c int64) (skip bool) {
119+
return
120+
})
121+
}
122+
}
123+
124+
func BenchmarkAddAllCache(b *testing.B) {
125+
g := Specific(Kn(100).Add(AllEdges()))
126+
for i := 0; i < b.N; i++ {
127+
g.Visit(0, func(w int, c int64) (skip bool) {
128+
return
129+
})
130+
}
131+
}
132+
133+
func BenchmarkUnion(b *testing.B) {
134+
g := Kn(100).Union(Kn(100))
135+
for i := 0; i < b.N; i++ {
136+
g.Visit(0, func(w int, c int64) (skip bool) {
137+
return
138+
})
139+
}
140+
}
141+
142+
func BenchmarkIntersect(b *testing.B) {
143+
g := Kn(100).Intersect(Kn(100))
144+
for i := 0; i < b.N; i++ {
145+
g.Visit(0, func(w int, c int64) (skip bool) {
146+
return
147+
})
148+
}
149+
}
150+
151+
func BenchmarkTensor(b *testing.B) {
152+
g := Kn(10).Tensor(Kn(10))
153+
for i := 0; i < b.N; i++ {
154+
g.Visit(0, func(w int, c int64) (skip bool) {
155+
return
156+
})
157+
}
158+
}
159+
160+
func BenchmarkCartesian(b *testing.B) {
161+
g := Kn(50).Cartesian(Kn(50))
162+
for i := 0; i < b.N; i++ {
163+
g.Visit(0, func(w int, c int64) (skip bool) {
164+
return
165+
})
166+
}
167+
}

0 commit comments

Comments
 (0)