wongi-engine 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 461346062a679921c61fc0b35bc2e89ef0d06920745d650b48fedbbc452b780a
4
- data.tar.gz: df2bf13a3551dc049e08398b11ac42440a34e4cb651f5092b74d3efdd5a3aecf
3
+ metadata.gz: 435d4ced6ab1fc3b576d5bb226d7a676ab67121377454da93d5f627077e21fcd
4
+ data.tar.gz: 788b07e8814de7e398d65a5c90ce8c0acbc9c12c5b20a3497f980b4544e1d2b4
5
5
  SHA512:
6
- metadata.gz: 0a3495df610621e35c8cef1a0cbf39aa0b26a8cee6d699df2bf4cdb451f4c06db534d7943bb4f30778d21289406d54ba0264f54ecfe3b839e3b1d50ccd6b63b3
7
- data.tar.gz: 8f85d69a8f476eec9a6ee8cf97ade3a4b8e9959616114511ca65007cd225feb0963613750628a450d5ea5f905fcaed65082662db828491a7caa9c533dc70db37
6
+ metadata.gz: fae43ecc031d91650b11a9a6195149280a3bb37197edd553e168417af0d9a7973c0234a165fc2e825ce250e4a26e679e29e28ce142889e24e19c0427ffa27190
7
+ data.tar.gz: 2344d2a636e05b2210861846b0e842cef7160aaca647bf09431b89deeb27af96994ebed72f9768ed4632b68c826196085f0ff1b3c1e93a33767ff25b3beed3ce
data/examples/ex01.rb CHANGED
@@ -1,23 +1,21 @@
1
- include Wongi::Engine
1
+ engine = Wongi::Engine.create
2
2
 
3
- ds = Network.new
4
-
5
- ds << WME.new("Alice", "friend", "Bob")
3
+ engine << ["Alice", "friend", "Bob"]
6
4
 
7
5
  puts "Enumerate all:"
8
6
 
9
- ds.each do |wme|
7
+ engine.each do |wme|
10
8
  puts wme
11
9
  end
12
10
 
13
11
  puts "Enumerate by pattern:"
14
12
 
15
- ds.each :_, "friend", :_ do |wme|
13
+ engine.each :_, "friend", :_ do |wme|
16
14
  puts wme
17
15
  end
18
16
 
19
17
  puts "Mismatching pattern:"
20
18
 
21
- ds.each :_, "foe", :_ do |wme|
19
+ engine.each :_, "foe", :_ do |wme|
22
20
  puts wme
23
21
  end
@@ -1,5 +1,7 @@
1
1
  module Wongi::Engine
2
2
  class AssignmentNode < BetaNode
3
+ attr_reader :variable, :body
4
+
3
5
  def initialize(parent, variable, body)
4
6
  super(parent)
5
7
  @variable = variable
@@ -11,8 +13,8 @@ module Wongi::Engine
11
13
 
12
14
  overlay.add_token(token)
13
15
  children.each do |child|
14
- value = @body.respond_to?(:call) ? @body.call(token) : @body
15
- child.beta_activate Token.new(child, token, nil, { @variable => value })
16
+ value = body.respond_to?(:call) ? body.call(token) : body
17
+ child.beta_activate Token.new(child, token, nil, { variable => value })
16
18
  end
17
19
  end
18
20
 
@@ -30,7 +32,7 @@ module Wongi::Engine
30
32
 
31
33
  def refresh_child(child)
32
34
  tokens.each do |token|
33
- child.beta_activate Token.new(child, token, nil, { @variable => @body.respond_to?(:call) ? @body.call(token) : @body })
35
+ child.beta_activate Token.new(child, token, nil, { variable => body.respond_to?(:call) ? body.call(token) : body })
34
36
  end
35
37
  end
36
38
  end
@@ -1,11 +1,12 @@
1
1
  module Wongi
2
2
  module Engine
3
3
  class ProductionNode < BetaNode
4
- attr_accessor :tracer, :compilation_context
4
+ attr_accessor :tracer, :compilation_context, :name
5
5
 
6
- def initialize(parent, actions)
6
+ def initialize(name, parent, actions)
7
7
  super(parent)
8
8
  @actions = actions.each { |action| action.production = self }
9
+ @name = name
9
10
  end
10
11
 
11
12
  def beta_activate(token)
@@ -100,7 +100,8 @@ module Wongi::Engine
100
100
  end
101
101
 
102
102
  def filter_node(filter)
103
- self.node = FilterNode.new(node, filter).tap(&:refresh)
103
+ existing = node.children.find { |n| n.is_a?(FilterNode) && n.test == filter }
104
+ self.node = existing || FilterNode.new(node, filter).tap(&:refresh)
104
105
  end
105
106
  end
106
107
  end
@@ -29,5 +29,9 @@ module Wongi::Engine
29
29
  def ==(other)
30
30
  self.class == other.class && x == other.x && y == other.y
31
31
  end
32
+
33
+ def to_s
34
+ "#{x} == #{y}"
35
+ end
32
36
  end
33
37
  end
@@ -31,5 +31,9 @@ module Wongi::Engine
31
31
  def ==(other)
32
32
  self.class == other.class && x == other.x && y == other.y
33
33
  end
34
+
35
+ def to_s
36
+ "#{x} >= #{y}"
37
+ end
34
38
  end
35
39
  end
@@ -29,5 +29,9 @@ module Wongi::Engine
29
29
  def ==(other)
30
30
  self.class == other.class && x == other.x && y == other.y
31
31
  end
32
+
33
+ def to_s
34
+ "#{x} > #{y}"
35
+ end
32
36
  end
33
37
  end
@@ -29,5 +29,9 @@ module Wongi::Engine
29
29
  def ==(other)
30
30
  self.class == other.class && x == other.x && y == other.y
31
31
  end
32
+
33
+ def to_s
34
+ "#{x} in #{y}"
35
+ end
32
36
  end
33
37
  end
@@ -29,5 +29,9 @@ module Wongi::Engine
29
29
  def ==(other)
30
30
  self.class == other.class && x == other.x && y == other.y
31
31
  end
32
+
33
+ def to_s
34
+ "#{x} != #{y}"
35
+ end
32
36
  end
33
37
  end
@@ -31,5 +31,9 @@ module Wongi::Engine
31
31
  def ==(other)
32
32
  self.class == other.class && x == other.x && y == other.y
33
33
  end
34
+
35
+ def to_s
36
+ "#{x} <= #{y}"
37
+ end
34
38
  end
35
39
  end
@@ -29,5 +29,9 @@ module Wongi::Engine
29
29
  def ==(other)
30
30
  self.class == other.class && x == other.x && y == other.y
31
31
  end
32
+
33
+ def to_s
34
+ "#{x} < #{y}"
35
+ end
32
36
  end
33
37
  end
@@ -29,5 +29,9 @@ module Wongi::Engine
29
29
  def ==(other)
30
30
  self.class == other.class && x == other.x && y == other.y
31
31
  end
32
+
33
+ def to_s
34
+ "#{x} not in #{y}"
35
+ end
32
36
  end
33
37
  end
@@ -29,22 +29,22 @@ module Wongi::Engine
29
29
  end
30
30
 
31
31
  def dump_alphas(io)
32
- io.puts "subgraph cluster_alphas {"
33
32
  @rete.alphas.reject { |alpha| alpha.betas.empty? }.each do |alpha|
34
- io.puts "node#{print_hash alpha.object_id} [shape=box label=\"#{alpha.template.to_s.gsub(/"/, '"')}\"];"
33
+ io.puts "node#{print_hash alpha.object_id} [shape=box style=filled fillcolor=olivedrab1 label=#{alpha_label(alpha).dump}];"
35
34
  end
36
- io.puts "};"
37
35
  end
38
36
 
39
37
  def dump_betas(io, opts)
40
- dump_beta(io, @rete.beta_top, opts)
38
+ @rete.beta_top.children.each do |child|
39
+ dump_beta(io, child, opts)
40
+ end
41
41
  end
42
42
 
43
43
  def dump_beta(io, beta, opts)
44
44
  return if @seen_betas.include? beta
45
45
 
46
46
  @seen_betas << beta
47
- io.puts "node#{print_hash beta.object_id} [label=\"#{beta.class.name.split('::').last}\\nid=#{beta.object_id}\"];"
47
+ io.puts "node#{print_hash beta.object_id} [style=filled fillcolor=#{beta_fillcolor(beta)} label=#{beta_label(beta).dump}];"
48
48
  if beta.is_a? NccNode
49
49
  io.puts "node#{print_hash beta.partner.object_id} -> node#{print_hash beta.object_id};"
50
50
  io.puts "{ rank=same; node#{print_hash beta.partner.object_id} node#{print_hash beta.object_id} }"
@@ -58,5 +58,47 @@ module Wongi::Engine
58
58
  dump_beta(io, child, opts)
59
59
  end
60
60
  end
61
+
62
+ def alpha_label(node)
63
+ node.template.to_s
64
+ end
65
+
66
+ def beta_label(node)
67
+ label = node.class.name.split('::').last
68
+ label += "\n" +
69
+ case node
70
+ when JoinNode, NegNode, OptionalNode
71
+ node.alpha.template.to_s
72
+ when FilterNode
73
+ node.test.to_s
74
+ when AssignmentNode
75
+ "#{node.variable} := #{node.body.respond_to?(:call) ? '<dynamic>' : node.body}"
76
+ when ProductionNode
77
+ node.name
78
+ else
79
+ ""
80
+ end
81
+
82
+ label
83
+ end
84
+
85
+ def beta_fillcolor(node)
86
+ case node
87
+ when JoinNode
88
+ "lightgreen"
89
+ when NegNode
90
+ "lightpink"
91
+ when OptionalNode
92
+ "palegreen"
93
+ when FilterNode
94
+ "lightblue"
95
+ when AssignmentNode
96
+ "lightyellow"
97
+ when ProductionNode
98
+ "lightcoral"
99
+ else
100
+ "white"
101
+ end
102
+ end
61
103
  end
62
104
  end
@@ -178,7 +178,7 @@ module Wongi::Engine
178
178
 
179
179
  def install_rule(rule)
180
180
  derived = rule.import_into self
181
- production = build_production beta_top, derived.conditions, [], derived.actions, false
181
+ production = build_production(rule.name, beta_top, derived.conditions, [], derived.actions, false)
182
182
  productions[rule.name] = production if rule.name
183
183
  production
184
184
  end
@@ -224,7 +224,7 @@ module Wongi::Engine
224
224
  query = queries[name] = RootNode.new(nil)
225
225
  query.rete = self
226
226
  query.seed(parameters.to_h { |param| [param, nil] })
227
- results[name] = build_production query, conditions, parameters, actions, true
227
+ results[name] = build_production(name, query, conditions, parameters, actions, true)
228
228
  end
229
229
 
230
230
  def execute(name, valuations)
@@ -296,9 +296,9 @@ module Wongi::Engine
296
296
  end
297
297
  end
298
298
 
299
- def build_production(root, conditions, parameters, actions, alpha_deaf)
299
+ def build_production(name, root, conditions, parameters, actions, alpha_deaf)
300
300
  compiler = Compiler.new(self, root, conditions, parameters, alpha_deaf)
301
- ProductionNode.new(compiler.compile, actions).tap do |production|
301
+ ProductionNode.new(name, compiler.compile, actions).tap do |production|
302
302
  production.compilation_context = compiler
303
303
  production.refresh
304
304
  end
@@ -155,7 +155,7 @@ module Wongi::Engine
155
155
  raise ArgumentError
156
156
  end
157
157
 
158
- each_by_template(template, &block)
158
+ each_by_template(template).each(&block)
159
159
  end
160
160
 
161
161
  def entity(subject)
@@ -1,5 +1,5 @@
1
1
  module Wongi
2
2
  module Engine
3
- VERSION = "0.4.2".freeze
3
+ VERSION = "0.4.4".freeze
4
4
  end
5
5
  end
data/spec/overlay_spec.rb CHANGED
@@ -68,6 +68,29 @@ describe Wongi::Engine::Overlay do
68
68
  expect(overlay.each(1, 11, 111)).to have(1).items
69
69
  expect(overlay.each(1, 11, 111).first).to eq(wmes.first)
70
70
  end
71
+
72
+ it 'iterates with a block' do
73
+ wmes = [
74
+ Wongi::Engine::WME.new(1, 11, 111),
75
+ Wongi::Engine::WME.new(1, 11, 112),
76
+ Wongi::Engine::WME.new(1, 11, 113),
77
+ Wongi::Engine::WME.new(1, 12, 121),
78
+ Wongi::Engine::WME.new(1, 12, 122),
79
+ Wongi::Engine::WME.new(2, 11, 111),
80
+ Wongi::Engine::WME.new(2, 11, 222),
81
+ Wongi::Engine::WME.new(2, 22, 222),
82
+ Wongi::Engine::WME.new(2, 22, 223),
83
+ Wongi::Engine::WME.new(3, 33, 113),
84
+ Wongi::Engine::WME.new(3, 33, 333),
85
+ Wongi::Engine::WME.new(3, 34, 333),
86
+ ]
87
+ wmes.each { overlay.assert(_1) }
88
+
89
+ returned = []
90
+ overlay.each { |wme| returned << wme }
91
+
92
+ expect(returned).to eq wmes
93
+ end
71
94
  end
72
95
 
73
96
  context "retracting facts" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wongi-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valeri Sokolov
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-15 00:00:00.000000000 Z
11
+ date: 2023-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -189,7 +189,7 @@ licenses:
189
189
  metadata:
190
190
  documentation_uri: https://ulfurinn.github.io/wongi-engine/
191
191
  rubygems_mfa_required: 'true'
192
- post_install_message:
192
+ post_install_message:
193
193
  rdoc_options: []
194
194
  require_paths:
195
195
  - lib
@@ -204,8 +204,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
204
  - !ruby/object:Gem::Version
205
205
  version: '0'
206
206
  requirements: []
207
- rubygems_version: 3.3.7
208
- signing_key:
207
+ rubygems_version: 3.4.3
208
+ signing_key:
209
209
  specification_version: 4
210
210
  summary: A forward-chaining rule engine in pure Ruby.
211
211
  test_files: []