AI-FuzzyInference
view release on metacpan or search on metacpan
FuzzyInference.pm view on Meta::CPAN
},
);
# this hash defines the currently implemented implication methods.
my %_implication = qw(
clip 1
scale 1
default clip
);
# this hash defines the currently implemented aggregation methods.
my %_aggregation = qw(
max 1
default max
);
# this hash defines the currently implemented defuzzification methods.
my %_defuzzification = qw(
centroid 1
default centroid
);
# sub new() - constructor.
#
# doesn't take any arguments. Returns an initialized AI::FuzzyInference object.
sub new {
my $self = shift;
my $class = ref($self) || $self;
my $obj = bless {} => $class;
$obj->_init;
return $obj;
}
# sub _init() - private method.
#
# no arguments. Initializes the data structures we will need.
# It also defines the default logic operations we might need.
sub _init {
my $self = shift;
$self->{SET} = new AI::FuzzyInference::Set;
$self->{INVARS} = {};
$self->{OUTVARS} = {};
$self->{RULES} = [];
$self->{RESULTS} = {};
$self->{IMPLICATION} = $_implication{default};
$self->{AGGREGATION} = $_aggregation{default};
$self->{DEFUZZIFICATION} = $_defuzzification{default};
for my $op (qw/& | !/) {
$self->{OPERATIONS}{$op} = $_operations{$op}{default};
}
}
# sub implication() - public method.
#
# one optional argument: has to match one of the keys of the %_implication hash.
# used to query/set the implication method.
sub implication {
my ($self,
$new,
) = @_;
if (defined $new and exists $_implication{$new}) {
$self->{IMPLICATION} = $new;
}
return $self->{IMPLICATION};
}
# sub aggregation() - public method.
#
# one optional argument: has to match one of the keys of the %_aggregation hash.
# used to query/set the aggregation method.
sub aggregation {
my ($self,
$new,
) = @_;
if (defined $new and exists $_aggregation{$new}) {
$self->{AGGREGATION} = $new;
}
return $self->{AGGREGATION};
}
# sub defuzzification() - public method.
#
# one optional argument: has to match one of the keys of the %_defuzzification hash.
# used to query/set the defuzzification method.
sub defuzzification {
my ($self,
$new,
) = @_;
if (defined $new and exists $_defuzzification{$new}) {
$self->{DEFUZZIFICATION} = $new;
}
return $self->{DEFUZZIFICATION};
}
# sub operation() - public method.
#
# two arguments: first one mandatory and specifies the logic operation
# in question. Second one is optional and has to match one of the keys
# of the %{$_operations{$first_arg}} hash.
# Used to query/set the logic operations method.
sub operation {
my ($self,
$op,
$new,
) = @_;
return unless defined $op && exists $_operations{$op};
if (defined $new and exists $_operations{$op}{$new}) {
$self->{OPERATIONS}{$op} = $new;
}
return $self->{OPERATIONS}{$op};
}
# sub inVar() - public method.
#
# 4 arguments or more : First is a name of a new input variable.
# Second and third are the min and max values of that variable.
# These define the universe of discourse for that variable.
# Additional argumets constitute a hash. The keys of the hash
# are term set names defined for the given variable. The values
# are the coordinates of the vertices of the term sets.
#
# ex. $obj->inVar('height',
# 5, 8, # xmin, xmax (in feet, say)
# 'tall' => [0, 0,
# 5, 1,
# 10,0],
# ....);
sub inVar {
my ($self,
$var,
$xmin,
$xmax,
@sets,
) = @_;
$self->{INVARS}{$var} = [$xmin, $xmax];
while (@sets) {
my $s = shift @sets;
my $c = shift @sets;
$self->{SET}->add("$var:$s", $xmin, $xmax, @$c);
}
}
# sub outVar() - public method.
#
# 4 arguments or more : First is a name of a new output variable.
# Second and third are the min and max values of that variable.
# These define the universe of discourse for that variable.
# Additional argumets constitute a hash. The keys of the hash
# are term set names defined for the given variable. The values
# are the coordinates of the vertices of the term sets.
sub outVar {
my ($self,
$var,
$xmin,
$xmax,
@sets,
) = @_;
$self->{OUTVARS}{$var} = [$xmin, $xmax];
while (@sets) {
my $s = shift @sets;
my $c = shift @sets;
$self->{SET}->add("$var:$s", $xmin, $xmax, @$c);
}
}
# sub addRule() - public method.
#
# Adds fuzzy if-then inference rules.
#
# $obj->addRule('x=medium' => 'z = slow',
# 'x=low & y=small' => 'z = fast',
# 'x=high & y=tiny' => 'z=veryfast');
# spaces are optional. The characters [&=|] are special.
sub addRule {
my ($self, %rules) = @_;
for my $k (keys %rules) {
my $v = $rules{$k};
s/\s+//g for $v, $k;
push @{$self->{RULES}} => [$k, $v];
}
return 1;
}
# sub show() - public method.
#
# This method displays the computed values of all
# output variables.
# It is ugly, and will be removed. Here for debugging.
sub show {
my $self = shift;
for my $var (keys %{$self->{RESULTS}}) {
print "Var $var = $self->{RESULTS}{$var}.\n";
}
}
# sub value() - public method.
#
# one argument: the name of an output variable.
# This method returns the computed value of a given output var.
sub value {
my ($self,
$var,
) = @_;
return undef unless exists $self->{RESULTS}{$var};
return $self->{RESULTS}{$var};
}
# sub reset() - public method
#
# cleans the data structures used.
sub reset {
my $self = shift;
my @list = $self->{SET}->listMatching(q|:implicated$|);
push @list => $self->{SET}->listMatching(q|:aggregated$|);
$self->{SET}->delete($_) for @list;
$self->{RESULTS} = {};
}
# sub compute() - public method
#
# This method takes as input crisp values for each
# of the input vars, and produces a crisp output value
# based on the application of the fuzzy if-then rules.
# ex.
# $z = $obj->compute(x => 5,
# y => 24);
sub compute {
my ($self,
%vars,
) = @_;
$self->reset();
# First thing we do is to fuzzify the inputs.
$self->_fuzzify(%vars);
# Now, apply the rules to see which ones fire.
$self->_infer;
# implicate
$self->_implicate;
# aggregate
$self->_aggregate;
# defuzzify .. final step.
$self->_defuzzify;
return 1;
}
# sub _defuzzify() - private method.
#
# no arguments. This method applies the defuzzification technique
# to get a crisp value out of the aggregated set of each output
# var.
sub _defuzzify {
my $self = shift;
my $_defuzzification = $self->{DEFUZZIFICATION};
# iterate through all output vars.
for my $var (keys %{$self->{OUTVARS}}) {
my $result = 0;
if ($self->{SET}->exists("$var:aggregated")) {
$result = $self->{SET}->$_defuzzification("$var:aggregated");
}
$self->{RESULTS}{$var} = $result;
}
}
# sub _aggregate() - private method.
#
# no arguments. This method applies the aggregation technique to get
# one fuzzy set out of the implicated sets of each output var.
FuzzyInference.pm view on Meta::CPAN
'service=poor & food=good' => 'tip=poor',
'service=good & food=good' => 'tip=good',
'service=excellent & food=good' => 'tip=good',
'service=amazing & food=good' => 'tip=excellent',
'service=poor & food=excellent' => 'tip=good',
'service=good & food=excellent' => 'tip=excellent',
'service=excellent & food=excellent' => 'tip=excellent',
'service=amazing & food=excellent' => 'tip=amazing',
'service=poor & food=amazing' => 'tip=good',
'service=good & food=amazing' => 'tip=excellent',
'service=excellent & food=amazing' => 'tip=amazing',
'service=amazing & food=amazing' => 'tip=amazing',
);
$s->compute(service => 2,
food => 7);
=head1 DESCRIPTION
This module implements a fuzzy inference system. Very briefly, an FIS
is a system defined by a set of input and output variables, and a set
of fuzzy rules relating the input variables to the output variables.
Given crisp values for the input variables, the FIS uses the fuzzy rules
to compute a crisp value for each of the output variables.
The operation of an FIS is split into 4 distinct parts: I<fuzzification>,
I<inference>, I<aggregation> and I<defuzzification>.
=head2 Fuzzification
In this step, the crisp values of the input variables are used to
compute a degree of membership of each of the input variables in each
of its term sets. This produces a set of fuzzy sets.
=head2 Inference
In this step, all the defined rules are examined. Each rule has two parts:
the I<precedent> and the I<consequent>. The degree of support for each
rule is computed by applying fuzzy operators (I<and>, I<or>) to combine
all parts of its precendent, and generate a single crisp value. This value
indicates the "strength of firing" of the rule, and is used to reshape
(I<implicate>) the consequent part of the rule, generating modified
fuzzy sets.
=head2 Aggregation
Here, all implicated fuzzy sets of the fired rules are combined using
fuzzy operators to generate a single fuzzy set for each of the
output variables.
=head2 Defuzzification
Finally, a defuzzification operator is applied to the aggregated fuzzy
set to generate a single crisp value for each of the output variables.
For a more detailed explanation of fuzzy inference, you can check out
the tutorial by Jerry Mendel at
S<http://sipi.usc.edu/~mendel/publications/FLS_Engr_Tutorial_Errata.pdf>.
Note: The terminology used in this module might differ from that used
in the above tutorial.
=head1 PUBLIC METHODS
The module has the following public methods:
=over 4
=item new()
This is the constructor. It takes no arguments, and returns an
initialized AI::FuzzyInference object.
=item operation()
This method is used to set/query the fuzzy operations. It takes at least
one argument, and at most 2. The first argument specifies the logic
operation in question, and can be either C<&> for logical I<AND>,
C<|> for logical I<OR>, or C<!> for logical I<NOT>. The second
argument is used to set what method to use for the given operator.
The following values are possible:
=item &
=over 8
=item min
The result of C<A and B> is C<min(A, B)>. This is the default.
=item product
The result of C<A and B> is C<A * B>.
=back
=item |
=over 8
=item max
The result of C<A or B> is C<max(A, B)>. This is the default.
=item sum
The result of C<A or B> is C<min(A + B, 1)>.
=back
=item !
=over 8
=item complement
The result of C<not A> is C<1 - A>. This is the default.
=back
The method returns the name of the method to be used for the given
operation.
=item implication()
( run in 0.996 second using v1.01-cache-2.11-cpan-39bf76dae61 )