1use crate::aggregations::Aggregations;
2use crate::defuzzifications::{Defuzzifiers, TSKDefuzzifiers};
3use crate::implications::Implications;
4use crate::rules::{self, Rule};
5use crate::s_norms::SNorms;
6use crate::t_norms::TNorms;
7use crate::variables::{InputVariable, OutputVariable, TSKOutputVariable};
8
9#[derive(Debug)]
10pub struct MamdaniFuzzyInferenceSystem {
11 s_norm: SNorms,
12 t_norm: TNorms,
13 implication: Implications,
14 aggregation: Aggregations,
15 defuzzifier: Defuzzifiers,
16 rules: Vec<Rule>,
17 inputs: Vec<InputVariable>,
18 outputs: Vec<OutputVariable>,
19}
20
21pub type MamdaniFIS = MamdaniFuzzyInferenceSystem;
22
23impl MamdaniFuzzyInferenceSystem {
24 pub fn new(
25 s_norm: SNorms,
26 t_norm: TNorms,
27 implication: Implications,
28 aggregation: Aggregations,
29 defuzzifier: Defuzzifiers,
30 ) -> Self {
31 Self {
32 s_norm,
33 t_norm,
34 implication,
35 aggregation,
36 defuzzifier,
37 rules: Vec::new(),
38 inputs: Vec::new(),
39 outputs: Vec::new(),
40 }
41 }
42
43 pub fn new_all(
44 s_norm: SNorms,
45 t_norm: TNorms,
46 implication: Implications,
47 aggregation: Aggregations,
48 defuzzifier: Defuzzifiers,
49 rules: Vec<Rule>,
50 inputs: Vec<InputVariable>,
51 outputs: Vec<OutputVariable>,
52 ) -> Self {
53 Self {
54 s_norm,
55 t_norm,
56 implication,
57 aggregation,
58 defuzzifier,
59 rules,
60 inputs,
61 outputs,
62 }
63 }
64
65 pub fn add_input(&mut self, input: InputVariable) {
66 self.inputs.push(input);
67 }
68
69 pub fn add_output(&mut self, output: OutputVariable) {
70 self.outputs.push(output);
71 }
72
73 pub fn add_rule(&mut self, rule: Rule) {
74 self.rules.push(rule);
75 }
76
77 pub fn get_s_norm(&self, fuzzified: &[f64]) -> f64 {
78 self.s_norm.s_norm(fuzzified)
79 }
80
81 pub fn get_t_norm(&self, fuzzified: &[f64]) -> f64 {
82 self.t_norm.t_norm(fuzzified)
83 }
84
85 pub fn get_rules(&self, rule_index: usize) -> &[i32] {
86 self.rules[rule_index].get_rules()
87 }
88
89 pub fn get_input_rules(&self, rule_index: usize) -> &[i32] {
90 self.rules[rule_index].get_input_rules(self.inputs.len())
91 }
92
93 pub fn get_output_rules(&self, rule_index: usize) -> &[i32] {
94 self.rules[rule_index].get_output_rules(self.inputs.len())
95 }
96
97 pub fn fuzzification(&self, input_vec: Vec<f64>) -> Vec<Vec<f64>> {
98 let mut fuzzified: Vec<Vec<f64>> = Vec::new();
99 for i in 0..self.rules.len() {
100 let input_rule: &[i32] = self.get_input_rules(i);
101 let mut temp_vec: Vec<f64> = Vec::new();
102 for ii in 0..self.inputs.len() {
103 let index;
104 let complement;
105 if input_rule[ii] < 0 {
106 index = (-input_rule[ii]) as usize;
107 complement = true;
108 } else {
109 index = input_rule[ii] as usize;
110 complement = false;
111 }
112 let fuzzed: f64 = self.inputs[ii].fuzzify(index, input_vec[ii]);
113 temp_vec.push(match complement {
114 true => 1.0 - fuzzed,
115 false => fuzzed,
116 });
117 }
119 fuzzified.push(temp_vec);
120 }
121 fuzzified
122 }
123
124 pub fn connect_inputs(&self, fuzzified: Vec<Vec<f64>>) -> Vec<f64> {
125 fuzzified
126 .into_iter()
127 .zip(&self.rules)
128 .map(|(fuzz, rule)| match rule.get_kind() {
129 rules::Kind::OR => self.get_s_norm(&fuzz),
130 rules::Kind::AND => self.get_t_norm(&fuzz),
131 })
132 .collect()
133 }
134
135 pub fn weighed_inputs(&self, connected_inputs: Vec<f64>) -> Vec<f64> {
136 connected_inputs
137 .into_iter()
138 .zip(&self.rules)
139 .map(|(mu, rule)| rule.get_weight() * mu)
140 .collect()
141 }
142
143 pub fn implication(&self, connected_inputs: Vec<f64>) -> Vec<Vec<Vec<f64>>> {
144 let mut implication_vec = Vec::new();
145 for i in 0..self.outputs.len() {
146 let mut temp_vec = Vec::new();
147 for ii in 0..self.rules.len() {
148 let output_rule = self.get_output_rules(ii);
149 let index;
150 let complement;
151 if output_rule[i] < 0 {
152 index = (-output_rule[i]) as usize;
153 complement = true;
154 } else {
155 index = output_rule[i] as usize;
156 complement = false;
157 }
158 let range: Vec<f64> = self.outputs[i]
159 .get_mu(index)
160 .into_iter()
161 .map(|e| if complement { 1.0 - e } else { e.to_owned() })
162 .collect();
163
164 temp_vec.push(self.implication.implication(connected_inputs[ii], &range));
165 }
166 implication_vec.push(temp_vec);
167 }
168 implication_vec
169 }
170
171 pub fn aggregation(&self, implication_vec: Vec<Vec<Vec<f64>>>) -> Vec<Vec<f64>> {
172 implication_vec
173 .into_iter()
174 .map(|vec| self.aggregation.aggregation(&vec))
175 .collect()
176 }
177
178 pub fn defuzzification(&self, aggregation_vec: Vec<Vec<f64>>) -> Vec<f64> {
179 aggregation_vec
180 .into_iter()
181 .enumerate()
182 .map(|(index, aggregated)| {
183 self.defuzzifier
184 .defuzzify(aggregated, self.outputs[index].get_universe())
185 })
186 .collect()
187 }
188
189 pub fn compute_outputs(&self, input_vec: Vec<f64>) -> Vec<f64> {
190 assert!(self.inputs.len() != 0, "You must add at least one INPUT");
191 assert!(self.outputs.len() != 0, "You must add at least one OUTPUT");
192 assert!(self.rules.len() != 0, "You must add at least one RULE");
193
194 let fuzzified = self.fuzzification(input_vec);
196 let connected_inputs = self.connect_inputs(fuzzified);
197 let weighted_inputs = self.weighed_inputs(connected_inputs);
198 let implication_vec = self.implication(weighted_inputs);
200 let aggregation_vec = self.aggregation(implication_vec);
202 self.defuzzification(aggregation_vec)
204 }
205}
206
207#[derive(Debug)]
208pub struct TSKFuzzyInferenceSystem {
209 s_norm: SNorms,
210 t_norm: TNorms,
211 defuzzification: TSKDefuzzifiers,
212 rules: Vec<Rule>,
213 inputs: Vec<InputVariable>,
214 outputs: Vec<TSKOutputVariable>,
215}
216
217pub type TSKFIS = TSKFuzzyInferenceSystem;
218
219impl TSKFuzzyInferenceSystem {
220 pub fn new(s_norm: SNorms, t_norm: TNorms, defuzzification: TSKDefuzzifiers) -> Self {
221 Self {
222 s_norm,
223 t_norm,
224 defuzzification,
225 rules: Vec::new(),
226 inputs: Vec::new(),
227 outputs: Vec::new(),
228 }
229 }
230
231 pub fn add_input(&mut self, input: InputVariable) {
232 self.inputs.push(input);
233 }
234
235 pub fn add_output(&mut self, variable: TSKOutputVariable) {
236 self.outputs.push(variable);
237 }
238
239 pub fn add_rule(&mut self, rule: Rule) {
240 self.rules.push(rule);
241 }
242
243 pub fn get_s_norm(&self, fuzzified: &[f64]) -> f64 {
244 self.s_norm.s_norm(fuzzified)
245 }
246
247 pub fn get_t_norm(&self, fuzzified: &[f64]) -> f64 {
248 self.t_norm.t_norm(fuzzified)
249 }
250
251 pub fn get_rules(&self, rule_index: usize) -> &[i32] {
252 self.rules[rule_index].get_rules()
253 }
254
255 pub fn get_input_rules(&self, rule_index: usize) -> &[i32] {
256 self.rules[rule_index].get_input_rules(self.inputs.len())
257 }
258
259 pub fn get_output_rules(&self, rule_index: usize) -> &[i32] {
260 self.rules[rule_index].get_output_rules(self.inputs.len())
261 }
262
263 pub fn fuzzification(&self, input_vec: Vec<f64>) -> Vec<Vec<f64>> {
264 let mut fuzzified: Vec<Vec<f64>> = Vec::new();
265 for i in 0..self.rules.len() {
266 let input_rule = self.get_input_rules(i);
267 let mut temp_vec: Vec<f64> = Vec::new();
268 for ii in 0..self.inputs.len() {
269 let index;
270 let complement;
271 if input_rule[ii] < 0 {
272 index = (-input_rule[ii]) as usize;
273 complement = true;
274 } else {
275 index = input_rule[ii] as usize;
276 complement = false;
277 }
278 let fuzzed = self.inputs[ii].fuzzify(index, input_vec[ii]);
279 temp_vec.push(match complement {
280 true => 1.0 - fuzzed,
281 false => fuzzed,
282 });
283 }
285 fuzzified.push(temp_vec);
286 }
287 fuzzified
288 }
289
290 pub fn connect_inputs(&self, fuzzified: Vec<Vec<f64>>) -> Vec<f64> {
291 fuzzified
292 .into_iter()
293 .zip(&self.rules)
294 .map(|(fuzz, rule)| match rule.get_kind() {
295 rules::Kind::OR => self.get_s_norm(&fuzz),
296 rules::Kind::AND => self.get_t_norm(&fuzz),
297 })
298 .collect()
299 }
300
301 pub fn weighed_inputs(&self, connected_inputs: Vec<f64>) -> Vec<f64> {
302 connected_inputs
303 .into_iter()
304 .zip(&self.rules)
305 .map(|(mu, rule)| rule.get_weight() * mu)
306 .collect()
307 }
308
309 pub fn get_mu(&self, input_vec: &Vec<f64>) -> Vec<Vec<f64>> {
310 let mut output = Vec::new();
311 for i in 0..self.outputs.len() {
312 let mut temp_vec = Vec::new();
313 for ii in 0..self.rules.len() {
314 let output_rule = self.rules[ii].get_output_rules(self.inputs.len());
315 temp_vec.push(
316 self.outputs[i].get_mu(output_rule[i as usize].try_into().unwrap(), &input_vec),
317 )
318 }
319 output.push(temp_vec);
320 }
321 output
322 }
323
324 pub fn compute_outputs(&self, input: Vec<f64>) -> Vec<f64> {
325 let mut output = Vec::new();
326
327 let fuzzified = self.fuzzification(input.clone());
329 let connected_inputs = self.connect_inputs(fuzzified);
330 let weighted_input = self.weighed_inputs(connected_inputs);
331 let mu_vec = self.get_mu(&input);
335 for i in 0..self.outputs.len() {
336 output.push(self.defuzzification.defuzzify(&mu_vec[i], &weighted_input));
337 }
338
339 output
340 }
341}