ruleby 0.2 → 0.3
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.
- data/benchmarks/basic_rules.rb +66 -0
- data/benchmarks/joined_rules.rb +73 -0
- data/benchmarks/miss_manners/data.rb +11 -0
- data/benchmarks/miss_manners/miss_manners.rb +11 -1
- data/benchmarks/miss_manners/model.rb +11 -0
- data/benchmarks/miss_manners/rules.rb +49 -110
- data/benchmarks/model.rb +36 -0
- data/examples/example_diagnosis.rb +35 -73
- data/examples/example_hello.rb +20 -22
- data/examples/example_politician.rb +22 -11
- data/examples/example_ticket.rb +40 -85
- data/examples/fibonacci_example1.rb +13 -2
- data/examples/fibonacci_example2.rb +11 -0
- data/examples/fibonacci_rulebook.rb +58 -111
- data/examples/test_self_reference.rb +51 -9
- data/lib/core/atoms.rb +53 -116
- data/lib/core/engine.rb +96 -96
- data/lib/core/nodes.rb +330 -298
- data/lib/core/patterns.rb +36 -39
- data/lib/core/utils.rb +141 -3
- data/lib/dsl/ferrari.rb +263 -0
- data/lib/dsl/letigre.rb +212 -0
- data/lib/dsl/steel.rb +313 -0
- data/lib/rulebook.rb +82 -265
- data/lib/ruleby.rb +13 -0
- metadata +21 -19
- data/benchmarks/50_joined_rules.rb +0 -78
- data/benchmarks/50_rules.rb +0 -57
- data/benchmarks/5_joined_rules.rb +0 -78
- data/benchmarks/5_rules.rb +0 -57
@@ -0,0 +1,66 @@
|
|
1
|
+
# This file is part of the Ruleby project (http://ruleby.org)
|
2
|
+
#
|
3
|
+
# This application is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the Ruby license defined in the
|
5
|
+
# LICENSE.txt file.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
|
8
|
+
#
|
9
|
+
# * Authors: Joe Kutner, Matt Smith
|
10
|
+
#
|
11
|
+
|
12
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
13
|
+
require 'ruleby'
|
14
|
+
require 'model'
|
15
|
+
|
16
|
+
include Ruleby
|
17
|
+
|
18
|
+
class TestRulebook < Rulebook
|
19
|
+
def rules(n)
|
20
|
+
(0..n).each do |index|
|
21
|
+
rule "Rule-#{index}".to_sym do |r|
|
22
|
+
r.when do |has|
|
23
|
+
has.a Account
|
24
|
+
has.a.status = 'standard'
|
25
|
+
has.a.title = 'mr'
|
26
|
+
has.a.account_id = "acc#{index}"
|
27
|
+
end
|
28
|
+
|
29
|
+
r.then do |e,vars|
|
30
|
+
# puts "rule #{index} fired"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_benchmark(rules, facts)
|
38
|
+
puts "running benchmark for: #{rules} rules and #{facts} facts"
|
39
|
+
|
40
|
+
t1 = Time.new
|
41
|
+
engine :engine do |e|
|
42
|
+
TestRulebook.new(e).rules(rules)
|
43
|
+
|
44
|
+
t2 = Time.new
|
45
|
+
diff = t2.to_f - t1.to_f
|
46
|
+
puts 'time to create rule set: ' + diff.to_s
|
47
|
+
for k in (0..facts)
|
48
|
+
e.assert Account.new('standard', 'mr', ('acc'+k.to_s))
|
49
|
+
end
|
50
|
+
|
51
|
+
t3 = Time.new
|
52
|
+
diff = t3.to_f - t2.to_f
|
53
|
+
puts 'time to assert facts: ' + diff.to_s
|
54
|
+
e.match
|
55
|
+
|
56
|
+
t4 = Time.new
|
57
|
+
diff = t4.to_f - t3.to_f
|
58
|
+
puts 'time to run agenda: ' + diff.to_s
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
run_benchmark(5, 500)
|
63
|
+
puts '-------'
|
64
|
+
run_benchmark(50, 500)
|
65
|
+
puts '-------'
|
66
|
+
run_benchmark(500, 500)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# This file is part of the Ruleby project (http://ruleby.org)
|
2
|
+
#
|
3
|
+
# This application is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the Ruby license defined in the
|
5
|
+
# LICENSE.txt file.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
|
8
|
+
#
|
9
|
+
# * Authors: Joe Kutner, Matt Smith
|
10
|
+
#
|
11
|
+
|
12
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
13
|
+
require 'ruleby'
|
14
|
+
require 'model'
|
15
|
+
|
16
|
+
include Ruleby
|
17
|
+
|
18
|
+
class TestRulebook < Rulebook
|
19
|
+
def rules(n)
|
20
|
+
(0..n).each do |index|
|
21
|
+
rule "Rule-#{index}".to_sym do |r|
|
22
|
+
r.when do |has|
|
23
|
+
has.a Account
|
24
|
+
has.a.status = 'standard'
|
25
|
+
has.a.account_id :id
|
26
|
+
|
27
|
+
has.addr Address
|
28
|
+
has.addr.addr_id = :id, :%
|
29
|
+
has.addr.city = 'Foobar'
|
30
|
+
has.addr.state = 'FB'
|
31
|
+
has.addr.zip = '12345'
|
32
|
+
end
|
33
|
+
|
34
|
+
r.then do |e,vars|
|
35
|
+
# puts "rule #{index} fired"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def run_benchmark(rules,facts)
|
43
|
+
puts "running benchmark for: #{rules} rules and #{facts} facts"
|
44
|
+
|
45
|
+
t1 = Time.new
|
46
|
+
engine :engine do |e|
|
47
|
+
TestRulebook.new(e).rules(rules)
|
48
|
+
|
49
|
+
t2 = Time.new
|
50
|
+
diff = t2.to_f - t1.to_f
|
51
|
+
puts 'time to create rule set: ' + diff.to_s
|
52
|
+
|
53
|
+
|
54
|
+
for k in (0..facts)
|
55
|
+
e.assert Account.new('standard', nil, "acc#{k}")
|
56
|
+
e.assert Address.new("acc#{k}",'Foobar', 'FB', '12345')
|
57
|
+
end
|
58
|
+
|
59
|
+
t3 = Time.new
|
60
|
+
diff = t3.to_f - t2.to_f
|
61
|
+
puts 'time to assert facts: ' + diff.to_s
|
62
|
+
|
63
|
+
e.match
|
64
|
+
|
65
|
+
t4 = Time.new
|
66
|
+
diff = t4.to_f - t3.to_f
|
67
|
+
puts 'time to run agenda: ' + diff.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
run_benchmark(5, 50)
|
72
|
+
puts '-------'
|
73
|
+
run_benchmark(50, 50)
|
@@ -1,3 +1,14 @@
|
|
1
|
+
# This file is part of the Ruleby project (http://ruleby.org)
|
2
|
+
#
|
3
|
+
# This application is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the Ruby license defined in the
|
5
|
+
# LICENSE.txt file.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
|
8
|
+
#
|
9
|
+
# * Authors: Joe Kutner, Matt Smith
|
10
|
+
#
|
11
|
+
|
1
12
|
module MissManners
|
2
13
|
class MannersData
|
3
14
|
def initialize
|
@@ -1,6 +1,16 @@
|
|
1
|
+
# This file is part of the Ruleby project (http://ruleby.org)
|
2
|
+
#
|
3
|
+
# This application is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the Ruby license defined in the
|
5
|
+
# LICENSE.txt file.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
|
8
|
+
#
|
9
|
+
# * Authors: Joe Kutner, Matt Smith
|
10
|
+
#
|
11
|
+
|
1
12
|
$LOAD_PATH << File.join(File.dirname(__FILE__), '../../lib/')
|
2
13
|
require 'ruleby'
|
3
|
-
require 'rulebook'
|
4
14
|
require 'model'
|
5
15
|
require 'data'
|
6
16
|
require 'rules'
|
@@ -1,3 +1,14 @@
|
|
1
|
+
# This file is part of the Ruleby project (http://ruleby.org)
|
2
|
+
#
|
3
|
+
# This application is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the Ruby license defined in the
|
5
|
+
# LICENSE.txt file.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
|
8
|
+
#
|
9
|
+
# * Authors: Joe Kutner, Matt Smith
|
10
|
+
#
|
11
|
+
|
1
12
|
module MissManners
|
2
13
|
|
3
14
|
class Chosen
|
@@ -1,163 +1,102 @@
|
|
1
|
+
# This file is part of the Ruleby project (http://ruleby.org)
|
2
|
+
#
|
3
|
+
# This application is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the Ruby license defined in the
|
5
|
+
# LICENSE.txt file.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
|
8
|
+
#
|
9
|
+
# * Authors: Joe Kutner, Matt Smith
|
10
|
+
#
|
11
|
+
|
1
12
|
require 'model'
|
2
13
|
|
3
14
|
module MissManners
|
4
15
|
|
5
|
-
class MannersRulebook < Rulebook
|
16
|
+
class MannersRulebook < Ruleby::Rulebook
|
6
17
|
def rules
|
7
|
-
rule
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
r.then = action do |e,vars|
|
15
|
-
guestName = vars[:guest].name
|
16
|
-
|
18
|
+
rule :assignFirstSeat,
|
19
|
+
[Context,:context, m.state == Context::START_UP],
|
20
|
+
[Guest,:guest],
|
21
|
+
[Count,:count] do |e,vars|
|
22
|
+
guestName = vars[:guest].name
|
17
23
|
seating = Seating.new(vars[:count].value,1,true,1,guestName,1,guestName)
|
18
|
-
e.assert seating
|
19
|
-
|
24
|
+
e.assert seating
|
20
25
|
path = Path.new(vars[:count].value, 1, guestName)
|
21
26
|
e.assert path
|
22
|
-
|
23
27
|
e.retract vars[:count]
|
24
28
|
vars[:count].value = vars[:count].value + 1
|
25
29
|
e.assert vars[:count]
|
26
|
-
|
27
30
|
puts "assign first seat : #{seating.to_s} : #{path.to_s}"
|
28
|
-
|
29
31
|
vars[:context].state = Context::ASSIGN_SEATS
|
30
32
|
e.modify vars[:context]
|
31
|
-
end
|
32
33
|
end
|
33
34
|
|
34
|
-
rule
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
has.g(Guest).&.name(:name).&.sex(:rightGuestSex).&.hobby(:rightGuestHobby)
|
44
|
-
has.g.name = :seatingRightGuestName, :%
|
45
|
-
|
46
|
-
has.lg(Guest).&.name(:leftGuestName).&.sex:sex
|
47
|
-
has.lg.hobby(:hobby).&.hobby = :rightGuestHobby, :%
|
48
|
-
has.lg.sex :rightGuestSex do |s,rgs| s != rgs end
|
49
|
-
|
50
|
-
has.not.path(Path).&.id = :seatingId, :%
|
51
|
-
has.path.guestName = :leftGuestName, :%
|
52
|
-
|
53
|
-
has.not.chosen Chosen
|
54
|
-
has.chosen.id = :seatingId, :%
|
55
|
-
has.chosen.guestName = :leftGuestName, :%
|
56
|
-
has.chosen.hobby = :leftGuestHobby, :%
|
57
|
-
end
|
58
|
-
|
59
|
-
r.then = action do |e,vars|
|
35
|
+
rule :findSeating,
|
36
|
+
[Context,:context, {m.state == Context::ASSIGN_SEATS => :state}],
|
37
|
+
[Count,:count, {m.value => :countValue}],
|
38
|
+
[Seating,:seating, {m.path == true =>:p, m.id=>:seatingId, m.pid=>:seatingPid, m.rightSeat=>:seatingRightSeat, m.rightGuestName=>:seatingRightGuestName}],
|
39
|
+
[Guest,:g, {m.name=>:name, m.sex=>:rightGuestSex, m.hobby=>:rightGuestHobby}, m.name == b(:seatingRightGuestName)],
|
40
|
+
[Guest,:lg, {m.name=>:leftGuestName, m.sex=>:sex, m.hobby == b(:rightGuestHobby) => :hobby}, m.sex(:rightGuestSex, &c{|s,rgs| s != rgs} )],
|
41
|
+
[:~,Path, m.id == b(:seatingId), m.guestName == b(:leftGuestName)],
|
42
|
+
[:~,Chosen, m.id == b(:seatingId), m.guestName == b(:leftGuestName), m.hobby == b(:leftGuestHobby)] do |e,vars|
|
60
43
|
rightSeat = vars[:seatingRightSeat]
|
61
44
|
seatId = vars[:seatingId]
|
62
|
-
countValue = vars[:count].value
|
63
|
-
|
45
|
+
countValue = vars[:count].value
|
64
46
|
seating = Seating.new(countValue,seatId,false,rightSeat,vars[:seatingRightGuestName],rightSeat+1,vars[:leftGuestName])
|
65
47
|
path = Path.new(countValue,rightSeat+1,vars[:leftGuestName])
|
66
|
-
chosen = Chosen.new(seatId, vars[:leftGuestName], vars[:rightGuestHobby] )
|
67
|
-
|
48
|
+
chosen = Chosen.new(seatId, vars[:leftGuestName], vars[:rightGuestHobby] )
|
68
49
|
puts "find seating : #{seating} : #{path} : #{chosen}"
|
69
|
-
|
70
50
|
e.assert seating
|
71
51
|
e.assert path
|
72
52
|
e.assert chosen
|
73
|
-
|
74
53
|
vars[:count].value = countValue + 1
|
75
54
|
e.modify vars[:count]
|
76
|
-
|
77
55
|
vars[:context].state = Context::MAKE_PATH
|
78
56
|
e.modify vars[:context]
|
79
|
-
end
|
80
|
-
|
81
57
|
end
|
82
58
|
|
83
|
-
rule
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
has.seating.path(:p).&.path = false
|
89
|
-
|
90
|
-
has.path(Path).&.guestName(:pathGuestName).&.seat(:pathSeat)
|
91
|
-
has.path.id = :seatingPid, :%
|
92
|
-
|
93
|
-
has.not.path2 Path
|
94
|
-
has.path2.id = :seatingId, :%
|
95
|
-
has.path2.guestName = :pathGuestName, :%
|
96
|
-
end
|
97
|
-
|
98
|
-
r.then = action do |e,vars|
|
59
|
+
rule :makePath,
|
60
|
+
[Context,:context, {m.state == Context::MAKE_PATH => :s}],
|
61
|
+
[Seating,:seating, {m.id=>:seatingId, m.pid=>:seatingPid, m.path == false =>:p}],
|
62
|
+
[Path,:path, {m.guestName=>:pathGuestName, m.seat=>:pathSeat}, m.id == b(:seatingPid)],
|
63
|
+
[:~,Path,m.id == b(:seatingId), m.guestName == b(:pathGuestName)] do |e,vars|
|
99
64
|
path = Path.new(vars[:seatingId],vars[:pathSeat],vars[:pathGuestName])
|
100
65
|
e.assert path
|
101
66
|
puts "make Path : #{path}"
|
102
|
-
end
|
103
67
|
end
|
104
68
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
69
|
+
# NOTE We had to add this because Ruleby's conflict resolution strategy
|
70
|
+
# is not robust enough. If it worked correctly, this priority would not
|
71
|
+
# be nessecary because the 'make path' activations would have more
|
72
|
+
# recent facts supporting it.
|
73
|
+
rule :pathDone, {:priority => -5},
|
74
|
+
[Context,:context, m.state == Context::MAKE_PATH],
|
75
|
+
[Seating,:seating, m.path == false] do |e,vars|
|
112
76
|
vars[:seating].path = true
|
113
|
-
e.modify vars[:seating]
|
114
|
-
|
77
|
+
e.modify vars[:seating]
|
115
78
|
vars[:context].state = Context::CHECK_DONE
|
116
79
|
e.modify vars[:context]
|
117
80
|
puts "path Done : #{vars[:seating]}"
|
118
|
-
end
|
119
|
-
|
120
|
-
# HACK We had to add this because Ruleby's conflict resolution strategy
|
121
|
-
# is not robust enough. If it worked correctly, this priority would not
|
122
|
-
# be nessecary because the 'make path' activations would have more
|
123
|
-
# recent facts supporting it.
|
124
|
-
r.priority = -5
|
125
81
|
end
|
126
82
|
|
127
|
-
rule
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
has.seating(Seating).&.rightSeat = :lastSeat, :%
|
132
|
-
end
|
133
|
-
|
134
|
-
r.then = action do |e,vars|
|
83
|
+
rule :areWeDone,
|
84
|
+
[Context,:context, m.state == Context::CHECK_DONE],
|
85
|
+
[LastSeat,:ls, {m.seat => :lastSeat}],
|
86
|
+
[Seating,:seating, m.rightSeat == b(:lastSeat)] do |e,vars|
|
135
87
|
vars[:context].state = Context::PRINT_RESULTS
|
136
88
|
e.modify vars[:context]
|
137
|
-
end
|
138
89
|
end
|
139
90
|
|
140
|
-
rule
|
141
|
-
|
142
|
-
has.context Context
|
143
|
-
has.context.state = Context::CHECK_DONE
|
144
|
-
end
|
145
|
-
r.then = action do |e,vars|
|
91
|
+
rule :continue, {:priority => -5},
|
92
|
+
[Context,:context,m.state == Context::CHECK_DONE] do |e,vars|
|
146
93
|
vars[:context].state = Context::ASSIGN_SEATS
|
147
94
|
e.modify vars[:context]
|
148
|
-
end
|
149
|
-
r.priority = -5
|
150
95
|
end
|
151
96
|
|
152
|
-
rule
|
153
|
-
|
154
|
-
has.c Context
|
155
|
-
has.c.state = Context::PRINT_RESULTS
|
156
|
-
end
|
157
|
-
|
158
|
-
r.then = action do |e,vars|
|
97
|
+
rule :allDone,
|
98
|
+
[Context,:context,m.state == Context::PRINT_RESULTS] do |e,vars|
|
159
99
|
puts 'All done'
|
160
|
-
end
|
161
100
|
end
|
162
101
|
end
|
163
102
|
end
|
data/benchmarks/model.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# This file is part of the Ruleby project (http://ruleby.org)
|
2
|
+
#
|
3
|
+
# This application is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the Ruby license defined in the
|
5
|
+
# LICENSE.txt file.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
|
8
|
+
#
|
9
|
+
# * Authors: Joe Kutner, Matt Smith
|
10
|
+
#
|
11
|
+
|
12
|
+
class Account
|
13
|
+
def initialize(status, title, account_id)
|
14
|
+
@status = status
|
15
|
+
@title = title
|
16
|
+
@account_id = account_id
|
17
|
+
end
|
18
|
+
|
19
|
+
attr :status, true
|
20
|
+
attr :title, true
|
21
|
+
attr :account_id, true
|
22
|
+
end
|
23
|
+
|
24
|
+
class Address
|
25
|
+
def initialize(addr_id, city, state, zip)
|
26
|
+
@addr_id = addr_id
|
27
|
+
@city = city
|
28
|
+
@state = state
|
29
|
+
@zip = zip
|
30
|
+
end
|
31
|
+
|
32
|
+
attr :addr_id, true
|
33
|
+
attr :city, true
|
34
|
+
attr :state, true
|
35
|
+
attr :zip, true
|
36
|
+
end
|
@@ -1,6 +1,16 @@
|
|
1
|
+
# This file is part of the Ruleby project (http://ruleby.org)
|
2
|
+
#
|
3
|
+
# This application is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the Ruby license defined in the
|
5
|
+
# LICENSE.txt file.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
|
8
|
+
#
|
9
|
+
# * Authors: Joe Kutner, Matt Smith
|
10
|
+
#
|
11
|
+
|
1
12
|
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
2
13
|
require 'ruleby'
|
3
|
-
require 'rulebook'
|
4
14
|
|
5
15
|
class Patient
|
6
16
|
def initialize(name,fever,spots,rash,sore_throat,innoculated)
|
@@ -37,104 +47,56 @@ class Treatment
|
|
37
47
|
attr:treatment,true
|
38
48
|
end
|
39
49
|
|
40
|
-
class DiagnosisRulebook < Rulebook
|
50
|
+
class DiagnosisRulebook < Ruleby::Rulebook
|
41
51
|
def rules
|
42
|
-
rule
|
43
|
-
|
44
|
-
|
45
|
-
exists.p.fever=:high
|
46
|
-
exists.p.spots=true
|
47
|
-
exists.p.innoculated=true
|
48
|
-
end
|
49
|
-
r.then = action do |e,vars|
|
50
|
-
name = vars[:n]
|
52
|
+
rule :Measles, {:priority => 100},
|
53
|
+
[Patient,:p,{m.name=>:n},m.fever==:high,m.spots==true,m.innoculated==true] do |e,v|
|
54
|
+
name = v[:n]
|
51
55
|
e.assert Diagnosis.new(name, :measles)
|
52
|
-
puts "Measles diagnosed for #{name}"
|
53
|
-
end
|
54
|
-
r.priority = 100
|
56
|
+
puts "Measles diagnosed for #{name}"
|
55
57
|
end
|
56
58
|
|
57
|
-
rule
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
exists.p.spots=true
|
62
|
-
|
63
|
-
exists.not.d Diagnosis
|
64
|
-
exists.d.name = :n, :%
|
65
|
-
exists.d.diagnosis = :measles
|
66
|
-
end
|
67
|
-
r.then = action do |e,vars|
|
68
|
-
name = vars[:n]
|
59
|
+
rule :Allergy1,
|
60
|
+
[Patient,:p, {m.name=>:n}, m.spots==true],
|
61
|
+
[:not, Diagnosis, m.name==b(:n), m.diagnosis==:measles] do |e,v|
|
62
|
+
name = v[:n]
|
69
63
|
e.assert Diagnosis.new(name, :allergy)
|
70
64
|
puts "Allergy diagnosed for #{name} from spots and lack of measles"
|
71
|
-
end
|
72
65
|
end
|
73
66
|
|
74
|
-
rule
|
75
|
-
|
76
|
-
|
77
|
-
exists.p.name :n2
|
78
|
-
exists.p.rash = true
|
79
|
-
end
|
80
|
-
r.then = action do |e,vars|
|
81
|
-
name = vars[:n2]
|
67
|
+
rule :Allergy2,
|
68
|
+
[Patient,:p, {m.name=>:n}, m.rash==true] do |e,v|
|
69
|
+
name = v[:n]
|
82
70
|
e.assert Diagnosis.new(name, :allergy)
|
83
71
|
puts "Allergy diagnosed from rash for #{name}"
|
84
|
-
end
|
85
72
|
end
|
86
73
|
|
87
|
-
rule
|
88
|
-
|
89
|
-
|
90
|
-
exists.p.name :n3
|
91
|
-
exists.p.sore_throat=true
|
92
|
-
exists.p.fever do |f| f == :mild || f == :high end
|
93
|
-
end
|
94
|
-
r.then = action do |e,vars|
|
95
|
-
name = vars[:n3]
|
74
|
+
rule :Flu,
|
75
|
+
[Patient,:p, {m.name=>:n}, m.sore_throat==true, m.fever(&c{|f| f==:mild || f==:high})] do |e,v|
|
76
|
+
name = v[:n]
|
96
77
|
e.assert Diagnosis.new(name, :flu)
|
97
78
|
puts "Flu diagnosed for #{name}"
|
98
|
-
end
|
99
79
|
end
|
100
80
|
|
101
|
-
rule
|
102
|
-
|
103
|
-
|
104
|
-
exists.d.name :n4
|
105
|
-
exists.d.diagnosis = :measles
|
106
|
-
end
|
107
|
-
r.then = action do |e,vars|
|
108
|
-
name = vars[:n4]
|
81
|
+
rule :Penicillin,
|
82
|
+
[Diagnosis, :d, {m.name => :n}, m.diagnosis==:measles] do |e,v|
|
83
|
+
name = v[:n]
|
109
84
|
e.assert Treatment.new(name, :penicillin)
|
110
85
|
puts "Penicillin prescribed for #{name}"
|
111
|
-
end
|
112
86
|
end
|
113
87
|
|
114
|
-
rule
|
115
|
-
|
116
|
-
|
117
|
-
exists.d.name :n5
|
118
|
-
exists.d.diagnosis = :allergy
|
119
|
-
end
|
120
|
-
r.then = action do |e,vars|
|
121
|
-
name = vars[:n5]
|
88
|
+
rule :Allergy_pills,
|
89
|
+
[Diagnosis, :d, {m.name => :n}, m.diagnosis==:allergy] do |e,v|
|
90
|
+
name = v[:n]
|
122
91
|
e.assert Treatment.new(name, :allergy_shot)
|
123
92
|
puts "Allergy shot prescribed for #{name}"
|
124
|
-
end
|
125
93
|
end
|
126
94
|
|
127
|
-
rule
|
128
|
-
|
129
|
-
|
130
|
-
exists.d.name :n6
|
131
|
-
exists.d.diagnosis = :flu
|
132
|
-
end
|
133
|
-
r.then = action do |e,vars|
|
134
|
-
name = vars[:n6]
|
95
|
+
rule :Bed_rest,
|
96
|
+
[Diagnosis, :d, {m.name => :n}, m.diagnosis==:flu] do |e,v|
|
97
|
+
name = v[:n]
|
135
98
|
e.assert Treatment.new(name, :bed_rest)
|
136
99
|
puts "Bed rest prescribed for #{name}"
|
137
|
-
end
|
138
100
|
end
|
139
101
|
end
|
140
102
|
end
|