mort666-wongi-engine 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.hgignore +6 -0
- data/.hgtags +13 -0
- data/.ruby-gemset +1 -0
- data/.travis.yml +19 -0
- data/CHANGELOG.md +106 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +27 -0
- data/Rakefile +9 -0
- data/examples/ex01.rb +23 -0
- data/examples/ex02.rb +37 -0
- data/examples/graphviz.rb +16 -0
- data/examples/rdf.n3 +6 -0
- data/examples/rdf.rb +14 -0
- data/examples/timeline.rb +48 -0
- data/lib/wongi-engine.rb +36 -0
- data/lib/wongi-engine/alpha_memory.rb +60 -0
- data/lib/wongi-engine/beta.rb +11 -0
- data/lib/wongi-engine/beta/assignment_node.rb +40 -0
- data/lib/wongi-engine/beta/beta_memory.rb +49 -0
- data/lib/wongi-engine/beta/beta_node.rb +94 -0
- data/lib/wongi-engine/beta/filter_node.rb +48 -0
- data/lib/wongi-engine/beta/join_node.rb +140 -0
- data/lib/wongi-engine/beta/ncc_node.rb +67 -0
- data/lib/wongi-engine/beta/ncc_partner.rb +40 -0
- data/lib/wongi-engine/beta/neg_node.rb +115 -0
- data/lib/wongi-engine/beta/optional_node.rb +142 -0
- data/lib/wongi-engine/beta/or_node.rb +37 -0
- data/lib/wongi-engine/beta/production_node.rb +31 -0
- data/lib/wongi-engine/compiler.rb +115 -0
- data/lib/wongi-engine/core_ext.rb +63 -0
- data/lib/wongi-engine/data_overlay.rb +144 -0
- data/lib/wongi-engine/dsl.rb +132 -0
- data/lib/wongi-engine/dsl/action/base.rb +11 -0
- data/lib/wongi-engine/dsl/action/error_generator.rb +31 -0
- data/lib/wongi-engine/dsl/action/simple_action.rb +60 -0
- data/lib/wongi-engine/dsl/action/simple_collector.rb +52 -0
- data/lib/wongi-engine/dsl/action/statement_generator.rb +46 -0
- data/lib/wongi-engine/dsl/action/trace_action.rb +49 -0
- data/lib/wongi-engine/dsl/any_rule.rb +33 -0
- data/lib/wongi-engine/dsl/assuming.rb +31 -0
- data/lib/wongi-engine/dsl/builder.rb +44 -0
- data/lib/wongi-engine/dsl/clause/assign.rb +15 -0
- data/lib/wongi-engine/dsl/clause/fact.rb +71 -0
- data/lib/wongi-engine/dsl/clause/gen.rb +17 -0
- data/lib/wongi-engine/dsl/clause/generic.rb +38 -0
- data/lib/wongi-engine/dsl/generated.rb +43 -0
- data/lib/wongi-engine/dsl/ncc_subrule.rb +17 -0
- data/lib/wongi-engine/dsl/query.rb +24 -0
- data/lib/wongi-engine/dsl/rule.rb +84 -0
- data/lib/wongi-engine/enumerators.rb +21 -0
- data/lib/wongi-engine/error.rb +22 -0
- data/lib/wongi-engine/filter.rb +6 -0
- data/lib/wongi-engine/filter/asserting_test.rb +20 -0
- data/lib/wongi-engine/filter/equality_test.rb +36 -0
- data/lib/wongi-engine/filter/filter_test.rb +18 -0
- data/lib/wongi-engine/filter/greater_than_test.rb +36 -0
- data/lib/wongi-engine/filter/inequality_test.rb +36 -0
- data/lib/wongi-engine/filter/less_than_test.rb +36 -0
- data/lib/wongi-engine/graph.rb +73 -0
- data/lib/wongi-engine/network.rb +416 -0
- data/lib/wongi-engine/network/collectable.rb +42 -0
- data/lib/wongi-engine/network/debug.rb +85 -0
- data/lib/wongi-engine/ruleset.rb +74 -0
- data/lib/wongi-engine/template.rb +78 -0
- data/lib/wongi-engine/token.rb +114 -0
- data/lib/wongi-engine/version.rb +5 -0
- data/lib/wongi-engine/wme.rb +89 -0
- data/lib/wongi-engine/wme_match_data.rb +34 -0
- data/spec/beta_node_spec.rb +29 -0
- data/spec/bug_specs/issue_4_spec.rb +141 -0
- data/spec/dataset_spec.rb +27 -0
- data/spec/dsl_spec.rb +9 -0
- data/spec/filter_specs/assert_test_spec.rb +102 -0
- data/spec/filter_specs/less_test_spec.rb +41 -0
- data/spec/generation_spec.rb +116 -0
- data/spec/high_level_spec.rb +378 -0
- data/spec/network_spec.rb +182 -0
- data/spec/overlay_spec.rb +61 -0
- data/spec/rule_specs/any_rule_spec.rb +75 -0
- data/spec/rule_specs/assign_spec.rb +88 -0
- data/spec/rule_specs/assuming_spec.rb +66 -0
- data/spec/rule_specs/maybe_rule_spec.rb +101 -0
- data/spec/rule_specs/ncc_spec.rb +258 -0
- data/spec/rule_specs/negative_rule_spec.rb +105 -0
- data/spec/ruleset_spec.rb +54 -0
- data/spec/simple_action_spec.rb +40 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/wme_spec.rb +83 -0
- data/wongi-engine.gemspec +40 -0
- metadata +212 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'wongi-engine/beta/beta_node'
|
2
|
+
require 'wongi-engine/beta/beta_memory'
|
3
|
+
require 'wongi-engine/beta/filter_node'
|
4
|
+
require 'wongi-engine/beta/assignment_node'
|
5
|
+
require 'wongi-engine/beta/join_node'
|
6
|
+
require 'wongi-engine/beta/ncc_partner'
|
7
|
+
require 'wongi-engine/beta/ncc_node'
|
8
|
+
require 'wongi-engine/beta/neg_node'
|
9
|
+
require 'wongi-engine/beta/optional_node'
|
10
|
+
require 'wongi-engine/beta/or_node'
|
11
|
+
require 'wongi-engine/beta/production_node'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class AssignmentNode < BetaNode
|
4
|
+
|
5
|
+
def initialize parent, variable, body
|
6
|
+
super parent
|
7
|
+
@variable, @body = variable, body
|
8
|
+
end
|
9
|
+
|
10
|
+
def beta_activate token, wme = nil, assignments = { }
|
11
|
+
children.each do |child|
|
12
|
+
child.beta_activate Token.new( child, token, nil, { @variable => @body.respond_to?(:call) ? @body.call(token) : @body } )
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def beta_deactivate token
|
17
|
+
children.each do |child|
|
18
|
+
child.tokens.each do |t|
|
19
|
+
if t.parent == token
|
20
|
+
child.beta_deactivate t
|
21
|
+
#token.destroy
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def refresh_child child
|
28
|
+
tmp = children
|
29
|
+
self.children = [ child ]
|
30
|
+
parent.tokens.each do |token|
|
31
|
+
children.each do |child|
|
32
|
+
child.beta_activate Token.new( child, token, nil, { @variable => @body.respond_to?(:call) ? @body.call(token) : @body } )
|
33
|
+
end
|
34
|
+
end
|
35
|
+
self.children = tmp
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class BetaMemory < BetaNode
|
4
|
+
include TokenContainer
|
5
|
+
|
6
|
+
def seed assignments = {}
|
7
|
+
@seed = assignments
|
8
|
+
t = Token.new( self, nil, nil, assignments )
|
9
|
+
rete.default_overlay.add_token(t, self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def subst valuations
|
13
|
+
beta_deactivate(tokens.first)
|
14
|
+
token = Token.new( self, nil, nil, @seed )
|
15
|
+
valuations.each { |variable, value| token.subst variable, value }
|
16
|
+
beta_activate(token)
|
17
|
+
end
|
18
|
+
|
19
|
+
def beta_activate token
|
20
|
+
existing = tokens.find { |et| et.duplicate? token }
|
21
|
+
return if existing # TODO really?
|
22
|
+
token.overlay.add_token(token, self)
|
23
|
+
children.each do |child|
|
24
|
+
child.beta_activate token
|
25
|
+
end
|
26
|
+
token
|
27
|
+
end
|
28
|
+
|
29
|
+
def beta_deactivate token
|
30
|
+
return nil unless tokens.find token
|
31
|
+
token.overlay.remove_token(token, self)
|
32
|
+
token.deleted!
|
33
|
+
if token.parent
|
34
|
+
token.parent.children.delete token # should this go into Token#destroy?
|
35
|
+
end
|
36
|
+
children.each do |child|
|
37
|
+
child.beta_deactivate token
|
38
|
+
end
|
39
|
+
token
|
40
|
+
end
|
41
|
+
|
42
|
+
def refresh_child child
|
43
|
+
tokens.each do |token|
|
44
|
+
child.beta_activate token
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class BetaNode
|
4
|
+
|
5
|
+
module TokenContainer
|
6
|
+
def tokens
|
7
|
+
Enumerator.new do |y|
|
8
|
+
rete.overlays.each do |overlay|
|
9
|
+
overlay.raw_tokens(self).dup.each do |token|
|
10
|
+
y << token unless token.deleted?
|
11
|
+
end
|
12
|
+
overlay.raw_tokens(self).reject! &:deleted?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def empty?
|
18
|
+
tokens.first.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def size
|
22
|
+
tokens.count
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
include CoreExt
|
27
|
+
|
28
|
+
attr_writer :rete
|
29
|
+
attr_reader :parent
|
30
|
+
attr_accessor :children
|
31
|
+
attr_predicate :debug
|
32
|
+
|
33
|
+
def initialize parent = nil
|
34
|
+
@parent = parent
|
35
|
+
@children = []
|
36
|
+
if parent
|
37
|
+
parent.children << self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def root?
|
42
|
+
parent.nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
def depth
|
46
|
+
@depth ||= if parent.nil?
|
47
|
+
0
|
48
|
+
else
|
49
|
+
parent.depth + 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def rete
|
54
|
+
@rete ||= if parent
|
55
|
+
parent.rete
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
abstract :alpha_activate
|
60
|
+
abstract :alpha_deactivate
|
61
|
+
abstract :alpha_reactivate
|
62
|
+
abstract :beta_activate
|
63
|
+
abstract :beta_deactivate
|
64
|
+
abstract :beta_reactivate
|
65
|
+
|
66
|
+
def assignment_node variable, body
|
67
|
+
node = AssignmentNode.new self, variable, body
|
68
|
+
node.refresh
|
69
|
+
node
|
70
|
+
end
|
71
|
+
|
72
|
+
def refresh
|
73
|
+
parent.refresh_child self
|
74
|
+
end
|
75
|
+
|
76
|
+
def refresh_child node
|
77
|
+
raise "#{self.class} must implement refresh_child"
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def dp message
|
83
|
+
if debug?
|
84
|
+
puts "#{indent}#{message}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def indent
|
89
|
+
' ' * depth
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Wongi
|
2
|
+
module Engine
|
3
|
+
|
4
|
+
class FilterNode < BetaNode
|
5
|
+
|
6
|
+
attr_accessor :test
|
7
|
+
|
8
|
+
def initialize parent, test
|
9
|
+
super parent
|
10
|
+
self.test = test
|
11
|
+
end
|
12
|
+
|
13
|
+
def beta_activate token
|
14
|
+
if test.passes? token
|
15
|
+
children.each do |child|
|
16
|
+
child.beta_activate Token.new( child, token, nil, {} )
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def beta_deactivate token
|
22
|
+
children.each do |child|
|
23
|
+
child.tokens.each do |t|
|
24
|
+
if t.parent == token
|
25
|
+
child.beta_deactivate t
|
26
|
+
#token.destroy
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def equivalent? test
|
33
|
+
test == self.test
|
34
|
+
end
|
35
|
+
|
36
|
+
def refresh_child child
|
37
|
+
tmp = children
|
38
|
+
self.children = [ child ]
|
39
|
+
parent.tokens.each do |token|
|
40
|
+
beta_activate token
|
41
|
+
end
|
42
|
+
self.children = tmp
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Wongi
|
2
|
+
module Engine
|
3
|
+
|
4
|
+
TokenAssignment = Struct.new(:wme, :field) do
|
5
|
+
def call token = nil
|
6
|
+
wme.send field
|
7
|
+
end
|
8
|
+
def inspect
|
9
|
+
"#{field} of #{wme}"
|
10
|
+
end
|
11
|
+
def to_s
|
12
|
+
inspect
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class BetaTest
|
17
|
+
|
18
|
+
attr_reader :field
|
19
|
+
attr_reader :variable
|
20
|
+
|
21
|
+
def initialize field, variable
|
22
|
+
@field, @variable = field, variable
|
23
|
+
end
|
24
|
+
|
25
|
+
def matches? token, wme
|
26
|
+
assignment = token[ self.variable ]
|
27
|
+
field = wme.send( self.field )
|
28
|
+
#field.nil? ||
|
29
|
+
assignment && field == assignment
|
30
|
+
end
|
31
|
+
|
32
|
+
def equivalent? other
|
33
|
+
other.field == self.field && other.variable == self.variable
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class JoinNode < BetaNode
|
39
|
+
|
40
|
+
attr_accessor :alpha
|
41
|
+
attr_reader :tests
|
42
|
+
attr_reader :assignment_pattern
|
43
|
+
|
44
|
+
def initialize parent, tests, assignment
|
45
|
+
super(parent)
|
46
|
+
@tests = tests
|
47
|
+
@assignment_pattern = assignment
|
48
|
+
end
|
49
|
+
|
50
|
+
def equivalent? alpha, tests, assignment_pattern
|
51
|
+
return false unless self.alpha == alpha
|
52
|
+
return false unless self.assignment_pattern == assignment_pattern
|
53
|
+
return false unless (self.tests.empty? && tests.empty?) || self.tests.length == tests.length && self.tests.all? { |my_test|
|
54
|
+
tests.any? { |new_test|
|
55
|
+
my_test.equivalent? new_test
|
56
|
+
}
|
57
|
+
}
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def alpha_activate wme
|
62
|
+
assignments = collect_assignments( wme )
|
63
|
+
parent.tokens.each do |token|
|
64
|
+
if matches?( token, wme )
|
65
|
+
children.each do |beta|
|
66
|
+
beta.beta_activate Token.new( beta, token, wme, assignments )
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def alpha_deactivate wme
|
73
|
+
children.each do |child|
|
74
|
+
child.tokens.each do |token|
|
75
|
+
if token.wme == wme
|
76
|
+
child.beta_deactivate token
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def beta_activate token
|
83
|
+
self.alpha.wmes.each do |wme|
|
84
|
+
if matches?( token, wme )
|
85
|
+
assignments = collect_assignments( wme )
|
86
|
+
children.each do |beta|
|
87
|
+
beta.beta_activate Token.new( beta, token, wme, assignments )
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def beta_deactivate token
|
94
|
+
children.each do |child|
|
95
|
+
child.tokens.each do |t|
|
96
|
+
if t.parent == token
|
97
|
+
child.beta_deactivate t
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def refresh_child child
|
104
|
+
alpha.wmes.each do |wme|
|
105
|
+
assignments = collect_assignments( wme )
|
106
|
+
parent.tokens.each do |token|
|
107
|
+
if matches?( token, wme )
|
108
|
+
child.beta_activate Token.new( child, token, wme, assignments )
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
protected
|
115
|
+
|
116
|
+
def matches? token, wme
|
117
|
+
@tests.each do |test|
|
118
|
+
return false unless test.matches?( token, wme )
|
119
|
+
end
|
120
|
+
true
|
121
|
+
end
|
122
|
+
|
123
|
+
def collect_assignments wme
|
124
|
+
assignments = {}
|
125
|
+
return assignments if assignment_pattern.nil?
|
126
|
+
if assignment_pattern.subject != :_
|
127
|
+
assignments[ assignment_pattern.subject ] = TokenAssignment.new(wme, :subject)
|
128
|
+
end
|
129
|
+
if assignment_pattern.predicate != :_
|
130
|
+
assignments[ assignment_pattern.predicate ] = TokenAssignment.new(wme, :predicate)
|
131
|
+
end
|
132
|
+
if assignment_pattern.object != :_
|
133
|
+
assignments[ assignment_pattern.object ] = TokenAssignment.new(wme, :object)
|
134
|
+
end
|
135
|
+
assignments
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Wongi
|
2
|
+
module Engine
|
3
|
+
class NccNode < BetaNode
|
4
|
+
include TokenContainer
|
5
|
+
|
6
|
+
attr_accessor :partner
|
7
|
+
|
8
|
+
def initialize parent
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def beta_activate token
|
13
|
+
return if tokens.find { |t| t.parent == token }
|
14
|
+
t = Token.new self, token, nil, {}
|
15
|
+
t.overlay.add_token(t, self)
|
16
|
+
partner.tokens.each do |ncc_token|
|
17
|
+
next unless ncc_token.ancestors.find { |a| a.equal? token }
|
18
|
+
t.ncc_results << ncc_token
|
19
|
+
ncc_token.owner = t
|
20
|
+
end
|
21
|
+
if t.ncc_results.empty?
|
22
|
+
children.each do |child|
|
23
|
+
child.beta_activate Token.new( child, t, nil, { } )
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def beta_deactivate token
|
29
|
+
t = tokens.find { |tok| tok.parent == token }
|
30
|
+
return unless t
|
31
|
+
t.overlay.remove_token(t, self)
|
32
|
+
t.deleted!
|
33
|
+
partner.tokens.select { |ncc| ncc.owner == t }.each do |ncc_token|
|
34
|
+
ncc_token.owner = nil
|
35
|
+
t.ncc_results.delete ncc_token
|
36
|
+
end
|
37
|
+
children.each do |beta|
|
38
|
+
beta.tokens.select { |token| token.parent == t }.each do |token|
|
39
|
+
beta.beta_deactivate token
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def ncc_activate token
|
45
|
+
children.each do |child|
|
46
|
+
child.beta_activate Token.new( child, token, nil, { } )
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def ncc_deactivate token
|
51
|
+
children.each do |beta|
|
52
|
+
beta.tokens.select { |t| t.parent == token }.each do |t|
|
53
|
+
beta.beta_deactivate t
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def refresh_child child
|
59
|
+
tokens.each do |token|
|
60
|
+
if token.ncc_results.empty?
|
61
|
+
child.beta_activate Token.new( child, token, nil, { } )
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|