fuzzyrb 1.0.0 → 1.1.0

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/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ == 1.1.0 / 2007-11-15
2
+ * Added Takegi-Sugeno rules
3
+ * Added first minimum defuziffication method
4
+
5
+ * Changed inference to implementation
6
+ * Changed weightCenter to centerOfGravity
1
7
  == 1.0.0 / 2007-11-09
2
8
 
3
9
  * 1 major enhancement
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/fuzzy_inference.rb
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/test_fuzzy_inference.rb
13
+ test/test_fuzzy_implication.rb
14
+ test/test_fuzzy_rule.rb
13
15
  test/test_fuzzy_set.rb
data/README.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  fuzzyrb
2
2
  by Roman Kamyk
3
- http://fuzzyrb.rubyforge.org/
3
+ http://rubyforge.org/projects/fuzzyrb/
4
4
 
5
5
  == DESCRIPTION:
6
6
 
data/Rakefile CHANGED
@@ -4,14 +4,21 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
  require './lib/fuzzy.rb'
6
6
 
7
- Hoe.new('fuzzyrb', Fuzzyrb::VERSION) do |p|
8
- p.rubyforge_name = 'fuzzyrb'
9
- p.author = 'Roman Kamyk'
10
- p.email = 'roman.kamyk@gmail.com'
11
- p.summary = 'Fuzzy Sets for Ruby'
12
- p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
13
- p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
14
- p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
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
@@ -22,8 +22,8 @@ require 'point'
22
22
  require 'line'
23
23
  require 'fuzzy_set'
24
24
  require 'fuzzy_rule'
25
- require 'fuzzy_inference'
25
+ require 'fuzzy_implication'
26
26
 
27
27
  module Fuzzyrb
28
- VERSION = "1.0.0"
29
- end
28
+ VERSION = "1.1.0"
29
+ end
@@ -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
- def minOfArguments(values)
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.min
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 toLines
19
- lines = []
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 weigthCenter()
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
@@ -4,4 +4,5 @@ require 'test/unit'
4
4
  require 'test/unit/ui/console/testrunner'
5
5
 
6
6
  require 'test_fuzzy_set'
7
- require 'test_fuzzy_inference'
7
+ require 'test_fuzzy_rule'
8
+ require 'test_fuzzy_implication'
@@ -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.0.0
7
- date: 2007-11-10 00:00:00 +01:00
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/fuzzy_inference.rb
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/test_fuzzy_inference.rb
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/test_fuzzy_inference.rb
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
@@ -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
-