require 'bundler/setup'
-require 'graph.njae/graph'
-require 'graph.njae/edge'
-require 'graph.njae/vertex'
+require 'ostruct'
+
+require_relative 'graph.njae/graph'
+require_relative 'graph.njae/edge'
+require_relative 'graph.njae/vertex'
-require 'ostruct'
-
# A simple graph library
module GraphNjae
def to_s
'<E: ' + self.type.to_s + ' [' + self.vertices.map {|n| n.to_s}.join(', ') + '] >'
end
+
+ def to_dot(opts = {})
+ if block_given?
+ yield self
+ else
+ dot = self.connections[0].end.object_id.to_s + " -- " + self.connections[1].end.object_id.to_s
+ if opts.size > 0
+ dot << ' {'
+ dot << opts.keys.map { |k|
+ (k.to_s + ' = "' + self.instance_eval(opts[k].to_s).to_s) + '"'
+ }.join(', ')
+ dot << '}'
+ end
+ dot << ';'
+ end
+ end
+
end
# A connection between an Edge and a Vertex.The connection can have arbitrary attributes,
-require 'ostruct'
-
require 'logger'
$log = Logger.new(STDERR)
$log.level = Logger::WARN
edge << vertex1 << vertex2
end
+ def to_dot(opts = {})
+ vertex_args = opts[:vertex_args] || {}
+ vertex_block = opts[:vertex_block] || nil
+ edge_args = opts[:edge_args] || {}
+ edge_block = opts[:edge_block] || nil
+ dot = "graph {\n"
+ self.vertices.each do |v|
+ if vertex_block.nil?
+ dot << v.to_dot(vertex_args)
+ else
+ dot << v.do_dot(&vertex_block)
+ end
+ dot << "\n"
+ end
+ self.edges.each do |e|
+ if edge_block.nil?
+ dot << e.to_dot(edge_args)
+ else
+ dot << e.do_dot(&lambda {edge_block})
+ end
+ dot << "\n"
+ end
+ dot << '}'
+ end
+
# Form a product graph of this graph and the other.
# Return the product graph.
def product(other)
-require 'ostruct'
-
# A simple graph library
module GraphNjae
'<V: ' + self.name.to_s + '>'
end
+ def to_dot(opts = {})
+ if block_given?
+ yield self
+ else
+ dot = self.object_id.to_s
+ if opts.size > 0
+ dot << ' {'
+ dot << opts.keys.map { |k|
+ (k.to_s + ' = "' + self.instance_eval(opts[k].to_s).to_s) + '"'
+ }.join(', ')
+ dot << '}'
+ end
+ dot << ';'
+ end
+ end
+
end
end
module GraphNjae
describe Edge do
let (:e) { Edge.new }
- describe "#initialize" do
- it "creates an empty edge" do
+ let(:v1) {Vertex.new :name => :v1}
+ let(:v2) {Vertex.new :name => :v2}
+ let(:v3) {Vertex.new :name => :v3}
+
+ describe '#initialize' do
+ it 'creates an empty edge' do
e = Edge.new
e.connections.should be_empty
end
- it "creates an edge with some parameters" do
- e = Edge.new :value1 => 1, :value2 => "value2", :value3 => :v3
+ it 'creates an edge with some parameters' do
+ e = Edge.new :value1 => 1, :value2 => 'value2', :value3 => :v3
e.value1.should == 1
- e.value2.should == "value2"
+ e.value2.should == 'value2'
e.value3.should == :v3
e.value4.should be_nil
end
end # #initialize
- describe "adds attribues" do
- it "adds then reports arbitrary attributes" do
+ describe 'adds attribues' do
+ it 'adds then reports arbitrary attributes' do
e.score = 15
e.score.should == 15
end
describe "#<<" do
it "adds a new vertex to an edge (with a connection)" do
e.connections.should be_empty
- v1 = Vertex.new :name => :v1
- v2 = Vertex.new :name => :v2
e << v1
e.should have(1).connections
e.should have(1).vertices
v2.edges.should include(e)
end
- it "adds several vertices to an edge" do
+ it 'adds several vertices to an edge' do
e.connections.should be_empty
- v1 = Vertex.new :name => :v1
- v2 = Vertex.new :name => :v2
e << v1 << v2
e.vertices.should include(v1)
e.vertices.should include(v2)
e.should have(2).vertices
end
- it "adds a self-loop" do
+ it 'adds a self-loop' do
e.connections.should be_empty
- v1 = Vertex.new
e << v1 << v1
e.vertices.should include(v1)
e.should have(2).vertices
end
end # #<<
- describe "connection_at" do
- it "returns the connection that links to a vertex" do
+ describe 'connection_at' do
+ it 'returns the connection that links to a vertex' do
e.connections.should be_empty
- v1 = Vertex.new :name => :v1
- v2 = Vertex.new :name => :v2
e << v1 << v2
e.connection_at(v1).end.should be v1
e.connection_at(v2).end.should be v2
end
- it "returns nil if there is no connection to that vertex" do
+ it 'returns nil if there is no connection to that vertex' do
e.connections.should be_empty
- v1 = Vertex.new :name => :v1
- v2 = Vertex.new :name => :v2
- v3 = Vertex.new :name => :v3
e << v1 << v2
e.connection_at(v3).should be nil
end
- it "returns the vertex for a self-loop" do
+ it 'returns the vertex for a self-loop' do
e.connections.should be_empty
- v1 = Vertex.new :name => :v1
e << v1 << v1
e.connection_at(v1).end.should be v1
end
end # #connection_at
- describe "other_end" do
- it "returns the vertex at the other end of the given one" do
+ describe 'other_end' do
+ it 'returns the vertex at the other end of the given one' do
e.connections.should be_empty
- v1 = Vertex.new :name => :v1
- v2 = Vertex.new :name => :v2
e << v1 << v2
e.other_end(v1).should be v2
e.other_end(v2).should be v1
end
- it "returns the same vertex in a self-loop" do
+ it 'returns the same vertex in a self-loop' do
e.connections.should be_empty
- v1 = Vertex.new :name => :v1
e << v1 << v1
e.other_end(v1).should be v1
end
- it "returns one of the connected edges if given a vertex not connected to it" do
+ it 'returns one of the connected edges if given a vertex not connected to it' do
e.connections.should be_empty
- v1 = Vertex.new :name => :v1
- v2 = Vertex.new :name => :v2
- v3 = Vertex.new :name => :v3
e << v1 << v2
[v1, v2].should include e.other_end(v3)
end
- it "returns nil if it can't return something sensible" do
- v1 = Vertex.new :name => :v1
+ it 'returns nil if it cannot return something sensible' do
e.other_end(v1).should be_nil
e << v1
e.other_end(v1).should be_nil
end
end # other_end
+
+ describe '#to_dot' do
+ it 'describes an edge in dot notation' do
+ e << v1 << v2
+ e.to_dot.should == "#{v1.object_id.to_s} -- #{v2.object_id.to_s};"
+ end
+
+ it 'describes an edge in dot notation, using given attributes' do
+ e << v1 << v2
+ e.name = 'Edge name'
+ edot = e.to_dot :label => :name
+ edot.should == "#{v1.object_id.to_s} -- #{v2.object_id.to_s} {label = \"#{e.name}\"};"
+ end
+
+ it 'describes an edge in dot notation, given a block' do
+ e << v1 << v2
+ e.to_dot {|e| e.object_id.to_s}.should == e.object_id.to_s
+ end
+ end # dot
end # Edge
describe Connection do
let (:c) {Connection.new }
- describe "adds attribues" do
- it "adds then reports arbitrary attributes" do
+ describe 'adds attribues' do
+ it 'adds then reports arbitrary attributes' do
c.score = 15
c.score.should == 15
end
describe Graph do
let (:g) { Graph.new }
- describe "#initialize" do
- it "creates an empty graph" do
+ describe '#initialize' do
+ it 'creates an empty graph' do
g = Graph.new
g.edges.should be_empty
g.vertices.should be_empty
end
- it "creates a graph with some parameters" do
- g = Graph.new :value1 => 1, :value2 => "value2", :value3 => :v3
+ it 'creates a graph with some parameters' do
+ g = Graph.new :value1 => 1, :value2 => 'value2', :value3 => :v3
g.value1.should == 1
- g.value2.should == "value2"
+ g.value2.should == 'value2'
g.value3.should == :v3
g.value4.should be_nil
end
end # #initialize
- describe "adds attributes" do
- it "adds then reports arbitrary attributes" do
+ describe 'adds attributes' do
+ it 'adds then reports arbitrary attributes' do
g.score = 15
g.score.should == 15
end
end # adds attributes
- describe "#<<" do
- it "adds a set of vertices" do
+ describe '#<<' do
+ it 'adds a set of vertices' do
g.vertices.should be_empty
v1 = Vertex.new
v2 = Vertex.new
g.vertices.should include(v2)
end
- it "adds a set of edges" do
+ it 'adds a set of edges' do
g.edges.should be_empty
e1 = Edge.new
e2 = Edge.new
g.edges.should include(e2)
end
- it "adds a mixed set of vertices and edges" do
+ it 'adds a mixed set of vertices and edges' do
g.vertices.should be_empty
g.edges.should be_empty
v1 = Vertex.new
g.edges.should include(e2)
end
- it "adds a subclass of Vertex" do
+ it 'adds a subclass of Vertex' do
g.vertices.should be_empty
v1 = SVertex.new
v2 = SVertex.new
end
end # #<<
- describe "connect" do
- it "adds and records an edge between vertices" do
+ describe 'connect' do
+ it 'adds and records an edge between vertices' do
g.vertices.should be_empty
g.edges.should be_empty
v1 = Vertex.new(:name => :v1)
g.should have(1).edges
end
- it "adds and records an edge with attributes between vertices" do
+ it 'adds and records an edge with attributes between vertices' do
g.vertices.should be_empty
g.edges.should be_empty
v1 = Vertex.new(:name => :v1)
end
end # #connect
- describe "product" do
- it "finds a product graph of a pair of one-vertex graphs" do
+ describe '#to_dot' do
+ it 'gives the dot notation of a simple graph' do
+ v1 = Vertex.new(:name => :v1)
+ v2 = Vertex.new(:name => :v2)
+ g.connect(v1, v2, :type => :edge_type)
+ g.to_dot.should == "graph {\n#{v1.object_id.to_s};\n#{v2.object_id.to_s};\n#{v1.object_id.to_s} -- #{v2.object_id.to_s};\n}"
+ end
+
+ it "gives the dot notation of a simple graph, with vertex attributes" do
+ v1 = Vertex.new(:name => :v1)
+ v2 = Vertex.new(:name => :v2)
+ g.connect(v1, v2, :type => :edge_type)
+ gdot = g.to_dot(:vertex_args => {:label => :name})
+ gdot.should == "graph {\n#{v1.object_id.to_s} {label = \"#{v1.name}\"};\n#{v2.object_id.to_s} {label = \"#{v2.name}\"};\n#{v1.object_id.to_s} -- #{v2.object_id.to_s};\n}"
+ end
+
+ it "gives the dot notation of a simple graph, with vertices generated by a block" do
+ v1 = Vertex.new(:name => :v1)
+ v2 = Vertex.new(:name => :v2)
+ g.connect(v1, v2, :type => :edge_type)
+ gdot = g.to_dot(:vertex_block => lambda {|v| v.name})
+ gdot.should == "graph {\n#{v1.name};\n#{v2.name};\n#{v1.object_id.to_s} -- #{v2.object_id.to_s};\n}"
+ end
+
+ end # #to_dot
+
+ describe 'product' do
+ it 'finds a product graph of a pair of one-vertex graphs' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new
product.edges.should be_empty
end
- it "finds a product graph of a pair of simple graphs" do
+ it 'finds a product graph of a pair of simple graphs' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
pg.should have(2).edges
end
- it "finds a product graph of not-quite-simple graph" do
+ it 'finds a product graph of not-quite-simple graph' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
pg.should have(8).edges
end
- it "finds a product graph of a simple graph with edge types" do
+ it 'finds a product graph of a simple graph with edge types' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
pg.should have(4).edges
end
- it "finds a product graph of the example graph from paper" do
- pending "implementation of directed graphs as operands of the product graph"
+ it 'finds a product graph of the example graph from paper' do
+ pending 'implementation of directed graphs as operands of the product graph'
g1 = Graph.new
g2 = Graph.new
a = Vertex.new(:name => :a)
pg.should have(4).edges
pg.should have(6).vertices
end
-
-
end #product
- describe "initial_similarity" do
+ describe 'initial_similarity' do
before(:each) do
g1 = Graph.new
g2 = Graph.new
1 - n1.to_s.codepoints.to_a.delete_if {|c| n2.to_s.codepoints.to_a.include? c}.length / n1.to_s.length.to_f
end
- it "should give all nodes an initial similarity of 1 if no block is given" do
+ it 'should give all nodes an initial similarity of 1 if no block is given' do
@pg.initial_similarity
@pg.vertices.each do |v|
v.initial_similarity.should be_within(0.001).of(1.0)
end
end
- it "should give all nodes the similarity as defined by the given block" do
+ it 'should give all nodes the similarity as defined by the given block' do
@pg.initial_similarity {|v| simple_name_similarity v.g1_vertex.name, v.g2_vertex.name}
@pg.vertices.each do |v|
v.initial_similarity.should be_within(0.001).of( simple_name_similarity v.g1_vertex.name, v.g2_vertex.name )
end
end #initial similarity
- describe "similarity flood" do
- it "similarity floods a graph of two nodes" do
+ describe 'similarity flood' do
+ it 'similarity floods a graph of two nodes' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
end
end
- it "similarity floods a graph of three nodes, a -- b -- c" do
+ it 'similarity floods a graph of three nodes, a -- b -- c' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
pg.initial_similarity
pg.similarity_flood
expected_similarities = {
- "g1v1:g2v1" => 0.5,
- "g1v1:g2v2" => 0.6666666666666666,
- "g1v2:g2v1" => 0.6666666666666666,
- "g1v2:g2v2" => 1.0,
- "g1v2:g2v3" => 0.6666666666666666,
- "g1v3:g2v2" => 0.6666666666666666,
- "g1v3:g2v3" => 0.5}
+ 'g1v1:g2v1' => 0.5,
+ 'g1v1:g2v2' => 0.6666666666666666,
+ 'g1v2:g2v1' => 0.6666666666666666,
+ 'g1v2:g2v2' => 1.0,
+ 'g1v2:g2v3' => 0.6666666666666666,
+ 'g1v3:g2v2' => 0.6666666666666666,
+ 'g1v3:g2v3' => 0.5}
pg.vertices.each do |v|
- name = v.g1_vertex.name.to_s + ':' + v.g2_vertex.name.to_s
+ name = "#{v.g1_vertex.name.to_s}:#{v.g2_vertex.name.to_s}"
v.similarity.should be_within(0.001).of(expected_similarities[name])
end
end
- it "simialrity floods the sample graph from the paper" do
+ it 'simialrity floods the sample graph from the paper' do
pg = Graph.new
- ab = Vertex.new(:name => "a:b")
- a1b1 = Vertex.new(:name => "a1:b1")
- a2b1 = Vertex.new(:name => "a2:b1")
- a1b2 = Vertex.new(:name => "a1:b2")
- a1b = Vertex.new(:name => "a1:b")
- a2b2 = Vertex.new(:name => "a2:b2")
+ ab = Vertex.new(:name => 'a:b')
+ a1b1 = Vertex.new(:name => 'a1:b1')
+ a2b1 = Vertex.new(:name => 'a2:b1')
+ a1b2 = Vertex.new(:name => 'a1:b2')
+ a1b = Vertex.new(:name => 'a1:b')
+ a2b2 = Vertex.new(:name => 'a2:b2')
pg.connect(ab, a1b1, :type => :l1)
pg.connect(ab, a2b1, :type => :l1)
pg.connect(a2b1, a1b2, :type => :l2)
pg.similarity_flood
expected_similarities = {
- "a:b" => 1.0,
- "a2:b1" => 0.92,
- "a1:b2" => 0.71,
- "a1:b1" => 0.38,
- "a1:b" => 0.0,
- "a2:b2" => 0.0}
+ 'a:b' => 1.0,
+ 'a2:b1' => 0.92,
+ 'a1:b2' => 0.71,
+ 'a1:b1' => 0.38,
+ 'a1:b' => 0.0,
+ 'a2:b2' => 0.0}
pg.vertices.each do |v|
v.similarity.should be_within(0.02).of(expected_similarities[v.name])
end
end
- it "similarity floods a graph of three nodes, a -- b -- c, given a block that performs the default update" do
+ it 'similarity floods a graph of three nodes, a -- b -- c, given a block that performs the default update' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
v.similarity
end
expected_similarities = {
- "g1v1:g2v1" => 0.5,
- "g1v1:g2v2" => 0.6666666666666666,
- "g1v2:g2v1" => 0.6666666666666666,
- "g1v2:g2v2" => 1.0,
- "g1v2:g2v3" => 0.6666666666666666,
- "g1v3:g2v2" => 0.6666666666666666,
- "g1v3:g2v3" => 0.5}
+ 'g1v1:g2v1' => 0.5,
+ 'g1v1:g2v2' => 0.6666666666666666,
+ 'g1v2:g2v1' => 0.6666666666666666,
+ 'g1v2:g2v2' => 1.0,
+ 'g1v2:g2v3' => 0.6666666666666666,
+ 'g1v3:g2v2' => 0.6666666666666666,
+ 'g1v3:g2v3' => 0.5}
pg.vertices.each do |v|
- name = v.g1_vertex.name.to_s + ':' + v.g2_vertex.name.to_s
+ name = "#{v.g1_vertex.name.to_s}:#{v.g2_vertex.name.to_s}"
v.similarity.should be_within(0.001).of(expected_similarities[name])
end
end
- it "similarity floods a graph of three nodes, a -- b -- c, given a block that performs a different update (method A)" do
+ it 'similarity floods a graph of three nodes, a -- b -- c, given a block that performs a different update (method A)' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
v.similarity
end
expected_similarities = {
- "g1v1:g2v1" => 0.9269662921348315,
- "g1v1:g2v2" => 1.0,
- "g1v2:g2v1" => 0.6179775280898876,
- "g1v2:g2v2" => 1.0,
- "g1v2:g2v3" => 1.0,
- "g1v3:g2v2" => 0.6179775280898876,
- "g1v3:g2v3" => 0.6179775280898876}
+ 'g1v1:g2v1' => 0.9269662921348315,
+ 'g1v1:g2v2' => 1.0,
+ 'g1v2:g2v1' => 0.6179775280898876,
+ 'g1v2:g2v2' => 1.0,
+ 'g1v2:g2v3' => 1.0,
+ 'g1v3:g2v2' => 0.6179775280898876,
+ 'g1v3:g2v3' => 0.6179775280898876}
pg.vertices.each do |v|
- name = v.g1_vertex.name.to_s + ':' + v.g2_vertex.name.to_s
+ name = "#{v.g1_vertex.name.to_s}:#{v.g2_vertex.name.to_s}"
v.similarity.should be_within(0.001).of(expected_similarities[name])
end
end
- it "similarity floods a graph of three nodes, a -- b -- c, given a block that performs a different update (method B)" do
+ it 'similarity floods a graph of three nodes, a -- b -- c, given a block that performs a different update (method B)' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
v.similarity
end
expected_similarities = {
- "g1v1:g2v1" => 1.0,
- "g1v1:g2v2" => 1.0,
- "g1v2:g2v1" => 0.0,
- "g1v2:g2v2" => 1.0,
- "g1v2:g2v3" => 1.0,
- "g1v3:g2v2" => 0.0,
- "g1v3:g2v3" => 0.0}
+ 'g1v1:g2v1' => 1.0,
+ 'g1v1:g2v2' => 1.0,
+ 'g1v2:g2v1' => 0.0,
+ 'g1v2:g2v2' => 1.0,
+ 'g1v2:g2v3' => 1.0,
+ 'g1v3:g2v2' => 0.0,
+ 'g1v3:g2v3' => 0.0}
pg.vertices.each do |v|
- name = v.g1_vertex.name.to_s + ':' + v.g2_vertex.name.to_s
+ name = "#{v.g1_vertex.name.to_s}:#{v.g2_vertex.name.to_s}"
v.similarity.should be_within(0.001).of(expected_similarities[name])
end
end
- it "similarity floods a graph of three nodes, a -- b -- c, given a block that performs a different update (method C)" do
+ it 'similarity floods a graph of three nodes, a -- b -- c, given a block that performs a different update (method C)' do
g1 = Graph.new
g2 = Graph.new
g1v1 = Vertex.new(:name => :g1v1)
v.similarity
end
expected_similarities = {
- "g1v1:g2v1" => 0.8282781862745098,
- "g1v1:g2v2" => 1.0,
- "g1v2:g2v1" => 0.41421568627450983,
- "g1v2:g2v2" => 1.0,
- "g1v2:g2v3" => 1.0,
- "g1v3:g2v2" => 0.41421568627450983,
- "g1v3:g2v3" => 0.41421568627450983}
+ 'g1v1:g2v1' => 0.8282781862745098,
+ 'g1v1:g2v2' => 1.0,
+ 'g1v2:g2v1' => 0.41421568627450983,
+ 'g1v2:g2v2' => 1.0,
+ 'g1v2:g2v3' => 1.0,
+ 'g1v3:g2v2' => 0.41421568627450983,
+ 'g1v3:g2v3' => 0.41421568627450983}
pg.vertices.each do |v|
- name = v.g1_vertex.name.to_s + ':' + v.g2_vertex.name.to_s
+ name = "#{v.g1_vertex.name.to_s}:#{v.g2_vertex.name.to_s}"
v.similarity.should be_within(0.001).of(expected_similarities[name])
end
end
describe Vertex do
let (:v) { Vertex.new }
- describe "#initialize" do
- it "creates an empty vertex" do
+ describe '#initialize' do
+ it 'creates an empty vertex' do
v = Vertex.new
v.edges.should be_empty
end
- it "creates a vertex with some parameters" do
- v = Vertex.new :value1 => 1, :value2 => "value2", :value3 => :v3
+ it 'creates a vertex with some parameters' do
+ v = Vertex.new :value1 => 1, :value2 => 'value2', :value3 => :v3
v.value1.should == 1
- v.value2.should == "value2"
+ v.value2.should == 'value2'
v.value3.should == :v3
v.value4.should be_nil
end
end # #initialize
- describe "adds attribues" do
- it "adds then reports arbitrary attributes" do
+ describe 'adds attribues' do
+ it 'adds then reports arbitrary attributes' do
v.score = 15
v.score.should == 15
end
end
- describe "#<<" do
- it "adds a single edge between vertices" do
+ describe '#<<' do
+ it 'adds a single edge between vertices' do
v.neighbours.should be_empty
v.edges.should be_empty
v1.neighbours.should_not include(v1)
end
- it "adds a single edge as a self-loop" do
+ it 'adds a single edge as a self-loop' do
v.neighbours.should be_empty
v.edges.should be_empty
end
end # #<<
- describe "connect" do
- it "connects two vertices" do
+ describe 'connect' do
+ it 'connects two vertices' do
v1 = Vertex.new
v1.id = :v1 # Need this to ensure that v != v1
e.should have(2).connections
end
- it "connects two vertices by an edge with attributes" do
+ it 'connects two vertices by an edge with attributes' do
v1 = Vertex.new
v1.id = :v1
e = v.connect(v1, {:type => :edge_type})
e.type.should == :edge_type
end
- it "creates a self-connection" do
+ it 'creates a self-connection' do
e = v.connect v
v.should have(1).neighbours
e.should have(2).connections
end
- it "creates a self-connection with an edge with attributes" do
+ it 'creates a self-connection with an edge with attributes' do
e = v.connect(v, {:type => :edge_type})
e.type.should == :edge_type
end
end # #connect
- describe "#neighbours" do
- it "finds neighbours of a self loop" do
+ describe '#neighbours' do
+ it 'finds neighbours of a self loop' do
v << v
v.should have(1).neighbours
v.neighbours.should include v
end
- it "finds neighbours on an edge" do
+ it 'finds neighbours on an edge' do
v1 = Vertex.new
v << v1
v.should have(1).neighbours
v1.neighbours.should include v
end
- it "finds neighbours with multiple edges" do
+ it 'finds neighbours with multiple edges' do
v1 = Vertex.new
v1.id = :v1
v << v1
v1.neighbours.should_not include v1
end
- it "finds neighbours with multiple self loops" do
+ it 'finds neighbours with multiple self loops' do
v << v << v << v
v.should have(3).neighbours
v.neighbours.should include v
v.neighbours.uniq.length.should == 1
end
- it "finds neighbours with all sorts of edges" do
+ it 'finds neighbours with all sorts of edges' do
v1 = Vertex.new ; v1.id = :v1
v2 = Vertex.new ; v2.id = :v2
v3 = Vertex.new ; v3.id = :v3
v3.neighbours.should include v2
end
- it "finds neighbours in graphs with several vertices" do
+ it 'finds neighbours in graphs with several vertices' do
v1 = Vertex.new ; v1.id = :v1
v2 = Vertex.new ; v2.id = :v2
v3 = Vertex.new ; v3.id = :v3
v4.neighbours.should_not include v4
end
- it "finds neighbours with multiple edges between vertices" do
+ it 'finds neighbours with multiple edges between vertices' do
v1 = Vertex.new ; v1.id = :v1
v2 = Vertex.new ; v2.id = :v2
v3 = Vertex.new ; v3.id = :v3
v3.neighbours.uniq.length.should == 1
end
end # #neighbours
+
+ describe '#to_dot' do
+ it 'describes a vertex in dot notation' do
+ v = Vertex.new
+ v.to_dot.should == "#{v.object_id.to_s};"
+ end
+
+ it 'describes a vertex in dot notation, using given attributes' do
+ v = Vertex.new
+ v.name = 'vertex'
+ v.shape = 'house'
+ vdot = v.to_dot :label => :name, :shape => :shape
+ vdot.should == "#{v.object_id.to_s} {label = \"#{v.name}\", shape = \"#{v.shape}\"};"
+ end
+
+ it 'describes a vertex using a block' do
+ v = Vertex.new
+ v.field1 = 'f1'
+ vdot = v.to_dot {|v| v.field1 + ';'}
+ vdot.should == "#{v.field1};"
+ end
+ end # #to_dot
end
end