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.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/wongi-engine/network.rb', line 46

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



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/wongi-engine/network.rb', line 158

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::Statement
    assert WME.new( something.subject, something.predicate, something.object, self )
  #when Wongi::RDF::Document
    #  something.statements.each do |st|
    #    assert WME.new( st.subject, st.predicate, st.object, self )
    #  end
  when Network
    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



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

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

#alphasObject



70
71
72
# File 'lib/wongi-engine/network.rb', line 70

def alphas
  alpha_hash.values
end

#assert(wme) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/wongi-engine/network.rb', line 85

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



255
256
257
# File 'lib/wongi-engine/network.rb', line 255

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

#compile_alpha(condition) ⇒ Object



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/wongi-engine/network.rb', line 223

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: time + 1)
      @timeline.unshift Hash.new
    end
    @timeline[time+1][ hash ] = alpha
  end
  alpha
end

#context=(name) ⇒ Object



296
297
298
299
300
# File 'lib/wongi-engine/network.rb', line 296

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



66
67
68
# File 'lib/wongi-engine/network.rb', line 66

def dump
  beta_top.dump
end

#each(*args) ⇒ Object



318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/wongi-engine/network.rb', line 318

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



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

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)


314
315
316
# File 'lib/wongi-engine/network.rb', line 314

def exists? wme
  @cache[ wme ]
end

#find(s, p, o) ⇒ Object



344
345
346
347
348
349
# File 'lib/wongi-engine/network.rb', line 344

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



74
75
76
77
78
79
80
81
82
83
# File 'lib/wongi-engine/network.rb', line 74

def import thing
  case thing
  when String, Numeric, TrueClass, FalseClass, NilClass, Wongi::RDF::Node
    thing
  when Symbol
    thing
  else
    thing
  end
end

#in_snapshot?Boolean

Returns:

  • (Boolean)


123
124
125
# File 'lib/wongi-engine/network.rb', line 123

def in_snapshot?
  @in_snapshot
end

#initial_fill(alpha) ⇒ Object



259
260
261
262
263
264
265
266
267
# File 'lib/wongi-engine/network.rb', line 259

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



292
293
294
# File 'lib/wongi-engine/network.rb', line 292

def inspect
  "<Rete>"
end

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



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

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



152
153
154
155
156
# File 'lib/wongi-engine/network.rb', line 152

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

#rdf!Object



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

def rdf!
  if ! defined? Wongi::RDF::DocumentSupport
    begin
      require 'wongi-rdf'
    rescue LoadError => e
      raise "'wongi-rdf' is required for RDF support"
    end
  end

  extend Wongi::RDF::DocumentSupport
  class << self
    def statements
      alpha_top.wmes
    end
  end

  @namespaces = { }
  @blank_counter = 1
  @ns_counter = 0
  @used_blanks = { }
end

#remove_production(pnode) ⇒ Object



273
274
275
# File 'lib/wongi-engine/network.rb', line 273

def remove_production pnode
  delete_node_with_ancestors pnode
end

#retract(wme, is_real = false) ⇒ Object



194
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
# File 'lib/wongi-engine/network.rb', line 194

def retract wme, is_real = false

  if wme.is_a? Array
    return retract( WME.new(*wme), is_real )
  end

  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



302
303
304
305
306
307
308
309
310
311
312
# File 'lib/wongi-engine/network.rb', line 302

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



146
147
148
149
150
# File 'lib/wongi-engine/network.rb', line 146

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

#select(s, p, o) ⇒ Object



335
336
337
338
339
340
341
342
# File 'lib/wongi-engine/network.rb', line 335

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



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/wongi-engine/network.rb', line 127

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



117
118
119
# File 'lib/wongi-engine/network.rb', line 117

def wmes
  alpha_top.wmes
end