wongi-engine 0.0.17 → 0.1.0.alpha1

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.
@@ -56,7 +56,8 @@ describe "issue 4" do
56
56
 
57
57
  end
58
58
 
59
- it "should correctly retract later items from within a rule" do
59
+ # cascaded processing affects this
60
+ it "should not retract later items from within a rule", :debug do
60
61
 
61
62
  engine = Wongi::Engine.create
62
63
 
@@ -74,7 +75,7 @@ describe "issue 4" do
74
75
  engine.retract [number, :is_number, true]
75
76
  engine.retract [number + 1, :is_number, true]
76
77
  else
77
- # this should never be reached
78
+ # this is not reached without cascades
78
79
  engine << [number, :is_odd, true]
79
80
  end
80
81
  }
@@ -86,8 +87,8 @@ describe "issue 4" do
86
87
  odds = engine.select :_, :is_odd, true
87
88
 
88
89
  expect(numbers).to be_empty
89
- expect(evens.length).to eq(5)
90
- expect(odds).to be_empty
90
+ expect(evens).to have(5).items
91
+ expect(odds).to have(5).items
91
92
 
92
93
  end
93
94
 
@@ -28,7 +28,7 @@ describe "ASSERT test" do
28
28
  }
29
29
  }
30
30
 
31
- expect(production.size).to eq(1)
31
+ expect(production).to have(1).token
32
32
 
33
33
  end
34
34
 
@@ -42,7 +42,7 @@ describe "ASSERT test" do
42
42
  }
43
43
  }
44
44
 
45
- expect(production.size).to eq(0)
45
+ expect(production).to have(0).tokens
46
46
 
47
47
  end
48
48
 
@@ -59,11 +59,28 @@ describe "ASSERT test" do
59
59
 
60
60
  engine << ["resistance", "is", "futile"]
61
61
 
62
- expect(production.size).to eq(1)
62
+ expect(production).to have(1).token
63
63
  expect(production.tokens.first[:X]).to eq("resistance")
64
64
 
65
65
  end
66
66
 
67
+ it "should be retractable" do
68
+
69
+ test_rule {
70
+ forall {
71
+ has :X, "is", :Y
72
+ assert { |token|
73
+ token[:X] == "resistance"
74
+ }
75
+ }
76
+ }
77
+
78
+ engine << ["resistance", "is", "futile"]
79
+ engine.retract ["resistance", "is", "futile"]
80
+ expect(production).to have(0).tokens
81
+
82
+ end
83
+
67
84
  it "should use individual variables with arguments" do
68
85
 
69
86
  test_rule {
@@ -77,7 +94,7 @@ describe "ASSERT test" do
77
94
 
78
95
  engine << ["resistance", "is", "futile"]
79
96
 
80
- expect(production.size).to eq(1)
97
+ expect(production).to have(1).token
81
98
  expect(production.tokens.first[:X]).to eq("resistance")
82
99
 
83
100
  end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ describe Wongi::Engine::Network do
4
+
5
+ let( :engine ) { Wongi::Engine.create }
6
+ subject { engine }
7
+
8
+ it 'should assert facts' do
9
+ subject << [1,2,3]
10
+ expect( subject.select( :_, 2, :_) ).to have(1).item
11
+ end
12
+
13
+ it 'should retract facts' do
14
+ subject << [1,2,3]
15
+ subject.retract [1,2,3]
16
+ expect( subject.select( :_, 2, :_) ).to be_empty
17
+ end
18
+
19
+ it 'asserted facts end up in productions' do
20
+
21
+ prod = subject << rule { forall { has :X, 2, :Z } }
22
+ subject << [1,2,3]
23
+ expect( prod ).to have(1).tokens
24
+
25
+ end
26
+
27
+ it 'retracted facts are removed from productions' do
28
+
29
+ prod = subject << rule { forall { has :X, 2, :Z } }
30
+ subject << [1,2,3]
31
+ subject.retract [1,2,3]
32
+ expect( prod ).to have(0).tokens
33
+
34
+ end
35
+
36
+ it 'retracted facts should trigger deactivation' do
37
+
38
+ activated_z = nil
39
+ deactivated_z = nil
40
+
41
+ prod = subject << rule {
42
+ forall { has :X, 2, :Z }
43
+ make {
44
+ action activate: ->(token) { activated_z = token[:Z] },
45
+ deactivate: ->(token) { deactivated_z = token[:Z] }
46
+ }
47
+ }
48
+ subject << [1,2,3]
49
+ expect( activated_z ).to be == 3
50
+
51
+ subject.retract [1,2,3]
52
+ expect( deactivated_z ).to be == 3
53
+
54
+ end
55
+
56
+ it 'retracted facts should propagate through join chains' do
57
+
58
+ deactivated = nil
59
+
60
+ prod = engine << rule {
61
+ forall {
62
+ has :X, :is, :Y
63
+ has :Y, :is, :Z
64
+ }
65
+ make {
66
+ action deactivate: ->(token) { deactivated = token }
67
+ }
68
+ }
69
+
70
+ engine << [1, :is, 2]
71
+ engine << [2, :is, 3]
72
+
73
+ expect( prod ).to have(1).tokens
74
+
75
+ engine.retract [1, :is, 2]
76
+ expect( prod ).to have(0).tokens
77
+ expect( deactivated[:X] ).to be == 1
78
+ expect( deactivated[:Y] ).to be == 2
79
+ expect( deactivated[:Z] ).to be == 3
80
+
81
+ end
82
+
83
+ it 'retraction should reactivate neg nodes' do
84
+
85
+ prod = engine << rule { forall { neg 1, 2, 3} }
86
+
87
+ expect( prod ).to have(1).tokens
88
+
89
+ engine << [1, 2 ,3]
90
+ expect( prod ).to have(0).tokens
91
+
92
+ engine.retract [1, 2, 3]
93
+ expect( prod ).to have(1).tokens
94
+
95
+ end
96
+
97
+ describe 'retraction with neg nodes lower in the chain' do
98
+
99
+ def expect_tokens n
100
+ expect( prod ).to have(n).tokens
101
+ end
102
+
103
+ before :each do
104
+
105
+ engine << rule('retract') {
106
+ forall {
107
+ has :x, :u, :Y
108
+ neg :Y, :w, :_
109
+ }
110
+ }
111
+
112
+ end
113
+
114
+ let( :prod ) { engine.productions['retract'] }
115
+
116
+ specify 'case 1' do
117
+
118
+ engine << [:x, :u, :y]
119
+ expect_tokens 1
120
+
121
+ engine << [:y, :w, :z]
122
+ expect_tokens 0
123
+
124
+ engine.retract [:y, :w, :z]
125
+ expect_tokens 1
126
+
127
+ engine.retract [:x, :u, :y]
128
+ expect_tokens 0
129
+
130
+ end
131
+
132
+ specify 'case 2' do
133
+
134
+ engine << [:x, :u, :y]
135
+ expect_tokens 1
136
+
137
+ engine << [:y, :w, :z]
138
+ expect_tokens 0
139
+
140
+ engine.retract [:x, :u, :y]
141
+ expect_tokens 0
142
+
143
+ engine.retract [:y, :w, :z]
144
+ expect_tokens 0
145
+
146
+ end
147
+
148
+ specify 'case 3' do
149
+
150
+ engine << [:y, :w, :z]
151
+ expect_tokens 0
152
+
153
+ engine << [:x, :u, :y]
154
+ expect_tokens 0
155
+
156
+ engine.retract [:x, :u, :y]
157
+ expect_tokens 0
158
+
159
+ engine.retract [:y, :w, :z]
160
+ expect_tokens 0
161
+
162
+ end
163
+
164
+ specify 'case 4' do
165
+
166
+ engine << [:y, :w, :z]
167
+ expect_tokens 0
168
+
169
+ engine << [:x, :u, :y]
170
+ expect_tokens 0
171
+
172
+ engine.retract [:y, :w, :z]
173
+ expect_tokens 1
174
+
175
+ engine.retract [:x, :u, :y]
176
+ expect_tokens 0
177
+
178
+ end
179
+
180
+ end
181
+
182
+ end
@@ -2,25 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe "ASSIGN rule" do
4
4
 
5
- before :each do
6
- @engine = Wongi::Engine.create
7
- end
8
-
9
- def engine
10
- @engine
11
- end
12
-
13
- def production
14
- @production
15
- end
16
-
17
- def test_rule &block
18
- @production = ( engine << rule( 'test-rule', &block ) )
19
- end
5
+ let( :engine ) { Wongi::Engine.create }
20
6
 
21
7
  it "should assign simple expressions" do
22
8
 
23
- test_rule {
9
+ production = engine << rule {
24
10
  forall {
25
11
  assign :X do
26
12
  42
@@ -34,7 +20,7 @@ describe "ASSIGN rule" do
34
20
 
35
21
  it "should be able to access previous assignments" do
36
22
 
37
- test_rule {
23
+ production = engine << rule {
38
24
  forall {
39
25
  has 1, 2, :X
40
26
  assign :Y do |token|
@@ -48,4 +34,22 @@ describe "ASSIGN rule" do
48
34
 
49
35
  end
50
36
 
37
+ it 'should be deactivatable', :debug do
38
+
39
+ prod = engine << rule {
40
+ forall {
41
+ has 1, 2, :X
42
+ assign :Y do |token|
43
+ token[:X] * 2
44
+ end
45
+ }
46
+ }
47
+
48
+ engine << [1, 2, 5]
49
+ engine.retract [1, 2, 5]
50
+
51
+ expect( prod ).to have(0).tokens
52
+
53
+ end
54
+
51
55
  end
@@ -2,24 +2,19 @@ require "spec_helper"
2
2
 
3
3
  describe "MAYBE rule" do
4
4
 
5
- before :each do
6
- @engine = Wongi::Engine.create
7
- end
8
-
9
- def engine
10
- @engine
11
- end
12
-
13
- it "should pass with existing facts" do
14
-
15
- engine << rule('test') do
5
+ let( :engine ) { Wongi::Engine.create }
6
+ let( :maybe_rule ) {
7
+ rule {
16
8
  forall {
17
9
  has 1, 2, :X
18
10
  maybe :X, 4, :Y
19
11
  }
20
- end
12
+ }
13
+ }
21
14
 
22
- production = engine.productions['test']
15
+ it "should pass with existing facts" do
16
+
17
+ production = engine << maybe_rule
23
18
 
24
19
  engine << [1, 2, 3]
25
20
  engine << [3, 4, 5]
@@ -33,14 +28,7 @@ describe "MAYBE rule" do
33
28
 
34
29
  it "should pass with missing facts" do
35
30
 
36
- engine << rule('test') do
37
- forall {
38
- has 1, 2, :X
39
- maybe :X, 4, :Y
40
- }
41
- end
42
-
43
- production = engine.productions['test']
31
+ production = engine << maybe_rule
44
32
 
45
33
  engine << [1, 2, 3]
46
34
 
@@ -55,14 +43,7 @@ describe "MAYBE rule" do
55
43
 
56
44
  engine << [1, 2, 3]
57
45
 
58
- engine << rule('test') do
59
- forall {
60
- has 1, 2, :X
61
- maybe :X, 4, :Y
62
- }
63
- end
64
-
65
- production = engine.productions['test']
46
+ production = engine << maybe_rule
66
47
 
67
48
  expect(production.size).to eq(1)
68
49
 
@@ -71,4 +52,50 @@ describe "MAYBE rule" do
71
52
 
72
53
  end
73
54
 
55
+ it 'should pass with retracted facts', :debug do
56
+
57
+ prod = engine << maybe_rule
58
+
59
+ engine << [1, 2, 3]
60
+ engine << [3, 4, 5]
61
+ engine.retract [3, 4, 5]
62
+
63
+ expect(prod.size).to eq(1)
64
+
65
+ expect(prod.tokens.first[:X]).to eq(3)
66
+ expect(prod.tokens.first[:Y]).to be_nil
67
+
68
+ end
69
+
70
+ it 'should work with repeated activations' do
71
+
72
+ prod = engine << maybe_rule
73
+
74
+ engine << [1, 2, 3]
75
+ engine << [3, 4, 5]
76
+ engine.retract [3, 4, 5]
77
+
78
+ 10.times {
79
+ engine << [3, 4, 5]
80
+ expect(prod.size).to eq(1)
81
+ expect(prod.tokens.first[:Y]).to be == 5
82
+
83
+ engine.retract [3, 4, 5]
84
+ expect(prod.size).to eq(1)
85
+ expect(prod.tokens.first[:Y]).to be_nil
86
+ }
87
+
88
+ end
89
+
90
+ it 'should handle retracted parent tokens' do
91
+ prod = engine << maybe_rule
92
+
93
+ engine << [1, 2, 3]
94
+ engine << [3, 4, 5]
95
+ engine.retract [1, 2, 3]
96
+
97
+ expect(prod).to have(0).tokens
98
+ expect(engine.find(3,4,5).opt_join_results).to be_empty
99
+ end
100
+
74
101
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "NCC rule" do
3
+ describe Wongi::Engine::NccNode do
4
4
 
5
5
  before :each do
6
6
  @engine = Wongi::Engine.create
@@ -42,15 +42,15 @@ describe "NCC rule" do
42
42
 
43
43
  engine << ["base", "is", 1]
44
44
 
45
- expect(production.size).to eq(1)
45
+ expect(production).to have(1).token
46
46
 
47
47
  engine << [1, 2, 3]
48
48
 
49
- expect(production.size).to eq(1)
49
+ expect(production).to have(1).token
50
50
 
51
51
  engine << [3, 4, 5]
52
52
 
53
- expect(production.size).to eq(0)
53
+ expect(production).to have(0).token
54
54
 
55
55
  end
56
56
 
@@ -63,13 +63,13 @@ describe "NCC rule" do
63
63
  engine << [1, 2, 3]
64
64
  engine << [3, 4, 5]
65
65
 
66
- expect(production.size).to eq(0)
66
+ expect(production).to have(0).tokens
67
67
 
68
68
  engine.retract [3, 4, 5]
69
69
  expect( production ).to have(1).token
70
70
 
71
71
  engine.retract ["base", "is", 1]
72
- expect(production.size).to eq(0)
72
+ expect(production).to have(0).tokens
73
73
 
74
74
  end
75
75
 
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,2 @@
1
1
  require 'wongi-engine'
2
2
  require 'rspec/collection_matchers'
3
- require 'pry'
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.0.17
4
+ version: 0.1.0.alpha1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valeri Sokolov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-26 00:00:00.000000000 Z
11
+ date: 2015-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -16,48 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '10'
19
+ version: '10.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '10'
27
- - !ruby/object:Gem::Dependency
28
- name: pry
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '0.10'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '0.10'
26
+ version: '10.0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rspec
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - "~>"
46
32
  - !ruby/object:Gem::Version
47
- version: '3.1'
48
- - - "<"
49
- - !ruby/object:Gem::Version
50
- version: '3.2'
33
+ version: 3.1.0
51
34
  type: :development
52
35
  prerelease: false
53
36
  version_requirements: !ruby/object:Gem::Requirement
54
37
  requirements:
55
38
  - - "~>"
56
39
  - !ruby/object:Gem::Version
57
- version: '3.1'
58
- - - "<"
59
- - !ruby/object:Gem::Version
60
- version: '3.2'
40
+ version: 3.1.0
61
41
  - !ruby/object:Gem::Dependency
62
42
  name: rspec-collection_matchers
63
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +60,7 @@ extensions: []
80
60
  extra_rdoc_files: []
81
61
  files:
82
62
  - ".gitignore"
63
+ - ".hgtags"
83
64
  - ".ruby-gemset"
84
65
  - ".travis.yml"
85
66
  - Gemfile
@@ -150,6 +131,7 @@ files:
150
131
  - spec/filter_specs/assert_test_spec.rb
151
132
  - spec/filter_specs/less_test_spec.rb
152
133
  - spec/high_level_spec.rb
134
+ - spec/network_spec.rb
153
135
  - spec/rule_specs/any_rule_spec.rb
154
136
  - spec/rule_specs/assign_spec.rb
155
137
  - spec/rule_specs/assuming_spec.rb
@@ -160,7 +142,6 @@ files:
160
142
  - spec/simple_action_spec.rb
161
143
  - spec/spec_helper.rb
162
144
  - spec/wme_spec.rb
163
- - wongi-engine.gemspec
164
145
  homepage: https://github.com/ulfurinn/wongi-engine
165
146
  licenses:
166
147
  - MIT
@@ -176,9 +157,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
157
  version: '0'
177
158
  required_rubygems_version: !ruby/object:Gem::Requirement
178
159
  requirements:
179
- - - ">="
160
+ - - ">"
180
161
  - !ruby/object:Gem::Version
181
- version: '0'
162
+ version: 1.3.1
182
163
  requirements: []
183
164
  rubyforge_project:
184
165
  rubygems_version: 2.4.5
@@ -193,6 +174,7 @@ test_files:
193
174
  - spec/filter_specs/assert_test_spec.rb
194
175
  - spec/filter_specs/less_test_spec.rb
195
176
  - spec/high_level_spec.rb
177
+ - spec/network_spec.rb
196
178
  - spec/rule_specs/any_rule_spec.rb
197
179
  - spec/rule_specs/assign_spec.rb
198
180
  - spec/rule_specs/assuming_spec.rb
data/wongi-engine.gemspec DELETED
@@ -1,23 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/wongi-engine/version', __FILE__)
3
-
4
- Gem::Specification.new do |gem|
5
- gem.authors = ["Valeri Sokolov"]
6
- gem.email = ["ulfurinn@ulfurinn.net"]
7
- gem.description = %q{A rule engine.}
8
- gem.summary = %q{A forward-chaining rule engine in pure Ruby.}
9
- gem.homepage = "https://github.com/ulfurinn/wongi-engine"
10
- gem.licenses = %w(MIT)
11
-
12
- gem.files = `git ls-files`.split($\)
13
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
- gem.name = "wongi-engine"
16
- gem.require_paths = ["lib"]
17
- gem.version = Wongi::Engine::VERSION
18
-
19
- gem.add_development_dependency 'rake', '~> 10'
20
- gem.add_development_dependency 'pry', '~> 0.10'
21
- gem.add_development_dependency 'rspec', '~> 3.1', '< 3.2'
22
- gem.add_development_dependency 'rspec-collection_matchers', '~> 1.1'
23
- end