fuzzyrb 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/Manifest.txt +4 -2
- data/README.txt +1 -1
- data/Rakefile +15 -8
- data/index.html +12 -0
- data/lib/fuzzy.rb +3 -3
- data/lib/fuzzy_implication.rb +31 -0
- data/lib/fuzzy_rule.rb +23 -12
- data/lib/fuzzy_set.rb +46 -35
- data/test/test_fuzzy.rb +2 -1
- data/test/test_fuzzy_implication.rb +35 -0
- data/test/test_fuzzy_rule.rb +18 -0
- data.tar.gz.sig +0 -0
- metadata +8 -5
- metadata.gz.sig +0 -0
- data/lib/fuzzy_inference.rb +0 -19
- data/test/test_fuzzy_inference.rb +0 -27
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -2,12 +2,14 @@ History.txt
|
|
2
2
|
Manifest.txt
|
3
3
|
README.txt
|
4
4
|
Rakefile
|
5
|
+
index.html
|
5
6
|
lib/fuzzy.rb
|
6
|
-
lib/
|
7
|
+
lib/fuzzy_implication.rb
|
7
8
|
lib/fuzzy_rule.rb
|
8
9
|
lib/fuzzy_set.rb
|
9
10
|
lib/line.rb
|
10
11
|
lib/point.rb
|
11
12
|
test/test_fuzzy.rb
|
12
|
-
test/
|
13
|
+
test/test_fuzzy_implication.rb
|
14
|
+
test/test_fuzzy_rule.rb
|
13
15
|
test/test_fuzzy_set.rb
|
data/README.txt
CHANGED
data/Rakefile
CHANGED
@@ -4,14 +4,21 @@ require 'rubygems'
|
|
4
4
|
require 'hoe'
|
5
5
|
require './lib/fuzzy.rb'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
namespace :hoe do
|
8
|
+
Hoe.new('fuzzyrb', Fuzzyrb::VERSION) do |p|
|
9
|
+
p.rubyforge_name = 'fuzzyrb'
|
10
|
+
p.author = 'Roman Kamyk'
|
11
|
+
p.email = 'roman.kamyk@gmail.com'
|
12
|
+
p.summary = 'Fuzzy Sets for Ruby'
|
13
|
+
p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
|
14
|
+
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
15
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
task :publish => ['hoe:release', 'hoe:post_news', 'hoe:publish_docs'] do
|
20
|
+
sh "svn ci -m '#{@changes}'"
|
21
|
+
sh "hg ci -m '#{@changes}'"
|
15
22
|
end
|
16
23
|
|
17
24
|
# vim: syntax=Ruby
|
data/index.html
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
6
|
+
<title>redirect</title>
|
7
|
+
<meta http-equiv="Refresh" content="1; URL=fuzzyrb/">
|
8
|
+
</head>
|
9
|
+
<body id="index">
|
10
|
+
Please see: <a href="http://fuzzyrb.rubyforge.org/fuzzyrb/">documentation</a>.
|
11
|
+
</body>
|
12
|
+
</html>
|
data/lib/fuzzy.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
class FuzzyImplication
|
2
|
+
def initialize(rules)
|
3
|
+
@rules = rules
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class TakagiSugenoImplication < FuzzyImplication
|
8
|
+
def evaluate(t_norm, values)
|
9
|
+
sum = 0
|
10
|
+
result = @rules.map { |rule|
|
11
|
+
rule.evaluate(t_norm, :takagiSugeno, values)
|
12
|
+
}.inject(0) { |s, rv| sum += rv[1]; s + rv[0] }
|
13
|
+
return 0 if sum == 0
|
14
|
+
result/sum
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class MamdamiImplication < FuzzyImplication
|
19
|
+
def evaluate(t_norm, implication, defuzzification, values)
|
20
|
+
result = @rules.map { |rule|
|
21
|
+
rule.evaluate(t_norm, implication, values)
|
22
|
+
}.inject { |s, r| s + r }
|
23
|
+
if defuzzification == :CoG
|
24
|
+
return result.centerOfGravity
|
25
|
+
elsif defuzzification == :firstMin
|
26
|
+
return result.firstMinimum
|
27
|
+
else
|
28
|
+
raise Exception.new("Invalid deffuzification method")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/fuzzy_rule.rb
CHANGED
@@ -3,22 +3,33 @@ class FuzzyRule
|
|
3
3
|
@arguments = arguments
|
4
4
|
@result = result
|
5
5
|
end
|
6
|
+
|
7
|
+
def evaluate(t_norm, implication, values)
|
8
|
+
if t_norm == :min
|
9
|
+
val = argumentsValues(values).min
|
10
|
+
elsif t_norm == :mult
|
11
|
+
val = argumentsValues(values).inject(1) { |mult, v| mult*v}
|
12
|
+
elsif
|
13
|
+
raise Exception.new("Invalid t_norm")
|
14
|
+
end
|
15
|
+
if implication == :mamdani
|
16
|
+
return @result.min(val)
|
17
|
+
elsif implication == :larsen
|
18
|
+
return @result.scale(val)
|
19
|
+
elsif implication == :takagiSugeno
|
20
|
+
#rule value and certainity
|
21
|
+
return [@result.call(values), val]
|
22
|
+
else
|
23
|
+
raise Exception.new("Invalid type")
|
24
|
+
end
|
25
|
+
end
|
6
26
|
|
7
|
-
|
27
|
+
private
|
28
|
+
def argumentsValues(values)
|
8
29
|
tmp = []
|
9
30
|
for i in 0..(values.length-1)
|
10
31
|
tmp << @arguments[i][values[i]]
|
11
32
|
end
|
12
|
-
tmp
|
13
|
-
end
|
14
|
-
|
15
|
-
def larsen(values)
|
16
|
-
min = minOfArguments(values)
|
17
|
-
@result.scale(min)
|
18
|
-
end
|
19
|
-
|
20
|
-
def mandani(values)
|
21
|
-
min = minOfArguments(values)
|
22
|
-
@result.min(min)
|
33
|
+
tmp
|
23
34
|
end
|
24
35
|
end
|
data/lib/fuzzy_set.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
EPSILON = 0.0001
|
2
2
|
SCALE = 1
|
3
3
|
class FuzzySet
|
4
|
-
def initialize(points)
|
5
|
-
@points = points.sort
|
6
|
-
end
|
7
|
-
|
8
4
|
def self.trapezoid(array)
|
9
5
|
raise Exception.new("Trapezoid must have array length 4") if array.length != 4
|
10
6
|
points = []
|
@@ -14,38 +10,11 @@ class FuzzySet
|
|
14
10
|
points << Point.new(array[3], 0)
|
15
11
|
FuzzySet.new(points)
|
16
12
|
end
|
17
|
-
|
18
|
-
def
|
19
|
-
|
20
|
-
for i in 1..@points.length-1
|
21
|
-
lines << Line.new(@points[i], @points[i-1])
|
22
|
-
end
|
23
|
-
lines
|
13
|
+
|
14
|
+
def initialize(points)
|
15
|
+
@points = points.sort
|
24
16
|
end
|
25
17
|
|
26
|
-
def intersections(other)
|
27
|
-
if other.is_a?(Line)
|
28
|
-
points = []
|
29
|
-
toLines.each { |mline|
|
30
|
-
points << mline.intersect(other)
|
31
|
-
}
|
32
|
-
points.select { |point| (self[point.x]-point.y).abs <= EPSILON }
|
33
|
-
elsif other.is_a?(FuzzySet)
|
34
|
-
myLines = toLines
|
35
|
-
points = []
|
36
|
-
other.toLines.each { |line|
|
37
|
-
myLines.each { |mline|
|
38
|
-
points << mline.intersect(line)
|
39
|
-
}
|
40
|
-
}
|
41
|
-
points.select { |point|
|
42
|
-
(self[point.x]-point.y).abs + (other[point.x]-point.y).abs <= EPSILON
|
43
|
-
}
|
44
|
-
else
|
45
|
-
raise Exception.new("Unable to count intersection")
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
18
|
def +(other)
|
50
19
|
points = [@points, other.points, intersections(other)].flatten.uniq.sort
|
51
20
|
res = points.reject { |point|
|
@@ -72,7 +41,7 @@ class FuzzySet
|
|
72
41
|
end
|
73
42
|
attr_reader :points
|
74
43
|
|
75
|
-
def
|
44
|
+
def centerOfGravity()
|
76
45
|
nominator = 0.0
|
77
46
|
denominator = 0.0
|
78
47
|
for i in 1..@points.length-1
|
@@ -85,6 +54,16 @@ class FuzzySet
|
|
85
54
|
nominator/denominator
|
86
55
|
end
|
87
56
|
|
57
|
+
def firstMinimum()
|
58
|
+
maxIdx = 0
|
59
|
+
for i in 0..@points.length-1
|
60
|
+
if @points[i].y > @points[maxIdx].y
|
61
|
+
maxIdx = i
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@points[maxIdx].x
|
65
|
+
end
|
66
|
+
|
88
67
|
def scale(factor)
|
89
68
|
fs = FuzzySet.new(@points.map { |p| p.clone() })
|
90
69
|
fs.scale!(factor)
|
@@ -112,4 +91,36 @@ class FuzzySet
|
|
112
91
|
y2 = @points[idx].y
|
113
92
|
return 1.0*(y2 - y1)/(x2-x1) * (value - x1) + y1
|
114
93
|
end
|
94
|
+
|
95
|
+
def toLines
|
96
|
+
lines = []
|
97
|
+
for i in 1..@points.length-1
|
98
|
+
lines << Line.new(@points[i], @points[i-1])
|
99
|
+
end
|
100
|
+
lines
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
def intersections(other)
|
105
|
+
if other.is_a?(Line)
|
106
|
+
points = []
|
107
|
+
toLines.each { |mline|
|
108
|
+
points << mline.intersect(other)
|
109
|
+
}
|
110
|
+
points.select { |point| (self[point.x]-point.y).abs <= EPSILON }
|
111
|
+
elsif other.is_a?(FuzzySet)
|
112
|
+
myLines = toLines
|
113
|
+
points = []
|
114
|
+
other.toLines.each { |line|
|
115
|
+
myLines.each { |mline|
|
116
|
+
points << mline.intersect(line)
|
117
|
+
}
|
118
|
+
}
|
119
|
+
points.select { |point|
|
120
|
+
(self[point.x]-point.y).abs + (other[point.x]-point.y).abs <= EPSILON
|
121
|
+
}
|
122
|
+
else
|
123
|
+
raise Exception.new("Unable to count intersection")
|
124
|
+
end
|
125
|
+
end
|
115
126
|
end
|
data/test/test_fuzzy.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
3
|
+
require 'test/unit'
|
4
|
+
require 'fuzzy'
|
5
|
+
|
6
|
+
class TestFuzzyImplication < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
a11 = FuzzySet.trapezoid([4, 5, 5, 10])
|
9
|
+
a12 = FuzzySet.trapezoid([10, 19, 19, 20])
|
10
|
+
a21 = FuzzySet.trapezoid([4, 9, 9, 10])
|
11
|
+
a22 = FuzzySet.trapezoid([10, 12, 13, 20])
|
12
|
+
b1 = FuzzySet.trapezoid([20, 30, 30, 40])
|
13
|
+
b2 = FuzzySet.trapezoid([30, 45, 45, 50])
|
14
|
+
r1 = FuzzyRule.new([a11, a12], b1)
|
15
|
+
r2 = FuzzyRule.new([a21, a22], b2)
|
16
|
+
@fi = MamdamiImplication.new([r1, r2])
|
17
|
+
|
18
|
+
tr1 = FuzzyRule.new([a11, a12], Proc.new { |a, b| a+b })
|
19
|
+
tr2 = FuzzyRule.new([a21, a22], Proc.new { |a, b| a-b })
|
20
|
+
@tsi = TakagiSugenoImplication.new([tr1, tr2])
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_mamdani
|
24
|
+
assert_in_delta 33.71, @fi.evaluate(:min, :mamdani, :CoG, [7, 18]), 0.005
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_larsen
|
28
|
+
assert_in_delta 33.58, @fi.evaluate(:min, :larsen, :CoG, [7, 18]), 0.005
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_takagi_sugeno
|
32
|
+
assert_equal 0, @tsi.evaluate(:min, [10, 20])
|
33
|
+
assert_equal 8.75, @tsi.evaluate(:min, [5, 19])
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
3
|
+
require 'test/unit'
|
4
|
+
require 'fuzzy'
|
5
|
+
|
6
|
+
class TestFuzzyRule < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
a11 = FuzzySet.trapezoid([4, 5, 5, 10])
|
9
|
+
a12 = FuzzySet.trapezoid([8, 10, 12, 20])
|
10
|
+
@rule = FuzzyRule.new([a11, a12], Proc.new {|a, b| a+b})
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_larsen
|
14
|
+
assert_equal [25, 0.25], @rule.evaluate(:min, :takagiSugeno, [7, 18])
|
15
|
+
assert_equal [16, 1], @rule.evaluate(:min, :takagiSugeno, [5, 11])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: fuzzyrb
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2007-11-
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2007-11-15 00:00:00 +01:00
|
8
8
|
summary: Fuzzy Sets for Ruby
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -55,18 +55,21 @@ files:
|
|
55
55
|
- Manifest.txt
|
56
56
|
- README.txt
|
57
57
|
- Rakefile
|
58
|
+
- index.html
|
58
59
|
- lib/fuzzy.rb
|
59
|
-
- lib/
|
60
|
+
- lib/fuzzy_implication.rb
|
60
61
|
- lib/fuzzy_rule.rb
|
61
62
|
- lib/fuzzy_set.rb
|
62
63
|
- lib/line.rb
|
63
64
|
- lib/point.rb
|
64
65
|
- test/test_fuzzy.rb
|
65
|
-
- test/
|
66
|
+
- test/test_fuzzy_implication.rb
|
67
|
+
- test/test_fuzzy_rule.rb
|
66
68
|
- test/test_fuzzy_set.rb
|
67
69
|
test_files:
|
68
70
|
- test/test_fuzzy.rb
|
69
|
-
- test/
|
71
|
+
- test/test_fuzzy_implication.rb
|
72
|
+
- test/test_fuzzy_rule.rb
|
70
73
|
- test/test_fuzzy_set.rb
|
71
74
|
rdoc_options:
|
72
75
|
- --main
|
metadata.gz.sig
CHANGED
Binary file
|
data/lib/fuzzy_inference.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
class FuzzyInference
|
2
|
-
def initialize(rules)
|
3
|
-
@rules = rules
|
4
|
-
end
|
5
|
-
|
6
|
-
def mandani(values)
|
7
|
-
result = @rules.map { |rule|
|
8
|
-
rule.mandani(values)
|
9
|
-
}.inject { |s, r| s + r }
|
10
|
-
result.weigthCenter
|
11
|
-
end
|
12
|
-
|
13
|
-
def larsen(values)
|
14
|
-
result = @rules.map { |rule|
|
15
|
-
rule.larsen(values)
|
16
|
-
}.inject { |s, r| s + r }
|
17
|
-
result.weigthCenter
|
18
|
-
end
|
19
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
3
|
-
require 'test/unit'
|
4
|
-
require 'fuzzy'
|
5
|
-
|
6
|
-
class TestFuzzyInference < Test::Unit::TestCase
|
7
|
-
def setup
|
8
|
-
a11 = FuzzySet.trapezoid([4, 5, 5, 10])
|
9
|
-
a12 = FuzzySet.trapezoid([10, 19, 19, 20])
|
10
|
-
a21 = FuzzySet.trapezoid([4, 9, 9, 10])
|
11
|
-
a22 = FuzzySet.trapezoid([10, 12, 13, 20])
|
12
|
-
b1 = FuzzySet.trapezoid([20, 30, 30, 40])
|
13
|
-
b2 = FuzzySet.trapezoid([30, 45, 45, 50])
|
14
|
-
r1 = FuzzyRule.new([a11, a12], b1)
|
15
|
-
r2 = FuzzyRule.new([a21, a22], b2)
|
16
|
-
@fi = FuzzyInference.new([r1, r2])
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_mandani
|
20
|
-
assert_in_delta 33.71, @fi.mandani([7, 18]), 0.005
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_larsen
|
24
|
-
assert_in_delta 33.58, @fi.larsen([7, 18]), 0.005
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|