fuzzyrb 1.0.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.tar.gz.sig ADDED
@@ -0,0 +1 @@
1
+ ]�#,��^L�B0�ﳘ.q��O������:|��7r�����&�L�� �ն���Y���9������nts�#����/�=���u(X�����ԍu�a�[�$ga
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ == 1.0.0 / 2007-11-09
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
5
+
data/Manifest.txt ADDED
@@ -0,0 +1,13 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/fuzzy.rb
6
+ lib/fuzzy_inference.rb
7
+ lib/fuzzy_rule.rb
8
+ lib/fuzzy_set.rb
9
+ lib/line.rb
10
+ lib/point.rb
11
+ test/test_fuzzy.rb
12
+ test/test_fuzzy_inference.rb
13
+ test/test_fuzzy_set.rb
data/README.txt ADDED
@@ -0,0 +1,50 @@
1
+ fuzzyrb
2
+ by Roman Kamyk
3
+ http://fuzzyrb.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Implements Fuzzy Sets in Ruby. I am very beginner at this topic, so it is very basic now. Any help will be appreciated.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Fuzzy Sets defined as line segments
12
+ * Fuzzy Rules. Only conjunction of arguments is possible.
13
+ * No error handling.
14
+ * Deffuzification as center of gravity.
15
+ * Reasoning - apply matching rule and combine the results.
16
+
17
+ == SYNOPSIS:
18
+
19
+ Cannot be used from console. See test/ for sample usage.
20
+
21
+ == REQUIREMENTS:
22
+
23
+ * Ruby
24
+
25
+ == INSTALL:
26
+
27
+ sudo gem install fuzzyrb
28
+
29
+ == LICENSE:
30
+
31
+ (The GPL License)
32
+
33
+ Copyright (C) 2007 Roman Kamyk
34
+
35
+ This program is free software: you can redistribute it and/or modify
36
+ it under the terms of the GNU General Public License as published by
37
+ the Free Software Foundation, either version 3 of the License, or
38
+ (at your option) any later version.
39
+
40
+ This program is distributed in the hope that it will be useful,
41
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
42
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43
+ GNU General Public License for more details.
44
+
45
+ You should have received a copy of the GNU General Public License
46
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
47
+
48
+ == Author
49
+ Roman 'MrStone' Kamyk (mailto:roman.kamyk@gmail.com),
50
+ Student of Poznan University Of Technology, Computing Science Institute, Inteligent Decision Support Systems
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/fuzzy.rb'
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")
15
+ end
16
+
17
+ # vim: syntax=Ruby
data/lib/fuzzy.rb ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # Created by Roman Kamyk <roman.kamyk@gmail.com on 2007-11-09.
3
+ # Copyright (C) 2007 Roman Kamyk
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'pp'
19
+
20
+ $:.unshift(File.dirname(__FILE__) + "/../lib/")
21
+ require 'point'
22
+ require 'line'
23
+ require 'fuzzy_set'
24
+ require 'fuzzy_rule'
25
+ require 'fuzzy_inference'
26
+
27
+ module Fuzzyrb
28
+ VERSION = "1.0.0"
29
+ end
@@ -0,0 +1,19 @@
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
data/lib/fuzzy_rule.rb ADDED
@@ -0,0 +1,24 @@
1
+ class FuzzyRule
2
+ def initialize(arguments, result)
3
+ @arguments = arguments
4
+ @result = result
5
+ end
6
+
7
+ def minOfArguments(values)
8
+ tmp = []
9
+ for i in 0..(values.length-1)
10
+ tmp << @arguments[i][values[i]]
11
+ 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)
23
+ end
24
+ end
data/lib/fuzzy_set.rb ADDED
@@ -0,0 +1,115 @@
1
+ EPSILON = 0.0001
2
+ SCALE = 1
3
+ class FuzzySet
4
+ def initialize(points)
5
+ @points = points.sort
6
+ end
7
+
8
+ def self.trapezoid(array)
9
+ raise Exception.new("Trapezoid must have array length 4") if array.length != 4
10
+ points = []
11
+ points << Point.new(array[0], 0)
12
+ points << Point.new(array[1], SCALE)
13
+ points << Point.new(array[2], SCALE) unless array[2] == array[1]
14
+ points << Point.new(array[3], 0)
15
+ FuzzySet.new(points)
16
+ 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
24
+ end
25
+
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
+ def +(other)
50
+ points = [@points, other.points, intersections(other)].flatten.uniq.sort
51
+ res = points.reject { |point|
52
+ self[point.x]-EPSILON > point.y or other[point.x]-EPSILON > point.y
53
+ }
54
+ FuzzySet.new(res)
55
+ end
56
+
57
+ def min(value)
58
+ line = Line.new(Point.new(0, value), Point.new(1, value))
59
+ points = [@points, intersections(line)].flatten.uniq.sort
60
+ res = points.reject { |p| self[p.x] - EPSILON > value }
61
+ FuzzySet.new(res)
62
+ end
63
+
64
+ # Choose min of current and _other_ set
65
+ def &(other)
66
+ points = [@points, crosspoints(other)].flatten.uniq.sort
67
+ res = []
68
+ points.each { |point|
69
+ res << point if self[point.x]-EPSILON < point.y and self[point.x]+EPSILON > point.y and other[point.x]+EPSILON >= self[point.x]
70
+ }
71
+ FuzzySet.new(res)
72
+ end
73
+ attr_reader :points
74
+
75
+ def weigthCenter()
76
+ nominator = 0.0
77
+ denominator = 0.0
78
+ for i in 1..@points.length-1
79
+ line = Line.new(@points[i], @points[i-1])
80
+ x2 = points[i].x
81
+ x1 = points[i-1].x
82
+ nominator += line.a * x2**3/3 + line.b * x2**2/2 - line.a * x1**3/3 - line.b * x1**2/2
83
+ denominator += line.a * x2**2/2 + line.b * x2 - line.a * x1**2/2 - line.b * x1
84
+ end
85
+ nominator/denominator
86
+ end
87
+
88
+ def scale(factor)
89
+ fs = FuzzySet.new(@points.map { |p| p.clone() })
90
+ fs.scale!(factor)
91
+ end
92
+
93
+ def scale!(factor)
94
+ @points.each { |point| point.y *= factor / SCALE }
95
+ self
96
+ end
97
+
98
+ def [](value)
99
+ if value<@points[0].x
100
+ return 0
101
+ elsif value > @points.last.x
102
+ return 0
103
+ end
104
+ idx = 0
105
+ while (@points[idx].x < value)
106
+ idx += 1
107
+ end
108
+ return @points[idx].y if @points[idx].x == value
109
+ x1 = @points[idx-1].x
110
+ x2 = @points[idx].x
111
+ y1 = @points[idx-1].y
112
+ y2 = @points[idx].y
113
+ return 1.0*(y2 - y1)/(x2-x1) * (value - x1) + y1
114
+ end
115
+ end
data/lib/line.rb ADDED
@@ -0,0 +1,16 @@
1
+ class Line
2
+ def initialize(p1, p2)
3
+ @a = 1.0*(p2.y-p1.y)/(p2.x-p1.x)
4
+ @b = 1.0*p1.y - @a*p1.x
5
+ # pp [p1, p2, @a, @b]
6
+ end
7
+
8
+ def intersect(other)
9
+ x = 1.0*(b-other.b)/(other.a-a)
10
+ y = 1.0*a*x+b
11
+ # pp [self, other, x, y]
12
+ Point.new(x, y)
13
+ end
14
+
15
+ attr_accessor :a, :b
16
+ end
data/lib/point.rb ADDED
@@ -0,0 +1,14 @@
1
+ class Point
2
+ def initialize(x, y)
3
+ @x = x
4
+ @y = y
5
+ end
6
+ def <=>(other)
7
+ self.x <=> other.x
8
+ end
9
+ def initialize_copy(orig)
10
+ @x = orig.x
11
+ @y = orig.y
12
+ end
13
+ attr_accessor :x, :y
14
+ end
@@ -0,0 +1,7 @@
1
+ $:.unshift(File.dirname(__FILE__) + "/../lib/")
2
+ $:.unshift(File.dirname(__FILE__) + "/../test/")
3
+ require 'test/unit'
4
+ require 'test/unit/ui/console/testrunner'
5
+
6
+ require 'test_fuzzy_set'
7
+ require 'test_fuzzy_inference'
@@ -0,0 +1,27 @@
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
+
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/ruby
2
+ require 'test/unit'
3
+ require 'fuzzy'
4
+
5
+ class TestFuzzySet < Test::Unit::TestCase
6
+ def test_trapezoid1
7
+ t = FuzzySet.trapezoid([4, 5, 5, 10])
8
+ assert_equal(0, t[4])
9
+ assert_equal(1, t[5])
10
+ assert_equal(0, t[10])
11
+ assert_equal(0.5, t[4.5])
12
+ assert_equal(0.8, t[6])
13
+ assert_equal(0.6, t[7])
14
+ end
15
+
16
+ def test_trapezoid2
17
+ t = FuzzySet.trapezoid([10, 12, 13, 20])
18
+ assert_equal(0, t[9])
19
+ assert_equal(0, t[10])
20
+ assert_equal(0.5, t[11])
21
+ assert_equal(0, t[-1000])
22
+ assert_equal(1, t[12])
23
+ assert_equal(1, t[12.5])
24
+ assert_equal(1, t[13])
25
+ assert_equal(0, t[20])
26
+ assert_equal(0, t[1000])
27
+ end
28
+ end
29
+
30
+
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: fuzzyrb
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2007-11-10 00:00:00 +01:00
8
+ summary: Fuzzy Sets for Ruby
9
+ require_paths:
10
+ - lib
11
+ email: roman.kamyk@gmail.com
12
+ homepage: " by Roman Kamyk"
13
+ rubyforge_project: fuzzyrb
14
+ description: "== FEATURES/PROBLEMS: * Fuzzy Sets defined as line segments * Fuzzy Rules. Only conjunction of arguments is possible. * No error handling. * Deffuzification as center of gravity. * Reasoning - apply matching rule and combine the results. == SYNOPSIS: Cannot be used from console. See test/ for sample usage. == REQUIREMENTS:"
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ - |
29
+ -----BEGIN CERTIFICATE-----
30
+ MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRQwEgYDVQQDDAtyb21h
31
+ bi5rYW15azEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD
32
+ Y29tMB4XDTA3MTExMDA1MzUzM1oXDTA4MTEwOTA1MzUzM1owQjEUMBIGA1UEAwwL
33
+ cm9tYW4ua2FteWsxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixk
34
+ ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMdV1ujoU4I2
35
+ daF4KANtDPTSjLYhXC1CiiyEgGEVA6GvieQ2NpNNsSXl+6tbWXGNUWFHj50rrLTC
36
+ e1dJSGGTZa9ZjI6fkeb/Gr13s71ncCJ+hBbpvktWIWdvOvzvNo9bdzNCKX00Rlk5
37
+ hQzxhm/ZxQ2VG4ZDYc/gWOCzKYH8aKrAzzdjRsxE/QMgnVbnirCGSPQTjPVhBvcX
38
+ pH2yDvZF9NOs3D89JvA4P50WRCe8/kKPx7TG9Qkd303/FmO8yDUvJn0KgiYkm1pc
39
+ Sb+kcDZnh2+2uvkygLLDQhV5m7DfFLLkgwb/t7R4tSNFqcHoa0829rnSVBbCZACg
40
+ mrXhThP3LX8CAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
41
+ BBYEFGVgSLBvjD5kTd+1XMf58PK9llj6MA0GCSqGSIb3DQEBBQUAA4IBAQCGX43w
42
+ PspP+rmsfCKztiUwtfb4d+eqW62WaAUBT37KeW8IEm3UpAe5T1c3fFm46bxM3a2Y
43
+ wUeLqSMSquXNzb2fy+3vLAUYHc4UkR5nA5kB+F3RJwuc7LJCBGlkPsCfa91dE6j5
44
+ S80vqeRf4ITITHZbFLuVFFvQb/nPGe2LtyP4+neAktSu4r7rQ5vLbQQ/NSAliFrP
45
+ pJbWXmfjKQsDKGgs1TiISC3kfLcynhCgCcbLCek5Oc0U195z36e8x3aYEJSGFVmF
46
+ y8xfBxyZ4t0FP3lTPvGMfmSKOVOjcwT4OVpzdvRXWR8lghrQlAzNG5HdOxMzeBjb
47
+ Z2byiG0rlbybmXMS
48
+ -----END CERTIFICATE-----
49
+
50
+ post_install_message:
51
+ authors:
52
+ - Roman Kamyk
53
+ files:
54
+ - History.txt
55
+ - Manifest.txt
56
+ - README.txt
57
+ - Rakefile
58
+ - lib/fuzzy.rb
59
+ - lib/fuzzy_inference.rb
60
+ - lib/fuzzy_rule.rb
61
+ - lib/fuzzy_set.rb
62
+ - lib/line.rb
63
+ - lib/point.rb
64
+ - test/test_fuzzy.rb
65
+ - test/test_fuzzy_inference.rb
66
+ - test/test_fuzzy_set.rb
67
+ test_files:
68
+ - test/test_fuzzy.rb
69
+ - test/test_fuzzy_inference.rb
70
+ - test/test_fuzzy_set.rb
71
+ rdoc_options:
72
+ - --main
73
+ - README.txt
74
+ extra_rdoc_files:
75
+ - History.txt
76
+ - Manifest.txt
77
+ - README.txt
78
+ executables: []
79
+
80
+ extensions: []
81
+
82
+ requirements: []
83
+
84
+ dependencies:
85
+ - !ruby/object:Gem::Dependency
86
+ name: hoe
87
+ version_requirement:
88
+ version_requirements: !ruby/object:Gem::Version::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.3.0
93
+ version:
metadata.gz.sig ADDED
Binary file