Skip to content

Commit

Permalink
all: factor iterators out into their own package
Browse files Browse the repository at this point in the history
  • Loading branch information
kortschak committed Aug 26, 2018
1 parent 7f895c5 commit 8e45e26
Show file tree
Hide file tree
Showing 33 changed files with 817 additions and 400 deletions.
8 changes: 4 additions & 4 deletions graph/community/louvain_directed.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"gonum.org/v1/gonum/graph"
"gonum.org/v1/gonum/graph/internal/ordered"
"gonum.org/v1/gonum/graph/internal/set"
"gonum.org/v1/gonum/graph/simple"
"gonum.org/v1/gonum/graph/iterator"
)

// qDirected returns the modularity Q score of the graph g subdivided into the
Expand Down Expand Up @@ -347,7 +347,7 @@ func (g *ReducedDirected) Nodes() graph.Nodes {
for i := range g.nodes {
nodes[i] = node(i)
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// From returns all nodes in g that can be reached directly from u.
Expand All @@ -357,7 +357,7 @@ func (g *ReducedDirected) From(uid int64) graph.Nodes {
for i, vid := range out {
nodes[i] = g.nodes[vid]
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// To returns all nodes in g that can reach directly to v.
Expand All @@ -367,7 +367,7 @@ func (g *ReducedDirected) To(vid int64) graph.Nodes {
for i, uid := range in {
nodes[i] = g.nodes[uid]
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// HasEdgeBetween returns whether an edge exists between nodes x and y.
Expand Down
10 changes: 5 additions & 5 deletions graph/community/louvain_directed_multiplex.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"gonum.org/v1/gonum/graph"
"gonum.org/v1/gonum/graph/internal/ordered"
"gonum.org/v1/gonum/graph/internal/set"
"gonum.org/v1/gonum/graph/simple"
"gonum.org/v1/gonum/graph/iterator"
)

// DirectedMultiplex is a directed multiplex graph.
Expand Down Expand Up @@ -229,7 +229,7 @@ func (g *ReducedDirectedMultiplex) Nodes() graph.Nodes {
for i := range g.nodes {
nodes[i] = node(i)
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// Depth returns the number of layers in the multiplex graph.
Expand Down Expand Up @@ -511,7 +511,7 @@ func (g directedLayerHandle) Nodes() graph.Nodes {
for i := range g.multiplex.nodes {
nodes[i] = node(i)
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// From returns all nodes in g that can be reached directly from u.
Expand All @@ -521,7 +521,7 @@ func (g directedLayerHandle) From(uid int64) graph.Nodes {
for i, vid := range out {
nodes[i] = g.multiplex.nodes[vid]
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// To returns all nodes in g that can reach directly to v.
Expand All @@ -531,7 +531,7 @@ func (g directedLayerHandle) To(vid int64) graph.Nodes {
for i, uid := range in {
nodes[i] = g.multiplex.nodes[uid]
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// HasEdgeBetween returns whether an edge exists between nodes x and y.
Expand Down
2 changes: 1 addition & 1 deletion graph/community/louvain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ func init() {
// such that every edge dupGraph is replaced
// with an edge that flows from the low node
// ID to the high node ID.
for _, e := range dupGraph.Edges() {
for _, e := range graph.EdgesOf(dupGraph.Edges()) {
if e.To().ID() < e.From().ID() {
se := e.(simple.Edge)
se.F, se.T = se.T, se.F
Expand Down
6 changes: 3 additions & 3 deletions graph/community/louvain_undirected.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"gonum.org/v1/gonum/graph"
"gonum.org/v1/gonum/graph/internal/ordered"
"gonum.org/v1/gonum/graph/internal/set"
"gonum.org/v1/gonum/graph/simple"
"gonum.org/v1/gonum/graph/iterator"
)

// qUndirected returns the modularity Q score of the graph g subdivided into the
Expand Down Expand Up @@ -307,7 +307,7 @@ func (g *ReducedUndirected) Nodes() graph.Nodes {
for i := range g.nodes {
nodes[i] = node(i)
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// From returns all nodes in g that can be reached directly from u.
Expand All @@ -317,7 +317,7 @@ func (g *ReducedUndirected) From(uid int64) graph.Nodes {
for i, vid := range out {
nodes[i] = g.nodes[vid]
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// HasEdgeBetween returns whether an edge exists between nodes x and y.
Expand Down
8 changes: 4 additions & 4 deletions graph/community/louvain_undirected_multiplex.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"gonum.org/v1/gonum/graph"
"gonum.org/v1/gonum/graph/internal/ordered"
"gonum.org/v1/gonum/graph/internal/set"
"gonum.org/v1/gonum/graph/simple"
"gonum.org/v1/gonum/graph/iterator"
)

// UndirectedMultiplex is an undirected multiplex graph.
Expand Down Expand Up @@ -225,7 +225,7 @@ func (g *ReducedUndirectedMultiplex) Nodes() graph.Nodes {
for i := range g.nodes {
nodes[i] = node(i)
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// Depth returns the number of layers in the multiplex graph.
Expand Down Expand Up @@ -469,7 +469,7 @@ func (g undirectedLayerHandle) Nodes() graph.Nodes {
for i := range g.multiplex.nodes {
nodes[i] = node(i)
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// From returns all nodes in g that can be reached directly from u.
Expand All @@ -479,7 +479,7 @@ func (g undirectedLayerHandle) From(uid int64) graph.Nodes {
for i, vid := range out {
nodes[i] = g.multiplex.nodes[vid]
}
return simple.NewNodeIterator(nodes)
return iterator.NewOrderedNodes(nodes)
}

// HasEdgeBetween returns whether an edge exists between nodes x and y.
Expand Down
9 changes: 5 additions & 4 deletions graph/ex/fdpclust/gn.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package main

import (
"gonum.org/v1/gonum/graph"
"gonum.org/v1/gonum/graph/iterator"
"gonum.org/v1/gonum/graph/simple"
)

Expand Down Expand Up @@ -103,7 +104,7 @@ func (g *GraphNode) Nodes() graph.Nodes {
}
}

return simple.NewNodeIterator(toReturn)
return iterator.NewOrderedNodes(toReturn)
}

func (g *GraphNode) nodes(list []graph.Node, visited map[int64]struct{}) []graph.Node {
Expand Down Expand Up @@ -133,15 +134,15 @@ func (g *GraphNode) nodes(list []graph.Node, visited map[int64]struct{}) []graph

func (g *GraphNode) From(id int64) graph.Nodes {
if id == g.ID() {
return simple.NewNodeIterator(g.neighbors)
return iterator.NewOrderedNodes(g.neighbors)
}

visited := map[int64]struct{}{g.id: {}}
for _, root := range g.roots {
visited[root.ID()] = struct{}{}

if result := root.findNeighbors(id, visited); result != nil {
return simple.NewNodeIterator(result)
return iterator.NewOrderedNodes(result)
}
}

Expand All @@ -150,7 +151,7 @@ func (g *GraphNode) From(id int64) graph.Nodes {

if gn, ok := neigh.(*GraphNode); ok {
if result := gn.findNeighbors(id, visited); result != nil {
return simple.NewNodeIterator(result)
return iterator.NewOrderedNodes(result)
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions graph/iterator/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright ©2018 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package iterator provides node, edge and line iterators.
//
// The iterators provided satisfy the graph.Nodes, graph.Edges and
// graph.Lines interfaces.
package iterator
129 changes: 129 additions & 0 deletions graph/iterator/edges.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Copyright ©2018 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package iterator

import "gonum.org/v1/gonum/graph"

// OrderedEdges implements the graph.Edges and graph.EdgeSlicer interfaces.
// The iteration order of OrderedEdges is the order of edges passed to
// NewEdgeIterator.
type OrderedEdges struct {
idx int
edges []graph.Edge
}

// NewOrderedEdges returns an OrderedEdges initialized with the provided edges.
func NewOrderedEdges(edges []graph.Edge) *OrderedEdges {
return &OrderedEdges{idx: -1, edges: edges}
}

// Len returns the remaining number of edges to be iterated over.
func (e *OrderedEdges) Len() int {
if e.idx >= len(e.edges) {
return 0
}
if e.idx <= 0 {
return len(e.edges)
}
return len(e.edges[e.idx:])
}

// Next returns whether the next call of Edge will return a valid edge.
func (e *OrderedEdges) Next() bool {
if uint(e.idx)+1 < uint(len(e.edges)) {
e.idx++
return true
}
e.idx = len(e.edges)
return false
}

// Edge returns the current edge of the iterator. Next must have been
// called prior a call to Edge.
func (e *OrderedEdges) Edge() graph.Edge {
if e.idx >= len(e.edges) || e.idx < 0 {
return nil
}
return e.edges[e.idx]
}

// EdgeSlice returns all the remaining edges in the iterator.
func (e *OrderedEdges) EdgeSlice() []graph.Edge {
if e.idx >= len(e.edges) {
return nil
}
idx := e.idx
if idx == -1 {
idx = 0
}
e.idx = len(e.edges)
return e.edges[idx:]
}

// Reset returns the iterator to its initial state.
func (e *OrderedEdges) Reset() {
e.idx = -1
}

// OrderedWeightedEdges implements the graph.Edges and graph.EdgeSlicer interfaces.
// The iteration order of OrderedWeightedEdges is the order of edges passed to
// NewEdgeIterator.
type OrderedWeightedEdges struct {
idx int
edges []graph.WeightedEdge
}

// NewOrderedWeightedEdges returns an OrderedWeightedEdges initialized with the provided edges.
func NewOrderedWeightedEdges(edges []graph.WeightedEdge) *OrderedWeightedEdges {
return &OrderedWeightedEdges{idx: -1, edges: edges}
}

// Len returns the remaining number of edges to be iterated over.
func (e *OrderedWeightedEdges) Len() int {
if e.idx >= len(e.edges) {
return 0
}
if e.idx <= 0 {
return len(e.edges)
}
return len(e.edges[e.idx:])
}

// Next returns whether the next call of WeightedEdge will return a valid edge.
func (e *OrderedWeightedEdges) Next() bool {
if uint(e.idx)+1 < uint(len(e.edges)) {
e.idx++
return true
}
e.idx = len(e.edges)
return false
}

// WeightedEdge returns the current edge of the iterator. Next must have been
// called prior a call to WeightedEdge.
func (e *OrderedWeightedEdges) WeightedEdge() graph.WeightedEdge {
if e.idx >= len(e.edges) || e.idx < 0 {
return nil
}
return e.edges[e.idx]
}

// WeightedEdgeSlice returns all the remaining edges in the iterator.
func (e *OrderedWeightedEdges) WeightedEdgeSlice() []graph.WeightedEdge {
if e.idx >= len(e.edges) {
return nil
}
idx := e.idx
if idx == -1 {
idx = 0
}
e.idx = len(e.edges)
return e.edges[idx:]
}

// Reset returns the iterator to its initial state.
func (e *OrderedWeightedEdges) Reset() {
e.idx = -1
}
Loading

0 comments on commit 8e45e26

Please sign in to comment.