Permalink
Browse files

Added Graph#get_neighbours

+ Added Graph#get_node
+ (Edge|Node).update now returns an object of the same class
+ Added Edge|Node support for x.foo aliased to x['foo'] or x[:foo]
+ tests added.
  • Loading branch information...
1 parent 960a447 commit 10c28102d35b4397ac9246c9c264b5ca19f93482 @bfontaine committed Feb 12, 2013
Showing with 189 additions and 7 deletions.
  1. +85 −7 lib/graph.rb
  2. +46 −0 tests/edge_tests.rb
  3. +47 −0 tests/graph_tests.rb
  4. +11 −0 tests/node_tests.rb
View
@@ -65,7 +65,15 @@ def ==(other)
@attrs == other.attrs
end
+ def update(h)
+ Node.new super(h)
+ end
+
def method_missing(method, *args, &block)
+
+ return @attrs[method.to_sym] if @attrs.has_key? method.to_sym
+ return @attrs[method.to_s] if @attrs.has_key? method.to_s
+
@attrs.send(method, *args, &block)
end
@@ -89,7 +97,15 @@ def ==(other)
@attrs == other.attrs
end
+ def update(h)
+ Edge.new super(h)
+ end
+
def method_missing(method, *args, &block)
+
+ return @attrs[method.to_sym] if @attrs.has_key? method.to_sym
+ return @attrs[method.to_s] if @attrs.has_key? method.to_s
+
@attrs.send(method, *args, &block)
end
@@ -117,11 +133,14 @@ def set_default(dict)
# @param n [Node]
def push(n)
if (!n.is_a?(Hash) && !n.is_a?(Node))
- raise TypeError.new "#{n.inspect} is not an Hash or a Node!"
+ raise TypeError.new "#{n.inspect} is not an Hash nor a Node!"
end
+ n = Node.new(n) if (n.is_a?(Hash))
+
super(n.clone.update(@defaults))
end
+
end
# An array of Edge objects
@@ -146,11 +165,14 @@ def set_default(dict)
# @param e [Edge]
def push(e)
if (!e.is_a?(Hash) && !e.is_a?(Edge))
- raise TypeError.new "#{e.inspect} is not an Hash or an Edge!"
+ raise TypeError.new "#{e.inspect} is not an Hash nor an Edge!"
end
+ e = Edge.new(e) if (e.is_a?(Hash))
+
super(e.clone.update(@defaults))
end
+
end
attr_accessor :nodes, :edges, :attrs
@@ -313,7 +335,7 @@ def write(filename, opts=nil)
# @see Graph#in_degree_of
# @see Graph#out_degree_of
def degree_of(n)
- label = Graph::get_label_from_node(n)
+ label = Graph::get_label(n)
degree = 0
@@ -337,7 +359,7 @@ def degree_of(n)
# @see Graph#degree_of
# @see Graph#out_degree_of
def in_degree_of(n)
- label = Graph::get_label_from_node(n)
+ label = Graph::get_label(n)
degree = 0
@@ -358,7 +380,7 @@ def in_degree_of(n)
# @see Graph#degree_of
# @see Graph#out_degree_of
def out_degree_of(n)
- label = Graph::get_label_from_node(n)
+ label = Graph::get_label(n)
degree = 0
@@ -369,12 +391,68 @@ def out_degree_of(n)
degree
end
+ # return the first node which mach the given label in the current graph
+ # @param label [String] A node's label
+ def get_node(label)
+
+ label = Graph::get_label(label)
+
+ self.nodes.find { |n| n.label == label }
+
+ end
+
+ # return an array of the neighbours of a node in the current graph.
+ # @param n [Node,String] A node with a 'label' or :label attribute, or a string
+ def get_neighbours(n)
+
+ label = Graph::get_label(n)
+ neighbours = NodeArray.new []
+
+ self.edges.each do |e|
+
+ begin
+
+ l1 = e.node1
+ l2 = e.node2
+
+ rescue NoMethodError; next; end
+
+ if l2 && l1 == label
+
+ n2 = self.get_node l2
+
+ unless neighbours.include?(l2)
+
+ neighbours.push(n2)
+
+ end
+
+ end
+
+ if l1 && l2 == label && self.directed?
+
+ n1 = self.get_node l1
+
+ unless neighbours.include?(n1)
+
+ neighbours.push(n1)
+
+ end
+
+ end
+
+ end
+
+ neighbours
+
+ end
+
# return the label of a node. Raise a TypeError exception if the argument
# is not a Node nor a String object.
# @param n [Node,String] A node with a 'label' or :label attribute, or a string
- def Graph::get_label_from_node(n)
+ def Graph::get_label(n)
label = n.is_a?(Node) \
- ? (n['label'] || n[:label]).to_s \
+ ? n.label.to_s \
: n.is_a?(String) ? n : nil
raise TypeError.new("#{n.inspect} must be a Node or String object.") if label.nil?
View
@@ -0,0 +1,46 @@
+#! /usr/bin/ruby1.9.1
+# -*- coding: UTF-8 -*-
+
+class Edge_test < Test::Unit::TestCase
+
+ def setup
+ @@empty = Graph::Node.new
+ @@alice = Graph::Node.new('label' => 'Alice')
+
+ # Alice ----> Bob
+ # ↑ ↑
+ # | |
+ # Oscar -------'
+ @@sample_graph = Graph.new(
+ [
+ { 'label' => 'Alice' },
+ { 'label' => 'Bob' },
+ { 'label' => 'Oscar' }
+ ],
+ [
+ { 'node1' => 'Alice', 'node2' => 'Bob' },
+ { :node1 => 'Oscar', 'node2' => 'Alice'},
+ { 'node1' => 'Oscar', :node2 => 'Bob'}
+ ]
+ )
+
+ end
+
+ def test_edge_node1_attr
+ assert_equal('Alice', @@sample_graph.edges[0].node1)
+ assert_equal('Oscar', @@sample_graph.edges[1].node1)
+ end
+
+ def test_edge_node2_attr
+ assert_equal('Alice', @@sample_graph.edges[1].node2)
+ assert_equal('Bob', @@sample_graph.edges[2].node2)
+ end
+
+ def test_edge_update
+
+ e = Graph::Edge.new
+
+ assert_equal(true, e.update({}).is_a?(Graph::Edge))
+ end
+
+end
View
@@ -551,4 +551,51 @@ def test_graph_write_unknow_ext
end
assert_equal(false, File.exists?(f))
end
+
+ # == Graph#get_node == #
+
+ def test_graph_get_node_unexisting_label
+
+ n = @@sample_graph.get_node 'foobar'
+
+ assert_equal(nil, n)
+ end
+
+ def test_graph_get_node_existing_label
+
+ g = @@sample_graph;
+
+ n = g.get_node 'foo'
+
+ assert_equal(g.nodes[0], n)
+ end
+
+ # == Graph#get_neighbours == #
+
+ def test_graph_get_neighbours_unexisting_node_label
+
+ n = @@sample_graph.get_neighbours 'moo'
+
+ assert_equal([], n)
+
+ end
+
+ def test_graph_get_neighbours_unexisting_node_object
+
+ n = @@sample_graph.get_neighbours Graph::Node.new( :label => 'moo' )
+
+ assert_equal([], n)
+
+ end
+
+ def test_graph_get_neighbours
+
+ g = @@sample_graph
+
+ n = g.get_neighbours 'foo'
+
+ assert_equal([ 'bar', 'chuck' ], n.map { |m| m.label })
+
+ end
+
end
View
@@ -81,4 +81,15 @@ def test_node_out_degree_by_object
assert_equal(1, @@sample_graph.out_degree_of(@@alice))
end
+ def test_node_label_attr
+ assert_equal('Alice', @@alice.label)
+ end
+
+ def test_node_update
+
+ n = Graph::Node.new
+
+ assert_equal(true, n.update({}).is_a?(Graph::Node))
+ end
+
end

0 comments on commit 10c2810

Please sign in to comment.