kbs 0.1.0 → 0.2.1
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/CHANGELOG.md +19 -0
- data/README.md +85 -57
- data/docs/advanced/performance.md +109 -76
- data/docs/advanced/testing.md +399 -263
- data/docs/api/blackboard.md +1 -1
- data/docs/api/engine.md +77 -8
- data/docs/api/facts.md +3 -3
- data/docs/api/rules.md +110 -40
- data/docs/architecture/blackboard.md +108 -117
- data/docs/assets/images/fact-rule-relationship.svg +65 -0
- data/docs/assets/images/fact-structure.svg +42 -0
- data/docs/assets/images/inference-cycle.svg +47 -0
- data/docs/assets/images/kb-components.svg +43 -0
- data/docs/assets/images/rule-structure.svg +44 -0
- data/docs/assets/images/trading-signal-network.svg +1 -1
- data/docs/examples/index.md +219 -5
- data/docs/guides/blackboard-memory.md +89 -58
- data/docs/guides/dsl.md +24 -24
- data/docs/guides/getting-started.md +109 -107
- data/docs/guides/writing-rules.md +470 -311
- data/docs/index.md +16 -18
- data/docs/quick-start.md +92 -99
- data/docs/what-is-a-fact.md +694 -0
- data/docs/what-is-a-knowledge-base.md +350 -0
- data/docs/what-is-a-rule.md +833 -0
- data/examples/.gitignore +1 -0
- data/examples/advanced_example_dsl.rb +1 -1
- data/examples/ai_enhanced_kbs_dsl.rb +1 -1
- data/examples/car_diagnostic_dsl.rb +1 -1
- data/examples/concurrent_inference_demo.rb +0 -1
- data/examples/concurrent_inference_demo_dsl.rb +0 -1
- data/examples/csv_trading_system_dsl.rb +1 -1
- data/examples/iot_demo_using_dsl.rb +1 -1
- data/examples/portfolio_rebalancing_system_dsl.rb +1 -1
- data/examples/rule_source_demo.rb +123 -0
- data/examples/stock_trading_advanced_dsl.rb +1 -1
- data/examples/temp_dsl.txt +6214 -5269
- data/examples/timestamped_trading_dsl.rb +1 -1
- data/examples/trading_demo_dsl.rb +1 -1
- data/examples/working_demo_dsl.rb +1 -1
- data/lib/kbs/decompiler.rb +204 -0
- data/lib/kbs/dsl/knowledge_base.rb +100 -1
- data/lib/kbs/dsl.rb +3 -1
- data/lib/kbs/engine.rb +41 -0
- data/lib/kbs/version.rb +1 -1
- data/lib/kbs.rb +14 -12
- data/mkdocs.yml +30 -30
- metadata +15 -10
- data/docs/DOCUMENTATION_STATUS.md +0 -158
- data/docs/examples/expert-systems.md +0 -1031
- data/docs/examples/multi-agent.md +0 -1335
- data/docs/examples/stock-trading.md +0 -488
- data/examples/knowledge_base.db +0 -0
- data/examples/temp.txt +0 -7693
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KBS
|
|
4
|
+
# Reconstruct Ruby source from YARV bytecode.
|
|
5
|
+
#
|
|
6
|
+
# YARV bytecode is a stack machine. We simulate the stack,
|
|
7
|
+
# translating instructions back into Ruby expressions.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# KBS::Decompiler.new(some_proc).decompile # => "proc { |x| x + 1 }"
|
|
11
|
+
# KBS::Decompiler.new(some_lambda).decompile # => "->(x) { x + 1 }"
|
|
12
|
+
# KBS::Decompiler.new(some_proc).decompile_block # => "{ |x| x + 1 }"
|
|
13
|
+
#
|
|
14
|
+
class Decompiler
|
|
15
|
+
def initialize(proc_obj)
|
|
16
|
+
@iseq = RubyVM::InstructionSequence.of(proc_obj)
|
|
17
|
+
@arr = @iseq.to_a
|
|
18
|
+
@locals = @arr[10] # [:a, :b, ...]
|
|
19
|
+
@params = @arr[11] # {lead_num: 2, ...}
|
|
20
|
+
@body = @arr[13] # [1, :EVENT, [:instruction, ...], ...]
|
|
21
|
+
@children = []
|
|
22
|
+
@iseq.each_child { |c| @children << c }
|
|
23
|
+
@child_index = 0
|
|
24
|
+
@lambda = proc_obj.lambda?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def decompile
|
|
28
|
+
expr = decompile_body(@body)
|
|
29
|
+
params = build_params
|
|
30
|
+
if @lambda
|
|
31
|
+
"->(#{params}) { #{expr} }"
|
|
32
|
+
else
|
|
33
|
+
"proc { |#{params}| #{expr} }"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns just the block literal: { |params| body }
|
|
38
|
+
# Useful when the surrounding keyword (perform, satisfies, etc.)
|
|
39
|
+
# is supplied by the caller.
|
|
40
|
+
def decompile_block
|
|
41
|
+
expr = decompile_body(@body)
|
|
42
|
+
params = build_params
|
|
43
|
+
if params.empty?
|
|
44
|
+
"{ #{expr} }"
|
|
45
|
+
else
|
|
46
|
+
"{ |#{params}| #{expr} }"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def build_params
|
|
53
|
+
count = @params[:lead_num] || 0
|
|
54
|
+
@locals.first(count).join(", ")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def decompile_body(body)
|
|
58
|
+
stack = []
|
|
59
|
+
statements = []
|
|
60
|
+
instructions = body.select { |i| i.is_a?(Array) }
|
|
61
|
+
|
|
62
|
+
instructions.each do |inst|
|
|
63
|
+
op = inst[0]
|
|
64
|
+
case op
|
|
65
|
+
when :getlocal_WC_0
|
|
66
|
+
idx = inst[1]
|
|
67
|
+
name = slot_to_name(idx)
|
|
68
|
+
stack.push(name.to_s)
|
|
69
|
+
|
|
70
|
+
when :setlocal_WC_0
|
|
71
|
+
idx = inst[1]
|
|
72
|
+
name = slot_to_name(idx)
|
|
73
|
+
val = stack.pop
|
|
74
|
+
statements << "#{name} = #{val}"
|
|
75
|
+
|
|
76
|
+
when :putobject
|
|
77
|
+
stack.push(inst[1].inspect)
|
|
78
|
+
|
|
79
|
+
when :putobject_INT2FIX_0_
|
|
80
|
+
stack.push("0")
|
|
81
|
+
|
|
82
|
+
when :putobject_INT2FIX_1_
|
|
83
|
+
stack.push("1")
|
|
84
|
+
|
|
85
|
+
when :putself
|
|
86
|
+
stack.push("self")
|
|
87
|
+
|
|
88
|
+
when :putnil
|
|
89
|
+
stack.push("nil")
|
|
90
|
+
|
|
91
|
+
when :putchilledstring, :putstring
|
|
92
|
+
stack.push(inst[1].inspect)
|
|
93
|
+
|
|
94
|
+
when :opt_plus, :opt_minus, :opt_mult, :opt_div, :opt_mod,
|
|
95
|
+
:opt_eq, :opt_neq, :opt_lt, :opt_le, :opt_gt, :opt_ge,
|
|
96
|
+
:opt_ltlt
|
|
97
|
+
op_sym = inst[1][:mid]
|
|
98
|
+
b = stack.pop
|
|
99
|
+
a = stack.pop
|
|
100
|
+
stack.push("#{a} #{op_sym} #{b}")
|
|
101
|
+
|
|
102
|
+
when :opt_send_without_block
|
|
103
|
+
calldata = inst[1]
|
|
104
|
+
method = calldata[:mid]
|
|
105
|
+
argc = calldata[:orig_argc]
|
|
106
|
+
args = stack.pop(argc)
|
|
107
|
+
receiver = stack.pop
|
|
108
|
+
call_str = format_call(receiver, method, args)
|
|
109
|
+
stack.push(call_str)
|
|
110
|
+
|
|
111
|
+
when :send
|
|
112
|
+
calldata = inst[1]
|
|
113
|
+
method = calldata[:mid]
|
|
114
|
+
argc = calldata[:orig_argc]
|
|
115
|
+
args = stack.pop(argc)
|
|
116
|
+
receiver = stack.pop
|
|
117
|
+
|
|
118
|
+
child_iseq = @children[@child_index]
|
|
119
|
+
@child_index += 1
|
|
120
|
+
child_src = decompile_child(child_iseq)
|
|
121
|
+
|
|
122
|
+
base = format_call(receiver, method, args)
|
|
123
|
+
stack.push("#{base} { #{child_src} }")
|
|
124
|
+
|
|
125
|
+
when :newarray
|
|
126
|
+
count = inst[1]
|
|
127
|
+
items = stack.pop(count)
|
|
128
|
+
stack.push("[#{items.join(', ')}]")
|
|
129
|
+
|
|
130
|
+
when :newhash
|
|
131
|
+
count = inst[1]
|
|
132
|
+
pairs = stack.pop(count)
|
|
133
|
+
entries = pairs.each_slice(2).map { |k, v| "#{k} => #{v}" }
|
|
134
|
+
stack.push("{ #{entries.join(', ')} }")
|
|
135
|
+
|
|
136
|
+
when :branchunless
|
|
137
|
+
condition = stack.pop
|
|
138
|
+
remaining = instructions[instructions.index(inst) + 1..]
|
|
139
|
+
true_val = extract_value(remaining, 0)
|
|
140
|
+
false_val = extract_value(remaining, 1)
|
|
141
|
+
if true_val && false_val
|
|
142
|
+
stack.push("#{condition} ? #{true_val} : #{false_val}")
|
|
143
|
+
break
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
when :leave
|
|
147
|
+
# ignore
|
|
148
|
+
|
|
149
|
+
when :pop
|
|
150
|
+
val = stack.pop
|
|
151
|
+
statements << val if val
|
|
152
|
+
|
|
153
|
+
else
|
|
154
|
+
stack.push("/* #{op} */")
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
all = statements + [stack.last].compact
|
|
159
|
+
all.join("; ")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def format_call(receiver, method, args)
|
|
163
|
+
prefix = (receiver == "self") ? "" : "#{receiver}."
|
|
164
|
+
if args.empty?
|
|
165
|
+
"#{prefix}#{method}"
|
|
166
|
+
else
|
|
167
|
+
"#{prefix}#{method}(#{args.join(', ')})"
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def decompile_child(child_iseq)
|
|
172
|
+
child_arr = child_iseq.to_a
|
|
173
|
+
child_locals = child_arr[10]
|
|
174
|
+
child_params = child_arr[11]
|
|
175
|
+
child_body = child_arr[13]
|
|
176
|
+
count = child_params[:lead_num] || 0
|
|
177
|
+
param_names = child_locals.first(count).join(", ")
|
|
178
|
+
|
|
179
|
+
saved = [@locals, @params, @body]
|
|
180
|
+
@locals, @params, @body = child_locals, child_params, child_body
|
|
181
|
+
expr = decompile_body(child_body)
|
|
182
|
+
@locals, @params, @body = saved
|
|
183
|
+
|
|
184
|
+
if count > 0
|
|
185
|
+
"|#{param_names}| #{expr}"
|
|
186
|
+
else
|
|
187
|
+
expr
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def extract_value(instructions, index)
|
|
192
|
+
values = instructions.select { |i|
|
|
193
|
+
i.is_a?(Array) && (i[0] == :putchilledstring || i[0] == :putstring || i[0] == :putobject)
|
|
194
|
+
}
|
|
195
|
+
val = values[index]
|
|
196
|
+
val[1].inspect if val
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def slot_to_name(slot_idx)
|
|
200
|
+
name_idx = @locals.size + 2 - slot_idx
|
|
201
|
+
@locals[name_idx] || "?local_#{slot_idx}"
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
@@ -9,9 +9,11 @@ module KBS
|
|
|
9
9
|
@engine = Engine.new
|
|
10
10
|
@rules = {}
|
|
11
11
|
@rule_builders = {}
|
|
12
|
+
@rule_source_locations = {}
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def rule(name, &block)
|
|
16
|
+
@rule_source_locations[name] = block.source_location if block
|
|
15
17
|
builder = RuleBuilder.new(name)
|
|
16
18
|
builder.instance_eval(&block) if block_given?
|
|
17
19
|
@rule_builders[name] = builder
|
|
@@ -42,7 +44,7 @@ module KBS
|
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def reset
|
|
45
|
-
@engine.
|
|
47
|
+
@engine.reset
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def facts
|
|
@@ -65,6 +67,30 @@ module KBS
|
|
|
65
67
|
puts "-" * 40
|
|
66
68
|
end
|
|
67
69
|
|
|
70
|
+
def rule_source(name)
|
|
71
|
+
# Try file-based source first
|
|
72
|
+
if (location = @rule_source_locations[name])
|
|
73
|
+
file, line = location
|
|
74
|
+
if file && File.exist?(file)
|
|
75
|
+
source = extract_rule_source(file, line)
|
|
76
|
+
return source if source
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Fall back to reconstruction from internal state
|
|
81
|
+
reconstruct_rule_source(name)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def print_rule_source(name)
|
|
85
|
+
source = rule_source(name)
|
|
86
|
+
unless source
|
|
87
|
+
puts "No source available for rule '#{name}'"
|
|
88
|
+
return
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
puts source
|
|
92
|
+
end
|
|
93
|
+
|
|
68
94
|
def print_rules
|
|
69
95
|
puts "Knowledge Base Rules:"
|
|
70
96
|
puts "-" * 40
|
|
@@ -81,6 +107,79 @@ module KBS
|
|
|
81
107
|
end
|
|
82
108
|
puts "-" * 40
|
|
83
109
|
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def reconstruct_rule_source(name)
|
|
114
|
+
builder = @rule_builders[name]
|
|
115
|
+
return nil unless builder
|
|
116
|
+
|
|
117
|
+
lines = []
|
|
118
|
+
lines << "rule #{name.inspect} do"
|
|
119
|
+
lines << " desc #{builder.description.inspect}" if builder.description
|
|
120
|
+
lines << " priority #{builder.priority}" if builder.priority != 0
|
|
121
|
+
|
|
122
|
+
builder.conditions.each do |cond|
|
|
123
|
+
keyword = cond.negated ? "without" : "on"
|
|
124
|
+
pattern_str = reconstruct_pattern(cond.pattern)
|
|
125
|
+
if pattern_str.empty?
|
|
126
|
+
lines << " #{keyword} #{cond.type.inspect}"
|
|
127
|
+
else
|
|
128
|
+
lines << " #{keyword} #{cond.type.inspect}, #{pattern_str}"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
if builder.action_block
|
|
133
|
+
block_str = decompile_proc_block(builder.action_block)
|
|
134
|
+
lines << " perform #{block_str}"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
lines << "end"
|
|
138
|
+
lines.join("\n")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def reconstruct_pattern(pattern)
|
|
142
|
+
return "" if pattern.empty?
|
|
143
|
+
|
|
144
|
+
pattern.map do |key, value|
|
|
145
|
+
val_str = if value.is_a?(Proc)
|
|
146
|
+
Decompiler.new(value).decompile
|
|
147
|
+
else
|
|
148
|
+
value.inspect
|
|
149
|
+
end
|
|
150
|
+
"#{key}: #{val_str}"
|
|
151
|
+
end.join(", ")
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def decompile_proc_block(proc_obj)
|
|
155
|
+
Decompiler.new(proc_obj).decompile_block
|
|
156
|
+
rescue => e
|
|
157
|
+
"{ <decompilation failed: #{e.message}> }"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def extract_rule_source(file, start_line)
|
|
161
|
+
lines = File.readlines(file)
|
|
162
|
+
start_idx = start_line - 1
|
|
163
|
+
return nil if start_idx < 0 || start_idx >= lines.length
|
|
164
|
+
|
|
165
|
+
# source_location points to the block's `do` line, which is
|
|
166
|
+
# normally the same line as the `rule` call. Walk back up to
|
|
167
|
+
# 2 lines in case they are on separate lines.
|
|
168
|
+
rule_idx = start_idx.downto([start_idx - 2, 0].max).find do |i|
|
|
169
|
+
lines[i].match?(/\b(?:rule|defrule)\b/)
|
|
170
|
+
end || start_idx
|
|
171
|
+
|
|
172
|
+
base_indent = lines[rule_idx][/^\s*/].length
|
|
173
|
+
end_pattern = /^\s{#{base_indent}}end\b/
|
|
174
|
+
|
|
175
|
+
result = []
|
|
176
|
+
(rule_idx...lines.length).each do |i|
|
|
177
|
+
result << lines[i]
|
|
178
|
+
break if i > rule_idx && lines[i].match?(end_pattern)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
result.join.chomp
|
|
182
|
+
end
|
|
84
183
|
end
|
|
85
184
|
end
|
|
86
185
|
end
|
data/lib/kbs/dsl.rb
CHANGED
data/lib/kbs/engine.rb
CHANGED
|
@@ -53,6 +53,47 @@ module KBS
|
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
+
# Clear all transient RETE state while preserving the compiled rule network.
|
|
57
|
+
#
|
|
58
|
+
# The RETE network has four levels of transient state:
|
|
59
|
+
# 1. WorkingMemory — holds all asserted facts
|
|
60
|
+
# 2. AlphaMemory — holds facts matching each pattern
|
|
61
|
+
# 3. BetaMemory — holds tokens from condition joins
|
|
62
|
+
# 4. ProductionNode — holds tokens ready to fire
|
|
63
|
+
#
|
|
64
|
+
# Simply clearing working memory facts doesn't cascade reliably
|
|
65
|
+
# through intermediate beta memories. Stale tokens in beta memories
|
|
66
|
+
# cause false matches when new facts are asserted on the next cycle.
|
|
67
|
+
#
|
|
68
|
+
# This method clears all four levels directly while preserving the
|
|
69
|
+
# root beta memory's dummy token (needed for first-condition joins).
|
|
70
|
+
def reset
|
|
71
|
+
# 1. Clear working memory directly (bypass observer — we clear everything)
|
|
72
|
+
@working_memory.facts.clear
|
|
73
|
+
|
|
74
|
+
# 2. Clear alpha memories and their downstream beta memories
|
|
75
|
+
@alpha_memories.each_value do |alpha_mem|
|
|
76
|
+
alpha_mem.items.clear
|
|
77
|
+
|
|
78
|
+
# Each alpha memory successor is a JoinNode or NegationNode.
|
|
79
|
+
# Their successors are intermediate BetaMemory nodes.
|
|
80
|
+
# The root beta memory is never a join node successor, so
|
|
81
|
+
# its dummy token is preserved.
|
|
82
|
+
alpha_mem.successors.each do |join_node|
|
|
83
|
+
next unless join_node.respond_to?(:successors)
|
|
84
|
+
join_node.successors.each do |beta_or_prod|
|
|
85
|
+
beta_or_prod.tokens.clear if beta_or_prod.respond_to?(:tokens)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# 3. Clear production node tokens
|
|
91
|
+
@production_nodes.each_value { |node| node.tokens.clear }
|
|
92
|
+
|
|
93
|
+
# 4. Clear stale child references from the root dummy token
|
|
94
|
+
@root_beta_memory.tokens.each { |t| t.children.clear }
|
|
95
|
+
end
|
|
96
|
+
|
|
56
97
|
private
|
|
57
98
|
|
|
58
99
|
def build_network_for_rule(rule)
|
data/lib/kbs/version.rb
CHANGED
data/lib/kbs.rb
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative 'kbs/version'
|
|
4
4
|
|
|
5
5
|
# Core RETE classes
|
|
6
|
-
require_relative
|
|
7
|
-
require_relative
|
|
8
|
-
require_relative
|
|
9
|
-
require_relative
|
|
10
|
-
require_relative
|
|
11
|
-
require_relative
|
|
12
|
-
require_relative
|
|
13
|
-
require_relative
|
|
14
|
-
require_relative
|
|
15
|
-
require_relative
|
|
16
|
-
require_relative
|
|
6
|
+
require_relative 'kbs/fact'
|
|
7
|
+
require_relative 'kbs/working_memory'
|
|
8
|
+
require_relative 'kbs/token'
|
|
9
|
+
require_relative 'kbs/alpha_memory'
|
|
10
|
+
require_relative 'kbs/beta_memory'
|
|
11
|
+
require_relative 'kbs/join_node'
|
|
12
|
+
require_relative 'kbs/negation_node'
|
|
13
|
+
require_relative 'kbs/production_node'
|
|
14
|
+
require_relative 'kbs/condition'
|
|
15
|
+
require_relative 'kbs/rule'
|
|
16
|
+
require_relative 'kbs/engine'
|
|
17
|
+
require_relative 'kbs/decompiler'
|
|
18
|
+
require_relative 'kbs/dsl'
|
|
17
19
|
|
|
18
20
|
module KBS
|
|
19
21
|
class Error < StandardError; end
|
data/mkdocs.yml
CHANGED
|
@@ -143,39 +143,39 @@ extra:
|
|
|
143
143
|
|
|
144
144
|
# Navigation
|
|
145
145
|
nav:
|
|
146
|
-
- Home:
|
|
146
|
+
- Home:
|
|
147
|
+
- index.md
|
|
148
|
+
- What is aKnowledge Base?: what-is-a-knowledge-base.md
|
|
149
|
+
- What is a Fact?: what-is-a-fact.md
|
|
150
|
+
- What is a Rule?: what-is-a-rule.md
|
|
147
151
|
- Installation: installation.md
|
|
148
152
|
- Quick Start: quick-start.md
|
|
149
153
|
- Architecture:
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
- architecture/index.md
|
|
155
|
+
- RETE Algorithm: architecture/rete-algorithm.md
|
|
156
|
+
- Blackboard System: architecture/blackboard.md
|
|
157
|
+
- Network Structure: architecture/network-structure.md
|
|
154
158
|
- Guides:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
- Examples:
|
|
166
|
-
- examples/index.md
|
|
167
|
-
- Stock Trading: examples/stock-trading.md
|
|
168
|
-
- Expert Systems: examples/expert-systems.md
|
|
169
|
-
- Multi-Agent Systems: examples/multi-agent.md
|
|
159
|
+
- guides/index.md
|
|
160
|
+
- Getting Started: guides/getting-started.md
|
|
161
|
+
- Writing Rules: guides/writing-rules.md
|
|
162
|
+
- DSL Reference: guides/dsl.md
|
|
163
|
+
- Working with Facts: guides/facts.md
|
|
164
|
+
- Pattern Matching: guides/pattern-matching.md
|
|
165
|
+
- Variable Binding: guides/variable-binding.md
|
|
166
|
+
- Negation: guides/negation.md
|
|
167
|
+
- Blackboard Memory: guides/blackboard-memory.md
|
|
168
|
+
- Persistence Options: guides/persistence.md
|
|
169
|
+
- Examples: examples/index.md
|
|
170
170
|
- Advanced:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
- advanced/index.md
|
|
172
|
+
- Performance Tuning: advanced/performance.md
|
|
173
|
+
- Custom Persistence: advanced/custom-persistence.md
|
|
174
|
+
- Debugging: advanced/debugging.md
|
|
175
|
+
- Testing Rules: advanced/testing.md
|
|
176
176
|
- API Reference:
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
- api/index.md
|
|
178
|
+
- ReteEngine: api/engine.md
|
|
179
|
+
- Facts: api/facts.md
|
|
180
|
+
- Rules: api/rules.md
|
|
181
|
+
- Blackboard: api/blackboard.md
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kbs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dewayne VanHoozer
|
|
@@ -13,14 +13,14 @@ dependencies:
|
|
|
13
13
|
name: sqlite3
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: '1.6'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- - "
|
|
23
|
+
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '1.6'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
@@ -90,7 +90,6 @@ files:
|
|
|
90
90
|
- LICENSE.txt
|
|
91
91
|
- README.md
|
|
92
92
|
- Rakefile
|
|
93
|
-
- docs/DOCUMENTATION_STATUS.md
|
|
94
93
|
- docs/advanced/custom-persistence.md
|
|
95
94
|
- docs/advanced/debugging.md
|
|
96
95
|
- docs/advanced/index.md
|
|
@@ -109,16 +108,18 @@ files:
|
|
|
109
108
|
- docs/assets/images/blackboard-architecture.svg
|
|
110
109
|
- docs/assets/images/compiled-network.svg
|
|
111
110
|
- docs/assets/images/fact-assertion-flow.svg
|
|
111
|
+
- docs/assets/images/fact-rule-relationship.svg
|
|
112
|
+
- docs/assets/images/fact-structure.svg
|
|
113
|
+
- docs/assets/images/inference-cycle.svg
|
|
114
|
+
- docs/assets/images/kb-components.svg
|
|
112
115
|
- docs/assets/images/kbs.jpg
|
|
113
116
|
- docs/assets/images/pattern-matching-trace.svg
|
|
114
117
|
- docs/assets/images/rete-network-layers.svg
|
|
118
|
+
- docs/assets/images/rule-structure.svg
|
|
115
119
|
- docs/assets/images/system-layers.svg
|
|
116
120
|
- docs/assets/images/trading-signal-network.svg
|
|
117
121
|
- docs/assets/js/mathjax.js
|
|
118
|
-
- docs/examples/expert-systems.md
|
|
119
122
|
- docs/examples/index.md
|
|
120
|
-
- docs/examples/multi-agent.md
|
|
121
|
-
- docs/examples/stock-trading.md
|
|
122
123
|
- docs/guides/blackboard-memory.md
|
|
123
124
|
- docs/guides/dsl.md
|
|
124
125
|
- docs/guides/facts.md
|
|
@@ -132,6 +133,10 @@ files:
|
|
|
132
133
|
- docs/index.md
|
|
133
134
|
- docs/installation.md
|
|
134
135
|
- docs/quick-start.md
|
|
136
|
+
- docs/what-is-a-fact.md
|
|
137
|
+
- docs/what-is-a-knowledge-base.md
|
|
138
|
+
- docs/what-is-a-rule.md
|
|
139
|
+
- examples/.gitignore
|
|
135
140
|
- examples/README.md
|
|
136
141
|
- examples/advanced_example.rb
|
|
137
142
|
- examples/advanced_example_dsl.rb
|
|
@@ -146,17 +151,16 @@ files:
|
|
|
146
151
|
- examples/csv_trading_system.rb
|
|
147
152
|
- examples/csv_trading_system_dsl.rb
|
|
148
153
|
- examples/iot_demo_using_dsl.rb
|
|
149
|
-
- examples/knowledge_base.db
|
|
150
154
|
- examples/portfolio_rebalancing_system.rb
|
|
151
155
|
- examples/portfolio_rebalancing_system_dsl.rb
|
|
152
156
|
- examples/redis_trading_demo.rb
|
|
153
157
|
- examples/redis_trading_demo_dsl.rb
|
|
158
|
+
- examples/rule_source_demo.rb
|
|
154
159
|
- examples/run_all.rb
|
|
155
160
|
- examples/run_all_dsl.rb
|
|
156
161
|
- examples/sample_stock_data.csv
|
|
157
162
|
- examples/stock_trading_advanced.rb
|
|
158
163
|
- examples/stock_trading_advanced_dsl.rb
|
|
159
|
-
- examples/temp.txt
|
|
160
164
|
- examples/temp_dsl.txt
|
|
161
165
|
- examples/timestamped_trading.rb
|
|
162
166
|
- examples/timestamped_trading_dsl.rb
|
|
@@ -180,6 +184,7 @@ files:
|
|
|
180
184
|
- lib/kbs/blackboard/redis_audit_log.rb
|
|
181
185
|
- lib/kbs/blackboard/redis_message_queue.rb
|
|
182
186
|
- lib/kbs/condition.rb
|
|
187
|
+
- lib/kbs/decompiler.rb
|
|
183
188
|
- lib/kbs/dsl.rb
|
|
184
189
|
- lib/kbs/dsl/condition_helpers.rb
|
|
185
190
|
- lib/kbs/dsl/knowledge_base.rb
|
|
@@ -217,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
217
222
|
- !ruby/object:Gem::Version
|
|
218
223
|
version: '0'
|
|
219
224
|
requirements: []
|
|
220
|
-
rubygems_version:
|
|
225
|
+
rubygems_version: 4.0.7
|
|
221
226
|
specification_version: 4
|
|
222
227
|
summary: Knowledge-Based System with RETE inference, Blackboard architecture, and
|
|
223
228
|
AI integration
|