class Graph

Graph models directed graphs and subgraphs and outputs in graphviz's dot format.

Attributes

edge_attribs[R]

Global attributes for edges in this graph.

edges[R]

The hash of hashes of edges in this graph. Use [] or node to create edges.

graph[RW]

A parent graph, if any. Only used for subgraphs.

graph_attribs[R]

Global attributes for this graph.

name[RW]

The name of the graph. Optional for graphs and subgraphs. Prefix the name of a subgraph with “cluster” for subgraph that is boxed.

node_attribs[R]

Global attributes for nodes in this graph.

nodes[R]

The hash of nodes in this graph. Use [] or node to create nodes.

scheme[RW]

Shortcut method to create a new colorscheme Attribute instance. If passed n, name must match one of the brewer color scheme names and it will generate accessors for each fillcolor as well as push the colorscheme onto the node_attribs.

subgraphs[R]

An array of subgraphs.

Public Class Methods

escape_label(s) click to toggle source
# File lib/graph.rb, line 293
def self.escape_label s
  s = s.to_s.gsub(/\n/, '\n').gsub(/\"/, '\\"')
  if s[0] == ?< and s[-1] == ?> then
    s
  else
    "\"#{s}\""
  end
end
new(name = nil, graph = nil, &block) click to toggle source

Creates a new graph object. Optional name and parent graph are available. Also takes an optional block for DSL-like use.

# File lib/graph.rb, line 137
def initialize name = nil, graph = nil, &block
  @name = name
  @graph = graph
  graph << self if graph
  @nodes_order = []
  @nodes  = Hash.new { |h,k| @nodes_order << k; h[k] = Node.new self, k }
  @edges_order = []
  @edges  = Hash.new { |h,k|
    h[k] = Hash.new { |h2, k2|
      @edges_order << [k, k2]
      h2[k2] = Edge.new self, self[k], self[k2]
    }
  }
  @graph_attribs = []
  @node_attribs  = []
  @edge_attribs  = []
  @subgraphs     = []

  self.scheme = graph.scheme if graph
  node_attribs << scheme if scheme

  instance_eval(&block) if block
end

Public Instance Methods

<<(subgraph) click to toggle source

Push a subgraph into the current graph. Sets the subgraph's graph to self.

# File lib/graph.rb, line 164
def << subgraph
  subgraphs << subgraph
  subgraph.graph = self
end
[](name) click to toggle source

Access a node by name

# File lib/graph.rb, line 172
def [] name
  nodes[name]
end
arrowhead(shape) click to toggle source

Shortcut method for creating an arrowhead attribute.

# File lib/graph.rb, line 179
def arrowhead shape
  raise ArgumentError, "Bad arrow shape: #{shape}" unless shape =~ ARROW_RE
  Attribute.new "arrowhead = #{shape}"
end
arrowsize(size) click to toggle source

Shortcut method for creating an arrowsize attribute.

# File lib/graph.rb, line 195
def arrowsize size
  Attribute.new "arrowsize = #{size}"
end
arrowtail(shape) click to toggle source

Shortcut method for creating an arrowtail attribute.

# File lib/graph.rb, line 187
def arrowtail shape
  raise ArgumentError, "Bad arrow shape: #{shape}" unless shape =~ ARROW_RE
  Attribute.new "arrowtail = #{shape}"
end
boxes() click to toggle source

Shortcut method to set the global node attributes to use boxes.

# File lib/graph.rb, line 202
def boxes
  node_attribs << shape("box")
end
cluster(name, &block) click to toggle source

Shortcut method to create a clustered subgraph in the current graph. Use with the top-level digraph method in block form for a graph DSL.

# File lib/graph.rb, line 371
def cluster name, &block
  subgraph "cluster_#{name}", &block
end
color(color) click to toggle source

Shortcut method to create a new color Attribute instance.

# File lib/graph.rb, line 209
def color color
  Attribute.new "color = #{color}"
end
colorscheme(name, n = nil) click to toggle source

Shortcut method to create and set the graph to use a colorscheme.

# File lib/graph.rb, line 224
def colorscheme name, n = nil
  self.scheme = Attribute.new "colorscheme = #{name}#{n}"
  max = COLOR_SCHEME_MAX[name.to_sym]

  node_attribs << scheme if max

  scheme
end
delete_node(node_name) click to toggle source

Deletes a node from the graph

# File lib/graph.rb, line 377
def delete_node node_name
  nodes.delete node_name
  nodes_order.delete node_name

  edges_order.each do |(a, b)|
    edges[a].delete b if b == node_name
    edges.delete a if a == node_name
    edges.delete a if edges[a].empty?
  end

  edges_order.delete_if { |ary| ary.include? node_name }
end
edge(*names) click to toggle source

Define one or more edges.

edge "a", "b", "c", ...

is equivalent to:

edge "a", "b"
edge "b", "c"
...
# File lib/graph.rb, line 250
def edge(*names)
  last = nil
  names.each_cons(2) do |from, to|
    last = self[from][to]
  end
  last
end
fillcolor(n) click to toggle source

Shortcut method to create a new fillcolor Attribute instance.

# File lib/graph.rb, line 274
def fillcolor n
  Attribute.new "fillcolor = #{n}"
end
font(name) click to toggle source

Shortcut method to create a new font Attribute instance. You can pass in both the name and an optional font size.

# File lib/graph.rb, line 282
def font name
  Attribute.new "fontname = #{name.inspect}"
end
fontsize(size) click to toggle source

Shortcut method to create a new fontsize Attribute instance.

# File lib/graph.rb, line 289
def fontsize size
  Attribute.new "fontsize = #{size}"
end
invert() click to toggle source

Creates a new Graph whose edges point the other direction.

# File lib/graph.rb, line 261
def invert
  result = self.class.new
  edges.each do |from, h|
    h.each do |to, edge|
      result[to][from]
    end
  end
  result
end
label(name) click to toggle source

Shortcut method to set the graph's label. Usually used with subgraphs.

# File lib/graph.rb, line 305
def label name
  graph_attribs << "label = #{Graph.escape_label name}"
end
node(name, label = nil) click to toggle source

Access a node by name, supplying an optional label

# File lib/graph.rb, line 312
def node name, label = nil
  n = nodes[name]
  n.label label if label
  n
end
orient(dir = "TB") click to toggle source

Shortcut method to specify the orientation of the graph. Defaults to the graphviz default “TB”.

# File lib/graph.rb, line 322
def orient dir = "TB"
  graph_attribs << "rankdir = #{dir}"
end
rotate(dir = "LR") click to toggle source

Shortcut method to specify the orientation of the graph. Defaults to “LR”.

# File lib/graph.rb, line 329
def rotate dir = "LR"
  orient dir
end
save(path, type = nil) click to toggle source

Saves out both a dot file to path and an image for the specified type. Specify type as nil to skip exporting an image.

# File lib/graph.rb, line 337
def save path, type = nil
  File.open "#{path}.dot", "w" do |f|
    f.puts self.to_s
  end
  system "dot -T#{type} #{path}.dot > #{path}.#{type}" if type
end
shape(shape) click to toggle source

Shortcut method to create a new shape Attribute instance.

# File lib/graph.rb, line 347
def shape shape
  Attribute.new "shape = #{shape}"
end
style(name) click to toggle source

Shortcut method to create a new style Attribute instance.

# File lib/graph.rb, line 354
def style name
  Attribute.new "style = #{name}"
end
subgraph(name = nil, &block) click to toggle source

Shortcut method to create a subgraph in the current graph. Use with the top-level digraph method in block form for a graph DSL.

# File lib/graph.rb, line 362
def subgraph name = nil, &block
  Graph.new name, self, &block
end
to_s() click to toggle source

Outputs a graphviz graph.

# File lib/graph.rb, line 393
def to_s
  result = []

  type = graph ? "subgraph " : "digraph "
  type << "\"#{name}\"" if name and !name.empty?
  result << type
  result << "  {"

  graph_attribs.each do |line|
    result << "    #{line};"
  end

  unless node_attribs.empty? then
    result << "    node [ #{node_attribs.join(", ")} ];"
  end

  unless edge_attribs.empty? then
    result << "    edge [ #{edge_attribs.join(", ")} ];"
  end

  subgraphs.each do |line|
    result << "    #{line};"
  end

  nodes_order.each do |name|
    node = nodes[name]
    result << "    #{node};" if graph or node.attributes? or node.orphan?
  end

  edges_order.uniq.each do |(from, to)|
    edge = edges[from][to]
    result << "    #{edge};"
  end

  result << "  }"
  result.join "\n"
end