Stoopid Simple Graphing Library

| | Comments (1)
At Eric's behest, I'm releasing the code that I used to generate the ABC colored graphs that I posted about earlier. It allows for quick and dirty (I prefer the term "clean") graphs through Graphviz's dot language.
graph = Graph.new
graph["from"] << "to"
puts graph.to_s

when processed becomes:

pretty.png

It has other bells and whistles, when a plain graph just won't do, but the emphasis is on simplicity and getting things done. Best of all, it is only 65 lines long. Code after the cut...

#!/usr/local/bin/ruby -w

class Graph < Hash

  attr_reader :attribs
  attr_reader :prefix
  attr_reader :order
  def initialize
    super { |h,k| h[k] = [] }
    @prefix = []
    @attribs = Hash.new { |h,k| h[k] = [] }
    @order = []
  end

  def []=(key, val)
    @order << key unless self.has_key? key
    super(key, val)
  end
  
  def each_pair
    @order.each do |from|
      self[from].each do |to|
        yield(from, to)
      end
    end
  end
  
  def invert
    result = self.class.new
    each_pair do |from, to|
      result[to] << from
    end
    result
  end

  def counts
    result = Hash.new(0)
    each_pair do |from, to|
      result[from] += 1
    end
    result
  end
  
  def keys_by_count
    counts.sort_by { |x,y| y }.map {|x| x.first }
  end

  def to_s
    result = []
    result << "digraph absent"
    result << "  {"
    @prefix.each do |line|
      result << line
    end
    @attribs.sort.each do |node, attribs|
      result << "    #{node.inspect} [ #{attribs.join(',')} ]"
    end
    each_pair do |from, to|
      result << "    #{from.inspect} -> #{to.inspect};"
    end
    result << "  }"
    result.join("\n")
  end
  
end

1 Comments

Very nice. Would you consider registering this on RubyForge and make it a gem? It would also be cool if you added integration with dot so you can do something like graph.write("some/file.png")

[absolutely--but do know there is a very bloated graphviz library on RAA already if you can't wait]

Leave a comment