/////////////////////////////////////////////////////////////////////////////
// rules.cc
//
// SIMLIB version: 2.16.3
// Date: 2001-04-04
// Copyright (c) 1999-2001 David Martinek, Dr. Ing. Petr Peringer
//
// This library is licensed under GNU Library GPL. See the file COPYING.
//
// Warning: this is EXPERIMENTAL code, interfaces can be changed
//
// Fuzzy subsystem for SIMLIB
// version 0.6 --- We apr 4 10:33:52 CEST 2001
//
/////////////////////////////////////////////////////////////////////////////
// FuzzyIIORules - specialized interface for typing in, representation and evaluation
// of inference rules for a fuzzy controller with two inputs and one output.
// FuzzyGeneralRules - interface for general fuzzy controller
/////////////////////////////////////////////////////////////////////////////
#include "fuzzy.h"
#include <internal.h>
#include <stdio.h>
#include <typeinfo>
/**
* It safely creates FuzzyRuleFactory.<br>
* Bezpečným způsobem vytvoří FuzzyRuleFactory.
*/
FuzzyRuleFactory * FuzzyInferenceRules::createRuleFactory()
{
return new FuzzyRuleFactory(this);
}
/////////////////////////////////////////////////////////////////////////////////////////
// FuzzyIIORules
/////////////////////////////////////////////////////////////////////////////////////////
/**
* Parameterless constructor. Fuzzy variables must be added explicitly.<br>
* Konstruktor bez parametru. Fuzzy proměnné je nutno přiřadit pomocí dalších funkcí explicitně.
*/
FuzzyIIORules::FuzzyIIORules()
{
init();
}
/**
* It initializes all input and output variables.<br>
* Inicializuje všechny vstupní a výstupní proměnné.
*/
FuzzyIIORules::FuzzyIIORules(FuzzyInput *in1, FuzzyInput *in2, FuzzyOutput *out)
{
init();
addFuzzyInput(in1);
addFuzzyInput(in2);
addFuzzyOutput(out);
}
/**
* Destructor - does NOT free memory allocated by FuzzyInput and FuzzyOutput!<br>
* Destruktor - NEuvolňuje paměť zabranou proměnnými FuzzyInput a FuzzyOutput!
* Uvolnění této paměti se musí provést JINDE!
*/
FuzzyIIORules::~FuzzyIIORules()
{
TRACE(printf("~FuzzyIIORules()\n"));
delete[] operation;
delete[] outWV;
}
/**
* It adds next rule into list. If there is too much rules, an error is indicated.<br>
* Přidá další pravidlo do seznamu. Pokud už je definováno příliš pravidel, nastane chyba.
* @param rule Inference rule with tree structure.<br>Inferenční pravidlo reprezentované stromovou strukturou.
*/
void FuzzyIIORules::add(FuzzyRule *rule, bool release)
{
if (
(typeid(*(rule->left->L)) != typeid(FPair)) ||
(typeid(*(rule->left->R)) != typeid(FPair))
)
{
SIMLIB_error("FuzzyIIORules::add: Tree in parameter (FuzzyRule) has bad structure!");
}
FPair * L = dynamic_cast<FPair *>(rule->left->L);
FPair * R = dynamic_cast<FPair *>(rule->left->R);
if (
(typeid(*(L->var)) != typeid(FuzzyInput)) ||
(typeid(*(R->var)) != typeid(FuzzyInput)) ||
!L->eq ||
!R->eq
)
{
SIMLIB_error("FuzzyIIORules::add: Tree in parameter (FuzzyRule) has bad structure!");
}
if (rule->right.size() != 1)
{
SIMLIB_error("FuzzyIIORules::add: In rule is one command in consequent expected!");
}
// není třeba ověřovat, jestli je Lvar a Rvar ve vektoru in
add(rule->left->op, L->wordValue, R->wordValue, rule->right[0]->wordValue);
if (release)
{
delete rule;
rule = NULL;
}
}
/** It initializes all member variables. <br> Inicializuje vnitřní proměnné */
void FuzzyIIORules::init()
{
// operation.reserve(2);
// outWV.reserve();
operation = NULL;
outWV = NULL;
out.reserve(1);
in.reserve(2);
inputs = outputs = rules = 0;
}
/**
* It alocates a memory space for operation and outWV arrays. A alocated array size is
* a product of numbers of word values of all input variables.<br>
* Alokuje prostor pro pole operation a outWV. Velikost alokovaného pole je součinem
* počtů slovních hodnot všech jednotlivých vstupních proměnných.
*/
void FuzzyIIORules::createVectors()
{
unsigned length = 1;
for (int i = 0; i < MAX_INPUTS; i++)
{
length *= in[i]->count();
}
operation = new Operations[length];
outWV = new int[length];
}
/** It tests if all arrays are allocated.<br>Testuje, jestli už jsou alokována pole. */
bool FuzzyIIORules::isAllCreated()
{
return (operation != NULL) && (outWV != NULL);
}
/** It adds next input variable.<br> Vloží další vstupní proměnnou. */
void FuzzyIIORules::addFuzzyInput(FuzzyInput *in)
{
if (inputs < MAX_INPUTS) { inputs++; FuzzyInferenceRules::addFuzzyInput(in); }
else { SIMLIB_error("FuzzyIIORules: can not store more than 2 fuzzy inputs."); }
if (isComplete() && !isAllCreated()) createVectors();
}
/** It adds output variable.<br> Vloží výstupní proměnnou. */
void FuzzyIIORules::addFuzzyOutput(FuzzyOutput *out)
{
if (outputs < MAX_OUTPUTS) { outputs++; FuzzyInferenceRules::addFuzzyOutput(out); }
else { SIMLIB_error("FuzzyIIORules: can not store more than 1 fuzzy output."); }
if (isComplete() && !isAllCreated()) createVectors();
}
/**
* It tests if all variables are assigned.<br>
* Testuje, jestli už jsou přiřazeny všechny proměnné.
* @see addFuzzyInput(FuzzyInput *in)
* @see addFuzzyOutput(FuzzyOutput *out)
*/
bool FuzzyIIORules::isComplete()
{
return (inputs == MAX_INPUTS) && (outputs == MAX_OUTPUTS);
}
/**
* Adds a rule into the list.<br>
* Přídá inferenční pravidlo do seznamu.
* @param operation operation which is used in rule<br>operace, která se použije v pravidle
* @param in1WVIndex index of first fuzzy input variable<br>index slovní hodnoty první vstupní proměnné
* @param in2WVIndex index of second fuzzy input variable<br>index slovní hodnoty druhé vstupní proměnné
* @param outWVIndex index of output fuzzy variable<br>index slovní hodnoty výstupní proměnné
*/
void FuzzyIIORules::add (const FuzzyInferenceRules::Operations operation,
int in1WVIndex,
int in2WVIndex,
int outWVIndex)
{
// if (rules >= in[2]->count*in[1]->count()) // chyba
rules++;
unsigned index = in2WVIndex*in[1]->count()+in1WVIndex;
this->operation[index] = operation;
this->outWV[index] = outWVIndex;
// printf("add (in1WVIndex=%d, in2WVIndex=%d, outWVIndex=%d) at index %d\n", in1WVIndex, in2WVIndex, outWVIndex, index);
}
/**
* Adds a rule into the list.<br>
* Přídá inferenční pravidlo do seznamu.
* @param operation operation which is used in rule<br>operace, která se použije v pravidle
* @param in1WordValue word value of first fuzzy input variable<br>slovní hodnota první vstupní fuzzy proměnné
* @param in2WordValue word value of second fuzzy input variable<br>slovní hodnota druhé vstupní fuzzy proměnné
* @param outWordValue word value of output fuzzy variable<br>slovní hodnota výstupní fuzzy proměnné
*/
void FuzzyIIORules::add (const FuzzyInferenceRules::Operations operation,
const char *in1WordValue,
const char *in2WordValue,
const char *outWordValue)
{
add(operation, in[0]->search(in1WordValue), in[1]->search(in2WordValue), out[0]->search(outWordValue));
}
/**
* Adds a rule into the list.<br>
* Přídá inferenční pravidlo do seznamu.
* @param operation operation which is used in rule<br>operace, která se použije v pravidle
* @param in1WVIndex index of first fuzzy input variable<br>index slovní hodnoty první vstupní proměnné
* @param in2WVIndex index of second fuzzy input variable<br>index slovní hodnoty druhé vstupní proměnné
* @param outWordValue word value of output fuzzy variable<br>slovní hodnota výstupní fuzzy proměnné
*/
void FuzzyIIORules::add (const FuzzyInferenceRules::Operations operation,
int in1WVIndex,
int in2WVIndex,
const char *outWordValue)
{
add(operation, in1WVIndex, in2WVIndex, out[0]->search(outWordValue));
}
/* pomocné funkce */
inline double rmin(double x, double y) { return (x < y) ? x : y; }
inline double rmax(double x, double y) { return (x > y) ? x : y; }
/**
* It evaluates the rules.<br>
* Vyhodnotí pravidla.
*/
void FuzzyIIORules::evaluate()
{
// if (rules >= in[2]->count*in[1]->count()) // chyba
for (int i = 0; i < rules; i++)
{
unsigned outindex = outWV[i]; // index slovní hodnoty výstupu
unsigned in0index = i % in[0]->count(); // index slovní hodnoty první vstupní proměnné
unsigned in1index = i/in[0]->count(); // index slovní hodnoty druhé vstupní proměnné
// printf("i: %d, outindex: %d, in0index: %d, in1index: %d\n", i, outindex, in0index, in1index);
switch (operation[i])
{
case opAND:// if (in0 == "something" && in1 == "someother") { out = "some"; }
// (*out)[i] - zpřístupní položku pole mval u FuzzyOutput
// (*in[])[i] - vrátí hodnotu z mval, kde je aktuální fuzzifikovaná hodnota
// = pro inty není přetíženo, proto pouze přiřadí výsledek
(*out[0])[outindex] = rmax((*out[0])[outindex], rmin((*in[0])[in0index], (*in[1])[in1index]));
break;
case opOR:// if (in0 == "something" || in1 == "someother") { out = "some"; }
(*out[0])[outindex] = rmax((*out[0])[outindex], rmax((*in[0])[in0index], (*in[1])[in1index]));
break;
case opNAND:// if (!(in0 == "something" && in1 == "someother")) { out = "some"; }
(*out[0])[outindex] = rmax((*out[0])[outindex], 1-rmin((*in[0])[in0index], (*in[1])[in1index]));
break;
case opNOR:// if (!(in0 == "something" || in1 == "someother")) { out = "some"; }
(*out[0])[outindex] = rmax((*out[0])[outindex], 1-rmax((*in[0])[in0index], (*in[1])[in1index]));
break;
default:
break;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////
// FuzzyGeneralRules
/////////////////////////////////////////////////////////////////////////////////////////
/**
* It returns true when all variables are assigned.<br>
* Testuje, jestli už jsou přiřazeny všechny proměnné.
* @see addFuzzyInput(FuzzyInput *in)
* @see addFuzzyOutput(FuzzyOutput *out)
*/
bool FuzzyGeneralRules::isComplete()
{
return (in.size() > 0) && (out.size() > 0);
}
/**
* It adds next rule into list. When it is too much rules here, error is indicated.<br>
*
* Přidá další pravidlo do seznamu. Pokud už je definováno příliš pravidel, nastane chyba.
* @param rule Inference rule who is represented by tree structure.
* Inferenční pravidlo reprezentované stromovou strukturou.
* @param release It has no meaning here.<br>Zde nemá význam.
*/
void FuzzyGeneralRules::add(FuzzyRule *rule, bool release)
{
rules.push_back(rule);
}
/**
* It evaluates all rules. This method is defaultly called from a method Behavior in class
* FuzzyRSBlock.<br>
* Vyhodnotí pravidla. Tato funkce je standardně volána z funkce Behavior třídy
* FuzzyRSBlock.
*/
void FuzzyGeneralRules::evaluate()
{
for (unsigned int i = 0; i < rules.size(); i++)
{
(*rules[i]).evaluate();
}
}
syntax highlighted by Code2HTML, v. 0.9.1