LinguisticVariable.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* Copyright 2010 Juan Rada-Vilela
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. #include "LinguisticVariable.h"
  13. #include "FuzzyExceptions.h"
  14. #include "StrOp.h"
  15. #include <algorithm>
  16. #include <math.h>
  17. #include "ShoulderTerm.h"
  18. #include "TriangularTerm.h"
  19. #include "TrapezoidalTerm.h"
  20. namespace fl {
  21. LinguisticVariable::LinguisticVariable() :
  22. _fuzzy_operator(NULL) {
  23. setFuzzyOperator(FuzzyOperator::DefaultFuzzyOperator());
  24. }
  25. LinguisticVariable::LinguisticVariable(const std::string& name) :
  26. _fuzzy_operator(NULL), _name(name) {
  27. setFuzzyOperator(FuzzyOperator::DefaultFuzzyOperator());
  28. }
  29. LinguisticVariable::LinguisticVariable(const FuzzyOperator& fuzzy_op,
  30. const std::string& name) :
  31. _fuzzy_operator(&fuzzy_op), _name(name) {
  32. }
  33. LinguisticVariable::~LinguisticVariable() {
  34. for (int i = numberOfTerms() - 1; i >= 0; --i) {
  35. delete removeTerm(i);
  36. }
  37. }
  38. std::string LinguisticVariable::name() const {
  39. return this->_name;
  40. }
  41. void LinguisticVariable::setName(const std::string& name) {
  42. this->_name = name;
  43. }
  44. void LinguisticVariable::setFuzzyOperator(const FuzzyOperator& fuzzy_operator) {
  45. this->_fuzzy_operator = &fuzzy_operator;
  46. }
  47. const FuzzyOperator& LinguisticVariable::fuzzyOperator() const {
  48. return *this->_fuzzy_operator;
  49. }
  50. int LinguisticVariable::positionFor(const LinguisticTerm* lterm) {
  51. for (int i = 0; i < numberOfTerms(); ++i) {
  52. if (FuzzyOperation::IsLEq(lterm->minimum(), term(i)->minimum())) {
  53. if (FuzzyOperation::IsEq(lterm->minimum(), term(i)->minimum())) {
  54. return lterm->membership(lterm->minimum()) > term(i)->membership(lterm->minimum())
  55. ? i : i + 1;
  56. }
  57. return i;
  58. }
  59. }
  60. return numberOfTerms();
  61. }
  62. void LinguisticVariable::addTerm(LinguisticTerm* term) {
  63. int pos = positionFor(term);
  64. _terms.insert(_terms.begin() + pos, term);
  65. }
  66. LinguisticTerm* LinguisticVariable::term(int index) const {
  67. return _terms[index];
  68. }
  69. LinguisticTerm* LinguisticVariable::term(const std::string& name) const {
  70. int index = indexOf(name);
  71. return index == -1 ? NULL : term(index);
  72. }
  73. int LinguisticVariable::indexOf(const std::string& name) const {
  74. for (int i = 0; i < numberOfTerms(); ++i) {
  75. if (term(i)->name() == name) {
  76. return i;
  77. }
  78. }
  79. return -1;
  80. }
  81. LinguisticTerm* LinguisticVariable::removeTerm(int index) {
  82. LinguisticTerm* result = _terms[index];
  83. _terms.erase(_terms.begin() + index);
  84. return result;
  85. }
  86. LinguisticTerm* LinguisticVariable::removeTerm(const std::string& name) {
  87. int index = indexOf(name);
  88. return index == -1 ? NULL : removeTerm(index);
  89. }
  90. LinguisticTerm* LinguisticVariable::firstTerm() const {
  91. return numberOfTerms() > 0 ? term(0) : NULL;
  92. }
  93. LinguisticTerm* LinguisticVariable::lastTerm() const {
  94. return numberOfTerms() > 0 ? term(numberOfTerms() - 1) : NULL;
  95. }
  96. bool LinguisticVariable::isEmpty() const {
  97. return numberOfTerms() == 0;
  98. }
  99. int LinguisticVariable::numberOfTerms() const {
  100. return _terms.size();
  101. }
  102. flScalar LinguisticVariable::minimum() const {
  103. return numberOfTerms() == 0 ? NAN : firstTerm()->minimum();
  104. }
  105. flScalar LinguisticVariable::maximum() const {
  106. return numberOfTerms() == 0 ? NAN : lastTerm()->maximum();
  107. }
  108. CompoundTerm LinguisticVariable::compound() const {
  109. CompoundTerm result("Accumulated " + name(), minimum(), maximum());
  110. for (int i = 0; i < numberOfTerms(); ++i) {
  111. result.addTerm(*term(i));
  112. }
  113. return result;
  114. }
  115. std::string LinguisticVariable::fuzzify(flScalar crisp) const {
  116. std::vector<std::string> fuzzyness;
  117. for (int i = 0; i < numberOfTerms(); ++i) {
  118. flScalar degree = term(i)->membership(crisp);
  119. fuzzyness.push_back(StrOp::ScalarToString(degree) + "/"
  120. + term(i)->name());
  121. }
  122. // StringOperator::sort(fuzzyness, false);
  123. std::string result;
  124. for (size_t i = 0; i < fuzzyness.size(); ++i) {
  125. result += fuzzyness[i] + (i < fuzzyness.size() - 1 ? " + " : "");
  126. }
  127. return result;
  128. }
  129. LinguisticTerm* LinguisticVariable::bestFuzzyApproximation(flScalar crisp) {
  130. LinguisticTerm* result = NULL;
  131. flScalar highest_degree = -1.0;
  132. for (int i = 0; i < numberOfTerms(); ++i) {
  133. flScalar degree = term(i)->membership(crisp);
  134. if (degree > highest_degree) {
  135. result = term(i);
  136. highest_degree = degree;
  137. }
  138. }
  139. return result;
  140. }
  141. void LinguisticVariable::createTerms(int number_of_terms,
  142. LinguisticTerm::eMembershipFunction mf, flScalar min, flScalar max,
  143. const std::vector<std::string>& labels) {
  144. std::vector<std::string> final_labels;
  145. for (int i = 0; i < number_of_terms; ++i) {
  146. if ((int) labels.size() <= i) {
  147. final_labels.push_back(name() + "-" + StrOp::IntToString(i + 1));
  148. } else {
  149. final_labels.push_back(labels[i]);
  150. }
  151. }
  152. fl::flScalar intersection = NAN; //Proportion of intersection between terms
  153. if (mf == LinguisticTerm::MF_TRAPEZOIDAL) {
  154. intersection = 4.0 / 5.0;
  155. } else {
  156. intersection = 0.5;
  157. }
  158. //TODO: What is the intersection in other terms?
  159. fl::flScalar term_range = (max - min) / (number_of_terms - number_of_terms / 2);
  160. fl::flScalar current_step = min + (1 - intersection) * term_range;
  161. for (int i = 0; i < number_of_terms; ++i) {
  162. fl::LinguisticTerm* term = NULL;
  163. switch (mf) {
  164. case LinguisticTerm::MF_TRIANGULAR:
  165. term = new fl::TriangularTerm(final_labels.at(i),
  166. current_step - (1 - intersection) * term_range,
  167. current_step + intersection * term_range);
  168. break;
  169. case LinguisticTerm::MF_SHOULDER:
  170. if (i == 0 || i == number_of_terms - 1) {
  171. term = new fl::ShoulderTerm(final_labels[i],
  172. current_step - (1 - intersection) * term_range,
  173. current_step + intersection * term_range, i == 0);
  174. } else {
  175. term = new fl::TriangularTerm(final_labels.at(i),
  176. current_step - (1 - intersection) * term_range,
  177. current_step + intersection * term_range);
  178. }
  179. break;
  180. case LinguisticTerm::MF_TRAPEZOIDAL:
  181. term = new fl::TrapezoidalTerm(final_labels.at(i),
  182. current_step - (1 - intersection) * term_range,
  183. current_step + intersection * term_range);
  184. // term = new fl::TriangularTerm(final_labels.at(i), current_step
  185. // - (1 - intersection) * term_range, current_step + intersection
  186. // * term_range);
  187. break;
  188. default:
  189. throw fl::InvalidArgumentException(FL_AT, "Invalid option for membership function");
  190. }
  191. current_step += intersection * term_range;
  192. addTerm(term);
  193. }
  194. }
  195. std::string LinguisticVariable::toString() const {
  196. std::string result(name());
  197. result += "={ ";
  198. for (int i = 0; i < numberOfTerms(); ++i) {
  199. result += term(i)->name() + " ";
  200. }
  201. result += "}";
  202. return result;
  203. }
  204. }