wongi-engine 0.0.17 → 0.1.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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