Class: OMF::Rete::JoinOP

Inherits:
Object
  • Object
show all
Defined in:
lib/omf_rete/join_op.rb

Overview

This class implements the join operation between two IndexedTupleSets feeding into a third, result tuple set. The size of both incoming tuple sets needs to be identical and they are supposed to be indexed on the same list of variables as this is what they wil be joined at.

Implementation Note: We first calculate a combinePattern from the description of the result set. The combinePattern describes how to create a joined tuple to insert into the result tuple set. The combinePattern is an array of the same size as the result tuple. Each element is a 2-array with the first element describing the input set (0 .. left, 1 .. right) and the second one the index from which to take the value.

Instance Method Summary collapse

Constructor Details

#initialize(leftSet, rightSet, resultSet) ⇒ JoinOP

Returns a new instance of JoinOP.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/omf_rete/join_op.rb', line 21

def initialize(leftSet, rightSet, resultSet)
  @resultSet = resultSet
  @left = leftSet
  @right = rightSet

  @combinePattern = resultSet.description.collect do |bname|
    side = 0
    unless (i = leftSet.index_for_binding(bname))
      side = 1
      unless (i = rightSet.index_for_binding(bname))
        raise "Can't find binding '#{bname}' in either streams. Should never happen"
      end
    end
    #description << bname
    [side, i]
  end
  @resultLength = @combinePattern.length
  @results = {} # Keep track of how may input tuples create the same result - necessary for 'removeTuple'

  leftSet.on_add_with_index do |index, ltuple|
    if (rs = rightSet[index])
      rs.each do |rtuple|
        add_result(ltuple, rtuple)
      end
    end
  end
  rightSet.on_add_with_index do |index, rtuple|
    if (ls = leftSet[index])
      ls.each do |ltuple|
        add_result(ltuple, rtuple)
      end
    end
  end

  leftSet.on_remove_with_index do |index, ltuple|
    if (index.nil?)
      clear_result()
    else
      if (rs = rightSet[index])
        rs.each do |rtuple|
          remove_result(ltuple, rtuple)
        end
      end
    end
  end
  rightSet.on_remove_with_index do |index, rtuple|
    if (index.nil?)
      clear_result()
    else
      if (ls = leftSet[index])
        ls.each do |ltuple|
          remove_result(ltuple, rtuple)
        end
      end
    end
  end

  # Supporting 'check_for_tuple'
  @left_pattern = @left.description.map do |bname|
    @resultSet.index_for_binding(bname)
  end
  @right_pattern = @right.description.map do |bname|
    @resultSet.index_for_binding(bname)
  end

end

Instance Method Details

#check_for_tuple(tuple) ⇒ Object

Check if tuple can be produced by this join op. We first check if we can find a match on one side and then request from the other side all the tuples which would lead to full join.



93
94
95
96
97
98
99
100
101
102
# File 'lib/omf_rete/join_op.rb', line 93

def check_for_tuple(tuple)
  ltuple = @left_pattern.map {|i| tuple[i]}
  if @left.check_for_tuple(ltuple)
    rtuple = @right_pattern.map {|i| tuple[i]}
    if @right.check_for_tuple(rtuple)
      return true
    end
  end
  return false
end

#describe(out = STDOUT, offset = 0, incr = 2, sep = "\n") ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/omf_rete/join_op.rb', line 117

def describe(out = STDOUT, offset = 0, incr = 2, sep = "\n")
  out.write(" " * offset)
  result = @combinePattern.collect do |side, index|
    (side == 0) ? @left.binding_at(index) : @right.binding_at(index)
  end
  out.write("join: [#{@left.indexPattern.sort.join(', ')}] => [#{result.sort.join(', ')}]#{sep}")
  @left.describe(out, offset + incr, incr, sep)
  @right.describe(out, offset + incr, incr, sep)
end

#descriptionObject



113
114
115
# File 'lib/omf_rete/join_op.rb', line 113

def description()
  @resultSet.description
end

#detachObject

Detach all streams from each other as they are no longer in use



106
107
108
109
110
# File 'lib/omf_rete/join_op.rb', line 106

def detach()
  @left.detach
  @right.detach
  @results.clear
end