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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a911e3e7948e5e31bf7cd4f8a4ddb0c8e28964dc29d727391588119626c79160
|
|
4
|
+
data.tar.gz: 678fd624d18377b944f8a747ed14105f0ee4786b49919d9492952ec91d3b9914
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2bf7222f147a9279c25b66a182b0e9ca9f198207a1b8e1ac96b477d2e6ebc4c45f8552501f0e6d62d516c3800f4e8824674fd1990c2865e54efa9d1cc40543c1
|
|
7
|
+
data.tar.gz: c26c98beba1576d766b8017b92eb31943c9a5640d0cc7a2ac16145dcbc596a858109892419844922bb4d36d4e09221c84ed220e2756e299636813d2a2c1d3690
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.1] - 2026-02-26
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Rule Source Introspection**: New `rule_source` and `print_rule_source` methods on `KnowledgeBase` to retrieve and display the DSL source code for any rule by name
|
|
7
|
+
- **Rule Decompiler**: `KBS::Decompiler` can reconstruct source for dynamically-created rules from Proc and Lambda objects
|
|
8
|
+
- **Working Memory Reset**: `KnowledgeBase#reset` now clears working memory while preserving the compiled rule network, enabling reuse with different initial facts
|
|
9
|
+
- **Rule Source Introspection Demo**: New `examples/rule_source_introspection_demo.rb` showcasing both file-based and dynamic rule source retrieval
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- **README rewritten to use DSL API**: Removed references to `KBS::ReteEngine` and `KBS::Rule`; all examples now use the DSL-based `KnowledgeBase` API
|
|
13
|
+
- **Dependencies bumped**: minitest updated to ~> 5.26
|
|
14
|
+
|
|
15
|
+
### Removed
|
|
16
|
+
- Deleted obsolete `expert-systems` example
|
|
17
|
+
- Deleted `DOCUMENTATION_STATUS.md`
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Updated `perform` method signatures in API documentation
|
|
21
|
+
|
|
3
22
|
## [0.1.0] - 2025-10-09
|
|
4
23
|
|
|
5
24
|
### Added
|
data/README.md
CHANGED
|
@@ -71,30 +71,25 @@ gem install kbs
|
|
|
71
71
|
```ruby
|
|
72
72
|
require 'kbs'
|
|
73
73
|
|
|
74
|
-
# Create
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"high_temperature_alert",
|
|
80
|
-
conditions: [
|
|
81
|
-
KBS::Condition.new(:sensor, { type: "temperature" }),
|
|
82
|
-
KBS::Condition.new(:reading, { value: ->(v) { v > 100 } })
|
|
83
|
-
],
|
|
84
|
-
action: lambda do |facts, bindings|
|
|
85
|
-
reading = facts.find { |f| f.type == :reading }
|
|
86
|
-
puts "🚨 HIGH TEMPERATURE: #{reading[:value]}°C"
|
|
87
|
-
end
|
|
88
|
-
)
|
|
74
|
+
# Create knowledge base with DSL
|
|
75
|
+
kb = KBS.knowledge_base do
|
|
76
|
+
rule "high_temperature_alert" do
|
|
77
|
+
on :sensor, type: "temperature"
|
|
78
|
+
on :reading, value: greater_than(100)
|
|
89
79
|
|
|
90
|
-
|
|
80
|
+
perform do |facts, bindings|
|
|
81
|
+
reading = facts.find { |f| f.type == :reading }
|
|
82
|
+
puts "🚨 HIGH TEMPERATURE: #{reading[:value]}°C"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
91
85
|
|
|
92
|
-
# Add facts
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
# Add facts
|
|
87
|
+
fact :sensor, type: "temperature", location: "reactor"
|
|
88
|
+
fact :reading, value: 105, unit: "celsius"
|
|
95
89
|
|
|
96
|
-
# Run inference
|
|
97
|
-
|
|
90
|
+
# Run inference
|
|
91
|
+
run
|
|
92
|
+
end
|
|
98
93
|
# => 🚨 HIGH TEMPERATURE: 105°C
|
|
99
94
|
```
|
|
100
95
|
|
|
@@ -102,7 +97,6 @@ engine.run
|
|
|
102
97
|
|
|
103
98
|
```ruby
|
|
104
99
|
require 'kbs'
|
|
105
|
-
require 'kbs/dsl'
|
|
106
100
|
|
|
107
101
|
kb = KBS.knowledge_base do
|
|
108
102
|
rule "momentum_breakout" do
|
|
@@ -130,18 +124,29 @@ kb.run
|
|
|
130
124
|
```ruby
|
|
131
125
|
require 'kbs/blackboard'
|
|
132
126
|
|
|
133
|
-
# Create persistent blackboard
|
|
134
|
-
engine = KBS::Blackboard::Engine.new(
|
|
135
|
-
|
|
136
|
-
)
|
|
127
|
+
# Create persistent blackboard with DSL
|
|
128
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'knowledge.db')
|
|
129
|
+
|
|
130
|
+
kb = KBS.knowledge_base(engine: engine) do
|
|
131
|
+
rule "temperature_monitor" do
|
|
132
|
+
on :sensor, type: "temperature", value: greater_than(25)
|
|
133
|
+
|
|
134
|
+
perform do |facts|
|
|
135
|
+
sensor = facts.first
|
|
136
|
+
puts "⚠️ High temperature at #{sensor[:location]}: #{sensor[:value]}°C"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
137
139
|
|
|
138
|
-
# Add persistent facts
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
# Add persistent facts
|
|
141
|
+
fact :sensor, type: "temperature", location: "room1", value: 22
|
|
142
|
+
fact :sensor, type: "temperature", location: "room2", value: 28
|
|
143
|
+
|
|
144
|
+
run
|
|
145
|
+
end
|
|
141
146
|
|
|
142
147
|
# Query facts
|
|
143
148
|
sensors = engine.blackboard.get_facts(:sensor)
|
|
144
|
-
sensors.each { |s| puts "#{s[:type]} at #{s[:location]}" }
|
|
149
|
+
sensors.each { |s| puts "#{s[:type]} at #{s[:location]}: #{s[:value]}°C" }
|
|
145
150
|
|
|
146
151
|
# View audit history
|
|
147
152
|
history = engine.blackboard.get_history(limit: 10)
|
|
@@ -155,51 +160,74 @@ end
|
|
|
155
160
|
```ruby
|
|
156
161
|
require 'kbs/blackboard'
|
|
157
162
|
|
|
158
|
-
# High-frequency trading with Redis
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
163
|
+
# High-frequency trading with Redis and DSL
|
|
164
|
+
store = KBS::Blackboard::Persistence::RedisStore.new(url: 'redis://localhost:6379/0')
|
|
165
|
+
engine = KBS::Blackboard::Engine.new(store: store)
|
|
166
|
+
|
|
167
|
+
kb = KBS.knowledge_base(engine: engine) do
|
|
168
|
+
rule "price_alert" do
|
|
169
|
+
on :market_price, volume: greater_than(500_000)
|
|
170
|
+
|
|
171
|
+
perform do |facts|
|
|
172
|
+
price = facts.first
|
|
173
|
+
puts "📊 High volume: #{price[:symbol]} - #{price[:volume]} shares"
|
|
174
|
+
# Post message for other components
|
|
175
|
+
engine.post_message("PriceAlert", "high_volume",
|
|
176
|
+
{ symbol: price[:symbol], volume: price[:volume] },
|
|
177
|
+
priority: 10
|
|
178
|
+
)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
164
181
|
|
|
165
|
-
# Fast in-memory fact storage
|
|
166
|
-
|
|
182
|
+
# Fast in-memory fact storage
|
|
183
|
+
fact :market_price, symbol: "AAPL", price: 150.25, volume: 1_000_000
|
|
167
184
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
{ symbol: "AAPL", bid: 150.24, ask: 150.26 },
|
|
171
|
-
priority: 10
|
|
172
|
-
)
|
|
185
|
+
run
|
|
186
|
+
end
|
|
173
187
|
|
|
174
|
-
|
|
175
|
-
|
|
188
|
+
# Consume messages
|
|
189
|
+
message = engine.consume_message("high_volume", "TradingStrategy")
|
|
190
|
+
puts "Received: #{message[:content]}" if message
|
|
176
191
|
```
|
|
177
192
|
|
|
178
193
|
### AI-Enhanced Reasoning
|
|
179
194
|
|
|
180
195
|
```ruby
|
|
181
196
|
require 'kbs'
|
|
182
|
-
require '
|
|
197
|
+
require 'ruby_llm'
|
|
183
198
|
|
|
184
199
|
# Requires Ollama with a model installed
|
|
185
200
|
# export OLLAMA_MODEL=gpt-oss:latest
|
|
186
201
|
|
|
187
|
-
|
|
202
|
+
kb = KBS.knowledge_base do
|
|
203
|
+
rule "ai_sentiment_analysis" do
|
|
204
|
+
on :news_data, symbol: satisfies { |s| s && s.length > 0 }
|
|
205
|
+
|
|
206
|
+
perform do |facts|
|
|
207
|
+
news = facts.first
|
|
208
|
+
# AI-powered sentiment analysis
|
|
209
|
+
client = RubyLLM::Chat.new(provider: :ollama, model: 'gpt-oss:latest')
|
|
210
|
+
response = client.ask("Analyze sentiment: #{news[:headline]}")
|
|
211
|
+
|
|
212
|
+
puts "🤖 AI SENTIMENT ANALYSIS: #{news[:symbol]}"
|
|
213
|
+
puts " Headline: #{news[:headline]}"
|
|
214
|
+
puts " AI Analysis: #{response.content}"
|
|
215
|
+
end
|
|
216
|
+
end
|
|
188
217
|
|
|
189
|
-
# Add news for AI sentiment analysis
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
})
|
|
218
|
+
# Add news for AI sentiment analysis
|
|
219
|
+
fact :news_data,
|
|
220
|
+
symbol: "AAPL",
|
|
221
|
+
headline: "Apple Reports Record Q4 Earnings, Beats Expectations by 15%",
|
|
222
|
+
content: "Apple Inc. announced exceptional results..."
|
|
195
223
|
|
|
196
|
-
|
|
224
|
+
run
|
|
225
|
+
end
|
|
197
226
|
|
|
198
227
|
# Output:
|
|
199
228
|
# 🤖 AI SENTIMENT ANALYSIS: AAPL
|
|
200
|
-
#
|
|
201
|
-
#
|
|
202
|
-
# Market Impact: bullish
|
|
229
|
+
# Headline: Apple Reports Record Q4 Earnings, Beats Expectations by 15%
|
|
230
|
+
# AI Analysis: positive (92%) - strong earnings growth, bullish outlook
|
|
203
231
|
```
|
|
204
232
|
|
|
205
233
|
## 📚 Examples
|
|
@@ -20,25 +20,19 @@ KBS performance depends on:
|
|
|
20
20
|
require 'benchmark'
|
|
21
21
|
require 'kbs'
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
r.action = lambda do |facts, bindings|
|
|
32
|
-
# Simple action
|
|
23
|
+
kb = KBS.knowledge_base do
|
|
24
|
+
rule "simple_rule" do
|
|
25
|
+
on :fact, value: :v?
|
|
26
|
+
perform do |facts, bindings|
|
|
27
|
+
# Simple action
|
|
28
|
+
end
|
|
33
29
|
end
|
|
34
30
|
end
|
|
35
31
|
|
|
36
|
-
engine.add_rule(rule)
|
|
37
|
-
|
|
38
32
|
# Benchmark fact addition
|
|
39
33
|
time = Benchmark.measure do
|
|
40
34
|
10_000.times do |i|
|
|
41
|
-
|
|
35
|
+
kb.fact :fact, value: i
|
|
42
36
|
end
|
|
43
37
|
end
|
|
44
38
|
|
|
@@ -47,7 +41,7 @@ puts "#{(10_000 / time.real).round(2)} facts/second"
|
|
|
47
41
|
|
|
48
42
|
# Benchmark engine run
|
|
49
43
|
time = Benchmark.measure do
|
|
50
|
-
|
|
44
|
+
kb.run
|
|
51
45
|
end
|
|
52
46
|
|
|
53
47
|
puts "Ran engine in #{time.real} seconds"
|
|
@@ -67,24 +61,39 @@ class KBSBenchmark
|
|
|
67
61
|
def setup_engine
|
|
68
62
|
case @engine_type
|
|
69
63
|
when :memory
|
|
70
|
-
|
|
64
|
+
# Return a new knowledge base context
|
|
65
|
+
@kb_context = :memory
|
|
71
66
|
when :blackboard_sqlite
|
|
72
|
-
|
|
67
|
+
@kb_context = :blackboard_sqlite
|
|
68
|
+
@db_path = ':memory:'
|
|
73
69
|
when :blackboard_redis
|
|
74
70
|
require 'kbs/blackboard/persistence/redis_store'
|
|
75
|
-
|
|
71
|
+
@kb_context = :blackboard_redis
|
|
72
|
+
@store = KBS::Blackboard::Persistence::RedisStore.new(
|
|
76
73
|
url: 'redis://localhost:6379/15' # Test database
|
|
77
74
|
)
|
|
78
|
-
KBS::Blackboard::Engine.new(store: store)
|
|
79
75
|
end
|
|
80
76
|
end
|
|
81
77
|
|
|
82
78
|
def benchmark_fact_addition(count: 10_000)
|
|
83
|
-
|
|
79
|
+
setup_engine
|
|
80
|
+
|
|
81
|
+
kb = case @kb_context
|
|
82
|
+
when :memory
|
|
83
|
+
KBS.knowledge_base do
|
|
84
|
+
# Add facts in benchmark block
|
|
85
|
+
end
|
|
86
|
+
when :blackboard_sqlite
|
|
87
|
+
engine = KBS::Blackboard::Engine.new(db_path: @db_path)
|
|
88
|
+
KBS.knowledge_base(engine: engine)
|
|
89
|
+
when :blackboard_redis
|
|
90
|
+
engine = KBS::Blackboard::Engine.new(store: @store)
|
|
91
|
+
KBS.knowledge_base(engine: engine)
|
|
92
|
+
end
|
|
84
93
|
|
|
85
94
|
time = Benchmark.measure do
|
|
86
95
|
count.times do |i|
|
|
87
|
-
|
|
96
|
+
kb.fact :fact, id: i, value: rand(1000)
|
|
88
97
|
end
|
|
89
98
|
end
|
|
90
99
|
|
|
@@ -96,30 +105,57 @@ class KBSBenchmark
|
|
|
96
105
|
end
|
|
97
106
|
|
|
98
107
|
def benchmark_simple_rules(fact_count: 1000, rule_count: 10)
|
|
99
|
-
|
|
108
|
+
setup_engine
|
|
100
109
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
kb = case @kb_context
|
|
111
|
+
when :memory
|
|
112
|
+
KBS.knowledge_base do
|
|
113
|
+
# Add rules
|
|
114
|
+
rule_count.times do |i|
|
|
115
|
+
rule "rule_#{i}" do
|
|
116
|
+
on :fact, value: :v?
|
|
117
|
+
perform do |facts, bindings|
|
|
118
|
+
# Minimal action
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
107
122
|
|
|
108
|
-
|
|
109
|
-
|
|
123
|
+
# Add facts
|
|
124
|
+
fact_count.times do |i|
|
|
125
|
+
fact :fact, value: i
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
when :blackboard_sqlite
|
|
129
|
+
engine = KBS::Blackboard::Engine.new(db_path: @db_path)
|
|
130
|
+
kb = KBS.knowledge_base(engine: engine) do
|
|
131
|
+
rule_count.times do |i|
|
|
132
|
+
rule "rule_#{i}" do
|
|
133
|
+
on :fact, value: :v?
|
|
134
|
+
perform { }
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
fact_count.times do |i|
|
|
138
|
+
fact :fact, value: i
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
when :blackboard_redis
|
|
142
|
+
engine = KBS::Blackboard::Engine.new(store: @store)
|
|
143
|
+
kb = KBS.knowledge_base(engine: engine) do
|
|
144
|
+
rule_count.times do |i|
|
|
145
|
+
rule "rule_#{i}" do
|
|
146
|
+
on :fact, value: :v?
|
|
147
|
+
perform { }
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
fact_count.times do |i|
|
|
151
|
+
fact :fact, value: i
|
|
110
152
|
end
|
|
111
153
|
end
|
|
112
|
-
engine.add_rule(rule)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# Add facts
|
|
116
|
-
fact_count.times do |i|
|
|
117
|
-
engine.add_fact(:fact, { value: i })
|
|
118
154
|
end
|
|
119
155
|
|
|
120
156
|
# Benchmark engine run
|
|
121
157
|
time = Benchmark.measure do
|
|
122
|
-
|
|
158
|
+
kb.run
|
|
123
159
|
end
|
|
124
160
|
|
|
125
161
|
@results[:simple_rules] = {
|
|
@@ -130,33 +166,33 @@ class KBSBenchmark
|
|
|
130
166
|
end
|
|
131
167
|
|
|
132
168
|
def benchmark_complex_joins(fact_count: 500)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
# Rule with 3-way join
|
|
136
|
-
rule = KBS::Rule.new("complex_join") do |r|
|
|
137
|
-
r.conditions = [
|
|
138
|
-
KBS::Condition.new(:a, { id: :id?, value: :v? }),
|
|
139
|
-
KBS::Condition.new(:b, { a_id: :id?, score: :s? }),
|
|
140
|
-
KBS::Condition.new(:c, { b_score: :s? })
|
|
141
|
-
]
|
|
142
|
-
|
|
143
|
-
r.action = lambda do |facts, bindings|
|
|
144
|
-
# Action
|
|
145
|
-
end
|
|
146
|
-
end
|
|
169
|
+
setup_engine
|
|
147
170
|
|
|
148
|
-
|
|
171
|
+
kb = case @kb_context
|
|
172
|
+
when :memory
|
|
173
|
+
KBS.knowledge_base do
|
|
174
|
+
# Rule with 3-way join
|
|
175
|
+
rule "complex_join" do
|
|
176
|
+
on :a, id: :id?, value: :v?
|
|
177
|
+
on :b, a_id: :id?, score: :s?
|
|
178
|
+
on :c, b_score: :s?
|
|
179
|
+
perform do |facts, bindings|
|
|
180
|
+
# Action
|
|
181
|
+
end
|
|
182
|
+
end
|
|
149
183
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
184
|
+
# Add facts
|
|
185
|
+
fact_count.times do |i|
|
|
186
|
+
fact :a, id: i, value: rand(100)
|
|
187
|
+
fact :b, a_id: i, score: rand(100)
|
|
188
|
+
fact :c, b_score: i
|
|
189
|
+
end
|
|
190
|
+
end
|
|
155
191
|
end
|
|
156
192
|
|
|
157
193
|
# Benchmark
|
|
158
194
|
time = Benchmark.measure do
|
|
159
|
-
|
|
195
|
+
kb.run
|
|
160
196
|
end
|
|
161
197
|
|
|
162
198
|
@results[:complex_joins] = {
|
|
@@ -166,31 +202,28 @@ class KBSBenchmark
|
|
|
166
202
|
end
|
|
167
203
|
|
|
168
204
|
def benchmark_negation(fact_count: 1000)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
# Action
|
|
205
|
+
setup_engine
|
|
206
|
+
|
|
207
|
+
kb = KBS.knowledge_base do
|
|
208
|
+
# Rule with negation
|
|
209
|
+
rule "negation_rule" do
|
|
210
|
+
on :positive, id: :id?
|
|
211
|
+
without :negative, id: :id?
|
|
212
|
+
perform do |facts, bindings|
|
|
213
|
+
# Action
|
|
214
|
+
end
|
|
180
215
|
end
|
|
181
|
-
end
|
|
182
216
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
engine.add_fact(:negative, { id: i }) if i.even?
|
|
217
|
+
# Add facts (50% will match)
|
|
218
|
+
fact_count.times do |i|
|
|
219
|
+
fact :positive, id: i
|
|
220
|
+
fact :negative, id: i if i.even?
|
|
221
|
+
end
|
|
189
222
|
end
|
|
190
223
|
|
|
191
224
|
# Benchmark
|
|
192
225
|
time = Benchmark.measure do
|
|
193
|
-
|
|
226
|
+
kb.run
|
|
194
227
|
end
|
|
195
228
|
|
|
196
229
|
@results[:negation] = {
|