wongi-engine 0.0.16 → 0.0.17
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/README.md +23 -0
- data/lib/wongi-engine/alpha_memory.rb +1 -4
- data/lib/wongi-engine/beta/assignment_node.rb +2 -1
- data/lib/wongi-engine/beta/beta_memory.rb +7 -2
- data/lib/wongi-engine/beta/beta_node.rb +7 -2
- data/lib/wongi-engine/beta/join_node.rb +8 -2
- data/lib/wongi-engine/beta/ncc_node.rb +1 -0
- data/lib/wongi-engine/beta/neg_node.rb +92 -92
- data/lib/wongi-engine/beta/or_node.rb +3 -1
- data/lib/wongi-engine/dsl.rb +4 -1
- data/lib/wongi-engine/dsl/actions/statement_generator.rb +55 -55
- data/lib/wongi-engine/dsl/assuming.rb +37 -0
- data/lib/wongi-engine/dsl/generic_production_rule.rb +4 -4
- data/lib/wongi-engine/filter/filter_test.rb +1 -0
- data/lib/wongi-engine/network.rb +443 -442
- data/lib/wongi-engine/template.rb +3 -0
- data/lib/wongi-engine/token.rb +132 -138
- data/lib/wongi-engine/version.rb +1 -1
- data/lib/wongi-engine/wme.rb +138 -138
- data/spec/beta_node_spec.rb +27 -0
- data/spec/dataset_spec.rb +1 -0
- data/spec/rule_specs/assuming_spec.rb +66 -0
- data/spec/rule_specs/ncc_spec.rb +33 -0
- data/spec/rule_specs/negative_rule_spec.rb +105 -70
- data/spec/wme_spec.rb +0 -0
- data/wongi-engine.gemspec +0 -0
- metadata +7 -2
@@ -73,6 +73,7 @@ module Wongi::Engine
|
|
73
73
|
tests, assignment = *JoinNode.compile( self, context.earlier, context.parameters )
|
74
74
|
alpha = context.rete.compile_alpha( self )
|
75
75
|
context.node = context.node.beta_memory.join_node( alpha, tests, assignment, @filters, context.alpha_deaf )
|
76
|
+
context.node.context = context
|
76
77
|
context.node.debug = debug?
|
77
78
|
context.earlier << self
|
78
79
|
context
|
@@ -104,6 +105,7 @@ module Wongi::Engine
|
|
104
105
|
raise DefinitionError.new("Negative matches may not introduce new variables: #{assignment.variables}") unless assignment.root?
|
105
106
|
alpha = context.rete.compile_alpha( self )
|
106
107
|
context.node = context.node.neg_node( alpha, tests, context.alpha_deaf, unsafe )
|
108
|
+
context.node.context = context
|
107
109
|
context.node.debug = debug?
|
108
110
|
context.earlier << self
|
109
111
|
context
|
@@ -118,6 +120,7 @@ module Wongi::Engine
|
|
118
120
|
tests, assignment = *JoinNode.compile( self, context.earlier, context.parameters )
|
119
121
|
alpha = context.rete.compile_alpha( self )
|
120
122
|
context.node = context.node.beta_memory.optional_node( alpha, tests, assignment, context.alpha_deaf )
|
123
|
+
context.node.context = context
|
121
124
|
context.node.debug = debug?
|
122
125
|
context.earlier << self
|
123
126
|
context
|
data/lib/wongi-engine/token.rb
CHANGED
@@ -1,138 +1,132 @@
|
|
1
|
-
module Wongi::Engine
|
2
|
-
|
3
|
-
class Token
|
4
|
-
|
5
|
-
include CoreExt
|
6
|
-
|
7
|
-
attr_reader :
|
8
|
-
attr_accessor :node, :owner, :parent
|
9
|
-
attr_reader :neg_join_results
|
10
|
-
attr_reader :opt_join_results
|
11
|
-
attr_reader :ncc_results
|
12
|
-
attr_reader :generated_wmes
|
13
|
-
attr_predicate :has_optional
|
14
|
-
|
15
|
-
def initialize token, wme, assignments
|
16
|
-
@parent, @wme, @assignments = token, wme, assignments
|
17
|
-
@children = []
|
18
|
-
@deleted = false
|
19
|
-
@neg_join_results = []
|
20
|
-
@opt_join_results = []
|
21
|
-
@ncc_results = []
|
22
|
-
@generated_wmes = []
|
23
|
-
token.children << self if token
|
24
|
-
wme.tokens << self if wme
|
25
|
-
end
|
26
|
-
|
27
|
-
def ancestors
|
28
|
-
if parent
|
29
|
-
parent.ancestors.unshift parent
|
30
|
-
else
|
31
|
-
[]
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def subst variable, value
|
36
|
-
@cached_assignments = nil
|
37
|
-
if @assignments.has_key? variable
|
38
|
-
@assignments[ variable ] = value
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def assignments
|
43
|
-
@cached_assignments ||= all_assignments
|
44
|
-
end
|
45
|
-
|
46
|
-
def [] var
|
47
|
-
assignments[ var ]
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
str
|
58
|
-
str
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
@
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
@ncc_results = []
|
134
|
-
@generated_wmes = []
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class Token
|
4
|
+
|
5
|
+
include CoreExt
|
6
|
+
|
7
|
+
attr_reader :children
|
8
|
+
attr_accessor :node, :owner, :parent
|
9
|
+
attr_reader :neg_join_results
|
10
|
+
attr_reader :opt_join_results
|
11
|
+
attr_reader :ncc_results
|
12
|
+
attr_reader :generated_wmes
|
13
|
+
attr_predicate :has_optional
|
14
|
+
|
15
|
+
def initialize token, wme, assignments
|
16
|
+
@parent, @wme, @assignments = token, wme, assignments
|
17
|
+
@children = []
|
18
|
+
@deleted = false
|
19
|
+
@neg_join_results = []
|
20
|
+
@opt_join_results = []
|
21
|
+
@ncc_results = []
|
22
|
+
@generated_wmes = []
|
23
|
+
token.children << self if token
|
24
|
+
wme.tokens << self if wme
|
25
|
+
end
|
26
|
+
|
27
|
+
def ancestors
|
28
|
+
if parent
|
29
|
+
parent.ancestors.unshift parent
|
30
|
+
else
|
31
|
+
[]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def subst variable, value
|
36
|
+
@cached_assignments = nil
|
37
|
+
if @assignments.has_key? variable
|
38
|
+
@assignments[ variable ] = value.respond_to?(:call) ? value : Proc.new { value }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def assignments
|
43
|
+
@cached_assignments ||= all_assignments
|
44
|
+
end
|
45
|
+
|
46
|
+
def [] var
|
47
|
+
if a = assignments[ var ]
|
48
|
+
a.call( self )
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def duplicate? parent, wme, assignments
|
53
|
+
self.parent.equal?(parent) && @wme.equal?(wme) && self.assignments == assignments
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
str = "TOKEN [ parent=#{parent ? parent.object_id : 'nil'} "
|
58
|
+
all_assignments.each_pair { |key, value| str << "#{key} => #{value} " }
|
59
|
+
str << "]"
|
60
|
+
str
|
61
|
+
end
|
62
|
+
|
63
|
+
def destroy
|
64
|
+
delete_children
|
65
|
+
#@node.tokens.delete self unless @node.kind_of?( NccPartner )
|
66
|
+
@wme.tokens.delete self if @wme
|
67
|
+
@parent.children.delete self if @parent
|
68
|
+
|
69
|
+
retract_generated
|
70
|
+
@deleted = true
|
71
|
+
@node.delete_token self
|
72
|
+
end
|
73
|
+
|
74
|
+
def deleted?
|
75
|
+
@deleted
|
76
|
+
end
|
77
|
+
|
78
|
+
def delete_children
|
79
|
+
children = @children
|
80
|
+
@children = []
|
81
|
+
children.each do |token|
|
82
|
+
token.parent = nil
|
83
|
+
token.destroy
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def generated? wme
|
88
|
+
return true if generated_wmes.any? { |w| w == wme }
|
89
|
+
return children.any? { |t| t.generated? wme }
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
def retract_generated
|
95
|
+
for_retraction = []
|
96
|
+
|
97
|
+
@generated_wmes.dup.each do |wme|
|
98
|
+
unless wme.manual? # => TODO: does this ever fail at all?
|
99
|
+
wme.generating_tokens.delete self
|
100
|
+
if wme.generating_tokens.empty?
|
101
|
+
for_retraction << wme
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@generated_wmes = []
|
106
|
+
for_retraction.each { |wme| wme.rete.retract wme, true }
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
def all_assignments
|
111
|
+
raise "Assignments is not a hash" unless @assignments.kind_of?( Hash )
|
112
|
+
if @parent
|
113
|
+
@parent.assignments.merge @assignments
|
114
|
+
else
|
115
|
+
@assignments
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
class FakeToken < Token
|
122
|
+
def initialize token, wme, assignments
|
123
|
+
@parent, @wme, @assignments = token, wme, assignments
|
124
|
+
@children = []
|
125
|
+
@neg_join_results = []
|
126
|
+
@opt_join_results = []
|
127
|
+
@ncc_results = []
|
128
|
+
@generated_wmes = []
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
data/lib/wongi-engine/version.rb
CHANGED
data/lib/wongi-engine/wme.rb
CHANGED
@@ -1,138 +1,138 @@
|
|
1
|
-
module Wongi::Engine
|
2
|
-
|
3
|
-
class WME < Struct.new( :subject, :predicate, :object )
|
4
|
-
|
5
|
-
attr_reader :rete
|
6
|
-
|
7
|
-
attr_reader :alphas, :tokens, :generating_tokens
|
8
|
-
attr_reader :neg_join_results, :opt_join_results
|
9
|
-
|
10
|
-
def initialize s, p, o, r = nil
|
11
|
-
|
12
|
-
@deleted = false
|
13
|
-
@alphas = []
|
14
|
-
@tokens = []
|
15
|
-
@generating_tokens = []
|
16
|
-
@neg_join_results = []
|
17
|
-
@opt_join_results = []
|
18
|
-
|
19
|
-
@rete = r
|
20
|
-
|
21
|
-
if r
|
22
|
-
super( r.import(s), r.import(p), r.import(o) )
|
23
|
-
else
|
24
|
-
super( s, p, o )
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def import_into r
|
30
|
-
self.class.new subject, predicate, object, r
|
31
|
-
end
|
32
|
-
|
33
|
-
def dup
|
34
|
-
self.class.new subject, predicate, object, rete
|
35
|
-
end
|
36
|
-
|
37
|
-
def == other
|
38
|
-
subject == other.subject && predicate == other.predicate && object == other.object
|
39
|
-
end
|
40
|
-
|
41
|
-
def =~ template
|
42
|
-
raise "Cannot match a WME against a #{template.class}" unless Template === template
|
43
|
-
result = match_member( self.subject, template.subject ) & match_member( self.predicate, template.predicate ) & match_member( self.object, template.object )
|
44
|
-
if result.match?
|
45
|
-
result
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def manual?
|
50
|
-
generating_tokens.empty?
|
51
|
-
end
|
52
|
-
|
53
|
-
def generated?
|
54
|
-
!manual?
|
55
|
-
end
|
56
|
-
|
57
|
-
def deleted?
|
58
|
-
@deleted
|
59
|
-
end
|
60
|
-
|
61
|
-
def destroy
|
62
|
-
return if deleted?
|
63
|
-
@deleted = true
|
64
|
-
alphas.each { |alpha| alpha.remove self }.clear
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
destroy_neg_join_results
|
70
|
-
destroy_opt_join_results
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
def inspect
|
75
|
-
"<WME #{subject.inspect} #{predicate.inspect} #{object.inspect}>"
|
76
|
-
end
|
77
|
-
|
78
|
-
def to_s
|
79
|
-
inspect
|
80
|
-
end
|
81
|
-
|
82
|
-
def hash
|
83
|
-
@hash ||= array_form.map( &:hash ).hash
|
84
|
-
end
|
85
|
-
|
86
|
-
protected
|
87
|
-
|
88
|
-
def array_form
|
89
|
-
@array_form ||= [ subject, predicate, object ]
|
90
|
-
end
|
91
|
-
|
92
|
-
def destroy_neg_join_results
|
93
|
-
neg_join_results.each do |njr|
|
94
|
-
|
95
|
-
token = njr.owner
|
96
|
-
results = token.neg_join_results
|
97
|
-
results.delete njr
|
98
|
-
|
99
|
-
if results.empty? #&& !rete.in_snapshot?
|
100
|
-
token.node.children.each { |beta|
|
101
|
-
beta.beta_activate token, nil, { }
|
102
|
-
}
|
103
|
-
end
|
104
|
-
|
105
|
-
end.clear
|
106
|
-
end
|
107
|
-
|
108
|
-
def destroy_opt_join_results
|
109
|
-
opt_join_results.each do |ojr|
|
110
|
-
|
111
|
-
token = ojr.owner
|
112
|
-
results = token.opt_join_results
|
113
|
-
results.delete ojr
|
114
|
-
|
115
|
-
if results.empty?
|
116
|
-
token.delete_children
|
117
|
-
token.node.children.each { |beta|
|
118
|
-
beta.beta_activate token
|
119
|
-
}
|
120
|
-
end
|
121
|
-
|
122
|
-
end.clear
|
123
|
-
end
|
124
|
-
|
125
|
-
def match_member mine, theirs
|
126
|
-
result = WMEMatchData.new
|
127
|
-
if theirs == :_ || mine == theirs
|
128
|
-
result.match!
|
129
|
-
elsif Template.variable? theirs
|
130
|
-
result.match!
|
131
|
-
result[theirs] = mine
|
132
|
-
end
|
133
|
-
result
|
134
|
-
end
|
135
|
-
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class WME < Struct.new( :subject, :predicate, :object )
|
4
|
+
|
5
|
+
attr_reader :rete
|
6
|
+
|
7
|
+
attr_reader :alphas, :tokens, :generating_tokens
|
8
|
+
attr_reader :neg_join_results, :opt_join_results
|
9
|
+
|
10
|
+
def initialize s, p, o, r = nil
|
11
|
+
|
12
|
+
@deleted = false
|
13
|
+
@alphas = []
|
14
|
+
@tokens = []
|
15
|
+
@generating_tokens = []
|
16
|
+
@neg_join_results = []
|
17
|
+
@opt_join_results = []
|
18
|
+
|
19
|
+
@rete = r
|
20
|
+
|
21
|
+
if r
|
22
|
+
super( r.import(s), r.import(p), r.import(o) )
|
23
|
+
else
|
24
|
+
super( s, p, o )
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def import_into r
|
30
|
+
self.class.new subject, predicate, object, r
|
31
|
+
end
|
32
|
+
|
33
|
+
def dup
|
34
|
+
self.class.new subject, predicate, object, rete
|
35
|
+
end
|
36
|
+
|
37
|
+
def == other
|
38
|
+
subject == other.subject && predicate == other.predicate && object == other.object
|
39
|
+
end
|
40
|
+
|
41
|
+
def =~ template
|
42
|
+
raise "Cannot match a WME against a #{template.class}" unless Template === template
|
43
|
+
result = match_member( self.subject, template.subject ) & match_member( self.predicate, template.predicate ) & match_member( self.object, template.object )
|
44
|
+
if result.match?
|
45
|
+
result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def manual?
|
50
|
+
generating_tokens.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
def generated?
|
54
|
+
!manual?
|
55
|
+
end
|
56
|
+
|
57
|
+
def deleted?
|
58
|
+
@deleted
|
59
|
+
end
|
60
|
+
|
61
|
+
def destroy
|
62
|
+
return if deleted?
|
63
|
+
@deleted = true
|
64
|
+
alphas.each { |alpha| alpha.remove self }.clear
|
65
|
+
tokens = @tokens
|
66
|
+
@tokens = []
|
67
|
+
tokens.each &:destroy
|
68
|
+
|
69
|
+
destroy_neg_join_results
|
70
|
+
destroy_opt_join_results
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
def inspect
|
75
|
+
"<WME #{subject.inspect} #{predicate.inspect} #{object.inspect}>"
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_s
|
79
|
+
inspect
|
80
|
+
end
|
81
|
+
|
82
|
+
def hash
|
83
|
+
@hash ||= array_form.map( &:hash ).hash
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def array_form
|
89
|
+
@array_form ||= [ subject, predicate, object ]
|
90
|
+
end
|
91
|
+
|
92
|
+
def destroy_neg_join_results
|
93
|
+
neg_join_results.each do |njr|
|
94
|
+
|
95
|
+
token = njr.owner
|
96
|
+
results = token.neg_join_results
|
97
|
+
results.delete njr
|
98
|
+
|
99
|
+
if results.empty? #&& !rete.in_snapshot?
|
100
|
+
token.node.children.each { |beta|
|
101
|
+
beta.beta_activate token, nil, { }
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
end.clear
|
106
|
+
end
|
107
|
+
|
108
|
+
def destroy_opt_join_results
|
109
|
+
opt_join_results.each do |ojr|
|
110
|
+
|
111
|
+
token = ojr.owner
|
112
|
+
results = token.opt_join_results
|
113
|
+
results.delete ojr
|
114
|
+
|
115
|
+
if results.empty?
|
116
|
+
token.delete_children
|
117
|
+
token.node.children.each { |beta|
|
118
|
+
beta.beta_activate token
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
end.clear
|
123
|
+
end
|
124
|
+
|
125
|
+
def match_member mine, theirs
|
126
|
+
result = WMEMatchData.new
|
127
|
+
if theirs == :_ || mine == theirs
|
128
|
+
result.match!
|
129
|
+
elsif Template.variable? theirs
|
130
|
+
result.match!
|
131
|
+
result[theirs] = mine
|
132
|
+
end
|
133
|
+
result
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|