wongi-engine 0.0.16 → 0.0.17
Sign up to get free protection for your applications and to get access to all the features.
- 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
|