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/rule/RuleBlock.h"
18 
19 #include "fl/activation/General.h"
20 #include "fl/imex/FllExporter.h"
21 #include "fl/norm/TNorm.h"
22 #include "fl/norm/SNorm.h"
23 #include "fl/rule/Rule.h"
24 #include "fl/Operation.h"
25 
26 namespace fl {
27 
RuleBlock(const std::string & name)28     RuleBlock::RuleBlock(const std::string& name)
29     : _enabled(true), _name(name), _description("") { }
30 
RuleBlock(const RuleBlock & other)31     RuleBlock::RuleBlock(const RuleBlock& other) : _enabled(true), _name(other._name),
32     _description(other._description) {
33         copyFrom(other);
34     }
35 
operator =(const RuleBlock & other)36     RuleBlock& RuleBlock::operator=(const RuleBlock& other) {
37         if (this != &other) {
38             for (std::size_t i = 0; i < _rules.size(); ++i) {
39                 delete _rules.at(i);
40             }
41             _rules.clear();
42             _conjunction.reset(fl::null);
43             _disjunction.reset(fl::null);
44             _implication.reset(fl::null);
45             _activation.reset(fl::null);
46 
47             copyFrom(other);
48         }
49         return *this;
50     }
51 
copyFrom(const RuleBlock & source)52     void RuleBlock::copyFrom(const RuleBlock& source) {
53         _enabled = source._enabled;
54         _name = source._name;
55         _description = source._description;
56         if (source._conjunction.get()) _conjunction.reset(source._conjunction->clone());
57         if (source._disjunction.get()) _disjunction.reset(source._disjunction->clone());
58         if (source._implication.get()) _implication.reset(source._implication->clone());
59         if (source._activation.get()) _activation.reset(source._activation->clone());
60         for (std::size_t i = 0; i < source._rules.size(); ++i) {
61             _rules.push_back(source._rules.at(i)->clone());
62         }
63     }
64 
~RuleBlock()65     RuleBlock::~RuleBlock() {
66         for (std::size_t i = 0; i < _rules.size(); ++i) {
67             delete _rules.at(i);
68         }
69         _rules.clear();
70     }
71 
complexity() const72     Complexity RuleBlock::complexity() const {
73         Complexity result;
74         result.comparison(1);
75         if (_activation.get()) {
76             result += _activation->complexity(this);
77         } else {
78             for (std::size_t i = 0; i < _rules.size(); ++i) {
79                 result += _rules.at(i)->complexity(
80                         _conjunction.get(), _disjunction.get(), _implication.get());
81             }
82         }
83         return result;
84     }
85 
activate()86     void RuleBlock::activate() {
87         if (not _activation.get()) {
88             _activation.reset(new General);
89         }
90         _activation->activate(this);
91     }
92 
unloadRules() const93     void RuleBlock::unloadRules() const {
94         for (std::size_t i = 0; i < _rules.size(); ++i) {
95             _rules.at(i)->unload();
96         }
97     }
98 
loadRules(const Engine * engine)99     void RuleBlock::loadRules(const Engine* engine) {
100         std::ostringstream exceptions;
101         bool throwException = false;
102         for (std::size_t i = 0; i < _rules.size(); ++i) {
103             Rule* rule = _rules.at(i);
104             if (rule->isLoaded()) {
105                 rule->unload();
106             }
107             try {
108                 rule->load(engine);
109             } catch (std::exception& ex) {
110                 throwException = true;
111                 exceptions << ex.what() << "\n";
112             }
113         }
114         if (throwException) {
115             Exception exception("[ruleblock error] the following "
116                     "rules could not be loaded:\n" + exceptions.str(), FL_AT);
117             throw exception;
118         }
119     }
120 
reloadRules(const Engine * engine)121     void RuleBlock::reloadRules(const Engine* engine) {
122         unloadRules();
123         loadRules(engine);
124     }
125 
setName(std::string name)126     void RuleBlock::setName(std::string name) {
127         this->_name = name;
128     }
129 
getName() const130     std::string RuleBlock::getName() const {
131         return this->_name;
132     }
133 
setDescription(const std::string & description)134     void RuleBlock::setDescription(const std::string& description) {
135         this->_description = description;
136     }
137 
getDescription() const138     std::string RuleBlock::getDescription() const {
139         return this->_description;
140     }
141 
setConjunction(TNorm * tnorm)142     void RuleBlock::setConjunction(TNorm* tnorm) {
143         this->_conjunction.reset(tnorm);
144     }
145 
getConjunction() const146     TNorm* RuleBlock::getConjunction() const {
147         return this->_conjunction.get();
148     }
149 
setDisjunction(SNorm * snorm)150     void RuleBlock::setDisjunction(SNorm* snorm) {
151         this->_disjunction.reset(snorm);
152     }
153 
getDisjunction() const154     SNorm* RuleBlock::getDisjunction() const {
155         return this->_disjunction.get();
156     }
157 
setImplication(TNorm * implication)158     void RuleBlock::setImplication(TNorm* implication) {
159         this->_implication.reset(implication);
160     }
161 
getImplication() const162     TNorm* RuleBlock::getImplication() const {
163         return this->_implication.get();
164     }
165 
setActivation(Activation * activation)166     void RuleBlock::setActivation(Activation* activation) {
167         this->_activation.reset(activation);
168     }
169 
getActivation() const170     Activation* RuleBlock::getActivation() const {
171         return this->_activation.get();
172     }
173 
setEnabled(bool enabled)174     void RuleBlock::setEnabled(bool enabled) {
175         this->_enabled = enabled;
176     }
177 
isEnabled() const178     bool RuleBlock::isEnabled() const {
179         return this->_enabled;
180     }
181 
toString() const182     std::string RuleBlock::toString() const {
183         return FllExporter().toString(this);
184     }
185 
186     /**
187      * Operations for std::vector _rules
188      */
addRule(Rule * rule)189     void RuleBlock::addRule(Rule* rule) {
190         _rules.push_back(rule);
191     }
192 
insertRule(Rule * rule,std::size_t index)193     void RuleBlock::insertRule(Rule* rule, std::size_t index) {
194         _rules.insert(_rules.begin() + index, rule);
195     }
196 
getRule(std::size_t index) const197     Rule* RuleBlock::getRule(std::size_t index) const {
198         return _rules.at(index);
199     }
200 
removeRule(std::size_t index)201     Rule* RuleBlock::removeRule(std::size_t index) {
202         Rule* result = _rules.at(index);
203         _rules.erase(_rules.begin() + index);
204         return result;
205     }
206 
numberOfRules() const207     std::size_t RuleBlock::numberOfRules() const {
208         return _rules.size();
209     }
210 
rules() const211     const std::vector<Rule*>& RuleBlock::rules() const {
212         return this->_rules;
213     }
214 
setRules(const std::vector<Rule * > & rules)215     void RuleBlock::setRules(const std::vector<Rule*>& rules) {
216         this->_rules = rules;
217     }
218 
rules()219     std::vector<Rule*>& RuleBlock::rules() {
220         return this->_rules;
221     }
222 
clone() const223     RuleBlock* RuleBlock::clone() const {
224         return new RuleBlock(*this);
225     }
226 
227 }
228