#--
# Copyright (c) 2006 Shawn Patrick Garbett
# 
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
# 
#     * Redistributions of source code must retain the above copyright notice(s),
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright notice,
#       this list of conditions and the following disclaimer in the documentation
#       and/or other materials provided with the distribution.
#     * Neither the name of the Shawn Garbett nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#++

module GRATR
  module Graph
    module Comparability
      
      # A comparability graph is an UndirectedGraph that has a transitive
      # orientation. This returns a boolean that says if this graph
      # is a comparability graph.
      def comparability?() gamma_decomposition[1]; end
      
      # Returns an array with two values, the first being a hash of edges 
      # with a number containing their class assignment, the second valud
      # is a boolean which states whether or not the graph is a 
      # comparability graph
      #
      # Complexity in time O(d*|E|) where d is the maximum degree of a vertex
      # Complexity in space O(|V|+|E|)
      def gamma_decomposition
        k = 0; comparability=true; classification={}
        edges.map {|edge| [edge.source,edge.target]}.each do |e|
          if classification[e].nil?
            k += 1
            classification[e] = k; classification[e.reverse] = -k
            comparability &&= gratr_comparability_explore(e, k, classification)
          end
        end; [classification, comparability]
      end
      
      # Returns one of the possible transitive orientations of 
      # the UndirectedGraph as a Digraph
      def transitive_orientation(digraph_class=Digraph)
        raise NotImplementError
      end
      
     private
     
      # Taken from Figure 5.10, on pg. 130 of Martin Golumbic's, _Algorithmic_Graph_
      # _Theory_and_Perfect_Graphs.
      def gratr_comparability_explore(edge, k, classification, space='')
        ret = gratr_comparability_explore_inner(edge, k, classification, :forward, space)
        gratr_comparability_explore_inner(edge.reverse, k, classification, :backward, space) && ret
      end
      
      def gratr_comparability_explore_inner(edge, k, classification, direction,space)
        comparability = true  
        adj_target = adjacent(edge[1])
        adjacent(edge[0]).select do |mt|
          (classification[[edge[1],mt]] || k).abs < k or
          not adj_target.any? {|adj_t| adj_t == mt} 
        end.each do |m|
          e = (direction == :forward) ? [edge[0], m] : [m,edge[0]]
          if classification[e].nil?
            classification[e] = k
            classification[e.reverse] = -k
            comparability = gratr_comparability_explore(e, k, classification, '  '+space) && comparability
          elsif classification[e] == -k
            classification[e] = k
            gratr_comparability_explore(e, k, classification, '  '+space)
            comparability = false
          end
        end; comparability
      end # gratr_comparability_explore_inner
      
    end # Comparability
  end # Graph
end # GRATR

syntax highlighted by Code2HTML, v. 0.9.1