1 /*
2  fuzzylite (R), a fuzzy logic control library in C++.
3  Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
4  Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
5 
6  This file is part of fuzzylite.
7 
8  fuzzylite is free software: you can redistribute it and/or modify it under
9  the terms of the FuzzyLite License included with the software.
10 
11  You should have received a copy of the FuzzyLite License along with
12  fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
13 
14  fuzzylite is a registered trademark of FuzzyLite Limited.
15  */
16 
17 #include "fl/Complexity.h"
18 
19 #include "fl/Engine.h"
20 
21 #include "fl/variable/InputVariable.h"
22 #include "fl/variable/OutputVariable.h"
23 
24 #include "fl/rule/RuleBlock.h"
25 #include "fl/rule/Rule.h"
26 
27 namespace fl {
28 
Complexity(scalar all)29     Complexity::Complexity(scalar all) :
30     _comparison(all), _arithmetic(all), _function(all) { }
31 
Complexity(scalar comparison,scalar arithmetic,scalar function)32     Complexity::Complexity(scalar comparison, scalar arithmetic,
33             scalar function)
34     : _comparison(comparison), _arithmetic(arithmetic), _function(function) { }
35 
~Complexity()36     Complexity::~Complexity() { }
37 
operator +=(const Complexity & other)38     Complexity& Complexity::operator+=(const Complexity& other) {
39         return this->plus(other);
40     }
41 
operator -=(const Complexity & other)42     Complexity& Complexity::operator-=(const Complexity& other) {
43         return this->minus(other);
44     }
45 
operator *=(const Complexity & other)46     Complexity& Complexity::operator*=(const Complexity& other) {
47         return this->multiply(other);
48     }
49 
operator /=(const Complexity & other)50     Complexity& Complexity::operator/=(const Complexity& other) {
51         return this->divide(other);
52     }
53 
operator +(const Complexity & rhs) const54     Complexity Complexity::operator+(const Complexity& rhs) const {
55         return Complexity(*this).plus(rhs);
56     }
57 
operator -(const Complexity & rhs) const58     Complexity Complexity::operator-(const Complexity& rhs) const {
59         return Complexity(*this).minus(rhs);
60     }
61 
operator *(const Complexity & rhs) const62     Complexity Complexity::operator*(const Complexity& rhs) const {
63         return Complexity(*this).multiply(rhs);
64     }
65 
operator /(const Complexity & rhs) const66     Complexity Complexity::operator/(const Complexity& rhs) const {
67         return Complexity(*this).divide(rhs);
68     }
69 
operator ==(const Complexity & rhs) const70     bool Complexity::operator==(const Complexity& rhs) const {
71         return equals(rhs);
72     }
73 
operator !=(const Complexity & rhs) const74     bool Complexity::operator!=(const Complexity& rhs) const {
75         return not equals(rhs);
76     }
77 
operator <(const Complexity & rhs) const78     bool Complexity::operator<(const Complexity& rhs) const {
79         return lessThan(rhs);
80     }
81 
operator <=(const Complexity & rhs) const82     bool Complexity::operator<=(const Complexity& rhs) const {
83         return lessThanOrEqualsTo(rhs);
84     }
85 
operator >(const Complexity & rhs) const86     bool Complexity::operator>(const Complexity& rhs) const {
87         return greaterThan(rhs);
88     }
89 
operator >=(const Complexity & rhs) const90     bool Complexity::operator>=(const Complexity& rhs) const {
91         return greaterThanOrEqualsTo(rhs);
92     }
93 
plus(const Complexity & other)94     Complexity& Complexity::plus(const Complexity& other) {
95         this->_arithmetic += other._arithmetic;
96         this->_comparison += other._comparison;
97         this->_function += other._function;
98         return *this;
99     }
100 
plus(scalar x)101     Complexity& Complexity::plus(scalar x) {
102         return this->plus(Complexity().arithmetic(x).comparison(x).function(x));
103     }
104 
minus(const Complexity & other)105     Complexity& Complexity::minus(const Complexity& other) {
106         this->_comparison -= other._comparison;
107         this->_arithmetic -= other._arithmetic;
108         this->_function -= other._function;
109         return *this;
110     }
111 
minus(scalar x)112     Complexity& Complexity::minus(scalar x) {
113         return this->minus(Complexity().arithmetic(x).comparison(x).function(x));
114     }
115 
multiply(const Complexity & other)116     Complexity& Complexity::multiply(const Complexity& other) {
117         this->_comparison *= other._comparison;
118         this->_arithmetic *= other._arithmetic;
119         this->_function *= other._function;
120         return *this;
121     }
122 
multiply(scalar x)123     Complexity& Complexity::multiply(scalar x) {
124         return this->multiply(Complexity().arithmetic(x).comparison(x).function(x));
125     }
126 
divide(const Complexity & other)127     Complexity& Complexity::divide(const Complexity& other) {
128         this->_comparison /= other._comparison;
129         this->_arithmetic /= other._arithmetic;
130         this->_function /= other._function;
131         return *this;
132     }
133 
divide(scalar x)134     Complexity& Complexity::divide(scalar x) {
135         return this->divide(Complexity().arithmetic(x).comparison(x).function(x));
136     }
137 
equals(const Complexity & x,scalar macheps) const138     bool Complexity::equals(const Complexity& x, scalar macheps) const {
139         return Op::isEq(_comparison, x._comparison, macheps) and
140                 Op::isEq(_arithmetic, x._arithmetic, macheps) and
141                 Op::isEq(_function, x._function, macheps);
142     }
143 
lessThan(const Complexity & x,scalar macheps) const144     bool Complexity::lessThan(const Complexity& x, scalar macheps) const {
145         return Op::isLt(_comparison, x._comparison, macheps) and
146                 Op::isLt(_arithmetic, x._arithmetic, macheps) and
147                 Op::isLt(_function, x._function, macheps);
148     }
149 
lessThanOrEqualsTo(const Complexity & x,scalar macheps) const150     bool Complexity::lessThanOrEqualsTo(const Complexity& x, scalar macheps) const {
151         return Op::isLE(_comparison, x._comparison, macheps) and
152                 Op::isLE(_arithmetic, x._arithmetic, macheps) and
153                 Op::isLE(_function, x._function, macheps);
154     }
155 
greaterThan(const Complexity & x,scalar macheps) const156     bool Complexity::greaterThan(const Complexity& x, scalar macheps) const {
157         return Op::isGt(_comparison, x._comparison, macheps) and
158                 Op::isGt(_arithmetic, x._arithmetic, macheps) and
159                 Op::isGt(_function, x._function, macheps);
160     }
161 
greaterThanOrEqualsTo(const Complexity & x,scalar macheps) const162     bool Complexity::greaterThanOrEqualsTo(const Complexity& x, scalar macheps) const {
163         return Op::isGE(_comparison, x._comparison, macheps) and
164                 Op::isGE(_arithmetic, x._arithmetic, macheps) and
165                 Op::isGE(_function, x._function, macheps);
166     }
167 
comparison(scalar comparison)168     Complexity& Complexity::comparison(scalar comparison) {
169         this->_comparison += comparison;
170         return *this;
171     }
172 
setComparison(scalar comparison)173     void Complexity::setComparison(scalar comparison) {
174         this->_comparison = comparison;
175     }
176 
getComparison() const177     scalar Complexity::getComparison() const {
178         return _comparison;
179     }
180 
arithmetic(scalar arithmetic)181     Complexity& Complexity::arithmetic(scalar arithmetic) {
182         this->_arithmetic += arithmetic;
183         return *this;
184     }
185 
setArithmetic(scalar arithmetic)186     void Complexity::setArithmetic(scalar arithmetic) {
187         this->_arithmetic = arithmetic;
188     }
189 
getArithmetic() const190     scalar Complexity::getArithmetic() const {
191         return _arithmetic;
192     }
193 
function(scalar trigonometric)194     Complexity& Complexity::function(scalar trigonometric) {
195         this->_function += trigonometric;
196         return *this;
197     }
198 
setFunction(scalar trigonometric)199     void Complexity::setFunction(scalar trigonometric) {
200         this->_function = trigonometric;
201     }
202 
getFunction() const203     scalar Complexity::getFunction() const {
204         return _function;
205     }
206 
measures() const207     std::vector<Complexity::Measure> Complexity::measures() const {
208         std::vector<Measure> result;
209         result.push_back(Measure("arithmetic", _arithmetic));
210         result.push_back(Measure("comparison", _comparison));
211         result.push_back(Measure("function", _function));
212         return result;
213     }
214 
sum() const215     scalar Complexity::sum() const {
216         return _arithmetic + _comparison + _function;
217     }
218 
norm() const219     scalar Complexity::norm() const {
220         return std::sqrt(Complexity(*this).multiply(*this).sum());
221     }
222 
toString() const223     std::string Complexity::toString() const {
224         std::vector<std::string> result;
225         result.push_back("a=" + Op::str(_arithmetic));
226         result.push_back("c=" + Op::str(_comparison));
227         result.push_back("f=" + Op::str(_function));
228         return "C[" + Op::join(result, ", ") + "]";
229     }
230 
compute(const Engine * engine) const231     Complexity Complexity::compute(const Engine* engine) const {
232         return engine->complexity();
233     }
234 
compute(const InputVariable * inputVariable) const235     Complexity Complexity::compute(const InputVariable* inputVariable) const {
236         return inputVariable->complexity();
237     }
238 
compute(const OutputVariable * outputVariable) const239     Complexity Complexity::compute(const OutputVariable* outputVariable) const {
240         return outputVariable->complexity();
241     }
242 
compute(const RuleBlock * ruleBlock) const243     Complexity Complexity::compute(const RuleBlock* ruleBlock) const {
244         return ruleBlock->complexity();
245     }
246 
compute(const std::vector<InputVariable * > & inputVariables) const247     Complexity Complexity::compute(const std::vector<InputVariable*>& inputVariables) const {
248         Complexity result;
249         for (std::size_t i = 0; i < inputVariables.size(); ++i) {
250             result += inputVariables.at(i)->complexity();
251         }
252         return result;
253     }
254 
compute(const std::vector<OutputVariable * > & outputVariables,bool complexityOfDefuzzification) const255     Complexity Complexity::compute(const std::vector<OutputVariable*>& outputVariables,
256             bool complexityOfDefuzzification) const {
257         Complexity result;
258         for (std::size_t i = 0; i < outputVariables.size(); ++i) {
259             if (complexityOfDefuzzification)
260                 result += outputVariables.at(i)->complexityOfDefuzzification();
261             else
262                 result += outputVariables.at(i)->complexity();
263         }
264         return result;
265     }
266 
compute(const std::vector<Variable * > & variables) const267     Complexity Complexity::compute(const std::vector<Variable*>& variables) const {
268         Complexity result;
269         for (std::size_t i = 0; i < variables.size(); ++i) {
270             result += variables.at(i)->complexity();
271         }
272         return result;
273     }
274 
compute(const std::vector<RuleBlock * > & ruleBlocks) const275     Complexity Complexity::compute(const std::vector<RuleBlock*>& ruleBlocks) const {
276         Complexity result;
277         for (std::size_t i = 0; i < ruleBlocks.size(); ++i) {
278             result += ruleBlocks.at(i)->complexity();
279         }
280         return result;
281     }
282 
283 }
284