wongi-engine 0.3.6 → 0.3.7
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 +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +80 -0
- data/.travis.yml +6 -16
- data/Gemfile +4 -0
- data/README.md +3 -3
- data/Rakefile +1 -2
- data/examples/ex01.rb +1 -1
- data/examples/ex02.rb +3 -7
- data/examples/graphviz.rb +1 -1
- data/examples/rdf.rb +1 -1
- data/examples/timeline.rb +6 -6
- data/lib/wongi-engine/alpha_memory.rb +5 -9
- data/lib/wongi-engine/beta/aggregate_node.rb +93 -0
- data/lib/wongi-engine/beta/assignment_node.rb +10 -18
- data/lib/wongi-engine/beta/beta_memory.rb +20 -9
- data/lib/wongi-engine/beta/beta_node.rb +14 -22
- data/lib/wongi-engine/beta/filter_node.rb +12 -15
- data/lib/wongi-engine/beta/join_node.rb +47 -61
- data/lib/wongi-engine/beta/ncc_node.rb +17 -20
- data/lib/wongi-engine/beta/ncc_partner.rb +17 -17
- data/lib/wongi-engine/beta/neg_node.rb +37 -37
- data/lib/wongi-engine/beta/optional_node.rb +53 -60
- data/lib/wongi-engine/beta/or_node.rb +6 -9
- data/lib/wongi-engine/beta/production_node.rb +6 -9
- data/lib/wongi-engine/beta.rb +1 -0
- data/lib/wongi-engine/compiler.rb +38 -22
- data/lib/wongi-engine/core_ext.rb +11 -20
- data/lib/wongi-engine/data_overlay.rb +23 -26
- data/lib/wongi-engine/dsl/action/assign_action.rb +1 -1
- data/lib/wongi-engine/dsl/action/base.rb +1 -4
- data/lib/wongi-engine/dsl/action/error_generator.rb +9 -9
- data/lib/wongi-engine/dsl/action/simple_action.rb +14 -10
- data/lib/wongi-engine/dsl/action/simple_collector.rb +10 -25
- data/lib/wongi-engine/dsl/action/statement_generator.rb +15 -14
- data/lib/wongi-engine/dsl/action/trace_action.rb +9 -9
- data/lib/wongi-engine/dsl/any_rule.rb +16 -20
- data/lib/wongi-engine/dsl/assuming.rb +8 -15
- data/lib/wongi-engine/dsl/builder.rb +13 -12
- data/lib/wongi-engine/dsl/clause/aggregate.rb +21 -0
- data/lib/wongi-engine/dsl/clause/assign.rb +4 -4
- data/lib/wongi-engine/dsl/clause/fact.rb +10 -6
- data/lib/wongi-engine/dsl/clause/gen.rb +3 -5
- data/lib/wongi-engine/dsl/clause/generic.rb +7 -9
- data/lib/wongi-engine/dsl/generated.rb +6 -12
- data/lib/wongi-engine/dsl/ncc_subrule.rb +6 -9
- data/lib/wongi-engine/dsl/query.rb +12 -15
- data/lib/wongi-engine/dsl/rule.rb +45 -50
- data/lib/wongi-engine/dsl.rb +30 -16
- data/lib/wongi-engine/enumerators.rb +2 -1
- data/lib/wongi-engine/error.rb +6 -7
- data/lib/wongi-engine/filter/asserting_test.rb +4 -7
- data/lib/wongi-engine/filter/equality_test.rb +15 -18
- data/lib/wongi-engine/filter/filter_test.rb +3 -6
- data/lib/wongi-engine/filter/greater_than_or_equal_test.rb +5 -2
- data/lib/wongi-engine/filter/greater_than_test.rb +15 -18
- data/lib/wongi-engine/filter/inequality_test.rb +15 -18
- data/lib/wongi-engine/filter/less_than_or_equal_test.rb +5 -2
- data/lib/wongi-engine/filter/less_than_test.rb +15 -18
- data/lib/wongi-engine/filter.rb +1 -1
- data/lib/wongi-engine/graph.rb +13 -20
- data/lib/wongi-engine/network/collectable.rb +10 -14
- data/lib/wongi-engine/network/debug.rb +16 -24
- data/lib/wongi-engine/network.rb +110 -129
- data/lib/wongi-engine/ruleset.rb +18 -20
- data/lib/wongi-engine/template.rb +31 -30
- data/lib/wongi-engine/token.rb +33 -33
- data/lib/wongi-engine/version.rb +1 -1
- data/lib/wongi-engine/wme.rb +17 -23
- data/lib/wongi-engine/wme_match_data.rb +5 -9
- data/lib/wongi-engine.rb +0 -4
- data/spec/action_class_spec.rb +43 -49
- data/spec/beta_node_spec.rb +2 -8
- data/spec/bug_specs/issue_4_spec.rb +12 -20
- data/spec/dataset_spec.rb +3 -6
- data/spec/filter_specs/assert_test_spec.rb +12 -31
- data/spec/filter_specs/greater_than_equality_test_spec.rb +2 -5
- data/spec/filter_specs/less_test_spec.rb +7 -17
- data/spec/filter_specs/less_than_equality_test_spec.rb +3 -6
- data/spec/generation_spec.rb +45 -54
- data/spec/high_level_spec.rb +95 -141
- data/spec/network_spec.rb +77 -68
- data/spec/overlay_spec.rb +4 -5
- data/spec/rule_specs/aggregate_spec.rb +197 -0
- data/spec/rule_specs/any_rule_spec.rb +4 -19
- data/spec/rule_specs/assign_spec.rb +10 -16
- data/spec/rule_specs/assuming_spec.rb +10 -17
- data/spec/rule_specs/maybe_rule_spec.rb +4 -15
- data/spec/rule_specs/ncc_spec.rb +48 -65
- data/spec/rule_specs/negative_rule_spec.rb +13 -27
- data/spec/rule_specs/or_rule_spec.rb +3 -13
- data/spec/ruleset_spec.rb +11 -17
- data/spec/simple_action_spec.rb +4 -14
- data/spec/wme_spec.rb +14 -21
- data/wongi-engine.gemspec +22 -22
- metadata +16 -37
- data/.hgignore +0 -7
- data/spec/dsl_spec.rb +0 -9
@@ -1,31 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "LESS test" do
|
4
|
+
include Wongi::Engine::DSL
|
5
|
+
let(:engine) { Wongi::Engine.create }
|
4
6
|
|
5
|
-
|
6
|
-
@engine = Wongi::Engine.create
|
7
|
-
end
|
8
|
-
|
9
|
-
def engine
|
10
|
-
@engine
|
11
|
-
end
|
7
|
+
attr_reader :production
|
12
8
|
|
13
|
-
def
|
14
|
-
@production
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_rule &block
|
18
|
-
@production = ( engine << rule( 'test-rule', &block ) )
|
9
|
+
def test_rule(&block)
|
10
|
+
@production = (engine << rule('test-rule', &block))
|
19
11
|
end
|
20
12
|
|
21
13
|
it "should interact with optional node correctly" do
|
22
|
-
|
23
14
|
# before the fix, filters would try to piggy-back on optional templates
|
24
15
|
|
25
16
|
test_rule {
|
26
17
|
forall {
|
27
18
|
maybe "Z", "Z", "Z"
|
28
|
-
less 6,4 # this should fail
|
19
|
+
less 6, 4 # this should fail
|
29
20
|
}
|
30
21
|
|
31
22
|
make {
|
@@ -33,9 +24,8 @@ describe "LESS test" do
|
|
33
24
|
}
|
34
25
|
}
|
35
26
|
|
36
|
-
engine << [
|
27
|
+
engine << %w[A B C]
|
37
28
|
|
38
29
|
expect(@production.size).to eq(0)
|
39
30
|
end
|
40
|
-
|
41
31
|
end
|
@@ -3,11 +3,8 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe 'Less Than Or Equal test' do
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
attr_reader :engine
|
6
|
+
include Wongi::Engine::DSL
|
7
|
+
let(:engine) { Wongi::Engine.create }
|
11
8
|
|
12
9
|
attr_reader :production
|
13
10
|
|
@@ -27,7 +24,7 @@ describe 'Less Than Or Equal test' do
|
|
27
24
|
|
28
25
|
engine << [5, :assign_check, nil]
|
29
26
|
engine << [6, :assign_check, nil]
|
30
|
-
engine << [7, :assign_check, nil] #should not pass
|
27
|
+
engine << [7, :assign_check, nil] # should not pass
|
31
28
|
expect(@production.size).to eq(2)
|
32
29
|
end
|
33
30
|
end
|
data/spec/generation_spec.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Wongi::Engine::DSL::Action::StatementGenerator do
|
4
|
+
include Wongi::Engine::DSL
|
5
|
+
let(:engine) { Wongi::Engine.create }
|
4
6
|
|
5
|
-
let(
|
6
|
-
|
7
|
-
let( :transitive_rule ) {
|
7
|
+
let(:transitive_rule) {
|
8
8
|
rule {
|
9
9
|
forall {
|
10
10
|
has :P, :transitive, true
|
@@ -17,100 +17,91 @@ describe Wongi::Engine::DSL::Action::StatementGenerator do
|
|
17
17
|
}
|
18
18
|
}
|
19
19
|
|
20
|
-
let(
|
20
|
+
let(:production) { engine << transitive_rule }
|
21
21
|
|
22
22
|
shared_examples 'generation' do
|
23
|
-
|
24
23
|
it 'should generate facts' do
|
25
|
-
engine << %w
|
26
|
-
engine << %w
|
24
|
+
engine << %w[Alice relative Bob]
|
25
|
+
engine << %w[Bob relative Dwight]
|
27
26
|
|
28
|
-
expect(
|
29
|
-
expect(
|
27
|
+
expect(production).to have(1).token
|
28
|
+
expect(engine.find(*%w[Alice relative Dwight])).not_to be_nil
|
30
29
|
end
|
31
30
|
|
32
31
|
it 'should retrct generated facts' do
|
33
|
-
engine << %w
|
34
|
-
engine << %w
|
35
|
-
engine.retract %w
|
32
|
+
engine << %w[Alice relative Bob]
|
33
|
+
engine << %w[Bob relative Dwight]
|
34
|
+
engine.retract %w[Bob relative Dwight]
|
36
35
|
|
37
|
-
expect(
|
38
|
-
expect(
|
36
|
+
expect(production).to have(0).tokens
|
37
|
+
expect(engine.find(*%w[Alice relative Dwight])).to be_nil
|
39
38
|
end
|
40
39
|
|
41
40
|
context 'transitive diamond' do
|
42
|
-
|
43
|
-
|
44
|
-
engine << %w
|
45
|
-
engine << %w
|
46
|
-
engine << %w
|
47
|
-
engine << %w( Claire relative Dwight )
|
41
|
+
before do
|
42
|
+
engine << %w[Alice relative Bob]
|
43
|
+
engine << %w[Bob relative Dwight]
|
44
|
+
engine << %w[Alice relative Claire]
|
45
|
+
engine << %w[Claire relative Dwight]
|
48
46
|
end
|
49
47
|
|
50
48
|
it 'should be created' do
|
51
|
-
expect(
|
52
|
-
expect(
|
49
|
+
expect(production).to have(2).tokens
|
50
|
+
expect(engine.find(*%w[Alice relative Dwight])).not_to be_nil
|
53
51
|
end
|
54
52
|
|
55
53
|
it 'should remain after a single retraction' do
|
56
|
-
engine.retract %w
|
54
|
+
engine.retract %w[Claire relative Dwight]
|
57
55
|
|
58
|
-
expect(
|
59
|
-
expect(
|
56
|
+
expect(production).to have(1).token
|
57
|
+
expect(engine.find(*%w[Alice relative Dwight])).not_to be_nil
|
60
58
|
end
|
61
59
|
|
62
60
|
it 'should be destroyed after both retractions' do
|
63
|
-
engine.retract %w
|
64
|
-
engine.retract %w
|
61
|
+
engine.retract %w[Claire relative Dwight]
|
62
|
+
engine.retract %w[Alice relative Bob]
|
65
63
|
|
66
|
-
expect(
|
67
|
-
expect(
|
64
|
+
expect(production).to have(0).tokens
|
65
|
+
expect(engine.find(*%w[Alice relative Dwight])).to be_nil
|
68
66
|
end
|
69
|
-
|
70
67
|
end
|
71
|
-
|
72
68
|
end
|
73
69
|
|
74
70
|
context "pre-asserted", :pre do
|
75
|
-
|
76
|
-
|
77
|
-
engine << [ "relative", :transitive, true ]
|
71
|
+
before do
|
72
|
+
engine << ["relative", :transitive, true]
|
78
73
|
end
|
79
74
|
|
80
75
|
it_behaves_like 'generation'
|
81
|
-
|
82
76
|
end
|
83
77
|
|
84
78
|
context "post-asserted", :post do
|
85
|
-
|
86
|
-
before :each do
|
79
|
+
before do
|
87
80
|
production
|
88
|
-
engine << [
|
81
|
+
engine << ["relative", :transitive, true]
|
89
82
|
end
|
90
83
|
|
91
84
|
it_behaves_like 'generation'
|
92
85
|
|
93
86
|
it 'should not retract generated facts marked as manual', :wip do
|
94
|
-
engine << %w
|
95
|
-
engine << %w
|
96
|
-
engine << %w
|
97
|
-
engine.retract %w
|
87
|
+
engine << %w[Alice relative Bob]
|
88
|
+
engine << %w[Bob relative Dwight]
|
89
|
+
engine << %w[Alice relative Dwight]
|
90
|
+
engine.retract %w[Alice relative Bob]
|
98
91
|
|
99
|
-
expect(
|
100
|
-
expect(
|
92
|
+
expect(production).to have(0).tokens
|
93
|
+
expect(engine.find(*%w[Alice relative Dwight])).not_to be_nil
|
101
94
|
end
|
102
95
|
|
103
96
|
it 'should retract generated facts unmarked as manual', :wip do
|
104
|
-
engine << %w
|
105
|
-
engine << %w
|
106
|
-
engine << %w
|
107
|
-
engine.retract %w
|
108
|
-
engine.retract %w
|
109
|
-
|
110
|
-
expect(
|
111
|
-
expect(
|
97
|
+
engine << %w[Alice relative Bob]
|
98
|
+
engine << %w[Bob relative Dwight]
|
99
|
+
engine << %w[Alice relative Dwight]
|
100
|
+
engine.retract %w[Alice relative Dwight]
|
101
|
+
engine.retract %w[Alice relative Bob]
|
102
|
+
|
103
|
+
expect(production).to have(0).tokens
|
104
|
+
expect(engine.find(*%w[Alice relative Dwight])).to be_nil
|
112
105
|
end
|
113
|
-
|
114
106
|
end
|
115
|
-
|
116
107
|
end
|
data/spec/high_level_spec.rb
CHANGED
@@ -1,30 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
3
|
+
class << self
|
4
|
+
extend Wongi::Engine::DSL
|
5
|
+
|
6
|
+
dsl {
|
7
|
+
section :make
|
8
|
+
clause :test_collector
|
9
|
+
action Wongi::Engine::DSL::Action::SimpleCollector.collector
|
10
|
+
}
|
11
|
+
end
|
12
12
|
|
13
13
|
describe 'the engine' do
|
14
|
-
|
15
|
-
|
16
|
-
@rete = Wongi::Engine::Network.new
|
17
|
-
end
|
18
|
-
|
19
|
-
def rete
|
20
|
-
@rete
|
21
|
-
end
|
14
|
+
include Wongi::Engine::DSL
|
15
|
+
let(:engine) { Wongi::Engine.create }
|
22
16
|
|
23
17
|
context 'with a simple generative positive rule' do
|
24
|
-
|
25
18
|
it 'should generate wmes with an existing rule' do
|
26
|
-
|
27
|
-
rete << rule('symmetric') {
|
19
|
+
engine << rule('symmetric') {
|
28
20
|
forall {
|
29
21
|
has :P, "symmetric", true
|
30
22
|
has :A, :P, :B
|
@@ -34,23 +26,22 @@ describe 'the engine' do
|
|
34
26
|
}
|
35
27
|
}
|
36
28
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
expect(
|
41
|
-
expect(
|
42
|
-
generated =
|
43
|
-
expect(
|
29
|
+
engine << Wongi::Engine::WME.new("friend", "symmetric", true)
|
30
|
+
engine << Wongi::Engine::WME.new("Alice", "friend", "Bob")
|
31
|
+
|
32
|
+
expect(engine.facts.to_a.length).to eq(3)
|
33
|
+
expect(engine.facts.select(&:manual?).length).to eq(2)
|
34
|
+
generated = engine.facts.find(&:generated?)
|
35
|
+
expect(generated).to be == Wongi::Engine::WME.new("Bob", "friend", "Alice")
|
44
36
|
end
|
45
37
|
|
46
38
|
it 'should generate wmes with an added rule' do
|
39
|
+
engine << Wongi::Engine::WME.new("friend", "symmetric", true)
|
40
|
+
engine << Wongi::Engine::WME.new("Alice", "friend", "Bob")
|
47
41
|
|
48
|
-
|
49
|
-
rete << Wongi::Engine::WME.new( "Alice", "friend", "Bob" )
|
50
|
-
|
51
|
-
expect(rete.facts.to_a.length).to eq(2)
|
42
|
+
expect(engine.facts.to_a.length).to eq(2)
|
52
43
|
|
53
|
-
|
44
|
+
engine << rule('symmetric') {
|
54
45
|
forall {
|
55
46
|
has :P, "symmetric", true
|
56
47
|
has :A, :P, :B
|
@@ -60,13 +51,12 @@ describe 'the engine' do
|
|
60
51
|
}
|
61
52
|
}
|
62
53
|
|
63
|
-
expect(
|
64
|
-
expect(
|
54
|
+
expect(engine.facts.to_a.length).to eq(3)
|
55
|
+
expect(engine.facts.select(&:manual?).size).to eq(2)
|
65
56
|
end
|
66
57
|
|
67
58
|
it 'should not get confused by recursive activations' do
|
68
|
-
|
69
|
-
rete << rule('reflexive') {
|
59
|
+
engine << rule('reflexive') {
|
70
60
|
forall {
|
71
61
|
has :Predicate, "reflexive", true
|
72
62
|
has :X, :Predicate, :Y
|
@@ -77,37 +67,29 @@ describe 'the engine' do
|
|
77
67
|
}
|
78
68
|
}
|
79
69
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
expect(rete.wmes.to_a.length).to eq(4)
|
84
|
-
expect(rete.select(:x, :p, :x).length).to eq(1)
|
85
|
-
expect(rete.select(:y, :p, :y).length).to eq(1)
|
70
|
+
engine << [:p, "reflexive", true]
|
71
|
+
engine << %i[x p y]
|
86
72
|
|
73
|
+
expect(engine.wmes.to_a.length).to eq(4)
|
74
|
+
expect(engine.select(:x, :p, :x).length).to eq(1)
|
75
|
+
expect(engine.select(:y, :p, :y).length).to eq(1)
|
87
76
|
end
|
88
|
-
|
89
77
|
end
|
90
78
|
|
91
79
|
it 'should check equality' do
|
92
|
-
|
93
|
-
node = rete << rule('equality') {
|
80
|
+
node = engine << rule('equality') {
|
94
81
|
forall {
|
95
82
|
fact :A, "same", :B
|
96
83
|
same :A, :B
|
97
84
|
}
|
98
|
-
make {
|
99
|
-
|
100
|
-
}
|
101
85
|
}
|
102
86
|
|
103
|
-
|
87
|
+
engine << [42, "same", 42]
|
104
88
|
expect(node.size).to eq(1)
|
105
|
-
|
106
89
|
end
|
107
90
|
|
108
91
|
it 'should compare things' do
|
109
|
-
|
110
|
-
rete << rule('less') {
|
92
|
+
engine << rule('less') {
|
111
93
|
forall {
|
112
94
|
has :A, :age, :N1
|
113
95
|
has :B, :age, :N2
|
@@ -118,7 +100,7 @@ describe 'the engine' do
|
|
118
100
|
}
|
119
101
|
}
|
120
102
|
|
121
|
-
|
103
|
+
engine << rule('less') {
|
122
104
|
forall {
|
123
105
|
has :A, :age, :N1
|
124
106
|
has :B, :age, :N2
|
@@ -129,20 +111,18 @@ describe 'the engine' do
|
|
129
111
|
}
|
130
112
|
}
|
131
113
|
|
132
|
-
|
133
|
-
|
114
|
+
engine << ["Alice", :age, 42]
|
115
|
+
engine << ["Bob", :age, 43]
|
134
116
|
|
135
|
-
items =
|
117
|
+
items = engine.select "Alice", :younger, "Bob"
|
136
118
|
expect(items.size).to eq(1)
|
137
119
|
|
138
|
-
items =
|
120
|
+
items = engine.select "Bob", :older, "Alice"
|
139
121
|
expect(items.size).to eq(1)
|
140
|
-
|
141
122
|
end
|
142
123
|
|
143
124
|
it 'should use collectors' do
|
144
|
-
|
145
|
-
rete << rule('collector') {
|
125
|
+
engine << rule('collector') {
|
146
126
|
forall {
|
147
127
|
has :X, :_, 42
|
148
128
|
}
|
@@ -151,17 +131,16 @@ describe 'the engine' do
|
|
151
131
|
}
|
152
132
|
}
|
153
133
|
|
154
|
-
|
155
|
-
|
134
|
+
engine << ["answer", "is", 42]
|
135
|
+
engine << ["question", "is", -1]
|
156
136
|
|
157
|
-
collection =
|
137
|
+
collection = engine.collection(:test_collector)
|
158
138
|
expect(collection.size).to eq(1)
|
159
139
|
expect(collection.first).to eq("answer")
|
160
|
-
|
161
140
|
end
|
162
141
|
|
163
142
|
it "should properly show error messages" do
|
164
|
-
|
143
|
+
engine << rule("Error rule") {
|
165
144
|
forall {
|
166
145
|
has :_, :_, :TestNumber
|
167
146
|
greater :TestNumber, 0
|
@@ -171,15 +150,14 @@ describe 'the engine' do
|
|
171
150
|
}
|
172
151
|
}
|
173
152
|
|
174
|
-
|
153
|
+
engine << ["A", "B", 1]
|
175
154
|
|
176
|
-
error_messages =
|
155
|
+
error_messages = engine.errors.map(&:message)
|
177
156
|
expect(error_messages).to eq(["An error has occurred"])
|
178
157
|
end
|
179
158
|
|
180
159
|
it 'should use generic collectors' do
|
181
|
-
|
182
|
-
rete << rule('generic-collector') {
|
160
|
+
engine << rule('generic-collector') {
|
183
161
|
forall {
|
184
162
|
has :X, :_, 42
|
185
163
|
}
|
@@ -188,20 +166,17 @@ describe 'the engine' do
|
|
188
166
|
}
|
189
167
|
}
|
190
168
|
|
191
|
-
|
192
|
-
|
169
|
+
engine << ["answer", "is", 42]
|
170
|
+
engine << ["question", "is", -1]
|
193
171
|
|
194
|
-
collection =
|
172
|
+
collection = engine.collection(:things_that_are_42)
|
195
173
|
expect(collection.size).to eq(1)
|
196
174
|
expect(collection.first).to eq("answer")
|
197
|
-
|
198
175
|
end
|
199
176
|
|
200
177
|
it 'should accept several rules' do
|
201
|
-
|
202
178
|
expect {
|
203
|
-
|
204
|
-
rete << rule('generic-collector') {
|
179
|
+
engine << rule('generic-collector') {
|
205
180
|
forall {
|
206
181
|
has :X, :_, 42
|
207
182
|
}
|
@@ -210,7 +185,7 @@ describe 'the engine' do
|
|
210
185
|
}
|
211
186
|
}
|
212
187
|
|
213
|
-
|
188
|
+
engine << rule('collector') {
|
214
189
|
forall {
|
215
190
|
has :X, :_, 42
|
216
191
|
}
|
@@ -218,31 +193,26 @@ describe 'the engine' do
|
|
218
193
|
test_collector :X
|
219
194
|
}
|
220
195
|
}
|
221
|
-
|
222
196
|
}.not_to raise_error
|
223
|
-
|
224
197
|
end
|
225
198
|
|
226
199
|
it 'should process negative nodes' do
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
})
|
200
|
+
production = (engine << rule('negative') {
|
201
|
+
forall {
|
202
|
+
neg :_, :_, 42
|
203
|
+
}
|
204
|
+
})
|
233
205
|
|
234
206
|
expect(production.size).to eq(1)
|
235
207
|
|
236
|
-
|
208
|
+
engine << ["answer", "is", 42]
|
237
209
|
|
238
210
|
expect(production.size).to eq(0)
|
239
|
-
|
240
211
|
end
|
241
212
|
|
242
213
|
context 'queries' do
|
243
|
-
|
244
|
-
|
245
|
-
rete << query("test-query") {
|
214
|
+
before do
|
215
|
+
engine << query("test-query") {
|
246
216
|
search_on :X
|
247
217
|
forall {
|
248
218
|
has :X, "is", :Y
|
@@ -251,32 +221,25 @@ describe 'the engine' do
|
|
251
221
|
end
|
252
222
|
|
253
223
|
it 'should run' do
|
254
|
-
|
255
|
-
|
256
|
-
expect(
|
257
|
-
expect(
|
224
|
+
engine << ["answer", "is", 42]
|
225
|
+
engine.execute "test-query", { X: "answer" }
|
226
|
+
expect(engine.results["test-query"].size).to eq(1)
|
227
|
+
expect(engine.results["test-query"].tokens.first[:Y]).to eq(42)
|
258
228
|
end
|
259
229
|
|
260
230
|
it 'should run several times' do
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
expect(
|
266
|
-
expect(
|
231
|
+
engine << ["answer", "is", 42]
|
232
|
+
engine << %w[question is 6x9]
|
233
|
+
engine.execute "test-query", { X: "answer" }
|
234
|
+
engine.execute "test-query", { X: "question" }
|
235
|
+
expect(engine.results["test-query"].tokens.to_a.last[:Y]).to eq('6x9')
|
236
|
+
expect(engine.results["test-query"].size).to eq(1)
|
267
237
|
end
|
268
|
-
|
269
238
|
end
|
270
239
|
|
271
|
-
it 'should correctly execute a query several times' do
|
272
|
-
|
273
|
-
end
|
274
|
-
|
275
240
|
context 'with timelines' do
|
276
|
-
|
277
241
|
it 'should not match with no past point' do
|
278
|
-
|
279
|
-
production = rete.rule {
|
242
|
+
production = engine.rule {
|
280
243
|
forall {
|
281
244
|
has 1, 2, 3, time: -1
|
282
245
|
}
|
@@ -284,95 +247,86 @@ describe 'the engine' do
|
|
284
247
|
|
285
248
|
expect(production.size).to eq(0)
|
286
249
|
|
287
|
-
|
250
|
+
engine << [1, 2, 3]
|
288
251
|
|
289
252
|
expect(production.size).to eq(0)
|
290
|
-
|
291
253
|
end
|
292
254
|
|
293
255
|
it 'should match a simple past point' do
|
294
|
-
|
295
|
-
production = rete.rule {
|
256
|
+
production = engine.rule {
|
296
257
|
forall {
|
297
258
|
has 1, 2, 3, time: -1
|
298
259
|
}
|
299
260
|
}
|
300
261
|
|
301
|
-
|
302
|
-
|
262
|
+
engine << [1, 2, 3]
|
263
|
+
engine.snapshot!
|
303
264
|
|
304
265
|
expect(production.size).to eq(1)
|
305
|
-
|
306
266
|
end
|
307
267
|
|
308
268
|
context 'using the :asserted clause' do
|
309
|
-
|
310
269
|
it 'should match asserted items' do
|
311
270
|
count = 0
|
312
|
-
production =
|
271
|
+
production = engine.rule do
|
313
272
|
forall {
|
314
273
|
asserted 1, 2, 3
|
315
274
|
}
|
316
|
-
make { action { count += 1} }
|
275
|
+
make { action { count += 1 } }
|
317
276
|
end
|
318
277
|
expect(production.size).to eq(0)
|
319
|
-
|
320
|
-
|
278
|
+
engine.snapshot!
|
279
|
+
engine << [1, 2, 3]
|
321
280
|
expect(production.size).to eq(1)
|
322
|
-
#puts count
|
281
|
+
# puts count
|
323
282
|
end
|
324
283
|
|
325
284
|
it 'should not match kept items' do
|
326
285
|
count = 0
|
327
|
-
production =
|
286
|
+
production = engine.rule do
|
328
287
|
forall {
|
329
288
|
asserted 1, 2, 3
|
330
289
|
}
|
331
|
-
make { action { count += 1} }
|
290
|
+
make { action { count += 1 } }
|
332
291
|
end
|
333
|
-
|
292
|
+
engine << [1, 2, 3]
|
334
293
|
expect(production.size).to eq(1)
|
335
|
-
|
294
|
+
engine.snapshot!
|
336
295
|
expect(production.size).to eq(0)
|
337
|
-
#puts count
|
296
|
+
# puts count
|
338
297
|
end
|
339
|
-
|
340
298
|
end
|
341
299
|
|
342
300
|
context 'using the :kept clause' do
|
343
|
-
|
344
301
|
it 'should match kept items' do
|
345
302
|
count = 0
|
346
|
-
production =
|
303
|
+
production = engine.rule do
|
347
304
|
forall {
|
348
305
|
kept 1, 2, 3
|
349
306
|
}
|
350
|
-
make { action { count += 1} }
|
307
|
+
make { action { count += 1 } }
|
351
308
|
end
|
352
|
-
|
309
|
+
engine << [1, 2, 3]
|
353
310
|
expect(production.size).to eq(0)
|
354
|
-
|
311
|
+
engine.snapshot!
|
355
312
|
expect(production.size).to eq(1)
|
356
|
-
#puts count
|
313
|
+
# puts count
|
357
314
|
end
|
358
315
|
|
359
316
|
it 'should not match asserted wmes' do
|
360
317
|
count = 0
|
361
|
-
production =
|
318
|
+
production = engine.rule do
|
362
319
|
forall {
|
363
320
|
kept 1, 2, 3
|
364
321
|
}
|
365
|
-
make { action { count += 1} }
|
322
|
+
make { action { count += 1 } }
|
366
323
|
end
|
367
324
|
expect(production.size).to eq(0)
|
368
|
-
|
369
|
-
|
325
|
+
engine.snapshot!
|
326
|
+
engine << [1, 2, 3]
|
370
327
|
expect(production.size).to eq(0)
|
371
|
-
#puts count
|
328
|
+
# puts count
|
372
329
|
end
|
373
|
-
|
374
330
|
end
|
375
|
-
|
376
331
|
end
|
377
|
-
|
378
332
|
end
|