wongi-engine 0.4.0.pre.alpha5 → 0.4.0.pre.alpha6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/lib/wongi-engine/alpha_index.rb +3 -4
- data/lib/wongi-engine/overlay.rb +4 -2
- data/lib/wongi-engine/version.rb +1 -1
- data/spec/dataset_spec.rb +1 -1
- data/spec/greater_than_equality_test_spec.rb +6 -12
- data/spec/high_level_spec.rb +1 -1
- data/spec/less_test_spec.rb +3 -9
- data/spec/less_than_equality_test_spec.rb +1 -1
- data/spec/network_spec.rb +23 -25
- data/spec/ruleset_spec.rb +12 -12
- data/spec/wme_spec.rb +11 -11
- data/wongi-engine.gemspec +17 -14
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4fab0e9a6fff37b3dc1a6cb4e7aa2c10ea08c82dbe78c874a7d475a18dfef170
|
4
|
+
data.tar.gz: e23cedb3481395ff240868b45eeedc5854331f521c3c00e96ff6e537d2e7c7e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9344af4983e233a95b157b4877f432f17fc7068a6ae77de4ca4edb5678e3555fb079dc13c8dee1866b21a09afcb4c003077ff8e70d7ad1222605ceab828d7726
|
7
|
+
data.tar.gz: cda25e408f9ba4706002d476f1c03cc367d10dddaf6381736b27f17be9b9e6b43e2993c9d84947d8eee3e04d08e631ba79a31332948f08b7ee44ecf95fd17ffc
|
data/.rubocop.yml
CHANGED
@@ -16,10 +16,9 @@ module Wongi::Engine
|
|
16
16
|
def remove(wme)
|
17
17
|
collection = collection_for_wme(wme)
|
18
18
|
collection.delete(wme)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
19
|
+
|
20
|
+
# release some memory
|
21
|
+
index.delete(hashed_key(wme)) if collection.empty?
|
23
22
|
end
|
24
23
|
|
25
24
|
def collection_for_wme(wme)
|
data/lib/wongi-engine/overlay.rb
CHANGED
@@ -183,14 +183,16 @@ module Wongi::Engine
|
|
183
183
|
case operation
|
184
184
|
when :assert
|
185
185
|
wme = find_ignoring_hidden(wme) || wme
|
186
|
+
visible = !find(wme).nil?
|
186
187
|
add_wme(wme, **options)
|
187
|
-
rete.real_assert(wme)
|
188
|
+
rete.real_assert(wme) unless visible
|
188
189
|
when :retract
|
189
190
|
wme = find_ignoring_hidden(wme)
|
190
191
|
return if wme.nil? # it's perhaps better to return quietly, because complicated cascades may delete a WME while we're going through the queue
|
191
192
|
|
193
|
+
visible = !find(wme).nil?
|
192
194
|
remove_wme(wme, **options)
|
193
|
-
rete.real_retract(wme)
|
195
|
+
rete.real_retract(wme) if visible
|
194
196
|
end
|
195
197
|
end
|
196
198
|
end
|
data/lib/wongi-engine/version.rb
CHANGED
data/spec/dataset_spec.rb
CHANGED
@@ -2,29 +2,23 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe Wongi::Engine::GreaterThanOrEqualTest do
|
6
6
|
include Wongi::Engine::DSL
|
7
7
|
let(:engine) { Wongi::Engine.create }
|
8
8
|
|
9
|
-
attr_reader :production
|
10
|
-
|
11
|
-
def test_rule(&block)
|
12
|
-
@production = (engine << rule('test-rule', &block))
|
13
|
-
end
|
14
|
-
|
15
9
|
it 'interacts with optional node correctly' do
|
16
10
|
# before the fix, filters would try to piggy-back on optional templates
|
17
11
|
|
18
|
-
|
19
|
-
forall
|
12
|
+
production = engine << rule {
|
13
|
+
forall {
|
20
14
|
has :Number, :assign_check, :_
|
21
15
|
gte :Number, 6
|
22
|
-
|
23
|
-
|
16
|
+
}
|
17
|
+
}
|
24
18
|
|
25
19
|
engine << [6, :assign_check, nil]
|
26
20
|
engine << [7, :assign_check, nil]
|
27
21
|
engine << [5, :assign_check, nil]
|
28
|
-
expect(
|
22
|
+
expect(production.size).to eq(2)
|
29
23
|
end
|
30
24
|
end
|
data/spec/high_level_spec.rb
CHANGED
data/spec/less_test_spec.rb
CHANGED
@@ -1,19 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe Wongi::Engine::LessThanTest do
|
4
4
|
include Wongi::Engine::DSL
|
5
5
|
let(:engine) { Wongi::Engine.create }
|
6
6
|
|
7
|
-
attr_reader :production
|
8
|
-
|
9
|
-
def test_rule(&block)
|
10
|
-
@production = (engine << rule('test-rule', &block))
|
11
|
-
end
|
12
|
-
|
13
7
|
it "interacts with optional node correctly" do
|
14
8
|
# before the fix, filters would try to piggy-back on optional templates
|
15
9
|
|
16
|
-
|
10
|
+
production = engine << rule {
|
17
11
|
forall {
|
18
12
|
maybe "Z", "Z", "Z"
|
19
13
|
less 6, 4 # this should fail
|
@@ -26,6 +20,6 @@ describe "LESS test" do
|
|
26
20
|
|
27
21
|
engine << %w[A B C]
|
28
22
|
|
29
|
-
expect(
|
23
|
+
expect(production.size).to eq(0)
|
30
24
|
end
|
31
25
|
end
|
data/spec/network_spec.rb
CHANGED
@@ -3,62 +3,60 @@ require 'spec_helper'
|
|
3
3
|
describe Wongi::Engine::Network do
|
4
4
|
include Wongi::Engine::DSL
|
5
5
|
|
6
|
-
subject { engine }
|
7
|
-
|
8
6
|
let(:engine) { Wongi::Engine.create }
|
9
7
|
|
10
8
|
it 'asserts facts' do
|
11
|
-
|
12
|
-
expect(
|
9
|
+
engine << [1, 2, 3]
|
10
|
+
expect(engine.select(:_, 2, :_)).to have(1).item
|
13
11
|
end
|
14
12
|
|
15
13
|
it 'retracts facts' do
|
16
|
-
|
17
|
-
|
18
|
-
expect(
|
14
|
+
engine << [1, 2, 3]
|
15
|
+
engine.retract [1, 2, 3]
|
16
|
+
expect(engine.select(:_, 2, :_).count).to eq(0)
|
19
17
|
end
|
20
18
|
|
21
19
|
it 'asserted facts end up in productions' do
|
22
|
-
prod =
|
23
|
-
|
20
|
+
prod = engine << rule { forall { has :X, 2, :Z } }
|
21
|
+
engine << [1, 2, 3]
|
24
22
|
expect(prod).to have(1).tokens
|
25
23
|
end
|
26
24
|
|
27
25
|
it 'rules can be removed from engine' do
|
28
|
-
|
29
|
-
|
26
|
+
engine << [1, 2, 3]
|
27
|
+
engine << [4, 5, 6]
|
30
28
|
|
31
|
-
prod1 =
|
32
|
-
prod2 =
|
29
|
+
prod1 = engine << rule { forall { has :X, 2, :Z } }
|
30
|
+
prod2 = engine << rule { forall { has :X, 5, :Z } }
|
33
31
|
|
34
32
|
expect(prod1).to have(1).tokens
|
35
33
|
expect(prod2).to have(1).tokens
|
36
34
|
|
37
|
-
|
35
|
+
engine.remove_production(prod1)
|
38
36
|
|
39
37
|
expect(prod1).to have(0).tokens
|
40
38
|
expect(prod2).to have(1).tokens
|
41
39
|
end
|
42
40
|
|
43
41
|
it 'new rules can be added to engine after a rule has been been removed' do
|
44
|
-
|
45
|
-
|
42
|
+
engine << [1, 2, 3]
|
43
|
+
engine << [4, 5, 6]
|
46
44
|
|
47
|
-
prod1 =
|
45
|
+
prod1 = engine << rule { forall { has :X, 2, :Z } }
|
48
46
|
|
49
47
|
expect(prod1).to have(1).tokens
|
50
48
|
|
51
|
-
|
49
|
+
engine.remove_production(prod1)
|
52
50
|
expect(prod1).to have(0).tokens
|
53
51
|
|
54
|
-
prod2 =
|
52
|
+
prod2 = engine << rule { forall { has :X, 5, :Z } }
|
55
53
|
expect(prod2).to have(1).tokens
|
56
54
|
end
|
57
55
|
|
58
56
|
it 'retracted facts are removed from productions' do
|
59
|
-
prod =
|
60
|
-
|
61
|
-
|
57
|
+
prod = engine << rule { forall { has :X, 2, :Z } }
|
58
|
+
engine << [1, 2, 3]
|
59
|
+
engine.retract [1, 2, 3]
|
62
60
|
expect(prod).to have(0).tokens
|
63
61
|
end
|
64
62
|
|
@@ -66,17 +64,17 @@ describe Wongi::Engine::Network do
|
|
66
64
|
activated_z = nil
|
67
65
|
deactivated_z = nil
|
68
66
|
|
69
|
-
|
67
|
+
engine << rule {
|
70
68
|
forall { has :X, 2, :Z }
|
71
69
|
make {
|
72
70
|
action activate: ->(token) { activated_z = token[:Z] },
|
73
71
|
deactivate: ->(token) { deactivated_z = token[:Z] }
|
74
72
|
}
|
75
73
|
}
|
76
|
-
|
74
|
+
engine << [1, 2, 3]
|
77
75
|
expect(activated_z).to be == 3
|
78
76
|
|
79
|
-
|
77
|
+
engine.retract [1, 2, 3]
|
80
78
|
expect(deactivated_z).to be == 3
|
81
79
|
end
|
82
80
|
|
data/spec/ruleset_spec.rb
CHANGED
@@ -2,44 +2,44 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Wongi::Engine::Ruleset do
|
4
4
|
before do
|
5
|
-
|
5
|
+
described_class.reset
|
6
6
|
end
|
7
7
|
|
8
8
|
context 'initially' do
|
9
9
|
it 'has no rules' do
|
10
|
-
expect(
|
10
|
+
expect(described_class.rulesets).to be_empty
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
context 'when creating' do
|
15
15
|
it 'does not register itself when not given a name' do
|
16
|
-
ruleset =
|
16
|
+
ruleset = described_class.new
|
17
17
|
expect(ruleset.name).to be_nil
|
18
|
-
expect(
|
18
|
+
expect(described_class.rulesets).to be_empty
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'has a name' do
|
22
|
-
ruleset =
|
22
|
+
ruleset = described_class.new 'testing-ruleset'
|
23
23
|
expect(ruleset.name).to be == 'testing-ruleset'
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'registers itself when given a name' do
|
27
|
-
ruleset =
|
28
|
-
expect(
|
29
|
-
expect(
|
27
|
+
ruleset = described_class.new 'testing-ruleset'
|
28
|
+
expect(described_class.rulesets).not_to be_empty
|
29
|
+
expect(described_class[ruleset.name]).to be == ruleset
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'is able to clear registered rulesets' do
|
34
|
-
_ =
|
35
|
-
|
36
|
-
expect(
|
34
|
+
_ = described_class.new 'testing-ruleset'
|
35
|
+
described_class.reset
|
36
|
+
expect(described_class.rulesets).to be_empty
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'installs creating rules into a rete' do
|
40
40
|
rete = double 'rete'
|
41
41
|
|
42
|
-
ruleset =
|
42
|
+
ruleset = described_class.new
|
43
43
|
rule = ruleset.rule('test-rule') {}
|
44
44
|
|
45
45
|
expect(rete).to receive(:<<).with(rule).once
|
data/spec/wme_spec.rb
CHANGED
@@ -9,36 +9,36 @@ describe Wongi::Engine::WME do
|
|
9
9
|
# rete
|
10
10
|
# end
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
let(:wme) {
|
13
|
+
described_class.new "a", "b", "c"
|
14
14
|
}
|
15
15
|
|
16
16
|
context 'a new WME' do
|
17
17
|
it 'initializes and expose members' do
|
18
|
-
expect(
|
19
|
-
expect(
|
20
|
-
expect(
|
18
|
+
expect(wme.subject).to be == "a"
|
19
|
+
expect(wme.predicate).to be == "b"
|
20
|
+
expect(wme.object).to be == "c"
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'compares instances' do
|
25
|
-
wme1 =
|
26
|
-
wme2 =
|
27
|
-
wme3 =
|
25
|
+
wme1 = described_class.new "a", "b", "c"
|
26
|
+
wme2 = described_class.new "a", "b", "c"
|
27
|
+
wme3 = described_class.new "a", "b", "d"
|
28
28
|
|
29
29
|
expect(wme1).to be == wme2
|
30
30
|
expect(wme1).not_to be == wme3
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'does not match against non-templates' do
|
34
|
-
expect {
|
34
|
+
expect { wme =~ [1, 2, 3] }.to raise_error(Wongi::Engine::Error)
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'matches against templates' do
|
38
38
|
t1 = Wongi::Engine::Template.new "a", :_, :_
|
39
39
|
t2 = Wongi::Engine::Template.new "b", :_, :_
|
40
40
|
|
41
|
-
expect(
|
42
|
-
expect(
|
41
|
+
expect(wme).to be =~ t1
|
42
|
+
expect(wme).not_to be =~ t2
|
43
43
|
end
|
44
44
|
end
|
data/wongi-engine.gemspec
CHANGED
@@ -5,26 +5,30 @@ module GemHelper
|
|
5
5
|
def self.git?
|
6
6
|
File.exist?('.git')
|
7
7
|
end
|
8
|
-
|
9
|
-
def self.hg?
|
10
|
-
File.exist?('.hg')
|
11
|
-
end
|
12
8
|
end
|
13
9
|
|
14
10
|
Gem::Specification.new do |gem|
|
15
|
-
gem.authors
|
16
|
-
gem.email
|
17
|
-
|
18
|
-
gem.
|
19
|
-
gem.
|
20
|
-
|
11
|
+
gem.authors = ['Valeri Sokolov']
|
12
|
+
gem.email = ['ulfurinn@ulfurinn.net']
|
13
|
+
|
14
|
+
gem.description = 'A forward-chaining rule engine in pure Ruby.'
|
15
|
+
gem.summary = 'A forward-chaining rule engine in pure Ruby.'
|
16
|
+
|
17
|
+
gem.required_ruby_version = '>= 2.7.0'
|
18
|
+
|
19
|
+
gem.licenses = %w[MIT]
|
20
|
+
|
21
|
+
gem.homepage = 'https://github.com/ulfurinn/wongi-engine'
|
22
|
+
gem.metadata = {
|
23
|
+
"documentation_uri" => 'https://ulfurinn.github.io/wongi-engine/',
|
24
|
+
"rubygems_mfa_required" => 'true',
|
25
|
+
}
|
26
|
+
|
21
27
|
|
22
28
|
gem.files = if GemHelper.git?
|
23
29
|
`git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
24
|
-
elsif GemHelper.hg?
|
25
|
-
`hg st -cn`.split($OUTPUT_RECORD_SEPARATOR)
|
26
30
|
else
|
27
|
-
raise 'cannot enumerate files: not a git
|
31
|
+
raise 'cannot enumerate files: not a git repository'
|
28
32
|
end
|
29
33
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
30
34
|
gem.name = 'wongi-engine'
|
@@ -36,5 +40,4 @@ Gem::Specification.new do |gem|
|
|
36
40
|
# gem.add_development_dependency 'pry-byebug', '~> 2.0'
|
37
41
|
gem.add_development_dependency 'rspec', '~> 3.1'
|
38
42
|
gem.add_development_dependency 'rspec-collection_matchers', '~> 1.1'
|
39
|
-
gem.metadata['rubygems_mfa_required'] = 'true'
|
40
43
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wongi-engine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.0.pre.
|
4
|
+
version: 0.4.0.pre.alpha6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Valeri Sokolov
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.1'
|
69
|
-
description: A rule engine.
|
69
|
+
description: A forward-chaining rule engine in pure Ruby.
|
70
70
|
email:
|
71
71
|
- ulfurinn@ulfurinn.net
|
72
72
|
executables: []
|
@@ -180,6 +180,7 @@ homepage: https://github.com/ulfurinn/wongi-engine
|
|
180
180
|
licenses:
|
181
181
|
- MIT
|
182
182
|
metadata:
|
183
|
+
documentation_uri: https://ulfurinn.github.io/wongi-engine/
|
183
184
|
rubygems_mfa_required: 'true'
|
184
185
|
post_install_message:
|
185
186
|
rdoc_options: []
|
@@ -189,7 +190,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
189
190
|
requirements:
|
190
191
|
- - ">="
|
191
192
|
- !ruby/object:Gem::Version
|
192
|
-
version:
|
193
|
+
version: 2.7.0
|
193
194
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
195
|
requirements:
|
195
196
|
- - ">"
|