mini_kraken 0.2.03 → 0.3.03
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/.rubocop.yml +378 -333
- data/CHANGELOG.md +48 -0
- data/README.md +29 -21
- data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
- data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
- data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
- data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
- data/lib/mini_kraken/atomic/k_string.rb +17 -0
- data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
- data/lib/mini_kraken/composite/all_composite.rb +4 -0
- data/lib/mini_kraken/composite/composite_term.rb +27 -0
- data/lib/mini_kraken/composite/cons_cell.rb +301 -0
- data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
- 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 +492 -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 +22 -0
- data/lib/mini_kraken/core/log_var_ref.rb +108 -0
- data/lib/mini_kraken/core/nullary_relation.rb +2 -9
- data/lib/mini_kraken/core/parametrized_term.rb +68 -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 +44 -88
- 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 +143 -0
- data/lib/mini_kraken/rela/conj2.rb +65 -0
- data/lib/mini_kraken/rela/def_relation.rb +93 -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 +7 -9
- data/lib/mini_kraken/rela/unify.rb +265 -0
- data/lib/mini_kraken/version.rb +1 -1
- data/mini_kraken.gemspec +2 -2
- data/spec/.rubocop.yml +1 -1
- data/spec/atomic/atomic_term_spec.rb +98 -0
- data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
- data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
- data/spec/composite/cons_cell_spec.rb +225 -0
- data/spec/{core → composite}/cons_cell_visitor_spec.rb +36 -20
- data/spec/composite/list_spec.rb +50 -0
- data/spec/core/any_value_spec.rb +52 -0
- data/spec/core/arity_spec.rb +92 -0
- data/spec/core/association_copy_spec.rb +69 -0
- data/spec/core/association_spec.rb +31 -4
- data/spec/core/blackboard_spec.rb +287 -0
- data/spec/core/bookmark_spec.rb +40 -0
- data/spec/core/context_spec.rb +245 -0
- data/spec/core/core_spec.rb +40 -0
- data/spec/core/duck_fiber_spec.rb +16 -46
- data/spec/core/fail_spec.rb +5 -6
- data/spec/core/goal_spec.rb +22 -12
- data/spec/core/log_var_ref_spec.rb +105 -0
- data/spec/core/log_var_spec.rb +64 -0
- 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 -144
- data/spec/glue/dsl_chap2_spec.rb +454 -19
- data/spec/glue/run_star_expression_spec.rb +81 -906
- data/spec/rela/conde_spec.rb +153 -0
- 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 +29 -0
- data/spec/support/factory_composite.rb +21 -0
- data/spec/support/factory_methods.rb +11 -26
- metadata +98 -70
- data/lib/mini_kraken/core/association_walker.rb +0 -183
- data/lib/mini_kraken/core/atomic_term.rb +0 -67
- 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/composite_term.rb +0 -41
- data/lib/mini_kraken/core/conde.rb +0 -143
- data/lib/mini_kraken/core/conj2.rb +0 -79
- data/lib/mini_kraken/core/cons_cell.rb +0 -82
- data/lib/mini_kraken/core/cons_cell_visitor.rb +0 -102
- 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 -193
- 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/k_boolean.rb +0 -35
- data/lib/mini_kraken/core/outcome.rb +0 -63
- data/lib/mini_kraken/core/variable.rb +0 -41
- data/lib/mini_kraken/core/variable_ref.rb +0 -84
- data/lib/mini_kraken/core/vocabulary.rb +0 -446
- data/lib/mini_kraken/glue/fresh_env.rb +0 -103
- data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
- data/spec/core/association_walker_spec.rb +0 -192
- data/spec/core/conde_spec.rb +0 -147
- data/spec/core/conj2_spec.rb +0 -114
- data/spec/core/cons_cell_spec.rb +0 -107
- data/spec/core/def_relation_spec.rb +0 -97
- data/spec/core/disj2_spec.rb +0 -99
- data/spec/core/environment_spec.rb +0 -142
- data/spec/core/equals_spec.rb +0 -317
- data/spec/core/goal_template_spec.rb +0 -74
- data/spec/core/outcome_spec.rb +0 -56
- data/spec/core/variable_ref_spec.rb +0 -30
- data/spec/core/variable_spec.rb +0 -35
- data/spec/core/vocabulary_spec.rb +0 -219
- data/spec/glue/fresh_env_factory_spec.rb +0 -97
- data/spec/glue/fresh_env_spec.rb +0 -62
@@ -1,103 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../core/environment'
|
4
|
-
require_relative '../core/conj2'
|
5
|
-
require_relative '../core/goal_template'
|
6
|
-
require_relative '../core/variable'
|
7
|
-
|
8
|
-
module MiniKraken
|
9
|
-
module Glue
|
10
|
-
# A combination of an Environment (= a scope for one or more variables)
|
11
|
-
# and a goal. It quacks like a Goal object: when receiving the attain message,
|
12
|
-
# it attempts to achieve its given goal.
|
13
|
-
# (fresh (x) (== 'pea q))
|
14
|
-
# Introduces the new variable 'x'
|
15
|
-
# Takes a list of names and a goal-like object
|
16
|
-
# Must respond to message attain(aPublisher, vars) and must return an Outcome
|
17
|
-
class FreshEnv < Core::Environment
|
18
|
-
# @return [Goal]
|
19
|
-
attr_reader :goal
|
20
|
-
|
21
|
-
# @return [TrueClass, FalseClass] Do associations persist after goal exec?
|
22
|
-
attr_reader :persistent
|
23
|
-
|
24
|
-
# @param theNames [Array<String>] The variable names
|
25
|
-
# @param aGoal [Goal, Array<Goal>] The goal to achieve or the conjunction of them.
|
26
|
-
def initialize(theNames, aGoal, persistence = true)
|
27
|
-
super()
|
28
|
-
@goal = valid_goal(aGoal)
|
29
|
-
theNames.each do |nm|
|
30
|
-
var = Core::Variable.new(nm)
|
31
|
-
add_var(var)
|
32
|
-
end
|
33
|
-
@persistent = persistence
|
34
|
-
end
|
35
|
-
|
36
|
-
# Attempt to achieve the goal given this environment
|
37
|
-
# @param aParent [Environment]
|
38
|
-
# @return [Fiber<Outcome>] A Fiber object that will generate the results.
|
39
|
-
def attain(aParent)
|
40
|
-
# require 'debug'
|
41
|
-
self.parent = aParent
|
42
|
-
goal.attain(self)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Remove associations of variables of this environment, if
|
46
|
-
# persistence flag is set to false.
|
47
|
-
def prune(anOutcome)
|
48
|
-
return super(anOutcome) if persistent
|
49
|
-
|
50
|
-
vars.each_value do |v|
|
51
|
-
v_name = v.name
|
52
|
-
if anOutcome.associations.include?(v_name)
|
53
|
-
anOutcome.associations.delete(v_name)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
anOutcome
|
58
|
-
end
|
59
|
-
|
60
|
-
protected
|
61
|
-
|
62
|
-
def introspect
|
63
|
-
+", @vars=[#{vars.keys.join(', ')}]"
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def valid_goal(aGoal)
|
69
|
-
result = nil
|
70
|
-
|
71
|
-
case aGoal
|
72
|
-
when Core::Goal
|
73
|
-
result = aGoal
|
74
|
-
when FreshEnv
|
75
|
-
result = aGoal
|
76
|
-
when Core::GoalTemplate
|
77
|
-
result = aGoal
|
78
|
-
when Array # an Array of Goal?..
|
79
|
-
goal_array = aGoal
|
80
|
-
loop do
|
81
|
-
conjunctions = []
|
82
|
-
goal_array.each_slice(2) do |uno_duo|
|
83
|
-
if uno_duo.size == 2
|
84
|
-
conjunctions << Core::Goal.new(Core::Conj2.instance, uno_duo)
|
85
|
-
else
|
86
|
-
conjunctions << uno_duo[0]
|
87
|
-
end
|
88
|
-
end
|
89
|
-
if conjunctions.size == 1
|
90
|
-
result = conjunctions[0]
|
91
|
-
break
|
92
|
-
end
|
93
|
-
goal_array = conjunctions
|
94
|
-
end
|
95
|
-
else
|
96
|
-
raise StandardError, "Cannot handle argumment type #{aGoal.class}"
|
97
|
-
end
|
98
|
-
|
99
|
-
result
|
100
|
-
end
|
101
|
-
end # class
|
102
|
-
end # module
|
103
|
-
end # module
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../core/environment'
|
4
|
-
require_relative '../core/conj2'
|
5
|
-
require_relative '../core/goal_template'
|
6
|
-
require_relative '../core/variable'
|
7
|
-
require_relative 'fresh_env'
|
8
|
-
|
9
|
-
module MiniKraken
|
10
|
-
module Glue
|
11
|
-
# A combination of an Environment (= a scope for one or more variables)
|
12
|
-
# and a goal. It quacks like a Goal template object: when receiving the
|
13
|
-
# instantiate message, it creates a FreshEnv.
|
14
|
-
class FreshEnvFactory
|
15
|
-
# @return [Array<String>] The names of variables to be.
|
16
|
-
attr_reader :names
|
17
|
-
|
18
|
-
# @return [GoalTemplate] The goal template
|
19
|
-
attr_reader :goal_template
|
20
|
-
|
21
|
-
# @param theNames [Array<String>] The names of variables to build.
|
22
|
-
# @param aGoal [GoalTemplate, Array<Goal>] The goal template(s)
|
23
|
-
def initialize(theNames, aGoalTemplate)
|
24
|
-
@goal_template = valid_goal_template(aGoalTemplate)
|
25
|
-
@names = valid_names(theNames)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Factory method: Create a goal object.
|
29
|
-
# @param formals [Array<FormalArg>] Array of formal arguments
|
30
|
-
# @param actuals [Array<GoalArg>] Array of actual arguments
|
31
|
-
# @return [Goal] instantiate a goal object given the actuals and environment
|
32
|
-
def instantiate(formals, actuals)
|
33
|
-
# require 'debug'
|
34
|
-
goal = goal_template.instantiate(formals, actuals)
|
35
|
-
FreshEnv.new(names, goal, false)
|
36
|
-
end
|
37
|
-
|
38
|
-
protected
|
39
|
-
|
40
|
-
def introspect
|
41
|
-
+", @names=[#{names.join(', ')}]"
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def valid_names(theNames)
|
47
|
-
theNames
|
48
|
-
end
|
49
|
-
|
50
|
-
def valid_goal_template(aGoalTemplate)
|
51
|
-
result = nil
|
52
|
-
|
53
|
-
case aGoalTemplate
|
54
|
-
when FreshEnvFactory
|
55
|
-
result = aGoalTemplate
|
56
|
-
when Core::GoalTemplate
|
57
|
-
result = aGoalTemplate
|
58
|
-
# when Array # an Array of Goal?..
|
59
|
-
# goal_array = aGoalTemplate
|
60
|
-
# loop do
|
61
|
-
# conjunctions = []
|
62
|
-
# goal_array.each_slice(2) do |uno_duo|
|
63
|
-
# if uno_duo.size == 2
|
64
|
-
# conjunctions << Core::GoalTemplate.new(Core::Conj2.instance, uno_duo)
|
65
|
-
# else
|
66
|
-
# conjunctions << uno_duo[0]
|
67
|
-
# end
|
68
|
-
# end
|
69
|
-
# if conjunctions.size == 1
|
70
|
-
# result = conjunctions[0]
|
71
|
-
# break
|
72
|
-
# end
|
73
|
-
# goal_array = conjunctions
|
74
|
-
# end
|
75
|
-
else
|
76
|
-
raise StandardError, "Cannot handle argumment type #{aGoalTemplate.class}"
|
77
|
-
end
|
78
|
-
|
79
|
-
result
|
80
|
-
end
|
81
|
-
end # class
|
82
|
-
end # module
|
83
|
-
end # module
|
@@ -1,192 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
require_relative '../../lib/mini_kraken/core/environment'
|
5
|
-
require_relative '../support/factory_methods'
|
6
|
-
|
7
|
-
# Load the class under test
|
8
|
-
require_relative '../../lib/mini_kraken/core/association_walker'
|
9
|
-
|
10
|
-
|
11
|
-
module MiniKraken
|
12
|
-
module Core
|
13
|
-
describe AssociationWalker do
|
14
|
-
include FactoryMethods
|
15
|
-
|
16
|
-
subject { AssociationWalker.new }
|
17
|
-
|
18
|
-
context 'Initialization:' do
|
19
|
-
it 'should be initialized without argument' do
|
20
|
-
expect { AssociationWalker.new }.not_to raise_error
|
21
|
-
end
|
22
|
-
|
23
|
-
it "shouldn't have any visitee at initialization" do
|
24
|
-
expect(subject.visitees.size).to eq(0)
|
25
|
-
end
|
26
|
-
end # context
|
27
|
-
|
28
|
-
context 'Provided services:' do
|
29
|
-
let(:pea) { KSymbol.new(:pea) }
|
30
|
-
let(:pod) { KSymbol.new(:pod) }
|
31
|
-
let(:var_q) { Variable.new('q') }
|
32
|
-
let(:ref_q) { VariableRef.new('q') }
|
33
|
-
let(:var_x) { Variable.new('x') }
|
34
|
-
let(:ref_x) { VariableRef.new('x') }
|
35
|
-
let(:env) { Environment.new }
|
36
|
-
|
37
|
-
it 'should return composite when it has only atomic term(s)' do
|
38
|
-
expr1 = cons(pea)
|
39
|
-
expect(subject.walk_value(expr1, env)).to eq(expr1)
|
40
|
-
|
41
|
-
expr2 = cons(pea, pod)
|
42
|
-
expect(subject.walk_value(expr2, env)).to eq(expr2)
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'should return composite when it has ground composite term(s)' do
|
46
|
-
expr1 = cons(pea, cons(pod))
|
47
|
-
expect(subject.walk_value(expr1, env)).to eq(expr1)
|
48
|
-
|
49
|
-
expr2 = cons(pea, cons(pod, cons(pea, cons(pod))))
|
50
|
-
expect(subject.walk_value(expr2, env)).to eq(expr2)
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should return nil when there is one fresh variable' do
|
54
|
-
env.add_var(var_q)
|
55
|
-
expr1 = cons(pea, cons(pod, ref_q))
|
56
|
-
expect(subject.walk_value(expr1, env)).to be_nil
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'should return composite when it has ground composite term(s)' do
|
60
|
-
env.add_var(var_q)
|
61
|
-
env.add_assoc('q', pea)
|
62
|
-
expr1 = cons(pea, cons(pod, cons(ref_q)))
|
63
|
-
expect(subject.walk_value(expr1, env)).to eq(expr1)
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'should return nil when no assocation exists' do
|
67
|
-
env.add_var(var_q)
|
68
|
-
env.add_assoc('q', pea)
|
69
|
-
env.add_var(var_x)
|
70
|
-
|
71
|
-
expect(subject.find_ground(var_x.name, env)).to be_nil
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'should find an atomic term directly associated' do
|
75
|
-
env.add_var(var_q)
|
76
|
-
env.add_assoc('q', pea)
|
77
|
-
|
78
|
-
result = subject.find_ground(var_q.name, env)
|
79
|
-
expect(result).to eq(pea)
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'should find an atomic term directly associated' do
|
83
|
-
env.add_var(var_q)
|
84
|
-
env.add_var(var_x)
|
85
|
-
env.add_assoc('q', ref_x)
|
86
|
-
env.add_assoc('x', pea)
|
87
|
-
expect(env['x']).not_to be_nil
|
88
|
-
|
89
|
-
result = subject.find_ground(var_q.name, env)
|
90
|
-
expect(result).to eq(pea)
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'should cope with cyclic structures' do
|
94
|
-
env.add_var(var_q)
|
95
|
-
env.add_var(var_x)
|
96
|
-
env.add_assoc('q', ref_x)
|
97
|
-
env.add_assoc('x', pea)
|
98
|
-
env.add_assoc('x', ref_q)
|
99
|
-
|
100
|
-
result = subject.find_ground(var_q.name, env)
|
101
|
-
expect(result).to eq(pea)
|
102
|
-
|
103
|
-
result = subject.find_ground(var_x.name, env)
|
104
|
-
expect(result).to eq(pea)
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'should cope with a composite with atomic terms only' do
|
108
|
-
env.add_var(var_q)
|
109
|
-
expr = cons(pea, cons(pod, cons(pea)))
|
110
|
-
env.add_assoc('q', expr)
|
111
|
-
|
112
|
-
result = subject.find_ground(var_q.name, env)
|
113
|
-
expect(result).to eq(expr)
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should cope with a composite with one fresh variable' do
|
117
|
-
env.add_var(var_q)
|
118
|
-
env.add_var(var_x)
|
119
|
-
expr = cons(pea, cons(pod, cons(ref_x)))
|
120
|
-
env.add_assoc('q', expr)
|
121
|
-
|
122
|
-
result = subject.find_ground(var_q.name, env)
|
123
|
-
expect(result).to be_nil
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'should cope with a composite with one ground variable' do
|
127
|
-
env.add_var(var_q)
|
128
|
-
env.add_var(var_x)
|
129
|
-
expr = cons(pea, cons(pod, cons(ref_x)))
|
130
|
-
env.add_assoc('q', expr)
|
131
|
-
env.add_assoc('x', pod)
|
132
|
-
|
133
|
-
result = subject.find_ground(var_q.name, env)
|
134
|
-
expect(result).to eq(expr)
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'should categorize a variable without association as free' do
|
138
|
-
env.add_var(var_q)
|
139
|
-
result = subject.determine_freshness(ref_q, env)
|
140
|
-
expect(result).to be_fresh
|
141
|
-
expect(result.associated).to be_nil
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'should categorize a variable related to fresh variable as bound' do
|
145
|
-
env.add_var(var_q)
|
146
|
-
env.add_var(var_x)
|
147
|
-
env.add_assoc('q', ref_x)
|
148
|
-
|
149
|
-
result = subject.determine_freshness(ref_q, env)
|
150
|
-
expect(result).to be_bound
|
151
|
-
expect(result.associated).to eq(ref_x)
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'should categorize a variable even in presence of fused var(s)' do
|
155
|
-
env.add_var(var_q)
|
156
|
-
env.add_var(var_x)
|
157
|
-
env.add_assoc('q', ref_x)
|
158
|
-
env.add_assoc('x', ref_q)
|
159
|
-
# q and x are fused...
|
160
|
-
|
161
|
-
result = subject.determine_freshness(ref_q, env)
|
162
|
-
expect(result).to be_fresh
|
163
|
-
expect(var_q.i_name).to eq(var_x.i_name)
|
164
|
-
expect(env.associations).to be_empty
|
165
|
-
end
|
166
|
-
|
167
|
-
it 'should categorize an atomic term as ground term' do
|
168
|
-
result = subject.determine_freshness(pea, env)
|
169
|
-
expect(result).to be_ground
|
170
|
-
expect(result.associated).to eq(pea)
|
171
|
-
end
|
172
|
-
|
173
|
-
it 'should categorize a composite term as ground term' do
|
174
|
-
# Ground composite: a composite where all members are ground
|
175
|
-
composite = cons(pea, cons(pod))
|
176
|
-
result = subject.determine_freshness(composite, env)
|
177
|
-
expect(result).to be_ground
|
178
|
-
expect(result.associated).to eq(composite)
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'should categorize a composite term as bound term' do
|
182
|
-
# Bound composite: a composite where at least one member is fresh
|
183
|
-
env.add_var(var_q)
|
184
|
-
composite = cons(pea, cons(ref_q))
|
185
|
-
result = subject.determine_freshness(composite, env)
|
186
|
-
expect(result).to be_bound
|
187
|
-
expect(result.associated).to eq(composite)
|
188
|
-
end
|
189
|
-
end # context
|
190
|
-
end # describe
|
191
|
-
end # module
|
192
|
-
end # module
|
data/spec/core/conde_spec.rb
DELETED
@@ -1,147 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
require_relative '../../lib/mini_kraken/core/k_symbol'
|
5
|
-
require_relative '../../lib/mini_kraken/core/fail'
|
6
|
-
require_relative '../../lib/mini_kraken/core/succeed'
|
7
|
-
require_relative '../../lib/mini_kraken/core/equals'
|
8
|
-
require_relative '../../lib/mini_kraken/core/environment'
|
9
|
-
require_relative '../../lib/mini_kraken/core/variable'
|
10
|
-
require_relative '../../lib/mini_kraken/core/variable_ref'
|
11
|
-
|
12
|
-
# Load the class under test
|
13
|
-
require_relative '../../lib/mini_kraken/core/conde'
|
14
|
-
|
15
|
-
module MiniKraken
|
16
|
-
module Core
|
17
|
-
describe Conde do
|
18
|
-
subject { Conde.instance }
|
19
|
-
|
20
|
-
context 'Initialization:' do
|
21
|
-
it 'should be initialized without argument' do
|
22
|
-
expect { Conde.instance }.not_to raise_error
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'should know its name' do
|
26
|
-
expect(subject.name).to eq('conde')
|
27
|
-
end
|
28
|
-
end # context
|
29
|
-
|
30
|
-
context 'Provided services:' do
|
31
|
-
let(:bean) { KSymbol.new(:bean) }
|
32
|
-
let(:corn) { KSymbol.new(:corn) }
|
33
|
-
let(:meal) { KSymbol.new(:meal) }
|
34
|
-
let(:oil) { KSymbol.new(:oil) }
|
35
|
-
let(:olive) { KSymbol.new(:olive) }
|
36
|
-
let(:pea) { KSymbol.new(:pea) }
|
37
|
-
let(:red) { KSymbol.new(:red) }
|
38
|
-
let(:split) { KSymbol.new(:split) }
|
39
|
-
let(:fails) { Goal.new(Fail.instance, []) }
|
40
|
-
let(:succeeds) { Goal.new(Succeed.instance, []) }
|
41
|
-
let(:var_q) { Variable.new('q') }
|
42
|
-
let(:var_x) { Variable.new('x') }
|
43
|
-
let(:var_y) { Variable.new('y') }
|
44
|
-
let(:ref_q) { VariableRef.new('q') }
|
45
|
-
let(:ref_x) { VariableRef.new('x') }
|
46
|
-
let(:ref_y) { VariableRef.new('y') }
|
47
|
-
let(:env) do
|
48
|
-
e = Environment.new
|
49
|
-
e.add_var(var_q)
|
50
|
-
e.add_var(var_x)
|
51
|
-
e.add_var(var_y)
|
52
|
-
e
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'should complain when one of its argument is not a goal' do
|
56
|
-
err = StandardError
|
57
|
-
expect { subject.solver_for([succeeds, pea], env) }.to raise_error(err)
|
58
|
-
expect { subject.solver_for([pea, succeeds], env) }.to raise_error(err)
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'should fail when all goals fail' do
|
62
|
-
solver = subject.solver_for([fails, fails, fails], env)
|
63
|
-
expect(solver.resume).not_to be_success
|
64
|
-
expect(solver.resume).to be_nil
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'yield success if first argument succeeds' do
|
68
|
-
subgoal = Goal.new(Equals.instance, [olive, ref_q])
|
69
|
-
solver = subject.solver_for([subgoal, fails, fails], env)
|
70
|
-
outcome = solver.resume
|
71
|
-
expect(outcome).to be_success
|
72
|
-
expect(outcome.associations['q'].first.value).to eq(olive)
|
73
|
-
expect(solver.resume).to be_nil
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'yield success if second argument succeeds' do
|
77
|
-
subgoal = Goal.new(Equals.instance, [oil, ref_q])
|
78
|
-
solver = subject.solver_for([fails, subgoal, fails], env)
|
79
|
-
outcome = solver.resume
|
80
|
-
expect(outcome).to be_success
|
81
|
-
expect(outcome.associations['q'].first.value).to eq(oil)
|
82
|
-
expect(solver.resume).to be_nil
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'yield success if third argument succeeds' do
|
86
|
-
subgoal = Goal.new(Equals.instance, [oil, ref_q])
|
87
|
-
solver = subject.solver_for([fails, fails, subgoal], env)
|
88
|
-
outcome = solver.resume
|
89
|
-
expect(outcome).to be_success
|
90
|
-
expect(outcome.associations['q'].first.value).to eq(oil)
|
91
|
-
expect(solver.resume).to be_nil
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'yields three solutions if three goals succeed' do
|
95
|
-
# Covers frame 1:58
|
96
|
-
subgoal1 = Goal.new(Equals.instance, [olive, ref_q])
|
97
|
-
subgoal2 = Goal.new(Equals.instance, [oil, ref_q])
|
98
|
-
subgoal3 = Goal.new(Equals.instance, [pea, ref_q])
|
99
|
-
solver = subject.solver_for([subgoal1, subgoal2, subgoal3, fails], env)
|
100
|
-
|
101
|
-
# First solution
|
102
|
-
outcome1 = solver.resume
|
103
|
-
expect(outcome1).to be_success
|
104
|
-
expect(outcome1.associations['q'].first.value).to eq(olive)
|
105
|
-
|
106
|
-
# Second solution
|
107
|
-
outcome2 = solver.resume
|
108
|
-
expect(outcome2).to be_success
|
109
|
-
expect(outcome2.associations['q'].first.value).to eq(oil)
|
110
|
-
|
111
|
-
# Third solution
|
112
|
-
outcome3 = solver.resume
|
113
|
-
expect(outcome3).to be_success
|
114
|
-
expect(outcome3.associations['q'].first.value).to eq(pea)
|
115
|
-
|
116
|
-
expect(solver.resume).to be_nil
|
117
|
-
end
|
118
|
-
|
119
|
-
it 'also use conjunctions for nested goals' do
|
120
|
-
# Covers frame 1:88
|
121
|
-
subgoal1 = Goal.new(Equals.instance, [split, ref_x])
|
122
|
-
subgoal2 = Goal.new(Equals.instance, [pea, ref_y])
|
123
|
-
combo1 = [subgoal1, subgoal2]
|
124
|
-
|
125
|
-
subgoal3 = Goal.new(Equals.instance, [red, ref_x])
|
126
|
-
subgoal4 = Goal.new(Equals.instance, [bean, ref_y])
|
127
|
-
combo2 = [subgoal3, subgoal4]
|
128
|
-
solver = subject.solver_for([combo1, combo2], env)
|
129
|
-
|
130
|
-
# First solution
|
131
|
-
outcome1 = solver.resume
|
132
|
-
expect(outcome1).to be_success
|
133
|
-
expect(outcome1.associations['x'].first.value).to eq(split)
|
134
|
-
expect(outcome1.associations['y'].first.value).to eq(pea)
|
135
|
-
|
136
|
-
# Second solution
|
137
|
-
outcome2 = solver.resume
|
138
|
-
expect(outcome2).to be_success
|
139
|
-
expect(outcome2.associations['x'].first.value).to eq(red)
|
140
|
-
expect(outcome2.associations['y'].first.value).to eq(bean)
|
141
|
-
|
142
|
-
expect(solver.resume).to be_nil
|
143
|
-
end
|
144
|
-
end # context
|
145
|
-
end # describe
|
146
|
-
end # module
|
147
|
-
end # module
|