mini_kraken 0.2.04 → 0.3.00
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +16 -16
- data/lib/mini_kraken/atomic/all_atomic.rb +1 -0
- data/lib/mini_kraken/atomic/atomic_term.rb +32 -17
- data/lib/mini_kraken/atomic/k_integer.rb +0 -4
- data/lib/mini_kraken/atomic/k_string.rb +17 -0
- data/lib/mini_kraken/atomic/k_symbol.rb +0 -6
- data/lib/mini_kraken/composite/all_composite.rb +4 -0
- data/lib/mini_kraken/composite/composite_term.rb +2 -18
- data/lib/mini_kraken/composite/cons_cell.rb +178 -11
- data/lib/mini_kraken/composite/cons_cell_visitor.rb +12 -64
- data/lib/mini_kraken/composite/list.rb +32 -0
- data/lib/mini_kraken/core/all_core.rb +8 -0
- data/lib/mini_kraken/core/any_value.rb +31 -7
- data/lib/mini_kraken/core/arity.rb +69 -0
- data/lib/mini_kraken/core/association.rb +29 -4
- data/lib/mini_kraken/core/association_copy.rb +50 -0
- data/lib/mini_kraken/core/base_term.rb +13 -0
- data/lib/mini_kraken/core/blackboard.rb +315 -0
- data/lib/mini_kraken/core/bookmark.rb +46 -0
- data/lib/mini_kraken/core/context.rb +624 -0
- data/lib/mini_kraken/core/duck_fiber.rb +21 -19
- data/lib/mini_kraken/core/entry.rb +40 -0
- data/lib/mini_kraken/core/fail.rb +20 -18
- data/lib/mini_kraken/core/fusion.rb +29 -0
- data/lib/mini_kraken/core/goal.rb +20 -29
- data/lib/mini_kraken/core/log_var.rb +4 -30
- data/lib/mini_kraken/core/log_var_ref.rb +72 -48
- data/lib/mini_kraken/core/nullary_relation.rb +2 -9
- data/lib/mini_kraken/core/parametrized_term.rb +61 -0
- data/lib/mini_kraken/core/relation.rb +14 -28
- data/lib/mini_kraken/core/scope.rb +67 -0
- data/lib/mini_kraken/core/solver_adapter.rb +58 -0
- data/lib/mini_kraken/core/specification.rb +48 -0
- data/lib/mini_kraken/core/succeed.rb +21 -17
- data/lib/mini_kraken/core/symbol_table.rb +137 -0
- data/lib/mini_kraken/core/term.rb +15 -4
- data/lib/mini_kraken/glue/dsl.rb +35 -69
- data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
- data/lib/mini_kraken/rela/all_rela.rb +8 -0
- data/lib/mini_kraken/rela/binary_relation.rb +30 -0
- data/lib/mini_kraken/rela/conde.rb +146 -0
- data/lib/mini_kraken/rela/conj2.rb +65 -0
- data/lib/mini_kraken/rela/def_relation.rb +64 -0
- data/lib/mini_kraken/rela/disj2.rb +70 -0
- data/lib/mini_kraken/rela/fresh.rb +98 -0
- data/lib/mini_kraken/{core → rela}/goal_relation.rb +6 -8
- data/lib/mini_kraken/rela/unify.rb +258 -0
- data/lib/mini_kraken/version.rb +1 -1
- data/spec/atomic/atomic_term_spec.rb +23 -20
- data/spec/atomic/k_symbol_spec.rb +0 -5
- data/spec/composite/cons_cell_spec.rb +116 -0
- data/spec/composite/cons_cell_visitor_spec.rb +16 -3
- data/spec/composite/list_spec.rb +50 -0
- data/spec/core/any_value_spec.rb +52 -0
- data/spec/core/arity_spec.rb +91 -0
- data/spec/core/association_copy_spec.rb +69 -0
- data/spec/core/association_spec.rb +25 -0
- data/spec/core/blackboard_spec.rb +287 -0
- data/spec/core/bookmark_spec.rb +40 -0
- data/spec/core/context_spec.rb +221 -0
- data/spec/core/core_spec.rb +40 -0
- data/spec/core/duck_fiber_spec.rb +22 -46
- data/spec/core/fail_spec.rb +5 -6
- data/spec/core/goal_spec.rb +20 -11
- data/spec/core/log_var_ref_spec.rb +80 -5
- data/spec/core/log_var_spec.rb +35 -6
- data/spec/core/nullary_relation_spec.rb +33 -0
- data/spec/core/parametrized_tem_spec.rb +39 -0
- data/spec/core/relation_spec.rb +33 -0
- data/spec/core/scope_spec.rb +73 -0
- data/spec/core/solver_adapter_spec.rb +70 -0
- data/spec/core/specification_spec.rb +43 -0
- data/spec/core/succeed_spec.rb +5 -5
- data/spec/core/symbol_table_spec.rb +142 -0
- data/spec/glue/dsl_chap1_spec.rb +88 -99
- data/spec/glue/dsl_chap2_spec.rb +59 -41
- data/spec/glue/run_star_expression_spec.rb +69 -896
- data/spec/{core → rela}/conde_spec.rb +50 -46
- data/spec/rela/conj2_spec.rb +123 -0
- data/spec/rela/def_relation_spec.rb +119 -0
- data/spec/rela/disj2_spec.rb +117 -0
- data/spec/rela/fresh_spec.rb +147 -0
- data/spec/rela/unify_spec.rb +369 -0
- data/spec/support/factory_atomic.rb +7 -0
- data/spec/support/factory_composite.rb +21 -0
- metadata +71 -48
- data/lib/mini_kraken/core/association_walker.rb +0 -183
- data/lib/mini_kraken/core/base_arg.rb +0 -10
- data/lib/mini_kraken/core/binary_relation.rb +0 -63
- data/lib/mini_kraken/core/composite_goal.rb +0 -46
- data/lib/mini_kraken/core/conde.rb +0 -143
- data/lib/mini_kraken/core/conj2.rb +0 -79
- data/lib/mini_kraken/core/def_relation.rb +0 -53
- data/lib/mini_kraken/core/designation.rb +0 -55
- data/lib/mini_kraken/core/disj2.rb +0 -72
- data/lib/mini_kraken/core/environment.rb +0 -73
- data/lib/mini_kraken/core/equals.rb +0 -191
- data/lib/mini_kraken/core/formal_arg.rb +0 -22
- data/lib/mini_kraken/core/formal_ref.rb +0 -25
- data/lib/mini_kraken/core/freshness.rb +0 -45
- data/lib/mini_kraken/core/goal_arg.rb +0 -12
- data/lib/mini_kraken/core/goal_template.rb +0 -102
- data/lib/mini_kraken/core/outcome.rb +0 -63
- data/lib/mini_kraken/core/tap.rb +0 -46
- data/lib/mini_kraken/core/vocabulary.rb +0 -446
- data/lib/mini_kraken/glue/fresh_env.rb +0 -108
- data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
- data/spec/core/association_walker_spec.rb +0 -194
- data/spec/core/conj2_spec.rb +0 -116
- data/spec/core/def_relation_spec.rb +0 -99
- data/spec/core/disj2_spec.rb +0 -100
- data/spec/core/environment_spec.rb +0 -144
- data/spec/core/equals_spec.rb +0 -319
- data/spec/core/goal_template_spec.rb +0 -74
- data/spec/core/outcome_spec.rb +0 -56
- data/spec/core/vocabulary_spec.rb +0 -220
- data/spec/glue/fresh_env_factory_spec.rb +0 -99
- data/spec/glue/fresh_env_spec.rb +0 -62
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../support/factory_atomic'
|
5
|
+
require_relative '../../lib/mini_kraken/core/context'
|
6
|
+
require_relative '../../lib/mini_kraken/core/log_var'
|
7
|
+
require_relative '../../lib/mini_kraken/core/log_var_ref'
|
8
|
+
|
9
|
+
# Load the class under test
|
10
|
+
require_relative '../../lib/mini_kraken/core/association_copy'
|
11
|
+
|
12
|
+
module MiniKraken
|
13
|
+
module Core
|
14
|
+
describe AssociationCopy do
|
15
|
+
include MiniKraken::FactoryAtomic # Use mix-in module
|
16
|
+
|
17
|
+
let(:pea) { k_symbol(:pea) }
|
18
|
+
let(:q_assoc) { Association.new('q', pea) }
|
19
|
+
subject { AssociationCopy.new('q_x', q_assoc) }
|
20
|
+
|
21
|
+
context 'Initialization:' do
|
22
|
+
it 'should be initialized with a name and an association' do
|
23
|
+
expect { AssociationCopy.new('q_x', q_assoc) }.not_to raise_error
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should be initialized with a variable and an association' do
|
27
|
+
q_x_var = LogVar.new('q_x')
|
28
|
+
expect { AssociationCopy.new(q_x_var, q_assoc) }.not_to raise_error
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should know the internal variable name' do
|
32
|
+
expect(subject.i_name).to eq('q_x')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should know the associated value' do
|
36
|
+
expect(subject.value).to eq(pea)
|
37
|
+
end
|
38
|
+
end # context
|
39
|
+
|
40
|
+
context 'Provided services:' do
|
41
|
+
let(:ctx) { Context.new }
|
42
|
+
|
43
|
+
it 'should tell whether the associated value is pinned' do
|
44
|
+
ctx.add_vars(%w[q x q_x])
|
45
|
+
expect(subject).to be_pinned(ctx)
|
46
|
+
|
47
|
+
a = Association.new(ctx.lookup('q'), LogVarRef.new('x'))
|
48
|
+
instance = AssociationCopy.new(ctx.lookup('q_x'), a)
|
49
|
+
expect(instance).not_to be_pinned(ctx)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should tell whether the associated value is floating' do
|
53
|
+
ctx.add_vars(%w[q x q_x])
|
54
|
+
|
55
|
+
expect(subject).not_to be_floating(ctx)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should retrieve the dependencies in its value' do
|
59
|
+
expect(subject.dependencies(ctx)).to be_empty
|
60
|
+
|
61
|
+
ctx.add_vars(%w[q x q_x])
|
62
|
+
a = Association.new(ctx.lookup('q'), LogVarRef.new('x'))
|
63
|
+
instance = AssociationCopy.new(ctx.lookup('q_x'), a)
|
64
|
+
expect(instance.dependencies(ctx).size).to eq(1)
|
65
|
+
end
|
66
|
+
end # context
|
67
|
+
end # describe
|
68
|
+
end # module
|
69
|
+
end # module
|
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
require_relative '../spec_helper' # Use the RSpec framework
|
4
4
|
require_relative '../support/factory_atomic'
|
5
|
+
require_relative '../../lib/mini_kraken/core/context'
|
5
6
|
require_relative '../../lib/mini_kraken/core/log_var'
|
7
|
+
require_relative '../../lib/mini_kraken/core/log_var_ref'
|
6
8
|
|
7
9
|
# Load the class under test
|
8
10
|
require_relative '../../lib/mini_kraken/core/association'
|
@@ -34,6 +36,29 @@ module MiniKraken
|
|
34
36
|
end # context
|
35
37
|
|
36
38
|
context 'Provided services:' do
|
39
|
+
let(:ctx) { Context.new }
|
40
|
+
|
41
|
+
it 'should tell whether the associated value is pinned' do
|
42
|
+
ctx.add_vars(%w[q x])
|
43
|
+
|
44
|
+
expect(subject).to be_pinned(ctx)
|
45
|
+
instance = Association.new(ctx.lookup('q'), LogVarRef.new('x'))
|
46
|
+
expect(instance).not_to be_pinned(ctx)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should tell whether the associated value is floating' do
|
50
|
+
ctx.add_vars(%w[q x])
|
51
|
+
|
52
|
+
expect(subject).not_to be_floating(ctx)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should retrieve the dependencies in its value' do
|
56
|
+
expect(subject.dependencies(ctx)).to be_empty
|
57
|
+
|
58
|
+
ctx.add_vars(%w[q x])
|
59
|
+
instance = Association.new(ctx.lookup('q'), LogVarRef.new('x'))
|
60
|
+
expect(instance.dependencies(ctx).size).to eq(1)
|
61
|
+
end
|
37
62
|
end # context
|
38
63
|
end # describe
|
39
64
|
end # module
|
@@ -0,0 +1,287 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../support/factory_atomic'
|
5
|
+
require_relative '../../lib/mini_kraken/core/log_var_ref'
|
6
|
+
require_relative '../../lib/mini_kraken/core/scope'
|
7
|
+
require_relative '../../lib/mini_kraken/composite/cons_cell'
|
8
|
+
|
9
|
+
# Load the class under test
|
10
|
+
require_relative '../../lib/mini_kraken/core/blackboard'
|
11
|
+
|
12
|
+
module MiniKraken
|
13
|
+
module Core
|
14
|
+
describe Blackboard do
|
15
|
+
include MiniKraken::FactoryAtomic # Use mix-in module
|
16
|
+
subject { Blackboard.new }
|
17
|
+
|
18
|
+
context 'Initialization:' do
|
19
|
+
it 'should be initialized without argument' do
|
20
|
+
expect { Blackboard.new }.not_to raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it "shouldn't have internal name entry at initialization" do
|
24
|
+
expect(subject.i_name2moves).to be_empty
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should have an empty association queue at initialization' do
|
28
|
+
expect(subject.move_queue).to be_empty
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should be empty at initialization' do
|
32
|
+
expect(subject).to be_empty
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should be ready to assign a serial number' do
|
36
|
+
expect(subject.next_serial_num).to be_zero
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should have its resultant attribute un-initialized' do
|
40
|
+
expect(subject.resultant).to be_nil
|
41
|
+
end
|
42
|
+
end # context
|
43
|
+
|
44
|
+
context 'Provided services:' do
|
45
|
+
let(:a_ser_num) { 42 }
|
46
|
+
let(:pea) { k_symbol(:pea) }
|
47
|
+
let(:pod) { k_symbol(:pod) }
|
48
|
+
let(:x_assoc) { Core::Association.new('x', pea) }
|
49
|
+
let(:y_assoc) { Core::Association.new('y', pod) }
|
50
|
+
let(:z_assoc) { Core::Association.new('z', pea) }
|
51
|
+
|
52
|
+
def var_ref(aName)
|
53
|
+
LogVarRef.new(aName)
|
54
|
+
end
|
55
|
+
|
56
|
+
def cons(car, cdr = nil)
|
57
|
+
Composite::ConsCell.new(car, cdr)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should allow the enqueuing of one association' do
|
61
|
+
expect { subject.enqueue_association(x_assoc) }.not_to raise_error
|
62
|
+
expect(subject.i_name2moves).not_to be_empty
|
63
|
+
expect(subject.move_queue).not_to be_empty
|
64
|
+
expect(subject.i_name2moves['x']).to be_kind_of(Array)
|
65
|
+
expect(subject.i_name2moves['x'].first).to eq(0)
|
66
|
+
expect(subject.last_move).to eq(x_assoc)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should allow the enqueuing of multiple associations' do
|
70
|
+
expect(subject.enqueue_association(x_assoc)).to eq(x_assoc)
|
71
|
+
expect { subject.enqueue_association(y_assoc) }.not_to raise_error
|
72
|
+
expect(subject.i_name2moves.size).to eq(2)
|
73
|
+
expect(subject.move_queue.size).to eq(2)
|
74
|
+
expect(subject.i_name2moves['y']).to be_kind_of(Array)
|
75
|
+
expect(subject.i_name2moves['y'].first).to eq(1)
|
76
|
+
expect(subject.last_move).to eq(y_assoc)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should allow the enqueuing of multiple associations for same i_name' do
|
80
|
+
subject.enqueue_association(x_assoc)
|
81
|
+
|
82
|
+
x_assoc_b = Core::Association.new('x', double('something'))
|
83
|
+
expect { subject.enqueue_association(x_assoc_b) }.not_to raise_error
|
84
|
+
expect(subject.i_name2moves.size).to eq(1)
|
85
|
+
expect(subject.move_queue.size).to eq(2)
|
86
|
+
expect(subject.i_name2moves['x']).to be_kind_of(Array)
|
87
|
+
expect(subject.i_name2moves['x'].size).to eq(2)
|
88
|
+
expect(subject.i_name2moves['x'].last).to eq(1)
|
89
|
+
expect(subject.move_queue.pop).to eq(x_assoc_b)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should allow the removal of the association at TOS position' do
|
93
|
+
subject.enqueue_association(x_assoc)
|
94
|
+
x_assoc_b = Core::Association.new('x', double('something'))
|
95
|
+
subject.enqueue_association(x_assoc_b)
|
96
|
+
expect(subject.move_queue.size).to eq(2)
|
97
|
+
expect(subject.i_name2moves.size).to eq(1)
|
98
|
+
|
99
|
+
expect { subject.send(:dequeue_item) }.not_to raise_error
|
100
|
+
expect(subject.move_queue.size).to eq(1)
|
101
|
+
expect(subject.i_name2moves.size).to eq(1)
|
102
|
+
|
103
|
+
subject.send(:dequeue_item)
|
104
|
+
expect(subject.move_queue).to be_empty
|
105
|
+
expect(subject.i_name2moves).to be_empty
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should allow the enqueuing of a backtrack bookmark' do
|
109
|
+
subject.enqueue_association(x_assoc)
|
110
|
+
|
111
|
+
expect { subject.place_bt_point }.not_to raise_error
|
112
|
+
expect(subject.i_name2moves.size).to eq(1)
|
113
|
+
expect(subject.move_queue.size).to eq(2)
|
114
|
+
expect(subject.i_name2moves['x']).to be_kind_of(Array)
|
115
|
+
expect(subject.i_name2moves['x'].size).to eq(1)
|
116
|
+
expect(subject.last_move).to be_kind_of(Bookmark)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should allow the enqueuing of a scope bookmark' do
|
120
|
+
subject.enqueue_association(x_assoc)
|
121
|
+
|
122
|
+
expect { subject.enter_scope }.not_to raise_error
|
123
|
+
expect(subject.i_name2moves.size).to eq(1)
|
124
|
+
expect(subject.move_queue.size).to eq(2)
|
125
|
+
expect(subject.i_name2moves['x']).to be_kind_of(Array)
|
126
|
+
expect(subject.i_name2moves['x'].size).to eq(1)
|
127
|
+
expect(subject.last_move).to be_kind_of(Bookmark)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should allow the fusion of two unbound variables' do
|
131
|
+
q_var = LogVar.new('q')
|
132
|
+
x_var = LogVar.new('x')
|
133
|
+
q_x_var = LogVar.new('q_x')
|
134
|
+
fusion = Fusion.new(q_x_var.i_name, [q_var.i_name, x_var.i_name])
|
135
|
+
pre_size = subject.move_queue.size
|
136
|
+
subject.enqueue_fusion(fusion)
|
137
|
+
|
138
|
+
expect(subject.move_queue.size).to eq(pre_size + 1)
|
139
|
+
expect(subject.i_name2moves).to be_include(q_x_var.i_name)
|
140
|
+
expect(subject.vars2cv[q_var.i_name]).to eq(q_x_var.i_name)
|
141
|
+
expect(subject.vars2cv[x_var.i_name]).to eq(q_x_var.i_name)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should allow the fusion of one unbound and one floating variable' do
|
145
|
+
q_var = LogVar.new('q')
|
146
|
+
x_var = LogVar.new('x')
|
147
|
+
assoc_x = Association.new('x', cons(LogVarRef.new('y'), pea))
|
148
|
+
subject.enqueue_association(assoc_x)
|
149
|
+
q_x_var = LogVar.new('q_x')
|
150
|
+
fusion = Fusion.new(q_x_var.i_name, [q_var.i_name, x_var.i_name])
|
151
|
+
pre_size = subject.move_queue.size
|
152
|
+
|
153
|
+
subject.enqueue_fusion(fusion)
|
154
|
+
expect(subject.move_queue.size).to eq(pre_size + 2)
|
155
|
+
expect(subject.i_name2moves).to be_include(q_x_var.i_name)
|
156
|
+
indices = subject.i_name2moves[q_x_var.i_name]
|
157
|
+
expect(indices.size).to eq(2) # 2 = 1 Fusion + 1 AssocCopy
|
158
|
+
new_assoc = subject.move_queue[indices.last]
|
159
|
+
expect(new_assoc.value).to eq(assoc_x.value)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should allow the fusion of two floating variables' do
|
163
|
+
q_var = LogVar.new('q')
|
164
|
+
x_var = LogVar.new('x')
|
165
|
+
assoc_q = Association.new('x', cons(pod, var_ref('z')))
|
166
|
+
subject.enqueue_association(assoc_q)
|
167
|
+
assoc_x = Association.new('x', cons(var_ref('y'), pea))
|
168
|
+
subject.enqueue_association(assoc_x)
|
169
|
+
q_x_var = LogVar.new('q_x')
|
170
|
+
fusion = Fusion.new(q_x_var.i_name, [q_var.i_name, x_var.i_name])
|
171
|
+
pre_size = subject.move_queue.size
|
172
|
+
|
173
|
+
subject.enqueue_fusion(fusion)
|
174
|
+
expect(subject.move_queue.size).to eq(pre_size + 3)
|
175
|
+
expect(subject.i_name2moves).to be_include(q_x_var.i_name)
|
176
|
+
indices = subject.i_name2moves[q_x_var.i_name]
|
177
|
+
expect(indices.size).to eq(3)
|
178
|
+
new_move1 = subject.move_queue[indices[0]]
|
179
|
+
expect(new_move1).to be_kind_of(Core::Fusion)
|
180
|
+
new_move2 = subject.move_queue[indices[1]]
|
181
|
+
expect(new_move2.value).to eq(assoc_q.value)
|
182
|
+
new_move3 = subject.move_queue[indices[2]]
|
183
|
+
expect(new_move3.value).to eq(assoc_x.value)
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should allow the removal of a fusion object at TOS position' do
|
187
|
+
q_var = LogVar.new('q')
|
188
|
+
x_var = LogVar.new('x')
|
189
|
+
q_x_var = LogVar.new('q_x')
|
190
|
+
fusion = Fusion.new(q_x_var.i_name, [q_var.i_name, x_var.i_name])
|
191
|
+
pre_size = subject.move_queue.size
|
192
|
+
subject.enqueue_fusion(fusion)
|
193
|
+
|
194
|
+
expect(subject.move_queue.size).to eq(pre_size + 1)
|
195
|
+
expect(subject.i_name2moves).to be_include(q_x_var.i_name)
|
196
|
+
expect(subject.vars2cv[q_var.i_name]).to eq(q_x_var.i_name)
|
197
|
+
expect(subject.vars2cv[x_var.i_name]).to eq(q_x_var.i_name)
|
198
|
+
|
199
|
+
expect { subject.send(:dequeue_item) }.not_to raise_error
|
200
|
+
expect(subject.move_queue.size).to eq(pre_size)
|
201
|
+
expect(subject.i_name2moves).not_to be_include(q_x_var.i_name)
|
202
|
+
expect(subject.vars2cv[q_var.i_name]).to be_nil
|
203
|
+
expect(subject.vars2cv[x_var.i_name]).to be_nil
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should retrieve association for a given i_name (0 fusion)' do
|
207
|
+
subject.enqueue_association(x_assoc)
|
208
|
+
subject.enqueue_association(y_assoc)
|
209
|
+
|
210
|
+
x_assoc_b = Core::Association.new('x', double('something'))
|
211
|
+
subject.enqueue_association(x_assoc_b)
|
212
|
+
expect(subject.associations_for('z')).to be_empty
|
213
|
+
expect(subject.associations_for('y').size).to eq(1)
|
214
|
+
expect(subject.associations_for('x').size).to eq(2)
|
215
|
+
expect(subject.associations_for('x').last).to eq(x_assoc_b)
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'should retrieve association for a given i_name (1 fusion)' do
|
219
|
+
subject.enqueue_association(x_assoc)
|
220
|
+
expect(subject.associations_for('x').size).to eq(1)
|
221
|
+
expect(subject.associations_for('z').size).to eq(0)
|
222
|
+
expect(subject.associations_for('z', true).size).to eq(0)
|
223
|
+
|
224
|
+
x_z_var = LogVar.new('x_z')
|
225
|
+
fusion = Fusion.new(x_z_var.i_name, %w[x z])
|
226
|
+
subject.enqueue_fusion(fusion)
|
227
|
+
expect(subject.associations_for('z', true).size).to eq(1)
|
228
|
+
x_z_assoc = Core::Association.new(x_z_var.i_name, var_ref('y'))
|
229
|
+
subject.enqueue_association(x_z_assoc)
|
230
|
+
expect(subject.associations_for('z', false).size).to eq(0)
|
231
|
+
expect(subject.associations_for('z', true).size).to eq(2)
|
232
|
+
expect(subject.associations_for('x', false).size).to eq(1)
|
233
|
+
expect(subject.associations_for('x', true).size).to eq(2)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'should accept the succeeded notification' do
|
237
|
+
subject.enqueue_association(x_assoc)
|
238
|
+
subject.enqueue_association(y_assoc)
|
239
|
+
subject.succeeded!
|
240
|
+
expect(subject).to be_success
|
241
|
+
expect(subject.move_queue.size).to eq(2)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should accept the failed notification in absence of bookmarks' do
|
245
|
+
subject.enqueue_association(x_assoc)
|
246
|
+
subject.enqueue_association(y_assoc)
|
247
|
+
subject.failed!
|
248
|
+
expect(subject).to be_failure
|
249
|
+
expect(subject.move_queue).to be_empty
|
250
|
+
expect(subject.i_name2moves).to be_empty
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should accept the failed notification with backtrack' do
|
254
|
+
x_assoc2 = Core::Association.new('x', pea)
|
255
|
+
|
256
|
+
subject.enqueue_association(x_assoc)
|
257
|
+
subject.enqueue_association(y_assoc)
|
258
|
+
subject.place_bt_point
|
259
|
+
subject.enqueue_association(z_assoc)
|
260
|
+
subject.enqueue_association(x_assoc2)
|
261
|
+
expect(subject.i_name2moves['x'].size).to eq(2)
|
262
|
+
|
263
|
+
subject.failed!
|
264
|
+
expect(subject.resultant).to eq(:"#u")
|
265
|
+
expect(subject.last_move).to be_kind_of(Core::Bookmark)
|
266
|
+
expect(subject.i_name2moves.include?('z')).to be_falsey
|
267
|
+
expect(subject.i_name2moves['x'].size).to eq(1)
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'should accept the failed notification on a bookmark' do
|
271
|
+
subject.enqueue_association(x_assoc)
|
272
|
+
subject.enqueue_association(y_assoc)
|
273
|
+
subject.place_bt_point # Backtrack point bookmark added...
|
274
|
+
|
275
|
+
subject.enqueue_association(z_assoc)
|
276
|
+
subject.enter_scope # Scope bookmark
|
277
|
+
|
278
|
+
expect(subject.move_queue.size).to eq(5)
|
279
|
+
|
280
|
+
subject.failed!
|
281
|
+
expect(subject.resultant).to eq(:"#u")
|
282
|
+
expect(subject.move_queue.size).to eq(3) # 3 = 2 assocs + 1 bookmark
|
283
|
+
end
|
284
|
+
end # context
|
285
|
+
end # describe
|
286
|
+
end # module
|
287
|
+
end # module
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
|
5
|
+
# Load the class under test
|
6
|
+
require_relative '../../lib/mini_kraken/core/bookmark'
|
7
|
+
|
8
|
+
module MiniKraken
|
9
|
+
module Core
|
10
|
+
describe Bookmark do
|
11
|
+
let(:one_ser_num) { 42 }
|
12
|
+
let(:a_kind) { :scope }
|
13
|
+
subject { Bookmark.new(a_kind, one_ser_num) }
|
14
|
+
|
15
|
+
context 'Initialization:' do
|
16
|
+
it 'should be initialized with a Symbol and an Integer' do
|
17
|
+
expect { Bookmark.new(a_kind, one_ser_num) }.not_to raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should know its kind' do
|
21
|
+
expect(subject.kind).to eq(a_kind)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should know its serial number' do
|
25
|
+
expect(subject.ser_num).to eq(one_ser_num)
|
26
|
+
end
|
27
|
+
end # context
|
28
|
+
|
29
|
+
context 'Provided services:' do
|
30
|
+
it 'should compare to another instance' do
|
31
|
+
same = Bookmark.new(a_kind, one_ser_num)
|
32
|
+
expect(subject).to eq(same)
|
33
|
+
|
34
|
+
distinct = Bookmark.new(a_kind, 3)
|
35
|
+
expect(subject).not_to eq(distinct)
|
36
|
+
end
|
37
|
+
end # context
|
38
|
+
end # describe
|
39
|
+
end # module
|
40
|
+
end # module
|
@@ -0,0 +1,221 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../lib/mini_kraken/core/association'
|
5
|
+
require_relative '../../lib/mini_kraken/core/log_var'
|
6
|
+
require_relative '../../lib/mini_kraken/composite/all_composite'
|
7
|
+
|
8
|
+
require_relative '../support/factory_atomic'
|
9
|
+
require_relative '../support/factory_methods'
|
10
|
+
|
11
|
+
# Load the class under test
|
12
|
+
require_relative '../../lib/mini_kraken/core/context'
|
13
|
+
|
14
|
+
module MiniKraken
|
15
|
+
module Core
|
16
|
+
describe Context do
|
17
|
+
include MiniKraken::FactoryAtomic # Use mix-in module
|
18
|
+
subject { Context.new }
|
19
|
+
|
20
|
+
context 'Initialization:' do
|
21
|
+
it 'should be initialized without argument' do
|
22
|
+
expect { Context.new }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should have an empty symbol table' do
|
26
|
+
expect(subject.symbol_table).to be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should have an empty blackboard' do
|
30
|
+
expect(subject.blackboard).to be_empty
|
31
|
+
end
|
32
|
+
end # context
|
33
|
+
|
34
|
+
context 'Initialization:' do
|
35
|
+
def var(aName)
|
36
|
+
LogVar.new(aName)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should accept the addition of an entry in symbol table' do
|
40
|
+
subject.insert(var('x'))
|
41
|
+
expect(subject.symbol_table).not_to be_empty
|
42
|
+
expect(subject.symbol_table.current_scope.defns['x']).to be_kind_of(LogVar)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should create one or more variables from name(s)' do
|
46
|
+
# Case: single name
|
47
|
+
subject.add_vars('x')
|
48
|
+
expect(subject.symbol_table).not_to be_empty
|
49
|
+
expect(subject.symbol_table.current_scope.defns['x']).to be_kind_of(LogVar)
|
50
|
+
|
51
|
+
# Case: multiple names
|
52
|
+
subject.add_vars(%w[y z])
|
53
|
+
expect(subject.symbol_table.current_scope.defns['y']).to be_kind_of(LogVar)
|
54
|
+
expect(subject.symbol_table.current_scope.defns['z']).to be_kind_of(LogVar)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should accept the addition of an association to a given i_name' do
|
58
|
+
i_name_x = subject.insert(var('x'))
|
59
|
+
i_name_y = subject.insert(var('y'))
|
60
|
+
|
61
|
+
expect(subject.associations_for('x')).to be_empty
|
62
|
+
something = double('something')
|
63
|
+
assoc_x = subject.associate('x', something)
|
64
|
+
expect(subject.associations_for('x')).to eq([assoc_x])
|
65
|
+
|
66
|
+
thing = double('thing')
|
67
|
+
assoc_y = Association.new(i_name_y, thing)
|
68
|
+
subject.enqueue_association(assoc_y)
|
69
|
+
expect(subject.associations_for('y')).to eq([assoc_y])
|
70
|
+
|
71
|
+
blob = double('blob')
|
72
|
+
assoc2_x = Association.new(i_name_x, blob)
|
73
|
+
subject.enqueue_association(assoc2_x)
|
74
|
+
expect(subject.associations_for('x')).to eq([assoc_x, assoc2_x])
|
75
|
+
|
76
|
+
var_y = subject.lookup('y')
|
77
|
+
foo = double('bar')
|
78
|
+
assoc2_y = subject.associate(var_y, foo)
|
79
|
+
expect(subject.associations_for('y')).to eq([assoc_y, assoc2_y])
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should allow the fusion of two variables' do
|
83
|
+
symb_tbl = subject.symbol_table
|
84
|
+
i_name_q = subject.insert(var('q'))
|
85
|
+
symb_tbl.enter_scope(Core::Scope.new)
|
86
|
+
i_name_x = subject.insert(var('x'))
|
87
|
+
|
88
|
+
expect(subject.associations_for('q')).to be_empty
|
89
|
+
something = double('something')
|
90
|
+
assoc_x = subject.associate('x', something)
|
91
|
+
expect(subject.associations_for('x')).to eq([assoc_x])
|
92
|
+
pre_queue_size = subject.blackboard.move_queue.size
|
93
|
+
fusion = subject.fuse(%w[q x])
|
94
|
+
|
95
|
+
expect(fusion).to be_kind_of(Fusion)
|
96
|
+
expect(fusion.elements).to eq(%w[q x].map { |e| subject.lookup(e).i_name })
|
97
|
+
expect(subject.blackboard.move_queue.size).to eq(pre_queue_size + 2)
|
98
|
+
expect(subject.cv2vars).to be_include(fusion.i_name)
|
99
|
+
expect(subject.cv2vars[fusion.i_name]).to eq(fusion.elements)
|
100
|
+
expect(subject.blackboard.vars2cv[i_name_q]).to eq(fusion.i_name)
|
101
|
+
expect(subject.blackboard.vars2cv[i_name_x]).to eq(fusion.i_name)
|
102
|
+
expect(subject.associations_for('q')).not_to be_empty
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should allow the search of an entry based on its name' do
|
106
|
+
symb_tbl = subject.symbol_table
|
107
|
+
subject.add_vars(%w[q x])
|
108
|
+
symb_tbl.enter_scope(Core::Scope.new)
|
109
|
+
subject.add_vars(%w[q y])
|
110
|
+
|
111
|
+
# Search for unknown name
|
112
|
+
expect(subject.lookup('z')).to be_nil
|
113
|
+
|
114
|
+
# Search for existing unique names
|
115
|
+
expect(subject.lookup('y')).to eq(symb_tbl.current_scope.defns['y'])
|
116
|
+
expect(subject.lookup('x')).to eq(symb_tbl.root.defns['x'])
|
117
|
+
|
118
|
+
# Search for redefined name
|
119
|
+
expect(subject.lookup('q')).to eq(symb_tbl.current_scope.defns['q'])
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should determine the ranks of fresh variables' do
|
123
|
+
subject.add_vars(%w[x y z])
|
124
|
+
|
125
|
+
ref_y = LogVarRef.new('y')
|
126
|
+
subject.associate('x', ref_y)
|
127
|
+
subject.send(:calc_ranking)
|
128
|
+
expect(subject.ranking.size).to eq(2)
|
129
|
+
i_name_y = subject.lookup('y').i_name
|
130
|
+
expect(subject.ranking[i_name_y]).to eq(0)
|
131
|
+
i_name_z = subject.lookup('z').i_name
|
132
|
+
expect(subject.ranking[i_name_z]).to eq(1)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should allow entering in a new scope' do
|
136
|
+
new_scope = Scope.new
|
137
|
+
expect { subject.enter_scope(new_scope) }.not_to raise_error
|
138
|
+
expect(subject.symbol_table.current_scope).to eq(new_scope)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should allow leaving out current scope' do
|
142
|
+
subject.add_vars(%w[q x])
|
143
|
+
x_val = k_symbol(:foo)
|
144
|
+
assoc_x = subject.associate('x', x_val) # x => :foo
|
145
|
+
expect(subject.blackboard.move_queue.size).to eq(1)
|
146
|
+
new_scope = Scope.new
|
147
|
+
subject.enter_scope(new_scope) # Adds one bookmark
|
148
|
+
expect(subject.blackboard.move_queue.size).to eq(2)
|
149
|
+
subject.add_vars(%w[w x y z])
|
150
|
+
|
151
|
+
q_val = LogVarRef.new('x')
|
152
|
+
assoc_q = subject.associate('q', q_val)
|
153
|
+
w_val = k_symbol(:bar)
|
154
|
+
subject.associate('w', w_val)
|
155
|
+
x2_val = LogVarRef.new('z')
|
156
|
+
assoc2_x = subject.associate('x', x2_val)
|
157
|
+
y_val = k_symbol(:foobar)
|
158
|
+
subject.associate('y', y_val)
|
159
|
+
# x => :foo
|
160
|
+
# ------
|
161
|
+
# q => x
|
162
|
+
# w => :bar
|
163
|
+
# x => z
|
164
|
+
# y => :foobar
|
165
|
+
expect(subject.blackboard.i_name2moves.keys.size).to eq(5)
|
166
|
+
expect(subject.blackboard.move_queue.size).to eq(6)
|
167
|
+
# require 'debug'
|
168
|
+
expect { subject.leave_scope }.not_to raise_error
|
169
|
+
# Expected state:
|
170
|
+
# x => :foo
|
171
|
+
# q => x'
|
172
|
+
# x' => z
|
173
|
+
expect(subject.blackboard.move_queue.size).to eq(3)
|
174
|
+
symb_table = subject.symbol_table
|
175
|
+
expect(symb_table.current_scope).to eq(symb_table.root)
|
176
|
+
expect(subject.blackboard.i_name2moves.keys.size).to eq(3)
|
177
|
+
expect(subject.blackboard.move_queue).to eq([assoc_x, assoc_q, assoc2_x])
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should substitute values of associations (if needed)' do
|
181
|
+
subject.add_vars(%w[q x y z])
|
182
|
+
|
183
|
+
x_ref = LogVarRef.new('x')
|
184
|
+
foobar = Composite::ConsCell.new(k_symbol(:foo), k_symbol(:bar))
|
185
|
+
q_val = Composite::ConsCell.new(x_ref, foobar)
|
186
|
+
assoc_q = subject.associate('q', q_val)
|
187
|
+
subject.send(:calc_ranking)
|
188
|
+
|
189
|
+
expect(subject.send(:substitute, assoc_q).to_s).to eq('(_0 :foo . :bar)')
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should build a solution' do
|
193
|
+
subject.add_vars(%w[x y z])
|
194
|
+
|
195
|
+
subject.succeeded!
|
196
|
+
sol = subject.build_solution
|
197
|
+
expect(sol.size).to eq(3)
|
198
|
+
expect(sol['x']).to eq(:_0)
|
199
|
+
expect(sol['y']).to eq(:_1)
|
200
|
+
expect(sol['z']).to eq(:_2)
|
201
|
+
|
202
|
+
foo = k_symbol(:foo)
|
203
|
+
subject.associate('x', foo)
|
204
|
+
sol = subject.build_solution
|
205
|
+
expect(sol.size).to eq(3)
|
206
|
+
expect(sol['x']).to eq(foo)
|
207
|
+
expect(sol['y']).to eq(:_0)
|
208
|
+
expect(sol['z']).to eq(:_1)
|
209
|
+
|
210
|
+
bar = k_symbol(:bar)
|
211
|
+
subject.associate('y', bar)
|
212
|
+
sol = subject.build_solution
|
213
|
+
expect(sol.size).to eq(3)
|
214
|
+
expect(sol['x']).to eq(foo)
|
215
|
+
expect(sol['y']).to eq(bar)
|
216
|
+
expect(sol['z']).to eq(:_0)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end # describe
|
220
|
+
end # module
|
221
|
+
end # module
|