mort666-wongi-engine 0.2.9
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 +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,40 @@
|
|
1
|
+
module Wongi
|
2
|
+
module Engine
|
3
|
+
class NccPartner < BetaNode
|
4
|
+
include TokenContainer
|
5
|
+
|
6
|
+
attr_accessor :ncc
|
7
|
+
attr_accessor :divergent
|
8
|
+
|
9
|
+
def beta_activate token
|
10
|
+
t = Token.new self, token, nil, {}
|
11
|
+
owner = owner_for( t )
|
12
|
+
t.overlay.add_token(t, self)
|
13
|
+
if owner
|
14
|
+
owner.ncc_results << t
|
15
|
+
t.owner = owner
|
16
|
+
owner.node.ncc_deactivate owner
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def beta_deactivate t
|
21
|
+
token = tokens.find { |tok| tok.parent == t }
|
22
|
+
return unless token
|
23
|
+
token.overlay.remove_token(token, self)
|
24
|
+
if owner = token.owner
|
25
|
+
owner.ncc_results.delete token
|
26
|
+
if owner.ncc_results.empty?
|
27
|
+
ncc.ncc_activate owner
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def owner_for token
|
35
|
+
divergent_token = token.ancestors.find { |t| t.node == divergent }
|
36
|
+
ncc.tokens.find { |t| t.ancestors.include? divergent_token }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Wongi
|
2
|
+
module Engine
|
3
|
+
|
4
|
+
NegJoinResult = Struct.new :token, :wme do
|
5
|
+
def unlink
|
6
|
+
wme.neg_join_results.delete self
|
7
|
+
token.neg_join_results.delete self
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class NegNode < BetaNode
|
12
|
+
include TokenContainer
|
13
|
+
|
14
|
+
attr_reader :alpha, :tests
|
15
|
+
|
16
|
+
def initialize parent, tests, alpha, unsafe
|
17
|
+
super(parent)
|
18
|
+
@tests, @alpha, @unsafe = tests, alpha, unsafe
|
19
|
+
end
|
20
|
+
|
21
|
+
def alpha_activate wme
|
22
|
+
tokens.each do |token|
|
23
|
+
if matches?( token, wme ) && ( @unsafe || ! token.generated?( wme ) )# feedback loop protection
|
24
|
+
# order matters for proper invalidation
|
25
|
+
make_join_result(token, wme)
|
26
|
+
#token.delete_children #if token.neg_join_results.empty? # TODO why was this check here? it seems to break things
|
27
|
+
children.each do |child|
|
28
|
+
child.tokens.each do |t|
|
29
|
+
if t.parent == token
|
30
|
+
child.beta_deactivate t
|
31
|
+
#token.destroy
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def alpha_deactivate wme
|
40
|
+
wme.neg_join_results.dup.each do |njr|
|
41
|
+
tokens.each do |token|
|
42
|
+
next unless token == njr.token
|
43
|
+
njr.unlink
|
44
|
+
if token.neg_join_results.empty?
|
45
|
+
children.each do |child|
|
46
|
+
child.beta_activate Token.new( child, token, nil, {} )
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def beta_activate token
|
54
|
+
return if tokens.find { |et| et.duplicate? token }
|
55
|
+
token.overlay.add_token(token, self)
|
56
|
+
alpha.wmes.each do |wme|
|
57
|
+
if matches?( token, wme )
|
58
|
+
make_join_result(token, wme)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
if token.neg_join_results.empty?
|
62
|
+
children.each do |child|
|
63
|
+
child.beta_activate Token.new( child, token, nil, {} )
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def beta_deactivate token
|
69
|
+
return nil unless tokens.find token
|
70
|
+
token.overlay.remove_token(token, self)
|
71
|
+
token.deleted!
|
72
|
+
if token.parent
|
73
|
+
token.parent.children.delete token # should this go into Token#destroy?
|
74
|
+
end
|
75
|
+
token.neg_join_results.each &:unlink
|
76
|
+
children.each do |child|
|
77
|
+
child.tokens.each do |t|
|
78
|
+
if t.parent == token
|
79
|
+
child.beta_deactivate t
|
80
|
+
#token.destroy
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
token
|
85
|
+
end
|
86
|
+
|
87
|
+
def refresh_child child
|
88
|
+
tokens.each do |token|
|
89
|
+
if token.neg_join_results.empty?
|
90
|
+
child.beta_activate Token.new( child, token, nil, {} )
|
91
|
+
end
|
92
|
+
end
|
93
|
+
alpha.wmes.each do |wme|
|
94
|
+
alpha_activate wme
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
protected
|
99
|
+
|
100
|
+
def matches? token, wme
|
101
|
+
puts "matching #{wme} against #{token}" if debug?
|
102
|
+
@tests.each do |test|
|
103
|
+
return false unless test.matches?( token, wme )
|
104
|
+
end
|
105
|
+
true
|
106
|
+
end
|
107
|
+
|
108
|
+
def make_join_result token, wme
|
109
|
+
njr = NegJoinResult.new token, wme
|
110
|
+
token.neg_join_results << njr
|
111
|
+
wme.neg_join_results << njr
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Wongi
|
2
|
+
module Engine
|
3
|
+
|
4
|
+
OptionalJoinResult = Struct.new :token, :wme do
|
5
|
+
def unlink
|
6
|
+
wme.opt_join_results.delete self
|
7
|
+
token.opt_join_results.delete self
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class OptionalNode < BetaNode
|
12
|
+
include TokenContainer
|
13
|
+
|
14
|
+
attr_reader :alpha, :tests, :assignment_pattern
|
15
|
+
|
16
|
+
def initialize parent, alpha, tests, assignments
|
17
|
+
super( parent )
|
18
|
+
@alpha = alpha
|
19
|
+
@tests = tests
|
20
|
+
@assignment_pattern = assignments
|
21
|
+
end
|
22
|
+
|
23
|
+
def make_opt_result token, wme
|
24
|
+
jr = OptionalJoinResult.new token, wme
|
25
|
+
token.opt_join_results << jr
|
26
|
+
wme.opt_join_results << jr
|
27
|
+
end
|
28
|
+
|
29
|
+
def alpha_activate wme
|
30
|
+
assignments = collect_assignments( wme )
|
31
|
+
tokens.each do |token|
|
32
|
+
if matches? token, wme
|
33
|
+
children.each do |child|
|
34
|
+
if token.optional?
|
35
|
+
token.no_optional!
|
36
|
+
child.tokens.each do |ct|
|
37
|
+
child.beta_deactivate(ct) if ct.parent == token
|
38
|
+
end
|
39
|
+
end
|
40
|
+
child.beta_activate Token.new( child, token, wme, assignments )
|
41
|
+
end
|
42
|
+
make_opt_result token, wme
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def alpha_deactivate wme
|
48
|
+
wme.opt_join_results.dup.each do |ojr|
|
49
|
+
tokens.each do |token|
|
50
|
+
next unless token == ojr.token
|
51
|
+
ojr.unlink
|
52
|
+
if token.opt_join_results.empty?
|
53
|
+
children.each do |child|
|
54
|
+
child.tokens.each do |ct|
|
55
|
+
child.beta_deactivate(ct) if ct.parent == token
|
56
|
+
end
|
57
|
+
token.optional!
|
58
|
+
child.beta_activate Token.new( child, token, nil, { } )
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def beta_activate t
|
66
|
+
return if tokens.find { |token| token.parent == t }
|
67
|
+
token = Token.new( self, t, nil, { } )
|
68
|
+
token.overlay.add_token(token, self)
|
69
|
+
match = false
|
70
|
+
alpha.wmes.each do |wme|
|
71
|
+
assignments = collect_assignments(wme)
|
72
|
+
if matches? token, wme
|
73
|
+
match = true
|
74
|
+
children.each do |child|
|
75
|
+
child.beta_activate Token.new( child, token, wme, assignments )
|
76
|
+
end
|
77
|
+
make_opt_result token, wme
|
78
|
+
end
|
79
|
+
end
|
80
|
+
unless match
|
81
|
+
token.optional!
|
82
|
+
children.each do |child|
|
83
|
+
child.beta_activate Token.new( child, token, nil, { } )
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def beta_deactivate t
|
89
|
+
token = tokens.find { |token| token.parent == t }
|
90
|
+
return unless token
|
91
|
+
token.overlay.remove_token(token, self)
|
92
|
+
token.deleted!
|
93
|
+
if token.parent
|
94
|
+
token.parent.children.delete token
|
95
|
+
end
|
96
|
+
token.opt_join_results.each &:unlink
|
97
|
+
children.each do |child|
|
98
|
+
child.tokens.each do |t|
|
99
|
+
if t.parent == token
|
100
|
+
child.beta_deactivate t
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
token
|
105
|
+
end
|
106
|
+
|
107
|
+
def refresh_child child
|
108
|
+
tmp = children
|
109
|
+
self.children = [ child ]
|
110
|
+
refresh # do the beta part
|
111
|
+
alpha.wmes.each do |wme|
|
112
|
+
alpha_activate wme
|
113
|
+
end
|
114
|
+
self.children = tmp
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def matches? token, wme
|
120
|
+
@tests.each do |test|
|
121
|
+
return false unless test.matches?( token, wme )
|
122
|
+
end
|
123
|
+
true
|
124
|
+
end
|
125
|
+
|
126
|
+
def collect_assignments wme
|
127
|
+
assignments = {}
|
128
|
+
return assignments if assignment_pattern.nil?
|
129
|
+
if assignment_pattern.subject != :_
|
130
|
+
assignments[ assignment_pattern.subject ] = TokenAssignment.new(wme, :subject)
|
131
|
+
end
|
132
|
+
if assignment_pattern.predicate != :_
|
133
|
+
assignments[ assignment_pattern.predicate ] = TokenAssignment.new(wme, :predicate)
|
134
|
+
end
|
135
|
+
if assignment_pattern.object != :_
|
136
|
+
assignments[ assignment_pattern.object ] = TokenAssignment.new(wme, :object)
|
137
|
+
end
|
138
|
+
assignments
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Wongi
|
2
|
+
module Engine
|
3
|
+
class OrNode < BetaMemory
|
4
|
+
|
5
|
+
attr_reader :parents
|
6
|
+
attr_reader :rete
|
7
|
+
|
8
|
+
def initialize parents
|
9
|
+
super nil
|
10
|
+
@parents = parents
|
11
|
+
parents.each do |parent|
|
12
|
+
parent.children << self
|
13
|
+
end
|
14
|
+
retes = parents.map( &:rete ).uniq
|
15
|
+
raise "Cannot combine variants from several Retes" if retes.size > 1
|
16
|
+
@rete = retes.first
|
17
|
+
end
|
18
|
+
|
19
|
+
def ident
|
20
|
+
ids = parents.map( &:id ).join ", "
|
21
|
+
"<R> #{self.class} #{id}, parents #{ids}"
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def depth
|
26
|
+
parents.map( &:depth ).max + 1
|
27
|
+
end
|
28
|
+
|
29
|
+
def refresh
|
30
|
+
parents.each do |parent|
|
31
|
+
parent.refresh_child self
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Wongi
|
2
|
+
module Engine
|
3
|
+
|
4
|
+
class ProductionNode < BetaMemory
|
5
|
+
|
6
|
+
attr_accessor :tracer
|
7
|
+
attr_accessor :compilation_context
|
8
|
+
|
9
|
+
def initialize parent, actions
|
10
|
+
super(parent)
|
11
|
+
@actions = actions.each { |action| action.production = self }
|
12
|
+
end
|
13
|
+
|
14
|
+
def beta_activate token
|
15
|
+
return unless super
|
16
|
+
@actions.each do |action|
|
17
|
+
action.execute token if action.respond_to? :execute
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def beta_deactivate token
|
22
|
+
return unless super
|
23
|
+
@actions.each do |action|
|
24
|
+
action.deexecute token if action.respond_to? :deexecute
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
Compiler = Struct.new(:rete, :node, :conditions, :parameters, :alpha_deaf) do
|
3
|
+
|
4
|
+
def compile
|
5
|
+
conditions.inject(self) do |context, condition|
|
6
|
+
condition.compile context
|
7
|
+
end.node
|
8
|
+
end
|
9
|
+
|
10
|
+
def declares_variable?(v)
|
11
|
+
parameters.include?(v) || declared_variables.include?(v)
|
12
|
+
end
|
13
|
+
|
14
|
+
def declare(v)
|
15
|
+
unless declared_variables.include?(v)
|
16
|
+
declared_variables << v
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def declared_variables
|
21
|
+
@declared_variables ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def dup
|
25
|
+
Compiler.new(rete, node, conditions, parameters, alpha_deaf).tap do |compiler|
|
26
|
+
declared_variables.each { |v| compiler.declare(v) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# TODO: should the following be the responsibility of Compiler or of each individual DSL clause?
|
31
|
+
|
32
|
+
def beta_memory
|
33
|
+
return if node.is_a?(BetaMemory)
|
34
|
+
self.node = if existing = node.children.find { |n| n.is_a?(BetaMemory) }
|
35
|
+
existing
|
36
|
+
else
|
37
|
+
BetaMemory.new(node).tap do |memory|
|
38
|
+
memory.refresh
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def assignment_node(variable, body)
|
44
|
+
beta_memory
|
45
|
+
self.node = AssignmentNode.new(self.node, variable, body).tap &:refresh
|
46
|
+
declare(variable)
|
47
|
+
end
|
48
|
+
|
49
|
+
def join_node(condition, tests, assignment)
|
50
|
+
alpha = rete.compile_alpha(condition)
|
51
|
+
beta_memory
|
52
|
+
self.node = if existing = node.children.find { |n| n.is_a?(JoinNode) && n.equivalent?(alpha, tests, assignment) }
|
53
|
+
existing
|
54
|
+
else
|
55
|
+
JoinNode.new(node, tests, assignment).tap do |join|
|
56
|
+
join.alpha = alpha
|
57
|
+
alpha.betas << join unless alpha_deaf
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def neg_node(condition, tests, unsafe)
|
63
|
+
alpha = rete.compile_alpha(condition)
|
64
|
+
self.node = NegNode.new(node, tests, alpha, unsafe).tap do |node|
|
65
|
+
alpha.betas << node unless alpha_deaf
|
66
|
+
node.refresh
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def opt_node(condition, tests, assignment)
|
71
|
+
alpha = rete.compile_alpha(condition)
|
72
|
+
beta_memory
|
73
|
+
self.node = OptionalNode.new(node, alpha, tests, assignment).tap do |node|
|
74
|
+
alpha.betas << node unless alpha_deaf
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def or_node(variants)
|
79
|
+
beta_memory
|
80
|
+
branches = variants.map do |variant|
|
81
|
+
subcompiler = Compiler.new(rete, node, variant.conditions, parameters, false)
|
82
|
+
declared_variables.each { |v| subcompiler.declare(v) }
|
83
|
+
subcompiler.compile
|
84
|
+
subcompiler.declared_variables.each { |v| declare(v) }
|
85
|
+
subcompiler.node
|
86
|
+
end
|
87
|
+
self.node = OrNode.new(branches).tap &:refresh
|
88
|
+
end
|
89
|
+
|
90
|
+
def ncc_node(subrule, alpha_deaf)
|
91
|
+
beta_memory
|
92
|
+
subcompiler = Compiler.new(rete, node, subrule.conditions, parameters, alpha_deaf)
|
93
|
+
declared_variables.each { |v| subcompiler.declare(v) }
|
94
|
+
bottom = subcompiler.compile
|
95
|
+
if existing = node.children.find { |n| n.kind_of?( NccNode ) and n.partner.parent == bottom }
|
96
|
+
self.node = existing
|
97
|
+
return
|
98
|
+
end
|
99
|
+
ncc = NccNode.new node
|
100
|
+
partner = NccPartner.new subcompiler.tap(&:beta_memory).node
|
101
|
+
ncc.partner = partner
|
102
|
+
partner.ncc = ncc
|
103
|
+
partner.divergent = node
|
104
|
+
# partner.conjuncts = condition.children.size
|
105
|
+
ncc.refresh
|
106
|
+
partner.refresh
|
107
|
+
self.node = ncc
|
108
|
+
end
|
109
|
+
|
110
|
+
def filter_node(filter)
|
111
|
+
beta_memory
|
112
|
+
self.node = FilterNode.new(node, filter)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|