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
64
# 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 = {}
  @cache = {}
  @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)



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

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



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

def << something
  if something.respond_to?( :install )
    something.install( self )
  else
    case something
    when Array
      assert WME.new( *something )
    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



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

def add_overlay(o)
  overlays << o
end

#alphasObject



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

def alphas
  alpha_hash.values
end

#assert(wme) ⇒ Object



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

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

#cache(s, p, o) ⇒ Object



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

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

#compile_alpha(condition) ⇒ Object



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

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

#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



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

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

#dumpObject



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

def dump
  beta_top.dump
end

#each(*args) ⇒ Object



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

def each *args
  return unless block_given?
  unless args.length == 0 || args.length == 3
    raise Error, "Network#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

Raises:



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

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)


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

def exists? wme
  @cache[ wme ]
end

#find(s, p, o) ⇒ Object



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

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}"
  source.wmes.detect { |wme| wme =~ template }
end

#in_snapshot?Boolean

Returns:

  • (Boolean)


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

def in_snapshot?
  @in_snapshot
end

#initial_fill(alpha) ⇒ Object

TODO: pick an alpha with fewer candidates to go through



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

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

#inspectObject



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

def inspect
  "<Rete>"
end

#install_query(query) ⇒ Object



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

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

#install_rule(rule) ⇒ Object



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

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



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

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



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

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



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

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

  if existing = @cache[wme]
    existing.manual! if wme.manual?
    return
  end

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

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

  wme
end

#real_retract(wme, options) ⇒ Object



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

def real_retract wme, options
  real = @cache[wme]

  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

  @cache.delete(real)

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

#remove_overlay(o) ⇒ Object



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

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

#remove_production(pnode) ⇒ Object



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

def remove_production pnode
  delete_node_with_ancestors pnode
end

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



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

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

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



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

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

def select s, p, o
  template = Template.new(s, p, o)
  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



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

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



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

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

#wmesObject Also known as: statements, facts



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

def wmes
  alpha_top.wmes
end