class Class::FlattenedHierarchy

Attributes

ranges[R]

Public Class Methods

child_relations_among(*classes) click to toggle source
# File lib/redparse/decisiontree.rb, line 30
def self.child_relations_among(*classes)
  classes.unshift Object
  result={}
  classes.each{|klass| result[klass]=[] }

  classes.each{|klass| klass.ancestors.each{|anc|
    if anc=result[anc]
      anc << klass
      break
    end
  }}

  return result
end
new(*classes) click to toggle source
# File lib/redparse/decisiontree.rb, line 59
def initialize(*classes)
  @sorted=FlattenedHierarchy.sort_by_inheiritance(*classes)
  @ranges=create_member_ranges
end
sort_by_inheiritance(*classes) click to toggle source
# File lib/redparse/decisiontree.rb, line 46
def self.sort_by_inheiritance(*classes)
  children_of=child_relations_among(*classes)
  result=[]
  class_eater=proc{|klass|
    result << klass
    children_of[klass].each(&class_eater)
  }
  class_eater[::Object]
  #classes.each(&class_eater)

  return result
end

Public Instance Methods

nonoverlapping_class_range_list(classes) click to toggle source
# File lib/redparse/decisiontree.rb, line 75
def nonoverlapping_class_range_list(classes)
  classes,ranges=overlapping_class_range_list(classes)

  myclasses=[];myranges=[]
  classes_index_stack=[]
  classes.each_with_index{|k,i| 
    x=ranges[i].first
    if i>0 and ranges[i-1]===x #if overlaps previous range
      classes_index_stack.push i-1 #add to the stack of saved-up ranges
    else
      #pop off old superclasses that no longer apply
      #to this k, adding trailing fragments for the
      #ranges of those superclasses as we go along
      until classes_index_stack.empty?
        current_range=ranges[classes_index_stack.last]
        break if current_range===x  #stop if this superclass still applies

        ending=classes_index_stack.pop

        #trailing fragment
        done_thru=myranges.last.last
        current_end=current_range.last
        unless done_thru==current_end
          myranges << (done_thru+1..current_end)
          myclasses << classes[ending]
        end
      end
    end

    #if a gap between (sub-?)classes, emit a fragment for the appropriate super (or default to nil)
    next_expected=myranges.last.last+1
    if next_expected!=x  #was:   (ranges[i].huh)
      myclasses<< (classes[classes_index_stack.last] unless classes_index_stack.empty?)
      myranges<<(next_expected..x-1)
    end

    #emit initial fragment for current class
    myclasses << k
    myranges << (x..[ranges[i+1].first-1,ranges[i].last].min)
  }
 
  return myclasses, myranges    
end
nonoverlapping_results_range_list(class2results) click to toggle source
# File lib/redparse/decisiontree.rb, line 119
def nonoverlapping_results_range_list(class2results)
  classes=class2results.keys
  classes,ranges=nonoverlapping_class_range_list(classes)
  return classes.map{|k| class2results[k] }, ranges
end
overlapping_class_range_list(classes) click to toggle source
# File lib/redparse/decisiontree.rb, line 70
def overlapping_class_range_list(classes)
  classes=@sorted&classes
  return classes,classes.map{|k| @ranges[k] }   
end
range(klass) click to toggle source
# File lib/redparse/decisiontree.rb, line 64
def range klass
  @ranges[klass]
end

Private Instance Methods

create_member_ranges() click to toggle source
# File lib/redparse/decisiontree.rb, line 142
def create_member_ranges
  result={}
  @sorted.each_with_index{|klass,i| 
    result[klass]=i..last_member_num(klass,i)
  }
  return result
end
last_member_num(klass,i) click to toggle source
# File lib/redparse/decisiontree.rb, line 126
def last_member_num(klass,i)
  @sorted[i]==klass or fail
  low=i
  high=@sorted.size
  until low==high
    mid=(low+high)/2
    if classes[mid]<=klass
      low=mid
    else
      high=mid
    end
  end
 
  return high
end