AI-Fuzzy
view release on metacpan or search on metacpan
- fixed warning messages due to not checking "exists" for hash
values in Set.pm (union,intersection). Thanks to Richard Jelinek
for pointing this out, and a problem in the code in the docs.
0.04 Fri Dec 6 13:49:55 EST 2002
- replaced current AI::Fuzzy::Label with a new AI::Fuzzy::Axis (a container for label objects)
and changed AI::Fuzzy::Label to be concerned only about label data. This
will allow us to add new AI::Fuzzy::Label{Spline, Trapezoid, etc.} subclasses
of labels to the now independent Axis class. Axis will defer to the Label
itself to decide applicability, >,<,>=,<=, and the like.
- changed test.pl to work with the new setup
- added functions: greaterthan, greaterequal, lessthan, lessequal, and between
to AI::Fuzzy::Label
- added overriding of >,>=,<,<=, and <=> in AI::Fuzzy::Label.
0.03 Wed Oct 9 18:07:34 EDT 2002
- added functions: support, core, height, is_normal, is_subnormal
to AI::Fuzzy::Set
0.02 Wed Oct 9 16:41:29 EDT 2002
- ownership transfering to Tom Scanlan <tscanlan@openreach.com>
$c = $a->intersection($b);
print "a intersection b is: " . $c->as_string . "\n";
__END__
=head1 DESCRIPTION
AI::Fuzzy really consists of three modules - AI::Fuzzy::Axis, AI::Fuzzy::Label, and
AI::Fuzzy::Set.
A fuzzy set is simply a mathematical set to which members can
I<partially> belong. For example, a particular shade of gray may
partially belong to the set of dark colors, whereas black would have
full membership, and lemon yellow would have almost no membership.
A fuzzy axis holds fuzzy labels and can be used to classify values
by examining the degree to which they belong to several labels, and
selecting the most appropriate. For example, it can decide whether
to call water at 60 degrees Farenheight "cold", "cool", or "warm".
A fuzzy label classifies a particular range of the Axis. In the above example
the label is one of "cold", "cool", or "warm". A fuzzy label defines how
much a crisp value belongs to the classifier such as "cold", "warm", or "cool".
# $x will be .86
$x = B<membership> $fs_tall_people, "Max";
# get list of members, sorted from least membership to greatest:
@shortest_first = B<members> $fs_tall_people;
$fs = B<new> AI::Fuzzy::Set( x1 => .3, x2 => .5, x3 => .8, x4 => 0, x5 => 1);
B<complement>, B<union>, B<intersection>
Thesie are the fuzzy set version of the typical functions.
B<equal>
Returns true if the sets have the same elements and those elements
are all equal.
B<as_string>
Prints the set as tuples:
$b = new AI::Fuzzy::Set( x5 => .3, x6 => .5, x7 => .8, x8 => 0, x9 => 1);
print "b is: " . $b->as_string . "\n";
prints:
b is: x8/0, x5/0.3, x6/0.5, x7/0.8, x9/1
=head2 Fuzzy Labels
A Fuzzy::Label label has four attributes: the text of the label (it
can be any scalar, really), and three numbers: low, mid, high if you
imagine a cartesian plane (remember graph paper in algebra?) of all
$c = $a->intersection($b);
print "a intersection b is: " . $c->as_string . "\n";
__END__
DESCRIPTION
AI::Fuzzy really consists of two modules - AI::Fuzzy::Label and
AI::Fuzzy::Set.
A fuzzy set is simply a mathematical set to which members can
*partially* belong. For example, a particular shade of gray may
partially belong to the set of dark colors, whereas black would have
full membership, and lemon yellow would have almost no membership.
A fuzzy labeler classifies a particular crisp value by examining the
degree to which it belongs to several sets, and selecting the most
appropriate. For example, it can decide whether to call water at 60
degrees Farenheight "cold", "cool", or "warm". A fuzzy label might be
one of these labels, or a fuzzy set describing to what degree each of
the labels describes the particular value in question.
Fuzzy Sets
AI::Fuzzy:Set has these methods:
$fs = B<new> AI::Fuzzy::Set;
# here, "Bob" is unquestionably tall.. the others less so.
$fs_tall_people = B<new> AI::Fuzzy::Set( Lester=>.34, Bob=>1.00, Max=>.86 );
# $x will be .86
$x = B<membership> $fs_tall_people, "Max";
# get list of members, sorted from least membership to greatest:
@shortest_first = B<members> $fs_tall_people;
$fs = B<new> AI::Fuzzy::Set( x1 => .3, x2 => .5, x3 => .8, x4 => 0, x5 => 1);
B<complement>, B<union>, B<intersection>
Thesie are the fuzzy set version of the typical functions.
B<equal>
Returns true if the sets have the same elements and those elements
are all equal.
B<as_string>
Prints the set as tuples:
$b = new AI::Fuzzy::Set( x5 => .3, x6 => .5, x7 => .8, x8 => 0, x9 => 1);
print "b is: " . $b->as_string . "\n";
prints:
b is: x8/0, x5/0.3, x6/0.5, x7/0.8, x9/1
Fuzzy Labels
A Fuzzy::Label label has four attributes: the text of the label (it can
be any scalar, really), and three numbers: low, mid, high if you imagine
a cartesian plane (remember graph paper in algebra?) of all possible
lib/AI/Fuzzy/Set.pm view on Meta::CPAN
# accepts a hash of member weights..
# ( $members{$member}=$weight )
%{$self->{members}} = @_;
bless $self, $class;
}
sub membership {
# naturally, it returns a fuzzy value - the degree
# to wich $item is a member of the set! :)
my $self = shift;
my $item = shift;
if (defined(${$self->{members}}{$item})) {
return ${$self->{members}}{$item};
} else {
return 0;
}
}
sub members {
# returns list of members, sorted from least membership to greatest
my $self = shift;
my %l = %{$self->{members}};
return sort { $l{$a} <=> $l{$b} } keys %l;
}
sub equal {
# returns true if the argument set is equal to this one
my $self = shift;
my $otherset = shift;
my (%us, %them);
%us = %{$self->{members}} if (exists $self->{members});
%them = %{$otherset->{members}} if (exists $otherset->{members});
# for all keys in us and them
foreach my $key (keys (%us), keys (%them)) {
# not equal if either set is missing a key
return 0 unless (exists ($us{$key}) && exists ($them{$key}) );
# not equal if the membership of the keys isn't equal
return 0 unless (float_equal($us{$key},$them{$key}, 10));
}
# otherwise they are equal
return 1;
}
sub union {
# returns a set that is the union of us and the argument set
my $self = shift;
my $otherset = shift;
my (%us, %them, %new);
%us = %{$self->{members}} if (exists $self->{members});
%them = %{$otherset->{members}} if (exists $otherset->{members});
# for all keys in us and them
foreach my $key (keys (%us), keys (%them)) {
if (not exists $us{$key} and exists $them{$key}) {
$new{$key} = $them{$key};
next;
}
if (not exists $them{$key} and exists $us{$key}) {
$new{$key} = $us{$key};
next;
lib/AI/Fuzzy/Set.pm view on Meta::CPAN
$new{$key} = $us{$key};
} else {
$new{$key} = $them{$key};
}
}
return new AI::Fuzzy::Set(%new);
}
sub intersection {
# returns a set that is the intersection of us and the argument set
my $self = shift;
my $otherset = shift;
my (%us, %them, %new);
%us = %{$self->{members}} if (exists $self->{members});
%them = %{$otherset->{members}} if (exists $otherset->{members});
# for all keys in us and them
foreach my $key (keys (%us), keys (%them)) {
if (not exists $us{$key} or not exists $them{$key}) {
$new{$key} = 0;
next;
}
if ($us{$key} <= $them{$key}) {
$new{$key} = $us{$key};
} else {
$new{$key} = $them{$key};
}
}
return new AI::Fuzzy::Set(%new);
}
sub complement {
# returns a set that is the complement of us
# requires that the set contain values from 0 to 1
my $self = shift;
my (%new);
foreach my $member ($self->members) {
my $comp = 1 - $self->membership($member);
return undef if ($comp < 0 || $comp >1);
$new{$member} = $comp;
}
return new AI::Fuzzy::Set(%new);
}
sub support {
# returns the support set.
# defined as the set of all elements in our set with a non-zero membership.
my $self = shift;
my (%support);
foreach my $member ($self->members) {
$support{$member}++ if ($self->membership($member) != 0);
}
return new AI::Fuzzy::Set(%support);
}
sub core {
# returns the core set.
# defined as the set of all elements in our set with full membership
my $self = shift;
my (%core);
foreach my $member ($self->members) {
$core{$member}++ if ($self->membership($member) == 1);
}
return new AI::Fuzzy::Set(%core);
}
sub height {
# returns the height of the set
# defined as the maximal membership value in our set
my $self = shift;
my ($max) = 0;
foreach my $member ($self->members) {
$max = $self->membership($member) if ($self->membership($member) > $max);
}
return $max;
}
sub is_normal {
# Logical return
# normal is defined as a set with a height of 1
my $self = shift;
return 1 if ($self->height == 1);
return 0;
}
sub is_subnormal {
# Logical return
# normal is defined as a set with a height less than 1
my $self = shift;
return 1 if ($self->height < 1);
return 0;
}
sub as_string {
my $self = shift;
my @members;
( run in 0.536 second using v1.01-cache-2.11-cpan-49f99fa48dc )