porolog 0.0.4 → 1.0.0
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/README.md +30 -5
- data/Rakefile +7 -2
- data/bin/porolog +58 -1
- data/coverage/badge.svg +1 -1
- data/coverage/index.html +76733 -2638
- data/doc/Array.html +1066 -0
- data/doc/Object.html +674 -0
- data/doc/Porolog.html +4153 -74
- data/doc/Symbol.html +501 -0
- data/doc/_index.html +280 -6
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +34 -39
- data/doc/index.html +34 -39
- data/doc/method_list.html +1337 -57
- data/doc/top-level-namespace.html +4 -2
- data/lib/porolog.rb +1144 -4
- data/lib/porolog/arguments.rb +28 -24
- data/lib/porolog/core_ext.rb +188 -0
- data/lib/porolog/error.rb +9 -0
- data/lib/porolog/goal.rb +357 -0
- data/lib/porolog/instantiation.rb +346 -0
- data/lib/porolog/predicate.rb +74 -31
- data/lib/porolog/predicate/builtin.rb +825 -0
- data/lib/porolog/rule.rb +162 -0
- data/lib/porolog/scope.rb +4 -4
- data/lib/porolog/tail.rb +57 -0
- data/lib/porolog/value.rb +105 -0
- data/lib/porolog/variable.rb +325 -0
- data/test/porolog/arguments_test.rb +244 -195
- data/test/porolog/core_ext_test.rb +290 -0
- data/test/porolog/goal_test.rb +891 -0
- data/test/porolog/instantiation_test.rb +910 -0
- data/test/porolog/porolog_test.rb +2376 -13
- data/test/porolog/predicate/builtin_test.rb +1340 -0
- data/test/porolog/predicate_test.rb +84 -30
- data/test/porolog/rule_test.rb +527 -0
- data/test/porolog/scope_test.rb +0 -2
- data/test/porolog/tail_test.rb +127 -0
- data/test/porolog/value_test.rb +315 -0
- data/test/porolog/variable_test.rb +1614 -0
- data/test/samples_test.rb +277 -0
- data/test/test_helper.rb +115 -0
- metadata +34 -7
@@ -0,0 +1,1340 @@
|
|
1
|
+
#
|
2
|
+
# test/porolog/predicate/builtin_test.rb - Test Suite for Porolog::Predicate::Builtin
|
3
|
+
#
|
4
|
+
# Luis Esteban 30 July 2020
|
5
|
+
# created
|
6
|
+
#
|
7
|
+
|
8
|
+
require_relative '../../test_helper'
|
9
|
+
|
10
|
+
describe 'Porolog' do
|
11
|
+
|
12
|
+
describe 'Predicate' do
|
13
|
+
|
14
|
+
describe 'Builtin' do
|
15
|
+
|
16
|
+
before(:all) do
|
17
|
+
reset
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#write' do
|
21
|
+
|
22
|
+
it 'should output an atom' do
|
23
|
+
assert_output 'hello' do
|
24
|
+
builtin :write
|
25
|
+
|
26
|
+
assert_solutions write('hello'), [{}]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should output an integer' do
|
31
|
+
assert_output '456' do
|
32
|
+
builtin :write
|
33
|
+
|
34
|
+
assert_solutions write(456), [{}]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should output an uninstantiated variable' do
|
39
|
+
assert_output ':X' do
|
40
|
+
builtin :write
|
41
|
+
|
42
|
+
assert_solutions write(:X), [{ X: nil }]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should output an instantiated variable' do
|
47
|
+
assert_output '72' do
|
48
|
+
builtin :write, :is
|
49
|
+
predicate :inst
|
50
|
+
|
51
|
+
inst(:X, :Y) << [
|
52
|
+
is(:Y, :X) {|x| x + 4 },
|
53
|
+
write(:Y)
|
54
|
+
]
|
55
|
+
|
56
|
+
assert_solutions inst(23 + 45, :Y), [{ Y: 72 }]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#writenl' do
|
63
|
+
|
64
|
+
it 'should output an atom and a new line' do
|
65
|
+
assert_output "hello\n" do
|
66
|
+
builtin :writenl
|
67
|
+
|
68
|
+
assert_solutions writenl('hello'), [{}]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should output an integer and a new line' do
|
73
|
+
assert_output "456\n" do
|
74
|
+
builtin :writenl
|
75
|
+
|
76
|
+
assert_solutions writenl(456), [{}]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should output an uninstantiated variable and a new line' do
|
81
|
+
assert_output ":X\n" do
|
82
|
+
builtin :writenl
|
83
|
+
|
84
|
+
assert_solutions writenl(:X), [{ X: nil }]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should output an instantiated variable and a new line' do
|
89
|
+
assert_output "72\n" do
|
90
|
+
builtin :writenl, :is
|
91
|
+
predicate :inst
|
92
|
+
|
93
|
+
inst(:X, :Y) << [
|
94
|
+
is(:Y, :X) {|x| x + 4 },
|
95
|
+
writenl(:Y)
|
96
|
+
]
|
97
|
+
|
98
|
+
assert_solutions inst(23 + 45, :Y), [{ Y: 72 }]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#nl' do
|
105
|
+
|
106
|
+
it 'should output a newline' do
|
107
|
+
assert_output "\n\n\n" do
|
108
|
+
builtin :nl
|
109
|
+
predicate :f, :n
|
110
|
+
|
111
|
+
n(1).fact!
|
112
|
+
n(5).fact!
|
113
|
+
n(7).fact!
|
114
|
+
|
115
|
+
f() << [
|
116
|
+
n(:X),
|
117
|
+
nl
|
118
|
+
]
|
119
|
+
|
120
|
+
assert_solutions f(), [
|
121
|
+
{},
|
122
|
+
{},
|
123
|
+
{},
|
124
|
+
]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#is' do
|
131
|
+
|
132
|
+
it 'should raise an exception when not provided with a variable' do
|
133
|
+
builtin :is
|
134
|
+
predicate :is_test
|
135
|
+
|
136
|
+
is_test(:variable) << [
|
137
|
+
# :nocov:
|
138
|
+
is(6) { 6 }
|
139
|
+
# :nocov:
|
140
|
+
]
|
141
|
+
|
142
|
+
assert_raises NonVariableError do
|
143
|
+
assert_solutions is_test(6), [{}]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should not raise an exception when provided with an instantiated variable' do
|
148
|
+
builtin :is
|
149
|
+
predicate :is_test
|
150
|
+
|
151
|
+
is_test(:variable) << [
|
152
|
+
is(:variable) { 6 }
|
153
|
+
]
|
154
|
+
|
155
|
+
assert_solutions is_test(6), [{}]
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should call the block provided and instantiate the variable to the result of the provided block' do
|
159
|
+
builtin :is
|
160
|
+
predicate :is_test
|
161
|
+
|
162
|
+
calls = []
|
163
|
+
|
164
|
+
is_test(:variable1, :variable2) << [
|
165
|
+
is(:variable1) {
|
166
|
+
calls << 'first is called'
|
167
|
+
'first'
|
168
|
+
},
|
169
|
+
is(:variable2) {
|
170
|
+
calls << 'second is called'
|
171
|
+
'second'
|
172
|
+
}
|
173
|
+
]
|
174
|
+
|
175
|
+
assert_solutions is_test(:X, :Y), [{ X: 'first', Y: 'second'}]
|
176
|
+
assert_equal [
|
177
|
+
'first is called',
|
178
|
+
'second is called',
|
179
|
+
], calls
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should return false when the variable cannot be instantiated' do
|
183
|
+
builtin :is
|
184
|
+
predicate :is_test
|
185
|
+
|
186
|
+
calls = []
|
187
|
+
|
188
|
+
is_test(:variable1, :variable2) << [
|
189
|
+
is(:variable1) {
|
190
|
+
calls << 'first is called'
|
191
|
+
'first'
|
192
|
+
},
|
193
|
+
is(:variable2) {
|
194
|
+
# :nocov:
|
195
|
+
calls << 'second is called'
|
196
|
+
'second'
|
197
|
+
# :nocov:
|
198
|
+
}
|
199
|
+
]
|
200
|
+
|
201
|
+
assert_solutions is_test('one', 'two'), []
|
202
|
+
assert_equal [
|
203
|
+
'first is called',
|
204
|
+
], calls
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
describe '#eq' do
|
210
|
+
|
211
|
+
it 'should return no solutions when given unequal values' do
|
212
|
+
builtin :eq
|
213
|
+
|
214
|
+
assert_solutions eq([3,2,1,4], [1,2,3,4]), []
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should return a solution when given equal values' do
|
218
|
+
builtin :eq
|
219
|
+
|
220
|
+
assert_solutions eq([1,2,3,4], [1,2,3,4]), [{}]
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'should return a solution with an unbound variable when given the same unbound variable' do
|
224
|
+
builtin :eq
|
225
|
+
|
226
|
+
assert_solutions eq(:X, :X), [{ X: nil}]
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should return no solutions when given two unbound variables' do
|
230
|
+
builtin :eq
|
231
|
+
|
232
|
+
assert_solutions eq(:X, :Y), []
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'should return one solution with unbound variables when given given two uninstantiated variables that are bound to each other' do
|
236
|
+
builtin :eq, :is
|
237
|
+
predicate :bind_and_eq
|
238
|
+
|
239
|
+
bind_and_eq(:X, :Y) << [
|
240
|
+
is(:X, :Y) { |y| y },
|
241
|
+
eq(:X, :Y)
|
242
|
+
]
|
243
|
+
|
244
|
+
assert_solutions bind_and_eq(:X, :Y), [{ X: nil, Y: nil }]
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'should return no solutions when given two uninstantiated variables that are not bound to each other' do
|
248
|
+
builtin :eq, :is
|
249
|
+
predicate :bind_and_eq
|
250
|
+
|
251
|
+
bind_and_eq(:X, :Y) << [
|
252
|
+
is(:X, :P) { |p| p },
|
253
|
+
is(:Y, :Q) { |q| q },
|
254
|
+
eq(:X, :Y)
|
255
|
+
]
|
256
|
+
|
257
|
+
assert_solutions bind_and_eq(:X, :Y), []
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'should return no solutions when given a value and an uninstantiated variable' do
|
261
|
+
builtin :eq
|
262
|
+
|
263
|
+
assert_solutions eq([1,2,3,4], :L), []
|
264
|
+
assert_solutions eq(:L, [1,2,3,4]), []
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
describe '#is_eq' do
|
270
|
+
|
271
|
+
it 'should return no solutions when given unequal values' do
|
272
|
+
builtin :is_eq
|
273
|
+
|
274
|
+
assert_solutions is_eq([3,2,1,4], [1,2,3,4]), []
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'should return a solution when given equal values' do
|
278
|
+
builtin :is_eq
|
279
|
+
|
280
|
+
assert_solutions is_eq([1,2,3,4], [1,2,3,4]), []
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'should return a solution with an unbound variable when given the same unbound variable' do
|
284
|
+
builtin :is_eq
|
285
|
+
|
286
|
+
assert_solutions is_eq(:X, :X), [{ X: nil}]
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'should return no solutions when given given two unbound variables' do
|
290
|
+
builtin :is_eq
|
291
|
+
|
292
|
+
assert_solutions is_eq(:X, :Y), [{ X: nil, Y: nil }]
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'should return one solution with unbound variables when given given two uninstantiated variables that are bound to each other' do
|
296
|
+
builtin :is_eq, :is
|
297
|
+
predicate :bind_and_eq
|
298
|
+
|
299
|
+
bind_and_eq(:X, :Y) << [
|
300
|
+
is(:X, :Y) { |y| y },
|
301
|
+
is_eq(:X, :Y)
|
302
|
+
]
|
303
|
+
|
304
|
+
assert_solutions bind_and_eq(:X, :Y), [{ X: nil, Y: nil }]
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'should return no solutions when given given two uninstantiated variables that are not bound to each other' do
|
308
|
+
builtin :is_eq, :is
|
309
|
+
predicate :bind_and_eq
|
310
|
+
|
311
|
+
bind_and_eq(:X, :Y) << [
|
312
|
+
is(:X, :P) { |p| p },
|
313
|
+
is(:Y, :Q) { |q| q },
|
314
|
+
is_eq(:X, :Y)
|
315
|
+
]
|
316
|
+
|
317
|
+
assert_solutions bind_and_eq(:X, :Y), [{ X: nil, Y: nil }]
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'should not instantiate the right hand side when not given a left hand side variable' do
|
321
|
+
builtin :is_eq
|
322
|
+
|
323
|
+
assert_solutions is_eq([1,2,3,4], :L), []
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'should instantiate the left hand side variable' do
|
327
|
+
builtin :is_eq
|
328
|
+
|
329
|
+
assert_solutions is_eq(:L, [1,2,3,4]), [{ L: [1,2,3,4] }]
|
330
|
+
end
|
331
|
+
|
332
|
+
end
|
333
|
+
|
334
|
+
describe '#ruby' do
|
335
|
+
|
336
|
+
it 'should execute ruby code' do
|
337
|
+
builtin :ruby
|
338
|
+
predicate :logic, :data
|
339
|
+
|
340
|
+
data(1).fact!
|
341
|
+
data(5).fact!
|
342
|
+
data(7).cut_fact!
|
343
|
+
data(9).fact!
|
344
|
+
|
345
|
+
ruby_log = []
|
346
|
+
|
347
|
+
logic(:N) << [
|
348
|
+
ruby(:N){|goal, n|
|
349
|
+
ruby_log << (n.type == :variable ? n.to_sym : n)
|
350
|
+
},
|
351
|
+
data(:N),
|
352
|
+
ruby(:N){|goal, n|
|
353
|
+
ruby_log << (n.type == :variable ? n.to_sym : n)
|
354
|
+
}
|
355
|
+
]
|
356
|
+
|
357
|
+
assert_solutions logic(:N), [
|
358
|
+
{ N: 1 },
|
359
|
+
{ N: 5 },
|
360
|
+
{ N: 7 },
|
361
|
+
]
|
362
|
+
assert_equal [:N,1,5,7], ruby_log
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'should execute ruby code which triggers a failure' do
|
366
|
+
builtin :ruby
|
367
|
+
predicate :logic, :data
|
368
|
+
|
369
|
+
data(1).fact!
|
370
|
+
data(5).fact!
|
371
|
+
data(7).cut_fact!
|
372
|
+
data(9).fact!
|
373
|
+
|
374
|
+
ruby_log = []
|
375
|
+
|
376
|
+
logic(:N) << [
|
377
|
+
ruby(:N){|goal, n|
|
378
|
+
ruby_log << (n.type == :variable ? n.to_sym : n)
|
379
|
+
},
|
380
|
+
data(:N),
|
381
|
+
ruby(:N){|goal, n|
|
382
|
+
ruby_log << (n.type == :variable ? n.to_sym : n)
|
383
|
+
:fail
|
384
|
+
}
|
385
|
+
]
|
386
|
+
|
387
|
+
assert_solutions logic(:N), [
|
388
|
+
]
|
389
|
+
assert_equal [:N,1,5,7], ruby_log
|
390
|
+
end
|
391
|
+
|
392
|
+
end
|
393
|
+
|
394
|
+
describe '#noteq' do
|
395
|
+
|
396
|
+
it 'should return no solutions when given unequal values' do
|
397
|
+
builtin :noteq
|
398
|
+
|
399
|
+
assert_solutions noteq([3,2,1,4], [1,2,3,4]), [{}]
|
400
|
+
end
|
401
|
+
|
402
|
+
it 'should return a solution when given equal values' do
|
403
|
+
builtin :noteq
|
404
|
+
|
405
|
+
assert_solutions noteq([1,2,3,4], [1,2,3,4]), []
|
406
|
+
end
|
407
|
+
|
408
|
+
it 'should return a solution with an unbound variable when given the same unbound variable' do
|
409
|
+
builtin :noteq
|
410
|
+
|
411
|
+
assert_solutions noteq(:X, :X), []
|
412
|
+
end
|
413
|
+
|
414
|
+
it 'should return no solutions when given two unbound variables' do
|
415
|
+
builtin :noteq
|
416
|
+
|
417
|
+
assert_solutions noteq(:X, :Y), [{ X: nil, Y: nil }]
|
418
|
+
end
|
419
|
+
|
420
|
+
it 'should return one solution with unbound variables when given given two uninstantiated variables that are bound to each other' do
|
421
|
+
builtin :noteq, :is
|
422
|
+
predicate :bind_and_noteq
|
423
|
+
|
424
|
+
bind_and_noteq(:X, :Y) << [
|
425
|
+
is(:X, :Y) { |y| y },
|
426
|
+
noteq(:X, :Y)
|
427
|
+
]
|
428
|
+
|
429
|
+
assert_solutions bind_and_noteq(:X, :Y), []
|
430
|
+
end
|
431
|
+
|
432
|
+
it 'should return no solutions when given two uninstantiated variables that are not bound to each other' do
|
433
|
+
builtin :noteq, :is
|
434
|
+
predicate :bind_and_noteq
|
435
|
+
|
436
|
+
bind_and_noteq(:X, :Y) << [
|
437
|
+
is(:X, :P) { |p| p },
|
438
|
+
is(:Y, :Q) { |q| q },
|
439
|
+
noteq(:X, :Y)
|
440
|
+
]
|
441
|
+
|
442
|
+
assert_solutions bind_and_noteq(:X, :Y), [{ X: nil, Y: nil }]
|
443
|
+
end
|
444
|
+
|
445
|
+
it 'should return a solution when given an unbound variable' do
|
446
|
+
builtin :noteq
|
447
|
+
|
448
|
+
assert_solutions noteq([1,2,3,4], :L), [{ L: nil }]
|
449
|
+
assert_solutions noteq(:L, [1,2,3,4]), [{ L: nil }]
|
450
|
+
end
|
451
|
+
|
452
|
+
end
|
453
|
+
|
454
|
+
describe '#is_noteq' do
|
455
|
+
|
456
|
+
it 'should return solutions without the exclusions' do
|
457
|
+
builtin :is_noteq
|
458
|
+
|
459
|
+
assert_solutions is_noteq(:X, [1,2,3,4,5], 2, 5), [
|
460
|
+
{ X: 1, _a: [1,3,4] },
|
461
|
+
{ X: 3, _a: [1,3,4] },
|
462
|
+
{ X: 4, _a: [1,3,4] }
|
463
|
+
]
|
464
|
+
end
|
465
|
+
|
466
|
+
it 'should return no solutions when the exclusions are not unique' do
|
467
|
+
builtin :is_noteq
|
468
|
+
|
469
|
+
assert_solutions is_noteq(:X, [1,2,3,4,5], 2, 5, 2), []
|
470
|
+
end
|
471
|
+
|
472
|
+
it 'should return no solutions when the target is not a variable' do
|
473
|
+
builtin :is_noteq
|
474
|
+
|
475
|
+
assert_solutions is_noteq(7, [1,2,3,4,5], 2, 5, 2), []
|
476
|
+
end
|
477
|
+
|
478
|
+
end
|
479
|
+
|
480
|
+
describe '#less' do
|
481
|
+
|
482
|
+
it 'should return no solutions when given a greater value' do
|
483
|
+
builtin :less
|
484
|
+
|
485
|
+
assert_solutions less(7, 4), []
|
486
|
+
assert_solutions less('h', 'b'), []
|
487
|
+
assert_solutions less(1.01, 1.003), []
|
488
|
+
end
|
489
|
+
|
490
|
+
it 'should return no solutions when given equal values' do
|
491
|
+
builtin :less
|
492
|
+
|
493
|
+
assert_solutions less(4, 4), []
|
494
|
+
assert_solutions less('b', 'b'), []
|
495
|
+
assert_solutions less(1.003, 1.003), []
|
496
|
+
end
|
497
|
+
|
498
|
+
it 'should return a solution when given lesser values' do
|
499
|
+
builtin :less
|
500
|
+
|
501
|
+
assert_solutions less(2, 4), [{}]
|
502
|
+
end
|
503
|
+
|
504
|
+
it 'should return no solutions with an unbound variable when given the same unbound variable' do
|
505
|
+
builtin :less
|
506
|
+
|
507
|
+
assert_solutions less(:X, :X), []
|
508
|
+
end
|
509
|
+
|
510
|
+
it 'should return no solutions when given two unbound variables' do
|
511
|
+
builtin :less
|
512
|
+
|
513
|
+
assert_solutions less(:X, :Y), []
|
514
|
+
end
|
515
|
+
|
516
|
+
end
|
517
|
+
|
518
|
+
describe '#gtr' do
|
519
|
+
|
520
|
+
it 'should return no solutions when given a lesser value' do
|
521
|
+
builtin :gtr
|
522
|
+
|
523
|
+
assert_solutions gtr(4, 7), []
|
524
|
+
assert_solutions gtr('b', 'h'), []
|
525
|
+
assert_solutions gtr(1.003, 1.01), []
|
526
|
+
end
|
527
|
+
|
528
|
+
it 'should return no solutions when given equal values' do
|
529
|
+
builtin :gtr
|
530
|
+
|
531
|
+
assert_solutions gtr(4, 4), []
|
532
|
+
assert_solutions gtr('b', 'b'), []
|
533
|
+
assert_solutions gtr(1.003, 1.003), []
|
534
|
+
end
|
535
|
+
|
536
|
+
it 'should return a solution when given greater values' do
|
537
|
+
builtin :gtr
|
538
|
+
|
539
|
+
assert_solutions gtr(4, 2), [{}]
|
540
|
+
end
|
541
|
+
|
542
|
+
it 'should return no solutions with an unbound variable when given the same unbound variable' do
|
543
|
+
builtin :gtr
|
544
|
+
|
545
|
+
assert_solutions gtr(:X, :X), []
|
546
|
+
end
|
547
|
+
|
548
|
+
it 'should return no solutions when given two unbound variables' do
|
549
|
+
builtin :gtr
|
550
|
+
|
551
|
+
assert_solutions gtr(:X, :Y), []
|
552
|
+
end
|
553
|
+
|
554
|
+
end
|
555
|
+
|
556
|
+
describe '#lesseq' do
|
557
|
+
|
558
|
+
it 'should return no solutions when given a greater value' do
|
559
|
+
builtin :lesseq
|
560
|
+
|
561
|
+
assert_solutions lesseq(7, 4), []
|
562
|
+
assert_solutions lesseq('h', 'b'), []
|
563
|
+
assert_solutions lesseq(1.01, 1.003), []
|
564
|
+
end
|
565
|
+
|
566
|
+
it 'should return a solution when given equal values' do
|
567
|
+
builtin :lesseq
|
568
|
+
|
569
|
+
assert_solutions lesseq(4, 4), [{}]
|
570
|
+
assert_solutions lesseq('b', 'b'), [{}]
|
571
|
+
assert_solutions lesseq(1.003, 1.003), [{}]
|
572
|
+
end
|
573
|
+
|
574
|
+
it 'should return a solution when given lesser values' do
|
575
|
+
builtin :lesseq
|
576
|
+
|
577
|
+
assert_solutions lesseq(2, 4), [{}]
|
578
|
+
assert_solutions lesseq('b', 'h'), [{}]
|
579
|
+
assert_solutions lesseq(1.003, 1.01), [{}]
|
580
|
+
end
|
581
|
+
|
582
|
+
it 'should return a solution with an unbound variable when given the same unbound variable' do
|
583
|
+
builtin :lesseq
|
584
|
+
|
585
|
+
assert_solutions lesseq(:X, :X), [{ X: nil }]
|
586
|
+
end
|
587
|
+
|
588
|
+
it 'should return no solutions when given two unbound variables' do
|
589
|
+
builtin :lesseq
|
590
|
+
|
591
|
+
assert_solutions lesseq(:X, :Y), []
|
592
|
+
end
|
593
|
+
|
594
|
+
it 'should return no solutions when given one unbound variable' do
|
595
|
+
builtin :lesseq
|
596
|
+
|
597
|
+
assert_solutions lesseq(:X, 11), []
|
598
|
+
end
|
599
|
+
|
600
|
+
end
|
601
|
+
|
602
|
+
describe '#gtreq' do
|
603
|
+
|
604
|
+
it 'should return no solutions when given a lesser value' do
|
605
|
+
builtin :gtreq
|
606
|
+
|
607
|
+
assert_solutions gtreq(4, 7), []
|
608
|
+
assert_solutions gtreq('b', 'h'), []
|
609
|
+
assert_solutions gtreq(1.003, 1.01), []
|
610
|
+
end
|
611
|
+
|
612
|
+
it 'should return a solution when given equal values' do
|
613
|
+
builtin :gtreq
|
614
|
+
|
615
|
+
assert_solutions gtreq(4, 4), [{}]
|
616
|
+
assert_solutions gtreq('b', 'b'), [{}]
|
617
|
+
assert_solutions gtreq(1.003, 1.003), [{}]
|
618
|
+
end
|
619
|
+
|
620
|
+
it 'should return a solution when given gtreqer values' do
|
621
|
+
builtin :gtreq
|
622
|
+
|
623
|
+
assert_solutions gtreq(4, 2), [{}]
|
624
|
+
assert_solutions gtreq('h', 'b'), [{}]
|
625
|
+
assert_solutions gtreq(1.01, 1.003), [{}]
|
626
|
+
end
|
627
|
+
|
628
|
+
it 'should return a solution with an unbound variable when given the same unbound variable' do
|
629
|
+
builtin :gtreq
|
630
|
+
|
631
|
+
assert_solutions gtreq(:X, :X), [{ X: nil }]
|
632
|
+
end
|
633
|
+
|
634
|
+
it 'should return no solutions when given two unbound variables' do
|
635
|
+
builtin :gtreq
|
636
|
+
|
637
|
+
assert_solutions gtreq(:X, :Y), []
|
638
|
+
end
|
639
|
+
|
640
|
+
it 'should return no solutions when given one unbound variable' do
|
641
|
+
builtin :gtreq
|
642
|
+
|
643
|
+
assert_solutions gtreq(:X, 11), []
|
644
|
+
end
|
645
|
+
|
646
|
+
end
|
647
|
+
|
648
|
+
describe '#length' do
|
649
|
+
|
650
|
+
it 'should return a solution for an array and an integer' do
|
651
|
+
builtin :length
|
652
|
+
|
653
|
+
assert_solutions length([1,2,3,4,5], 5), [{}]
|
654
|
+
end
|
655
|
+
|
656
|
+
it 'should return no solutions for an array and an integer that do not satisy the length' do
|
657
|
+
builtin :length
|
658
|
+
|
659
|
+
assert_solutions length([1,2,3,4,5], 2), []
|
660
|
+
end
|
661
|
+
|
662
|
+
it 'should instaniate the length of the list' do
|
663
|
+
builtin :length
|
664
|
+
|
665
|
+
assert_solutions length([1,2,3,4,5], :N), [{ N: 5 }]
|
666
|
+
end
|
667
|
+
|
668
|
+
it 'should instaniate the list' do
|
669
|
+
builtin :length
|
670
|
+
|
671
|
+
assert_solutions length(:L, 4), [
|
672
|
+
{ L: [nil, nil, nil, nil], _a: nil, _b: nil, _c: nil, _d: nil }
|
673
|
+
]
|
674
|
+
end
|
675
|
+
|
676
|
+
it 'should return no solutions for a variable array and length' do
|
677
|
+
builtin :length
|
678
|
+
|
679
|
+
assert_solutions length(:L, :N), []
|
680
|
+
end
|
681
|
+
|
682
|
+
it 'should return no solutions for invalid types' do
|
683
|
+
builtin :length
|
684
|
+
|
685
|
+
assert_solutions length(3, [1,2,3]), []
|
686
|
+
end
|
687
|
+
|
688
|
+
end
|
689
|
+
|
690
|
+
describe '#between' do
|
691
|
+
|
692
|
+
it 'should return a solution when the value is in range' do
|
693
|
+
builtin :between
|
694
|
+
|
695
|
+
assert_solutions between(3, 1, 10), [{}]
|
696
|
+
end
|
697
|
+
|
698
|
+
it 'should return no solutions when the value is not in range' do
|
699
|
+
builtin :between
|
700
|
+
|
701
|
+
assert_solutions between(-40, 1, 10), []
|
702
|
+
end
|
703
|
+
|
704
|
+
it 'should return no solutions when given an uninstantiated variable for the range' do
|
705
|
+
builtin :between
|
706
|
+
|
707
|
+
assert_solutions between(:X, 1, :Ten), []
|
708
|
+
assert_solutions between(:X, :One, 10), []
|
709
|
+
end
|
710
|
+
|
711
|
+
it 'should return solutions for instantiating' do
|
712
|
+
builtin :between
|
713
|
+
|
714
|
+
assert_solutions between(:X, 1, 10), [
|
715
|
+
{ X: 1 },
|
716
|
+
{ X: 2 },
|
717
|
+
{ X: 3 },
|
718
|
+
{ X: 4 },
|
719
|
+
{ X: 5 },
|
720
|
+
{ X: 6 },
|
721
|
+
{ X: 7 },
|
722
|
+
{ X: 8 },
|
723
|
+
{ X: 9 },
|
724
|
+
{ X: 10 },
|
725
|
+
]
|
726
|
+
end
|
727
|
+
|
728
|
+
it 'should instantiate the minimum possible when the value is above the lower bound' do
|
729
|
+
builtin :between
|
730
|
+
|
731
|
+
assert_solutions between(4, 1, :upper), [{ upper: 4}]
|
732
|
+
end
|
733
|
+
|
734
|
+
it 'should instantiate the maximum possible when the value is below the upper bound' do
|
735
|
+
builtin :between
|
736
|
+
|
737
|
+
assert_solutions between(4, :lower, 10), [{ lower: 4}]
|
738
|
+
end
|
739
|
+
|
740
|
+
it 'should return no solutions the value is below the lower bound' do
|
741
|
+
builtin :between
|
742
|
+
|
743
|
+
assert_solutions between(-7, 1, :upper), []
|
744
|
+
end
|
745
|
+
|
746
|
+
it 'should return no solutions the value is above the upper bound' do
|
747
|
+
builtin :between
|
748
|
+
|
749
|
+
assert_solutions between(24, :lower, 10), []
|
750
|
+
end
|
751
|
+
|
752
|
+
it 'should instantiate both bounds when given a value' do
|
753
|
+
builtin :between
|
754
|
+
|
755
|
+
assert_solutions between(24, :lower, :upper), [{ lower: 24, upper: 24 }]
|
756
|
+
end
|
757
|
+
|
758
|
+
end
|
759
|
+
|
760
|
+
describe '#member' do
|
761
|
+
|
762
|
+
it 'should return no solutions for a non-member' do
|
763
|
+
builtin :member
|
764
|
+
|
765
|
+
assert_solutions member(5, [1,2,3,4]), []
|
766
|
+
end
|
767
|
+
|
768
|
+
it 'should return no solutions for a non-list' do
|
769
|
+
builtin :member
|
770
|
+
|
771
|
+
assert_solutions member(5, 5), []
|
772
|
+
end
|
773
|
+
|
774
|
+
it 'should return a solution for a member' do
|
775
|
+
builtin :member
|
776
|
+
|
777
|
+
assert_solutions member(3, [1,2,3,4]), [{}]
|
778
|
+
end
|
779
|
+
|
780
|
+
it 'should return a solution for an array member' do
|
781
|
+
builtin :member
|
782
|
+
|
783
|
+
assert_solutions member([2,3], [[1,2],[2,3],[3,4]]), [{}]
|
784
|
+
end
|
785
|
+
|
786
|
+
it 'should return a solution for a member' do
|
787
|
+
builtin :member
|
788
|
+
|
789
|
+
assert_solutions member(3, [1,2,3,4]), [{}]
|
790
|
+
end
|
791
|
+
|
792
|
+
it 'should return a solution for a member' do
|
793
|
+
builtin :member
|
794
|
+
|
795
|
+
assert_solutions member(3, [1,2,:C,4]), [{ C: 3 }]
|
796
|
+
end
|
797
|
+
|
798
|
+
it 'should return a solution for an array member' do
|
799
|
+
builtin :member
|
800
|
+
|
801
|
+
assert_solutions member([:A,3], [[1,2],[2,3],[3,4]]), [{ A: 2 }]
|
802
|
+
end
|
803
|
+
|
804
|
+
it 'should return a solution for an array member' do
|
805
|
+
builtin :member
|
806
|
+
|
807
|
+
assert_solutions member([2,3], [[1,:B],[:B,3],[3,4]]), [{ B: 2 }]
|
808
|
+
end
|
809
|
+
|
810
|
+
it 'should return solutions for each member' do
|
811
|
+
builtin :member
|
812
|
+
|
813
|
+
assert_solutions member(:M, [[1,2],[2,3],[3,4]]), [
|
814
|
+
{ M: [1,2] },
|
815
|
+
{ M: [2,3] },
|
816
|
+
{ M: [3,4] },
|
817
|
+
]
|
818
|
+
end
|
819
|
+
|
820
|
+
it 'should return limited solutions for variables' do
|
821
|
+
builtin :member
|
822
|
+
|
823
|
+
assert_solutions member(:M, :L, 12), Array.new(12){|i|
|
824
|
+
v = '_a'
|
825
|
+
{ M: nil, L: [*([nil] * (i+1)), UNKNOWN_TAIL] }.merge((1..(i * (i + 1) / 2)).map{ m = v.dup ; v.succ! ; [m.to_sym, nil] }.to_h)
|
826
|
+
}
|
827
|
+
end
|
828
|
+
|
829
|
+
end
|
830
|
+
|
831
|
+
describe '#append' do
|
832
|
+
|
833
|
+
it 'should return no solutions for a non-append' do
|
834
|
+
builtin :append
|
835
|
+
|
836
|
+
assert_solutions append([1,2,3], [4,5,6], [1,2,7,4,5,6]), []
|
837
|
+
end
|
838
|
+
|
839
|
+
it 'should return a solution for a valid append' do
|
840
|
+
builtin :append
|
841
|
+
|
842
|
+
assert_solutions append([1,2,3], [4,5,6], [1,2,3,4,5,6]), [{}]
|
843
|
+
end
|
844
|
+
|
845
|
+
it 'should return no solutions for a non-list' do
|
846
|
+
builtin :append
|
847
|
+
|
848
|
+
assert_solutions append(5, 5, 55), []
|
849
|
+
end
|
850
|
+
|
851
|
+
it 'should return a solution for a valid append' do
|
852
|
+
builtin :append
|
853
|
+
|
854
|
+
assert_solutions append([1,2,3], [4,5,6], [1,2,3,4,5,6]), [{}]
|
855
|
+
end
|
856
|
+
|
857
|
+
it 'should return a solution for an array append' do
|
858
|
+
builtin :append
|
859
|
+
|
860
|
+
assert_solutions append([[1,2],[2,3],[3,4]], [[4,5],[5,6],[6,7]], [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]), [{}]
|
861
|
+
end
|
862
|
+
|
863
|
+
it 'should instantiate prefix variable' do
|
864
|
+
builtin :append
|
865
|
+
|
866
|
+
assert_solutions append(:prefix, [[4,5],[5,6],[6,7]], [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]), [
|
867
|
+
{ prefix: [[1, 2], [2, 3], [3, 4]] }
|
868
|
+
]
|
869
|
+
end
|
870
|
+
|
871
|
+
it 'should instantiate suffix variable' do
|
872
|
+
builtin :append
|
873
|
+
|
874
|
+
assert_solutions append([[1,2],[2,3],[3,4]], :suffix, [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]), [
|
875
|
+
{ suffix: [[4, 5], [5, 6], [6, 7]] }
|
876
|
+
]
|
877
|
+
end
|
878
|
+
|
879
|
+
it 'should instantiate embedded variables' do
|
880
|
+
builtin :append
|
881
|
+
|
882
|
+
assert_solutions append([[:A,:B],[:C,:D],[:E,:F]], [:G,:H,:I], [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]), [
|
883
|
+
{ A: 1, B: 2, C: 2, D: 3, E: 3, F: 4, G: [4, 5], H: [5, 6], I: [6, 7] }
|
884
|
+
]
|
885
|
+
end
|
886
|
+
|
887
|
+
it 'should instantiate embedded variables' do
|
888
|
+
builtin :append
|
889
|
+
|
890
|
+
assert_solutions append([1,2,3,4], ['apple','banana','carrot'], :L), [
|
891
|
+
{ L: [1, 2, 3, 4, 'apple', 'banana', 'carrot'] }
|
892
|
+
]
|
893
|
+
end
|
894
|
+
|
895
|
+
it 'should return solutions for all possible splits of a list' do
|
896
|
+
builtin :append
|
897
|
+
|
898
|
+
assert_solutions append(:M, :L, [1,2,3,4,5]), [
|
899
|
+
{ M: [], L: [1, 2, 3, 4, 5] },
|
900
|
+
{ M: [1], L: [2, 3, 4, 5] },
|
901
|
+
{ M: [1, 2], L: [3, 4, 5] },
|
902
|
+
{ M: [1, 2, 3], L: [4, 5] },
|
903
|
+
{ M: [1, 2, 3, 4], L: [5] },
|
904
|
+
{ M: [1, 2, 3, 4, 5], L: [] }
|
905
|
+
]
|
906
|
+
end
|
907
|
+
|
908
|
+
it 'should instantiate using a head and tail for an unbound variable and an array' do
|
909
|
+
builtin :append, :is_eq
|
910
|
+
predicate :append_is_eq
|
911
|
+
|
912
|
+
append_is_eq(:A, :B, :C) << [
|
913
|
+
append(:A, :B, :C),
|
914
|
+
is_eq(:A, [1, 2, 3]),
|
915
|
+
]
|
916
|
+
|
917
|
+
assert_solutions append_is_eq(:A, [4,5,6], :C), [
|
918
|
+
{ A: [1, 2, 3], C: [1, 2, 3, 4, 5, 6] }
|
919
|
+
]
|
920
|
+
end
|
921
|
+
|
922
|
+
it 'should instantiate using a head and tail for unbound variables' do
|
923
|
+
builtin :append, :is_eq
|
924
|
+
predicate :append_is_eq
|
925
|
+
|
926
|
+
append_is_eq(:A, :B, :C) << [
|
927
|
+
append(:A, :B, :C),
|
928
|
+
is_eq(:B, [4, 5, 6]),
|
929
|
+
]
|
930
|
+
|
931
|
+
assert_solutions append_is_eq([1,2,3], :B, :C), [
|
932
|
+
{ B: [4, 5, 6], C: [1, 2, 3, 4, 5, 6] }
|
933
|
+
]
|
934
|
+
end
|
935
|
+
|
936
|
+
it 'should instantiate using a head and tail for unbound variables' do
|
937
|
+
builtin :append, :is_eq
|
938
|
+
predicate :append_is_eq
|
939
|
+
|
940
|
+
append_is_eq(:A, :B, :C) << [
|
941
|
+
append(:A, :B, :C),
|
942
|
+
is_eq(:A, [1, 2, 3]),
|
943
|
+
is_eq(:B, [4, 5, 6]),
|
944
|
+
]
|
945
|
+
|
946
|
+
assert_solutions append_is_eq(:A, :B, :C), [
|
947
|
+
{ A: [1, 2, 3], B: [4, 5, 6], C: [1, 2, 3, 4, 5, 6] }
|
948
|
+
]
|
949
|
+
end
|
950
|
+
|
951
|
+
end
|
952
|
+
|
953
|
+
describe '#permutation' do
|
954
|
+
|
955
|
+
it 'returns no solutions for non-arrays' do
|
956
|
+
builtin :permutation
|
957
|
+
|
958
|
+
assert_solutions permutation('1234', '1234'), []
|
959
|
+
end
|
960
|
+
|
961
|
+
it 'returns a solution for identical arrays without variables' do
|
962
|
+
builtin :permutation
|
963
|
+
|
964
|
+
assert_solutions permutation([1,2,3,4], [1,2,3,4]), [{}]
|
965
|
+
end
|
966
|
+
|
967
|
+
it 'returns a solutions for rearranged arrays without variables' do
|
968
|
+
builtin :permutation
|
969
|
+
|
970
|
+
assert_solutions permutation([3,2,1,4], [1,2,3,4]), [{}]
|
971
|
+
end
|
972
|
+
|
973
|
+
it 'returns a solution and instantiates a variable' do
|
974
|
+
builtin :permutation
|
975
|
+
|
976
|
+
assert_solutions permutation([3,2,:A,4], [1,2,3,4]), [{ A: 1 }]
|
977
|
+
end
|
978
|
+
|
979
|
+
it 'returns solutions of permutations of instantiations' do
|
980
|
+
builtin :permutation
|
981
|
+
|
982
|
+
assert_solutions permutation([3,2,:A,:B], [1,2,3,4]), [
|
983
|
+
{ A: 1, B: 4 },
|
984
|
+
{ A: 4, B: 1 },
|
985
|
+
]
|
986
|
+
end
|
987
|
+
|
988
|
+
it 'returns solutions of permutations of instantiations in the other list' do
|
989
|
+
builtin :permutation
|
990
|
+
|
991
|
+
assert_solutions permutation([3,2,1,4], [:A,2,3,:B]), [
|
992
|
+
{ A: 1, B: 4 },
|
993
|
+
{ A: 4, B: 1 },
|
994
|
+
]
|
995
|
+
end
|
996
|
+
|
997
|
+
it 'infers instantiations of variables in both arrays' do
|
998
|
+
builtin :permutation
|
999
|
+
|
1000
|
+
assert_solutions permutation([3,2,:A,4], [1,2,:C,4]), [
|
1001
|
+
{ A: 1, C: 3 }
|
1002
|
+
]
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
it 'infers instantiations of variables in both arrays when they represent the same value' do
|
1006
|
+
builtin :permutation
|
1007
|
+
|
1008
|
+
assert_solutions permutation([:A,2,1,4], [1,2,:C,4]), [
|
1009
|
+
{ A: 1, C: 1 },
|
1010
|
+
{ A: 2, C: 2 },
|
1011
|
+
{ A: nil, C: nil },
|
1012
|
+
{ A: 4, C: 4 }
|
1013
|
+
]
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
it 'returns all permutations of an array' do
|
1017
|
+
builtin :permutation
|
1018
|
+
|
1019
|
+
assert_solutions permutation([3,2,1,4], :L), [
|
1020
|
+
{ L: [3, 2, 1, 4] },
|
1021
|
+
{ L: [3, 2, 4, 1] },
|
1022
|
+
{ L: [3, 1, 2, 4] },
|
1023
|
+
{ L: [3, 1, 4, 2] },
|
1024
|
+
{ L: [3, 4, 2, 1] },
|
1025
|
+
{ L: [3, 4, 1, 2] },
|
1026
|
+
{ L: [2, 3, 1, 4] },
|
1027
|
+
{ L: [2, 3, 4, 1] },
|
1028
|
+
{ L: [2, 1, 3, 4] },
|
1029
|
+
{ L: [2, 1, 4, 3] },
|
1030
|
+
{ L: [2, 4, 3, 1] },
|
1031
|
+
{ L: [2, 4, 1, 3] },
|
1032
|
+
{ L: [1, 3, 2, 4] },
|
1033
|
+
{ L: [1, 3, 4, 2] },
|
1034
|
+
{ L: [1, 2, 3, 4] },
|
1035
|
+
{ L: [1, 2, 4, 3] },
|
1036
|
+
{ L: [1, 4, 3, 2] },
|
1037
|
+
{ L: [1, 4, 2, 3] },
|
1038
|
+
{ L: [4, 3, 2, 1] },
|
1039
|
+
{ L: [4, 3, 1, 2] },
|
1040
|
+
{ L: [4, 2, 3, 1] },
|
1041
|
+
{ L: [4, 2, 1, 3] },
|
1042
|
+
{ L: [4, 1, 3, 2] },
|
1043
|
+
{ L: [4, 1, 2, 3] }
|
1044
|
+
], goals: 1
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
it 'returns all permutations of an array when arguments are swapped' do
|
1048
|
+
builtin :permutation
|
1049
|
+
|
1050
|
+
assert_solutions permutation(:L, [3,2,1,4]), [
|
1051
|
+
{ L: [3, 2, 1, 4] },
|
1052
|
+
{ L: [3, 2, 4, 1] },
|
1053
|
+
{ L: [3, 1, 2, 4] },
|
1054
|
+
{ L: [3, 1, 4, 2] },
|
1055
|
+
{ L: [3, 4, 2, 1] },
|
1056
|
+
{ L: [3, 4, 1, 2] },
|
1057
|
+
{ L: [2, 3, 1, 4] },
|
1058
|
+
{ L: [2, 3, 4, 1] },
|
1059
|
+
{ L: [2, 1, 3, 4] },
|
1060
|
+
{ L: [2, 1, 4, 3] },
|
1061
|
+
{ L: [2, 4, 3, 1] },
|
1062
|
+
{ L: [2, 4, 1, 3] },
|
1063
|
+
{ L: [1, 3, 2, 4] },
|
1064
|
+
{ L: [1, 3, 4, 2] },
|
1065
|
+
{ L: [1, 2, 3, 4] },
|
1066
|
+
{ L: [1, 2, 4, 3] },
|
1067
|
+
{ L: [1, 4, 3, 2] },
|
1068
|
+
{ L: [1, 4, 2, 3] },
|
1069
|
+
{ L: [4, 3, 2, 1] },
|
1070
|
+
{ L: [4, 3, 1, 2] },
|
1071
|
+
{ L: [4, 2, 3, 1] },
|
1072
|
+
{ L: [4, 2, 1, 3] },
|
1073
|
+
{ L: [4, 1, 3, 2] },
|
1074
|
+
{ L: [4, 1, 2, 3] }
|
1075
|
+
], goals: 1
|
1076
|
+
end
|
1077
|
+
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
describe '#reverse' do
|
1081
|
+
|
1082
|
+
it 'returns no solutions for non-arrays' do
|
1083
|
+
builtin :reverse
|
1084
|
+
|
1085
|
+
assert_solutions reverse('1234', '1234'), []
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
it 'returns a solution for mirrored arrays without variables' do
|
1089
|
+
builtin :reverse
|
1090
|
+
|
1091
|
+
assert_solutions reverse([1,2,3,4], [4,3,2,1]), [{}]
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
it 'returns a solution and instantiates a variable' do
|
1095
|
+
builtin :reverse
|
1096
|
+
|
1097
|
+
assert_solutions reverse([4,3,:A,1], [1,2,3,4]), [{ A: 2 }]
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
it 'returns a solution and instantiates multiple variables' do
|
1101
|
+
builtin :reverse
|
1102
|
+
|
1103
|
+
assert_solutions reverse([4,3,:A,:B], [1,2,3,4]), [
|
1104
|
+
{ A: 2, B: 1 },
|
1105
|
+
]
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
it 'returns a solution and instantiates multiple variables in the other list' do
|
1109
|
+
builtin :reverse
|
1110
|
+
|
1111
|
+
assert_solutions reverse([4,3,2,1], [:A,2,3,:B]), [
|
1112
|
+
{ A: 1, B: 4 },
|
1113
|
+
]
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
it 'infers instantiations of variables in both arrays' do
|
1117
|
+
builtin :reverse
|
1118
|
+
|
1119
|
+
assert_solutions reverse([4,3,:A,1], [1,2,:C,4]), [
|
1120
|
+
{ A: 2, C: 3 }
|
1121
|
+
]
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
it 'infers instantiations of variables in both arrays when they represent the same value' do
|
1125
|
+
builtin :reverse
|
1126
|
+
|
1127
|
+
assert_solutions reverse([:A,3,2,1], [1,:A,3,:C]), [
|
1128
|
+
{ A: 2, C: 2 },
|
1129
|
+
]
|
1130
|
+
end
|
1131
|
+
|
1132
|
+
it 'allows unbound variables' do
|
1133
|
+
builtin :reverse
|
1134
|
+
|
1135
|
+
assert_solutions reverse([:A,3,2,1], :L), [
|
1136
|
+
{ A: nil, L: [1,2,3,nil] },
|
1137
|
+
]
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
it 'instantiates a variable to the reversed array' do
|
1141
|
+
builtin :reverse
|
1142
|
+
|
1143
|
+
assert_solutions reverse([4,3,2,1], :L), [
|
1144
|
+
{ L: [1, 2, 3, 4] },
|
1145
|
+
], goals: 1
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
it 'instantiates a variable to the reversed array when arguments are swapped' do
|
1149
|
+
builtin :reverse
|
1150
|
+
|
1151
|
+
assert_solutions reverse(:L, [4,3,2,1]), [
|
1152
|
+
{ L: [1, 2, 3, 4] },
|
1153
|
+
], goals: 1
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
it 'returns no solutions for uninstantiated variables' do
|
1157
|
+
builtin :reverse
|
1158
|
+
|
1159
|
+
assert_solutions reverse(:X, :Y), [], goals: 1
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
end
|
1163
|
+
|
1164
|
+
describe '#var' do
|
1165
|
+
|
1166
|
+
it 'should be unsuccessful for an atom' do
|
1167
|
+
builtin :var
|
1168
|
+
|
1169
|
+
assert_solutions var('1234'), []
|
1170
|
+
end
|
1171
|
+
|
1172
|
+
it 'should be successful for an uninstantiated variable' do
|
1173
|
+
builtin :var, :is_eq
|
1174
|
+
predicate :vartest
|
1175
|
+
|
1176
|
+
vartest(:variable) << [
|
1177
|
+
var(:variable),
|
1178
|
+
is_eq(:variable, 'value')
|
1179
|
+
]
|
1180
|
+
|
1181
|
+
assert_solutions vartest(:V), [{ V: 'value' }]
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
it 'should be successful for an uninstantiated bound variable' do
|
1185
|
+
builtin :var, :is_eq
|
1186
|
+
predicate :vartest
|
1187
|
+
|
1188
|
+
vartest(:variable) << [
|
1189
|
+
is_eq(:variable, :bound),
|
1190
|
+
var(:variable),
|
1191
|
+
is_eq(:bound, 'bound')
|
1192
|
+
]
|
1193
|
+
|
1194
|
+
assert_solutions vartest(:V), [{ V: 'bound' }]
|
1195
|
+
end
|
1196
|
+
|
1197
|
+
it 'should be successful for an uninstantiated bound variable' do
|
1198
|
+
builtin :var, :is_eq
|
1199
|
+
predicate :vartest
|
1200
|
+
|
1201
|
+
vartest(:variable) << [
|
1202
|
+
is_eq(:variable, 'instantiated'),
|
1203
|
+
var(:variable)
|
1204
|
+
]
|
1205
|
+
|
1206
|
+
assert_solutions vartest(:V), []
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
describe '#nonvar' do
|
1212
|
+
|
1213
|
+
it 'should be successful for an atom' do
|
1214
|
+
builtin :nonvar
|
1215
|
+
|
1216
|
+
assert_solutions nonvar('1234'), [{}]
|
1217
|
+
end
|
1218
|
+
|
1219
|
+
it 'should be unsuccessful for an uninstantiated variable' do
|
1220
|
+
builtin :nonvar, :is_eq
|
1221
|
+
predicate :nonvartest
|
1222
|
+
|
1223
|
+
nonvartest(:variable) << [
|
1224
|
+
nonvar(:variable),
|
1225
|
+
is_eq(:variable, 'value')
|
1226
|
+
]
|
1227
|
+
|
1228
|
+
assert_solutions nonvartest(:V), []
|
1229
|
+
end
|
1230
|
+
|
1231
|
+
it 'should be unsuccessful for an uninstantiated bound variable' do
|
1232
|
+
builtin :nonvar, :is_eq
|
1233
|
+
predicate :nonvartest
|
1234
|
+
|
1235
|
+
nonvartest(:variable) << [
|
1236
|
+
is_eq(:variable, :bound),
|
1237
|
+
nonvar(:variable),
|
1238
|
+
is_eq(:bound, 'bound')
|
1239
|
+
]
|
1240
|
+
|
1241
|
+
assert_solutions nonvartest(:V), []
|
1242
|
+
end
|
1243
|
+
|
1244
|
+
it 'should be unsuccessful for an uninstantiated bound variable' do
|
1245
|
+
builtin :nonvar, :is_eq
|
1246
|
+
predicate :nonvartest
|
1247
|
+
|
1248
|
+
nonvartest(:variable) << [
|
1249
|
+
is_eq(:variable, 'instantiated'),
|
1250
|
+
nonvar(:variable)
|
1251
|
+
]
|
1252
|
+
|
1253
|
+
assert_solutions nonvartest(:V), [{ V: 'instantiated' }]
|
1254
|
+
end
|
1255
|
+
|
1256
|
+
end
|
1257
|
+
|
1258
|
+
describe '#atom' do
|
1259
|
+
|
1260
|
+
it 'should be satisfied with a String' do
|
1261
|
+
builtin :atom
|
1262
|
+
|
1263
|
+
assert_solutions atom('banana'), [{}]
|
1264
|
+
end
|
1265
|
+
|
1266
|
+
it 'should not be satisfied with an Integer' do
|
1267
|
+
builtin :atom
|
1268
|
+
|
1269
|
+
assert_solutions atom(6), []
|
1270
|
+
end
|
1271
|
+
|
1272
|
+
it 'should not be satisfied with an Array' do
|
1273
|
+
builtin :atom
|
1274
|
+
|
1275
|
+
assert_solutions atom([]), []
|
1276
|
+
end
|
1277
|
+
|
1278
|
+
end
|
1279
|
+
|
1280
|
+
describe '#atomic' do
|
1281
|
+
|
1282
|
+
it 'should be satisfied with a String' do
|
1283
|
+
builtin :atomic
|
1284
|
+
|
1285
|
+
assert_solutions atomic('banana'), [{}]
|
1286
|
+
end
|
1287
|
+
|
1288
|
+
it 'should be satisfied with an Integer' do
|
1289
|
+
builtin :atomic
|
1290
|
+
|
1291
|
+
assert_solutions atomic(6), [{}]
|
1292
|
+
end
|
1293
|
+
|
1294
|
+
it 'should not be satisfied with an Array' do
|
1295
|
+
builtin :atomic
|
1296
|
+
|
1297
|
+
assert_solutions atomic([]), []
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
it 'should not be satisfied with an uninstantiated variable' do
|
1301
|
+
builtin :atomic
|
1302
|
+
|
1303
|
+
assert_solutions atomic(:X), []
|
1304
|
+
end
|
1305
|
+
|
1306
|
+
end
|
1307
|
+
|
1308
|
+
describe '#integer' do
|
1309
|
+
|
1310
|
+
it 'should not be satisfied with a String' do
|
1311
|
+
builtin :integer
|
1312
|
+
|
1313
|
+
assert_solutions integer('banana'), []
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
it 'should be satisfied with an Integer' do
|
1317
|
+
builtin :integer
|
1318
|
+
|
1319
|
+
assert_solutions integer(6), [{}]
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
it 'should not be satisfied with an Array' do
|
1323
|
+
builtin :integer
|
1324
|
+
|
1325
|
+
assert_solutions integer([]), []
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
it 'should not be satisfied with an uninstantiated variable' do
|
1329
|
+
builtin :integer
|
1330
|
+
|
1331
|
+
assert_solutions integer(:X), []
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
end
|
1337
|
+
|
1338
|
+
end
|
1339
|
+
|
1340
|
+
end
|