-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Issue#9] - internal/graph: partition algorithm #16
base: master
Are you sure you want to change the base?
Changes from all commits
e967317
f75e31b
037f784
a869368
01264a6
7b79d8c
f783132
5bc520d
afd6b38
1ba49f1
2c24453
4f11189
bfd037f
d0aaee7
e83341a
cb8463e
57eef69
b019b87
ac55b8d
776af2d
37876b2
f75ebe4
b5a786a
1007883
1b51055
d9dc68c
6d19fec
d32bf9c
786e562
f6aae20
0333162
448de64
80418b2
4f34901
b49641d
f24be6a
3ae6e82
f1e2a9c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
testdata/pkg/* |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,27 +29,30 @@ func (g Graph) ContainsNode(id string) bool { | |
return ok | ||
} | ||
|
||
// Partition returns a slice of nodes that should be split from a given source graph. | ||
// | ||
// TODO (Issue#8): actually add logic to properly partition | ||
func (g Graph) Partition() []*Node { | ||
res := make([]*Node, 0, len(g)) | ||
|
||
// TODO: for now, just return every node | ||
for _, v := range g { | ||
res = append(res, v) | ||
// Roots finds the many possible roots in the graph. | ||
// The order of the graph traversal matters because if a parent is added _after_ | ||
// a child, then that child node won't have the identified parent node. | ||
func (g Graph) Roots() []*Node { | ||
roots := make([]*Node, 0, len(g)) | ||
|
||
for _, node := range g { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. order matters here |
||
if len(node.Parents) == 0 { | ||
roots = append(roots, node) | ||
} | ||
} | ||
|
||
return res | ||
return roots | ||
} | ||
|
||
func (g Graph) shouldPartition() bool { | ||
if len(g) <= 1 { | ||
return false | ||
} | ||
// Edges returns all of the edges in the graph. | ||
func (g Graph) Edges() []WeightedEdge { | ||
edges := make([]WeightedEdge, 0) | ||
|
||
// TODO: thought; maybe eventually we store meta data about the graph | ||
// (e.g., types of edges such as method and if there are zero methods, maybe we consider not partitioning) | ||
for _, node := range g { | ||
for _, edge := range node.Edges { | ||
edges = append(edges, edge) | ||
} | ||
} | ||
|
||
return true | ||
return edges | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,15 +31,25 @@ func TestNew(t *testing.T) { | |
} | ||
|
||
var ( | ||
parentNode = Node{ID: "parent", Edges: make(map[string]WeightedEdge), Parents: make(map[string]WeightedEdge)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
parentEdge = map[string]WeightedEdge{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
"parent": WeightedEdge{ | ||
Weight: 1.0, | ||
Dest: &parentNode, | ||
}, | ||
} | ||
|
||
edgeB = map[string]WeightedEdge{ | ||
"b": WeightedEdge{ | ||
Weight: 1.0, | ||
Dest: &Node{ID: "b", Edges: make(map[string]WeightedEdge)}, | ||
Dest: &Node{ID: "b", Edges: make(map[string]WeightedEdge), Parents: make(map[string]WeightedEdge)}, | ||
}, | ||
} | ||
|
||
nodeAWithSingleEdgeB = Node{ID: "a", Edges: edgeB} | ||
nodeCWithSingleEdgeB = Node{ID: "c", Edges: edgeB} | ||
nodeAWithSingleEdgeB = Node{ID: "a", Edges: edgeB, Parents: make(map[string]WeightedEdge)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
nodeCWithSingleEdgeB = Node{ID: "c", Edges: edgeB, Parents: make(map[string]WeightedEdge)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
nodeCWithEdgeBAndParent = Node{ID: "c", Edges: edgeB, Parents: parentEdge} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
) | ||
|
||
func TestAddNode(t *testing.T) { | ||
|
@@ -153,3 +163,36 @@ func TestContainsNode(t *testing.T) { | |
}) | ||
} | ||
} | ||
|
||
func TestRoots(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Function |
||
tests := []struct { | ||
name string | ||
graph Graph | ||
want []*Node | ||
}{ | ||
{ | ||
name: "empty-graph", | ||
graph: Graph(make(map[string]*Node)), | ||
want: []*Node{}, | ||
}, | ||
|
||
{ | ||
name: "one-root-node", | ||
graph: Graph(map[string]*Node{ | ||
"parent": &parentNode, | ||
"c": &nodeCWithEdgeBAndParent, | ||
}), | ||
want: []*Node{&parentNode}, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
got := test.graph.Roots() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the variable on range scope |
||
|
||
if diff := cmp.Diff(test.want, got); diff != "" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the variable on range scope |
||
t.Errorf("(%+v) Roots() mismatch (-want +got): \n%s", test.graph, diff) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the variable on range scope |
||
} | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,26 @@ import ( | |
"testing" | ||
) | ||
|
||
var ( | ||
nodeA = Node{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
ID: "a", | ||
Object: nil, | ||
Edges: map[string]WeightedEdge{}, | ||
Parents: map[string]WeightedEdge{}, | ||
ShortestPath: 1.0, | ||
ShortestPaths: []float64{1.0}, | ||
} | ||
|
||
nodeB = Node{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
ID: "b", | ||
Object: nil, | ||
Edges: map[string]WeightedEdge{}, | ||
Parents: map[string]WeightedEdge{}, | ||
ShortestPath: 1.0, | ||
ShortestPaths: []float64{1.0}, | ||
} | ||
) | ||
|
||
func TestAddEdge(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
|
@@ -15,21 +35,31 @@ func TestAddEdge(t *testing.T) { | |
}{ | ||
{ | ||
name: "add-edge-w1.0-to-empty-slice-should-return-edges-with-single-value", | ||
node: &Node{"a", nil, map[string]WeightedEdge{}}, | ||
dest: &Node{"b", nil, map[string]WeightedEdge{}}, | ||
node: &nodeA, | ||
dest: &nodeB, | ||
weight: 1.0, | ||
want: Node{"a", nil, map[string]WeightedEdge{"b": WeightedEdge{ | ||
Weight: 1.0, | ||
Dest: &Node{ID: "b", Object: nil, Edges: map[string]WeightedEdge{}}, | ||
}}}, | ||
want: Node{ | ||
ID: "a", | ||
Object: nil, | ||
Edges: map[string]WeightedEdge{ | ||
"b": WeightedEdge{ | ||
Weight: 1.0, | ||
Source: &nodeA, | ||
Dest: &nodeB, | ||
}, | ||
}, | ||
Parents: map[string]WeightedEdge{}, | ||
ShortestPath: 1.0, | ||
ShortestPaths: []float64{1.0}, | ||
}, | ||
}, | ||
|
||
{ | ||
name: "add-edge-to-same-node-does-nothing", | ||
node: &Node{"a", nil, map[string]WeightedEdge{}}, | ||
dest: &Node{"a", nil, map[string]WeightedEdge{}}, | ||
node: &nodeA, | ||
dest: &nodeA, | ||
weight: 1.0, | ||
want: Node{"a", nil, map[string]WeightedEdge{}}, | ||
want: nodeA, | ||
}, | ||
} | ||
|
||
|
@@ -38,7 +68,7 @@ func TestAddEdge(t *testing.T) { | |
tt.node.AddEdge(tt.dest, tt.weight) | ||
|
||
if ok := reflect.DeepEqual(*tt.node, tt.want); !ok { | ||
t.Errorf("(%+v) AddEdge(%+v, %f) - mismatch \n%+v", tt.node, tt.dest, tt.weight, tt.want) | ||
t.Errorf("AddEdge() - mismatch \n\twant: %+v\n\tgot:%+v", tt.want, *tt.node) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the variable on range scope |
||
} | ||
}) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the variable on range scope
tt
in function literal (fromscopelint
)