Skip to content

Commit

Permalink
Extend merge_vertices to handle array-string case. Part of #7
Browse files Browse the repository at this point in the history
  • Loading branch information
D4L committed Mar 9, 2013
1 parent 7aa873e commit fe5ada4
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 31 deletions.
82 changes: 51 additions & 31 deletions lib/abstract_graph/graph/merge_vertices.rb
Expand Up @@ -7,54 +7,74 @@ class Graph
# v1 and v2 merge together to a vertex named vmerged and
# the edges that were adjacent to v1 and v2 are now
# adjacent to vmerged
# p: String v1, v2 represents the names of the vertices
# String vmerged represents the name of the merged vertex
# p: (Array, String)
# array is the string names of vertices to merge together
# string is the name of the final vertex
# (String, String, String)
# first two strings are the vertices to merge together
# last string is the name of the merged vertex
# e: the edges prioritize v1 to v2 if there are any conflicts
def merge_vertices( v1, v2, vmerged )
def merge_vertices( *args )
other = self.dup
other.merge_vertices! v1, v2, vmerged
other.merge_vertices!( *args )
end

# same as before except operates on the current graph
def merge_vertices!( v1, v2, vmerged )
def merge_vertices!( *args )

# first delete the edge in between
edgeInBetween = get_edge_name v1, v2
delete_edge!( edgeInBetween ) if edgeInBetween
# create a list of vertices we want to merge
mergeV = []
if args[0].class == Array
mergeV = args[0]
else
mergeV << args[0] << args[1]
end

# first construct an array of edges in between vertices
edgesInBetween = []
if ( args.size == 3 )
# do not need to go through the array of vertices
edgesInBetween << get_edge_name( args[0], args[1] )
else
edgesInBetween = @edges.values.collect do |e|
e.name if ( e.vertices.map do |v|
v.name
end & mergeV ).count == 2
end
end

# delete the edges in between vertices
edgesInBetween.each do |e|
delete_edge!( e ) if e
end

# get the list of connections we want vmerged to be merged with
finalConnections = {}
@edges.each do |name, e|
[0, 1].each do |vertexId|
[v1, v2].each do |vcheck|

# check if the edge contains our vertices
if e.vertices[vertexId].name == vcheck
otherVertex = e.vertices[(vertexId+1)%2].name
mergeV.reverse.each do |vCheck|
@edges.each do |name, e|
[0,1].each do |edgeVId|

# check if the vertex already existed
# if it did, we want to prioritize v1
if finalConnections[otherVertex]
if vcheck == v1
finalConnections[otherVertex] = name
end
else
finalConnections[otherVertex] = name
end
# check if the edge contains our vertex
if e.vertices[edgeVId].name == vCheck
otherVertex = e.vertices[(edgeVId+1)%2].name
# track the vertex with the edge name
finalConnections[otherVertex] = name
delete_edge! name
end

end
end
end

# delete the vertices
delete_vertex! v1
delete_vertex! v2
# delete the vertices we want to merge
mergeV.each do |v|
delete_vertex! v
end

# add vmerged and connect it to the adjacent vertices
add_vertex vmerged
finalConnections.each do |vertexName, name|
add_edge name, vertexName, vmerged
# add vmerged and connect it to adjacent vertices
add_vertex args.last
finalConnections.each do | vertexName, name |
add_edge name, vertexName, args.last
end

self
Expand Down
76 changes: 76 additions & 0 deletions spec/abstract_graph/graph/merge_vertices_spec.rb
Expand Up @@ -120,6 +120,82 @@ module Composition

end

describe "#merge_vertices(Array,String)" do

it "deletes the vertices in the array" do
arr = [ @v1, @v2 ]
@gnext = @g.merge_vertices( arr, @vmerged )
arr.each do |v|
@gnext.has_vertex?( v ).should be_false
end
end

it "removes the edges connecting the vertices in the array" do
arrV = [ @v1, @v2, @v3 ]
arrE = [ @e1, @e2 ]
@gnext = @g.merge_vertices( arrV, @vmerged )
arrE.each do |e|
@gnext.has_edge?( e ).should be_false
end
end

it "connects the merged vertex with the vertices in the array" do
arr = [ @v1, @v3 ]
@gnext = @g.merge_vertices( arr, @vmerged )
[ @v2, @v4 ].each do |v|
@gnext.is_adjacent?( @vmerged, v ).should be_true
end
end

it "preserves the edges of earlier vertices than later" do
arr = [ @v1, @v3 ]
@gnext = @g.merge_vertices( arr, @vmerged )
@gnext.has_edge?( @e1 ).should be_true
@gnext.has_edge?( @e2 ).should be_false
@gnext.has_edge?( @e3 ).should be_false
@gnext.has_edge?( @e4 ).should be_true
end

end

describe "#merge_vertices!(Array,String)" do

it "deletes the vertices in the array" do
arr = [ @v1, @v2 ]
@g.merge_vertices!( arr, @vmerged )
arr.each do |v|
@g.has_vertex?( v ).should be_false
end
end

it "removes the edges connecting the vertices in the array" do
arrV = [ @v1, @v2, @v3 ]
arrE = [ @e1, @e2 ]
@g.merge_vertices!( arrV, @vmerged )
arrE.each do |e|
@g.has_edge?( e ).should be_false
end
end

it "connects the merged vertex with the vertices in the array" do
arr = [ @v1, @v3 ]
@g.merge_vertices!( arr, @vmerged )
[ @v2, @v4 ].each do |v|
@g.is_adjacent?( @vmerged, v ).should be_true
end
end

it "preserves the edges of earlier vertices than later" do
arr = [ @v1, @v3 ]
@g.merge_vertices!( arr, @vmerged )
@g.has_edge?( @e1 ).should be_true
@g.has_edge?( @e2 ).should be_false
@g.has_edge?( @e3 ).should be_false
@g.has_edge?( @e4 ).should be_true
end

end

end
end
end

0 comments on commit fe5ada4

Please sign in to comment.