fork download
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define faster cin.tie(NULL);ios_base::sync_with_stdio(false);
  4. #include <iostream>
  5. #include <string>
  6.  
  7.  
  8. //////////////////////////Fuzzy Set/////////////////////////////
  9. class FuzzySet {
  10. public:
  11. string name;
  12. string shape;
  13. vector<double> Points;
  14.  
  15. FuzzySet(){}
  16.  
  17. FuzzySet( string name, string shape, vector<double> points)
  18. : name(name), shape(shape), Points(points) {}
  19.  
  20.  
  21.  
  22. double solveEquation(double input, double x1, double x2, double y1, double y2) {
  23. // y= ax+b -->a=slope
  24. double slope = (y2 - y1) / (x2 - x1);
  25. double b = y1 - (slope * x1); // by substitute
  26. return (slope * input) + b; //intersection
  27. }
  28.  
  29.  
  30. double getCentroid()
  31. {
  32. double centroid=0;
  33. for (int i = 0; i < Points.size(); ++i) {
  34. centroid += Points[i];
  35. }
  36. centroid /= Points.size();
  37. return centroid;
  38. }
  39.  
  40. double getIntersection(double input) {
  41. for (int i = 0; i < Points.size() - 1; ++i) {
  42. if (input >= Points[i] && input <= Points[i + 1]) { // in between
  43. double y1 = 1.0, y2 = 1.0;
  44. if (i == 0) {
  45. y1 = 0;
  46. }
  47. if (i + 1 == Points.size() - 1) {
  48. y2 = 0;
  49. }
  50. return solveEquation(input, Points[i], Points[i + 1], y1, y2);
  51. }
  52. }
  53. return 0.0; //no intersection
  54. }
  55.  
  56. };
  57.  
  58.  
  59.  
  60. //////////////////////////Variable/////////////////////////////
  61. class Variable {
  62. public:
  63. string name;
  64. string type; //In or OUT
  65. map<string,FuzzySet> sets;
  66. double low;
  67. double high;
  68. Variable(){}
  69. Variable( string name, string type, double low, double high)
  70. : name(name), type(type), low(low), high(high) {}
  71.  
  72. void addSet(FuzzySet set) {
  73. sets[set.name] = set;
  74. }
  75.  
  76. map< string, double> CalcMembership(double input) {
  77. map< string, double> map;
  78. for (const auto& setName : sets) {
  79. double membership = sets[setName.first].getIntersection(input);
  80. map[setName.first] = membership;
  81. }
  82. return map;
  83. }
  84.  
  85. };
  86.  
  87.  
  88.  
  89. //////////////////////////Rules/////////////////////////////
  90. class Rules{
  91. public:
  92. vector<string>splitRuleInput;
  93. vector<string>splitRuleOutput;
  94. Rules(string rule)
  95. {
  96. string str="";
  97. bool left=true;
  98. for (int i = 0; i <rule.size() ; ++i) {
  99. if(str=="=>")
  100. {
  101. left=false;
  102. str="";
  103. continue;
  104. }
  105. if(rule[i]==' ')
  106. {
  107. if(str!=""&&left)
  108. splitRuleInput.push_back(str);
  109. else if(str!=""&&!left)
  110. {
  111. splitRuleOutput.push_back(str);
  112. }
  113. str="";
  114. continue;
  115. }
  116. str+=rule[i];
  117.  
  118. }
  119. if(str!="") splitRuleOutput.push_back(str);
  120. }
  121.  
  122. pair<double,string>calculate( map<string, map<string, double>> memberShip)
  123. {
  124. pair<double,string>current;
  125. string name1=this->splitRuleInput[0];
  126. string dec1=this->splitRuleInput[1];
  127. double temp=memberShip[name1][dec1];
  128. for (int i = 2; i < this->splitRuleInput.size()-2;i++) {
  129. string op= this->splitRuleInput[i];
  130. string name2= this->splitRuleInput[i+1];
  131. string dec2=this->splitRuleInput[i+2];
  132. i++;i++;
  133. if(op=="or")
  134. {
  135. temp=max(temp,memberShip[name2][dec2]);
  136. }
  137. else if(op=="and")
  138. {
  139. temp=min(temp,memberShip[name2][dec2]);
  140. }
  141. else if(op=="and_not")
  142. {
  143. temp=min(temp,1-memberShip[name2][dec2]);
  144. }
  145. else if(op=="or_not")
  146. {
  147. temp=max(temp,1-memberShip[name2][dec2]);
  148. }
  149. }
  150. current.first=temp;
  151. current.second=this->splitRuleOutput[1];
  152. return current;
  153.  
  154. }
  155.  
  156. };
  157.  
  158.  
  159. //////////////////////////FuzzyLogicSystem/////////////////////////////
  160. class FuzzyLogicSystem{
  161. public:
  162. string name;
  163. string description;
  164. vector<Rules>rules;
  165. map<string,Variable>variables; //change
  166. //add variables -> add their sets -> add rules -> run
  167. bool steps[3]={false, false, false};
  168.  
  169. public:
  170. FuzzyLogicSystem(string &name, string &description)
  171. {
  172. this->name=name;
  173. this->description=description;
  174. steps[0]=steps[1]=steps[2] = false;
  175. }
  176.  
  177. void addVariables(Variable &variable)
  178. {
  179. variables[variable.name]=variable;
  180. steps[0]= true;
  181. }
  182. bool checkStep2(){
  183. for(auto variable :variables){
  184. if(variable.second.sets.empty())
  185. return false;
  186. }
  187. steps[1]=true;
  188. return true;
  189. }
  190. void addRule(Rules rule)
  191. {
  192. if(steps[0]&&checkStep2()) {
  193. rules.push_back(rule);
  194. steps[2]=true;
  195. }
  196. else
  197. cout<<"Please check that you Entered the variables and their sets!\n";
  198. }
  199.  
  200. void addVariableSet(string varName, FuzzySet fuzzySet) {
  201. variables[varName].addSet(fuzzySet);
  202.  
  203. }
  204.  
  205. /////////////////First Step//////////////////////////
  206. map<string, map<string, double>> Fuzzification( map<string, Variable>& myVariables, map<string, double>& input) {
  207. map<string, map<string, double>> fuzzification;
  208. for (auto curr : myVariables) {
  209. if (curr.second.type == "IN") {
  210. map<string, double> memberships = curr.second.CalcMembership(input[curr.first]);
  211. fuzzification[curr.first] = memberships; //input ---> intersection points for each variable
  212. }
  213. }
  214.  
  215. return fuzzification;
  216. }
  217.  
  218.  
  219. /////////////////Second Step//////////////////////////
  220. vector<pair<double,string>>Inference( map<string, map<string, double>>memberShip, vector<Rules>rules)
  221. {
  222. vector<pair<double,string>> inference;
  223. for (int i = 0; i < rules.size(); ++i) {
  224. inference.push_back(rules[i].calculate(memberShip));
  225. }
  226. return inference;
  227. }
  228.  
  229. /////////////////Third Step//////////////////////////
  230. double Defuzificztion(map<string, Variable>& myVariables, vector<pair<double,string>>inference)
  231. {
  232. double defuzzification;
  233. map<string,double>mp;
  234. for (auto curr : myVariables) {
  235. if (curr.second.type == "OUT") {
  236. for (auto currFact:curr.second.sets) {
  237. auto center=currFact.second.getCentroid();
  238. // cout<<center<<endl;
  239. mp[currFact.first]=center;
  240. }
  241. }
  242. }
  243. /////////weighted///////////
  244. double total=0;
  245. double weight=0;
  246. for (int i = 0; i <inference.size() ; ++i) {
  247. total+=(mp[inference[i].second]*inference[i].first);
  248. weight+=inference[i].first;
  249. }
  250. defuzzification=total/weight;
  251. return defuzzification;
  252. }
  253.  
  254. bool ready(){
  255. if(steps[0]&&steps[1]&&steps[2])
  256. return true;
  257. return false;
  258. }
  259.  
  260. };
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267. int main() {
  268. while (true)
  269. {
  270. cout<<"Fuzzy Logic Toolbox\n"
  271. "===================\n"
  272. "1- Create a new fuzzy system\n"
  273. "2- Quit\n";
  274. int choice; cin>>choice;
  275. if(choice==1)
  276. {
  277.  
  278. cout<<"Enter the system’s name and a brief description:\n";
  279. string fuzzyName,des; cin.ignore();
  280. getline(cin,fuzzyName);
  281. getline(cin,des);
  282. FuzzyLogicSystem newFuzzy(fuzzyName,des);
  283. while (true)
  284. {
  285.  
  286. cout<<"Main Menu:\n"
  287. "==========\n"
  288. "1- Add variables.\n"
  289. "2- Add fuzzy sets to an existing variable.\n"
  290. "3- Add rules.\n"
  291. "4- Run the simulation on crisp values.\n";
  292. int option;cin>>option;
  293. if(option==1)
  294. {
  295. cout<<"Enter the variable’s name, type (IN/OUT) and range ([lower, upper]):\n"
  296. "(Press x to finish)";
  297. string name;
  298. while (cin>>name &&name!="x")
  299. {
  300. string type; int low, high;
  301. char c;
  302. cin>>type>>c>>low>>c>>high>>c;
  303. int valid=1;
  304. if((type!="IN"&&type!="OUT")||low>high)
  305. valid=0;
  306. while (!valid){
  307. cout<<"Invalid Type or Range!"<<endl;
  308. cout<<"Enter Type (IN/OUT) and range ([lower, upper]) Again:\n";
  309. cin>>type>>c>>low>>c>>high>>c;
  310. if((type=="IN"||type=="OUT")&&low<=high)
  311. valid=1;
  312. }
  313. Variable variable(name,type,low,high);
  314. newFuzzy.addVariables(variable);
  315. }
  316.  
  317.  
  318. }
  319. else if(option==2)
  320. {
  321. cout<<"Enter the variable’s name:";
  322. string varName; cin>>varName;
  323. while (newFuzzy.variables.find(varName)==newFuzzy.variables.end()){
  324. cout<<"Invalid Variable Name!\nEnter it Again: (Press x to finish)\n";
  325. cin>>varName;
  326. }
  327. cout<<"Enter the fuzzy set name, type (TRI/TRAP) and values: (Press x to finish) ";
  328. string name;
  329. while (cin>>name &&name!="x")
  330. {
  331.  
  332. string shape;cin>>shape;
  333. while (shape!="TRI"&&shape!="TRAP"){
  334. cout<<"Invalid Type!\nEnter it Again:\n";
  335. cin>>shape;
  336. }
  337. vector<double>points;
  338. if(shape=="TRI")
  339. {
  340. for (int i = 0; i <3 ; ++i) {
  341. int currPoint; cin>>currPoint;
  342. points.push_back(currPoint);
  343. }
  344. }
  345. else
  346. {
  347. for (int i = 0; i <4 ; ++i) {
  348. int currPoint; cin>>currPoint;
  349. points.push_back(currPoint);
  350. }
  351. }
  352. FuzzySet fuzzySet(name,shape,points);
  353. newFuzzy.addVariableSet(varName, fuzzySet);
  354. }
  355. // map<string,double>input;
  356. // input["proj_funding"]=50;
  357. // input["exp_level"]=40;
  358. // map<string,map<string, double> >res=newFuzzy.Fuzzification(newFuzzy.variables,input);
  359. // cout<<"offfffffffffffffff"<<endl;
  360. // cout<<res.size()<<endl;
  361. // for (const auto &outer_pair : res) {
  362. // std::cout << "Outer Key: " << outer_pair.first << std::endl;
  363. //
  364. // // Loop through the inner map
  365. // for (const auto &inner_pair : outer_pair.second) {
  366. // std::cout << "\tInner Key: " << inner_pair.first
  367. // << ", Value: " << inner_pair.second << std::endl;
  368. // }
  369. // }
  370.  
  371. }
  372. else if(option==3)
  373. {
  374. cout<<"Enter the rules in this format: (Press x to finish) \n"
  375. "IN_variable set operator IN_variable set => OUT_variable set\n";
  376. string rule;
  377. cin.ignore();
  378. ///handle if it's invalid rule
  379. while (getline(cin,rule)&&rule!="x")
  380. {
  381. //cout<<rule<<endl;
  382. Rules myRule(rule);
  383. newFuzzy.addRule(myRule);
  384. }
  385. }
  386. else if(option==4)
  387. {
  388. cout<<"Enter the crisp values: ";
  389. //////////////////////////////////////dd**///
  390. if(!newFuzzy.ready()) {
  391. cout << "CAN’T START THE SIMULATION! Please add the fuzzy sets and rules first.\n";
  392. continue;
  393. }
  394. map<string,double>input;
  395. int x;
  396. for(auto currvar:newFuzzy.variables)
  397. {
  398. if(currvar.second.type=="IN")
  399. {
  400. cout<<currvar.first<<":";
  401. cin>>x;
  402. input[currvar.first]=x;
  403. cout<<endl;
  404. }
  405. }
  406. map<string,map<string, double> >memberShip=newFuzzy.Fuzzification(newFuzzy.variables,input);
  407. vector<pair<double,string>>inference=newFuzzy.Inference( memberShip,newFuzzy.rules);
  408. double defuzificztion =newFuzzy.Defuzificztion(newFuzzy.variables, inference);
  409. cout<<defuzificztion<<endl;
  410.  
  411.  
  412. }
  413. else
  414. break;
  415. }
  416.  
  417.  
  418. }
  419. else
  420. return 0;
  421. }
  422.  
  423. }
  424.  
Success #stdin #stdout 0.01s 5272KB
stdin
Standard input is empty
stdout
Fuzzy Logic Toolbox
===================
1- Create a new fuzzy system
2- Quit