Class: Wongi::Engine::Network

Inherits:
Object
  • Object
show all
Includes:
Wongi::Engine::NetworkParts::Collectable
Defined in:
lib/wongi-engine/network.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Wongi::Engine::NetworkParts::Collectable

#add_collector, #add_error_collector, #collected_tokens, #collection, #collectors, #error_collectors, #errors

Constructor Details

#initializeNetwork

Returns a new instance of Network.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/wongi-engine/network.rb', line 24

def initialize
  @timeline = []
  self.alpha_top = AlphaMemory.new( Template.new( :_, :_, :_ ), self )
  self.alpha_hash = { Template.hash_for( :_, :_, :_ ) => self.alpha_top }
  self.beta_top = BetaMemory.new(nil)
  self.beta_top.rete = self
  self.beta_top.seed
  self.queries = {}
  self.results = {}
  @cache = {}
  @revns = {}
  @contexts = {}

  @productions = { }

  @collectors = {}
  @collectors[:error] = []

end

Instance Attribute Details

#alpha_topObject

Returns the value of attribute alpha_top.



7
8
9
# File 'lib/wongi-engine/network.rb', line 7

def alpha_top
  @alpha_top
end

#beta_topObject

Returns the value of attribute beta_top.



7
8
9
# File 'lib/wongi-engine/network.rb', line 7

def beta_top
  @beta_top
end

#productionsObject (readonly)

Returns the value of attribute productions.



9
10
11
# File 'lib/wongi-engine/network.rb', line 9

def productions
  @productions
end

#queriesObject

Returns the value of attribute queries.



8
9
10
# File 'lib/wongi-engine/network.rb', line 8

def queries
  @queries
end

#resultsObject

Returns the value of attribute results.



8
9
10
# File 'lib/wongi-engine/network.rb', line 8

def results
  @results
end

Instance Method Details

#<<(something) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/wongi-engine/network.rb', line 136

def << something
  case something
  when Array
    if something.length == 3
      assert WME.new( *something )
    else
      raise "Arrays must have 3 elements"
    end
  when ProductionRule
    derived = something.import_into self
    production = add_production derived.conditions, derived.actions
    if something.name
      productions[ something.name ] = production
    end
  when Query
    derived = something.import_into self
    prepare_query derived.name, derived.conditions, derived.parameters, derived.actions
  when Ruleset
    something.install self
  when WME
    assert something
  #when Wongi::RDF::Document
    #  something.statements.each do |st|
    #    assert WME.new( st.subject, st.predicate, st.object, self )
    #  end
  when Rete
    something.each do |st|
      assert st.import_into( self )
    end
  else
    raise "I don't know how to accept a #{something.class}"
  end
end

#add_production(conditions, actions = []) ⇒ Object



241
242
243
# File 'lib/wongi-engine/network.rb', line 241

def add_production conditions, actions = []
  real_add_production self.beta_top, conditions, [], actions, false
end

#alphasObject



48
49
50
# File 'lib/wongi-engine/network.rb', line 48

def alphas
  alpha_hash.values
end

#assert(wme) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/wongi-engine/network.rb', line 63

def assert wme

  unless wme.rete == self
    wme = wme.import_into self
  end

  if @current_context
    @current_context.asserted_wmes << wme
    wme.context = @current_context
  end

  return if @cache.has_key?(wme)

  # puts "ASSERTING #{wme}"
  @cache[wme] = wme

  s = wme.subject
  p = wme.predicate
  o = wme.object

  alpha_activate(lookup( s,  p,  o), wme)
  alpha_activate(lookup( s,  p, :_), wme)
  alpha_activate(lookup( s, :_,  o), wme)
  alpha_activate(lookup(:_,  p,  o), wme)
  alpha_activate(lookup( s, :_, :_), wme)
  alpha_activate(lookup(:_,  p, :_), wme)
  alpha_activate(lookup(:_, :_,  o), wme)
  alpha_activate(lookup(:_, :_, :_), wme)

  wme
end

#cache(s, p, o) ⇒ Object



227
228
229
# File 'lib/wongi-engine/network.rb', line 227

def cache s, p, o
  compile_alpha Template.new(s, p, o).import_into( self )
end

#compile_alpha(condition) ⇒ Object



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/wongi-engine/network.rb', line 195

def compile_alpha condition
  template = Template.new :_, :_, :_
  time = condition.time

  template.subject = condition.subject unless Template.variable?( condition.subject )
  template.predicate = condition.predicate unless Template.variable?( condition.predicate )
  template.object = condition.object unless Template.variable?( condition.object )

  hash = template.hash
  # puts "COMPILED CONDITION #{condition} WITH KEY #{key}"
  if time == 0
    return self.alpha_hash[ hash ] if self.alpha_hash.has_key?( hash )
  else
    return @timeline[time+1][ hash ] if @timeline[time+1] && @timeline[time+1].has_key?( hash )
  end

  alpha = AlphaMemory.new( template, self )

  if time == 0
    self.alpha_hash[ hash ] = alpha
    initial_fill alpha
  else
    if @timeline[time+1].nil?
      # => ensure lineage from 0 to time
      compile_alpha condition.class.new(condition.subject, condition.predicate, condition.object, time + 1)
      @timeline.unshift Hash.new
    end
    @timeline[time+1][ hash ] = alpha
  end
  alpha
end

#context=(name) ⇒ Object



268
269
270
271
272
# File 'lib/wongi-engine/network.rb', line 268

def context= name
  if name && !@contexts.has_key?(name)
    @current_context = (@contexts[name] ||= ModelContext.new name)
  end
end

#debug!Object



20
21
22
# File 'lib/wongi-engine/network.rb', line 20

def debug!
  extend NetworkParts::Debug
end

#dumpObject



44
45
46
# File 'lib/wongi-engine/network.rb', line 44

def dump
  beta_top.dump
end

#each(*args) ⇒ Object



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/wongi-engine/network.rb', line 290

def each *args
  return unless block_given?
  unless args.length == 0 || args.length == 3
    raise "Document#each expects a pattern or nothing at all"
  end
  s, p, o = if args.empty?
    [:_, :_, :_]
  else
    args
  end
  no_check = s == :_ && p == :_ && o == :_
  template = Template.new(s, p, o).import_into self
  alpha_top.wmes.each do |wme|
    yield wme if (no_check || wme =~ template)
  end
end

#execute(name, valuations) ⇒ Object



258
259
260
261
262
# File 'lib/wongi-engine/network.rb', line 258

def execute name, valuations
  beta = self.queries[name]
  raise "Undefined query #{name}; known queries are #{queries.keys}" unless beta
  beta.subst valuations
end

#exists?(wme) ⇒ Boolean

Returns:

  • (Boolean)


286
287
288
# File 'lib/wongi-engine/network.rb', line 286

def exists? wme
  @cache[ wme ]
end

#find(s, p, o) ⇒ Object



316
317
318
319
320
321
# File 'lib/wongi-engine/network.rb', line 316

def find s, p, o
  template = Template.new(s, p, o).import_into self
  source = best_alpha(template)
  # puts "looking for #{template} among #{source.wmes.size} triples of #{source.template}"
  source.wmes.detect { |wme| wme =~ template }
end

#import(thing) ⇒ Object



52
53
54
55
56
57
58
59
60
61
# File 'lib/wongi-engine/network.rb', line 52

def import thing
  case thing
  when String, Numeric, TrueClass, FalseClass, NilClass
    thing
  when Symbol
    thing
  else
    raise "I don't know how to import a #{thing.class}"
  end
end

#in_snapshot?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/wongi-engine/network.rb', line 101

def in_snapshot?
  @in_snapshot
end

#initial_fill(alpha) ⇒ Object



231
232
233
234
235
236
237
238
239
# File 'lib/wongi-engine/network.rb', line 231

def initial_fill alpha
  tpl = alpha.template
  source = more_generic_alpha(tpl)
  # puts "more efficient by #{alpha_top.wmes.size - source.wmes.size}" unless source ==
  # alpha_top
  source.wmes.each do |wme|
    alpha.activate wme if wme =~ tpl
  end
end

#inspectObject



264
265
266
# File 'lib/wongi-engine/network.rb', line 264

def inspect
  "<Rete>"
end

#prepare_query(name, conditions, parameters, actions = []) ⇒ Object



249
250
251
252
253
254
255
256
# File 'lib/wongi-engine/network.rb', line 249

def prepare_query name, conditions, parameters, actions = []
  query = self.queries[ name ] = BetaMemory.new( nil )
  query.rete = self
  transformed = {}
  parameters.each { |param| transformed[param] = nil }
  query.seed transformed
  self.results[ name ] = real_add_production query, conditions, parameters, actions, true
end

#query(name, &block) ⇒ Object



130
131
132
133
134
# File 'lib/wongi-engine/network.rb', line 130

def query name, &block
  q = Query.new name
  q.instance_eval &block
  self << q
end

#remove_production(pnode) ⇒ Object



245
246
247
# File 'lib/wongi-engine/network.rb', line 245

def remove_production pnode
  delete_node_with_ancestors pnode
end

#retract(wme, is_real = false) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/wongi-engine/network.rb', line 170

def retract wme, is_real = false

  if ! is_real
    if @current_context
      @current_context.retracted_wmes << wme
    end
  end

  real = if is_real
    wme
  else
    #find(wme.subject, wme.predicate, wme.object)
    @cache[wme]
  end

  return false if real.nil?
  @cache.delete(real)
  raise "Cannot retract inferred statements" unless real.manual?

  real.destroy

  true

end

#retract_context(name) ⇒ Object



274
275
276
277
278
279
280
281
282
283
284
# File 'lib/wongi-engine/network.rb', line 274

def retract_context name
  return unless @contexts.has_key?(name)

  if @current_context && @current_context.name == name
    @current_context = nil
  end
  ctx = @contexts[name]
  ctx.asserted_wmes.select { |wme| wme.generating_tokens.empty?  }.each { |wme| retract(wme, true) }
  ctx.retracted_wmes.each { |wme| assert(wme) }
  @contexts.delete name
end

#rule(name = nil, &block) ⇒ Object



124
125
126
127
128
# File 'lib/wongi-engine/network.rb', line 124

def rule name = nil, &block
  r = ProductionRule.new( name || generate_rule_name )
  r.instance_eval &block
  self << r
end

#select(s, p, o) ⇒ Object



307
308
309
310
311
312
313
314
# File 'lib/wongi-engine/network.rb', line 307

def select s, p, o
  template = Template.new(s, p, o).import_into self
  matching = alpha_top.wmes.select { |wme| wme =~ template }
  if block_given?
    matching.each { |st| yield st.subject, st.predicate, st.object }
  end
  matching
end

#snapshot!Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/wongi-engine/network.rb', line 105

def snapshot!
  @timeline.each_with_index do |slice, index|
    source = if index == @timeline.size - 1
      alpha_hash
    else
      @timeline[index+1]
    end
    # puts "source = #{source}"
    wmes = {}
    slice.each { |key, alpha| wmes[key] = alpha.wmes }
    slice.each do |key, alpha|
      in_snapshot {
        wmes[key].dup.each { |wme| wme.destroy }
      }
      alpha.snapshot! source[key]
    end
  end
end

#wmesObject Also known as: statements, facts



95
96
97
# File 'lib/wongi-engine/network.rb', line 95

def wmes
  alpha_top.wmes
end