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.



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

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

  @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

#overlaysObject (readonly)



108
109
110
# File 'lib/wongi-engine/network.rb', line 108

def overlays
  @overlays
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



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/wongi-engine/network.rb', line 197

def << something
  if something.respond_to?( :install )
    something.install( self )
  else
    case something
    when Array
      assert WME.new( *something ).tap { |wme| wme.overlay = default_overlay }
    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.wmes.each { |wme| assert( wme ) }
    else
      raise Error, "I don't know how to accept a #{something.class}"
    end
  end
end

#add_overlay(o) ⇒ Object



93
94
95
# File 'lib/wongi-engine/network.rb', line 93

def add_overlay(o)
  overlays << o
end

#alphasObject



73
74
75
# File 'lib/wongi-engine/network.rb', line 73

def alphas
  alpha_hash.values
end

#assert(wme) ⇒ Object



112
113
114
# File 'lib/wongi-engine/network.rb', line 112

def assert(wme)
  default_overlay.assert(wme)
end

#cache(s, p, o) ⇒ Object



266
267
268
# File 'lib/wongi-engine/network.rb', line 266

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

#compile_alpha(condition) ⇒ Object



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/wongi-engine/network.rb', line 234

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

#current_overlayObject



103
104
105
# File 'lib/wongi-engine/network.rb', line 103

def current_overlay
  overlays.last
end

#debug!Object



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

def debug!
  extend NetworkParts::Debug
end

#default_overlayObject

def import thing

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

end



88
89
90
# File 'lib/wongi-engine/network.rb', line 88

def default_overlay
  @default_overlay ||= DataOverlay.new(self)
end

#dumpObject



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

def dump
  beta_top.dump
end

#each(*args, &block) ⇒ Object



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

def each *args, &block
  template = case args.length
  when 0
    Template.new(:_, :_, :_)
  when 3
    Template.new(*args)
  else
    raise Error, "Network#each expect a template or nothing at all"
  end
  source = best_alpha(template)
  matching = current_overlay.wmes(source).select { |wme| wme =~ template }
  if block_given?
    matching.each(&block)
  else
    matching.each
  end
end

#execute(name, valuations) ⇒ Object

Raises:



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

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

#exists?(wme) ⇒ Boolean

Returns:

  • (Boolean)


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

def exists? wme
  find(wme.subject, wme.predicate, wme.object)
end

#find(s, p, o) ⇒ Object



330
331
332
333
334
335
# File 'lib/wongi-engine/network.rb', line 330

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

#in_snapshot?Boolean

Returns:

  • (Boolean)


162
163
164
# File 'lib/wongi-engine/network.rb', line 162

def in_snapshot?
  @in_snapshot
end

#initial_fill(alpha) ⇒ Object

TODO: pick an alpha with fewer candidates to go through



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

def initial_fill alpha
  alpha_top.wmes.each do |wme|
    alpha.activate wme if wme =~ alpha.template
  end
end

#inspectObject



294
295
296
# File 'lib/wongi-engine/network.rb', line 294

def inspect
  "<Rete>"
end

#install_query(query) ⇒ Object



229
230
231
232
# File 'lib/wongi-engine/network.rb', line 229

def install_query( query )
  derived = query.import_into self
  prepare_query derived.name, derived.conditions, derived.parameters, derived.actions
end

#install_rule(rule) ⇒ Object



220
221
222
223
224
225
226
227
# File 'lib/wongi-engine/network.rb', line 220

def install_rule( rule )
  derived = rule.import_into self
  production = build_production beta_top, derived.conditions, [], derived.actions, false
  if rule.name
    productions[ rule.name ] = production
  end
  production
end

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



281
282
283
284
285
286
# File 'lib/wongi-engine/network.rb', line 281

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

#query(name, &block) ⇒ Object



191
192
193
194
195
# File 'lib/wongi-engine/network.rb', line 191

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

#rdf!Object



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

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

#real_assert(wme) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/wongi-engine/network.rb', line 121

def real_assert( wme )
  unless wme.rete == self
    wme = wme.import_into self
  end

  source = best_alpha(wme)
  if existing = find(wme.subject, wme.predicate, wme.object)
    existing.manual! if wme.manual?
    return
  end

  alphas_for( wme ).each { |a| a.activate wme }

  wme
end

#real_retract(wme, options) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/wongi-engine/network.rb', line 138

def real_retract wme, options
  real = find(wme.subject, wme.predicate, wme.object)
  return if real.nil?
  if real.generated? # still some generator tokens left
    if real.manual?
      real.manual = false
    else
      raise Error, "cannot retract automatic facts"
    end
  else
    if options[:automatic] && real.manual? # auto-retracting a fact that has been added manually
      return
    end
  end

  alphas_for( real ).each { |a| a.deactivate real }
end

#remove_overlay(o) ⇒ Object



98
99
100
# File 'lib/wongi-engine/network.rb', line 98

def remove_overlay(o)
  overlays.delete(o) unless o == default_overlay
end

#remove_production(pnode) ⇒ Object



277
278
279
# File 'lib/wongi-engine/network.rb', line 277

def remove_production pnode
  delete_node_with_ancestors pnode
end

#retract(wme, options = {}) ⇒ Object



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

def retract(wme, options = {})
  default_overlay.retract(wme, options)
end

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



185
186
187
188
189
# File 'lib/wongi-engine/network.rb', line 185

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

#select(s, p, o) ⇒ Object



320
321
322
323
324
325
326
327
328
# File 'lib/wongi-engine/network.rb', line 320

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

#snapshot!Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/wongi-engine/network.rb', line 166

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

#with_overlay(&block) ⇒ Object



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

def with_overlay(&block)
  default_overlay.with_child(&block)
end

#wmesObject Also known as: statements, facts



156
157
158
# File 'lib/wongi-engine/network.rb', line 156

def wmes
  alpha_top.wmes
end