class FuzzyAssociativeMemory::Ruleset
Copyright 2013, Prylis Incorporated.
This file is part of The Ruby Fuzzy Associative Memory github.com/cpowell/fuzzy-associative-memory You can redistribute and/or modify this software only in accordance with the terms found in the “LICENSE” file included with the library.
Attributes
implication[R]
name[R]
rules[RW]
Public Class Methods
new(name, implication_mechanism)
click to toggle source
# File lib/fuzzy_associative_memory/ruleset.rb, line 15 def initialize(name, implication_mechanism) raise ArgumentError, 'invalid implication mechanism' unless [:larsen, :mamdani].include? implication_mechanism @name = name @rules = [] @implication = implication_mechanism @consequent_mus = {} end
Public Instance Methods
add_rule(rule)
click to toggle source
# File lib/fuzzy_associative_memory/ruleset.rb, line 23 def add_rule(rule) @rules << rule end
calculate(*input_values)
click to toggle source
# File lib/fuzzy_associative_memory/ruleset.rb, line 27 def calculate(*input_values) # puts ">>> Firing all rules..." if $verbosity for rule in @rules # Fire each rule to determine the µ value (degree of fit). # Gather the µ vals by consequent, since each consequent may in fact # have been fired more than once and we'll need that knowledge in a # moment... mu = rule.fire(input_values) cons = rule.consequent # Since any given consequent may have been activated more than once, we # need to get just a single µ value out -- we only care about the 'best' # µ. A popular way of doing so is to OR the values together, i.e. keep the # maximum µ value and discard the others. curr_best = @consequent_mus[cons] @consequent_mus[cons] = mu if curr_best.nil? || mu > curr_best end # Using each µ value, alter the consequent fuzzy set's polgyon. This is # called implication, and 'weights' the consequents properly. There are # several common ways of doing it, such as Larsen (scaling) and Mamdani # (clipping). numerator=0 denominator=0 @consequent_mus.each do |cons, mu| case @implication when :mamdani tmp = cons.mamdani(mu) when :larsen tmp = cons.larsen(mu) else raise RuntimeError, "I must have been passed an unknown implication mechanism: #{@implication}" end # Defuzzify into a discrete & usable value by adding up the weighted # consequents' contributions to the output. Again there are several ways # of doing it, such as computing the centroid of the combined 'mass', or # the 'mean of maximum' of the tallest set(s). Here we use the "Average # of Maxima" summation mechanism. MaxAv is defined as: # (∑ representative value * height) / (∑ height) for all output sets # where 'representative value' is shape-dependent. numerator += tmp.centroid_x * tmp.height denominator += tmp.height end @consequent_mus.clear return numerator/denominator end