Skip to content

Commit 3d1ca1b

Browse files
Add files via upload
1 parent b7533aa commit 3d1ca1b

File tree

6 files changed

+279
-0
lines changed

6 files changed

+279
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.pyc
2+
*cache__/*
3+
*_cache
4+
.vscode/*

fuzzyRule.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from typing import List, Callable, Any, Tuple
2+
3+
'''
4+
examples of rules:
5+
- from left to right
6+
- no precedence
7+
8+
rule:A and B or C
9+
variables: [A,B,C]
10+
operators: [and,or]
11+
12+
rule: A or B and C
13+
variables: [A,[B,C]]
14+
operators: [or, and]
15+
16+
rule: A and B or (B and C)
17+
variables: [A,B,[B,C]]
18+
operators: [and,or,and]
19+
20+
rule: A and (B or C and A) or C and D
21+
variables: [A,[B,[C,A]],[C,D]]
22+
operators: [and, or, and, or, and]
23+
24+
'''
25+
26+
def compute_rule(variables:List[any], operators:List[Callable[[float, float], float]]) -> float:
27+
val = compute_parenthesis(variables, operators, 0)[1]
28+
# print(len(operators), op_idx)
29+
return val
30+
31+
def compute_parenthesis(variables:List[Any], operators:List[Callable[[float, float], float]], curr_idx: int) -> Tuple[int, float]:
32+
tmp = variables[0]
33+
if tmp is list:
34+
curr_idx, tmp = compute_parenthesis(tmp, operators, curr_idx)
35+
for var in variables[1:]:
36+
if type(var) is list:
37+
tmp_idx = curr_idx
38+
curr_idx += 1
39+
curr_idx, aux = compute_parenthesis(var, operators, curr_idx)
40+
else:
41+
aux = var
42+
tmp_idx = None
43+
if tmp_idx is not None:
44+
tmp = operators[tmp_idx](tmp, aux)
45+
tmp_idx = None
46+
else:
47+
tmp = operators[curr_idx](tmp, aux)
48+
curr_idx += 1
49+
return curr_idx, tmp

fuzzyVar.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from typing import Tuple, Dict, List, Callable, NoReturn
2+
3+
class FuzzyVar:
4+
# X, T, U, M
5+
# X = base_value -> accessed using its index
6+
# T = values -> list of different linguistic values for the variable
7+
# U = universe -> meaning range -> using [0.,1.]
8+
# M = meaning -> meaning of var with base_value x, for value t in T
9+
def __init__(self, values: List[float], meaning:Dict[str, Callable[[float], float]]) -> NoReturn:
10+
self.values:List[float] = values
11+
self.meaning:Dict[str, Callable[[float], float]] = meaning
12+
13+
def get_meaning(self, value:float, base_value:float) -> float:
14+
meaning = self.meaning[value](base_value)
15+
if meaning < 0.:
16+
return 0.
17+
elif meaning > 1.:
18+
return 1.
19+
else:
20+
return meaning

operators.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from typing import Callable
2+
from math import pow
3+
from random import random
4+
5+
class Operators:
6+
def __init__(self, gama:float, p:float, alpha: float):
7+
if p is None:
8+
p = 1. + random()
9+
elif p < 1.:
10+
p = 1.
11+
if gama is None:
12+
gama = random()
13+
elif gama < 0.:
14+
gama = 0.
15+
elif gama > 1.:
16+
gama = 1.
17+
if alpha is None:
18+
alpha = random()
19+
elif alpha < 0.:
20+
alpha = 0.
21+
elif alpha > 1.:
22+
alpha = 1.
23+
24+
self.p = p
25+
self.alpha = alpha
26+
self.gama = gama
27+
28+
29+
def minimum(self, x: float, y: float) -> float:
30+
return min(x,y)
31+
32+
def maximum(self, x: float, y: float) -> float:
33+
return max(x,y)
34+
35+
def drastic_product(self, x:float, y:float) -> float:
36+
if(max(x,y) == 1.):
37+
return min(x,y)
38+
else:
39+
return 0.
40+
41+
def drastic_sum(self, x:float, y:float) -> float:
42+
if(min(x,y) == 0.):
43+
return max(x,y)
44+
else:
45+
return 1.
46+
47+
def bounded_difference(self, x:float, y:float) -> float:
48+
return max(0., x + y - 1.)
49+
50+
def bounded_sum(self, x:float, y:float) -> float:
51+
return min(1., x + y)
52+
53+
def einstein_product(self, x:float, y:float) -> float:
54+
aux = x * y
55+
return aux/(2. - x + y - aux)
56+
57+
def einstein_sum(self, x:float, y:float) -> float:
58+
return (x + y)/(1. - x * y)
59+
60+
def hamacher_product(self, x:float, y:float) -> float:
61+
aux = x * y
62+
return aux / (x + y - aux)
63+
64+
def hamacher_sum(self, x:float, y:float) -> float:
65+
aux = x * y
66+
return (x + y - 2. * aux)/(1. - aux)
67+
68+
def hamacher_union(self, x:float, y:float) -> float:
69+
return ((self.gama - 1.) * y + x + y) / (1. + self.gama * x * y)
70+
71+
def yaeger_intersection(self, x:float, y:float) -> float:
72+
return 1 - min(1, pow(pow(1. - x, self.p) + pow(1. - y, self.p), self.p))
73+
74+
def yaeger_union(self, x:float, y:float) -> float:
75+
return min(1., pow((x ** self.p + y ** self.p), 1./self.p))
76+
77+
def dubois_prade_intersection(self, x:float, y:float) -> float:
78+
return (x * y)/(max(x, y, self.alpha))
79+
80+
def union(self, x:float, y:float) -> float:
81+
return x + y - x * y - min(x, y, 1. - self.alpha)/max(1. - x, 1. - y, self.alpha)
82+

readme.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
2+
# Mini Fuzzy Solver
3+
4+
This package implements a simple normalized fuzzy solver
5+
6+
## Classes
7+
8+
---
9+
10+
### FuzzyVar
11+
12+
- Retains info about the fuzzy variables
13+
- List of linguistic values
14+
- Meaning function for each linguistic value
15+
16+
---
17+
18+
### Operators
19+
20+
- Define the operators and parameters used in each operator(minimum, maximum, union, intersect, etc)
21+
22+
### How to use
23+
24+
1. Define your fuzzy variables
25+
26+
__a)__ Base variables
27+
__b)__ Linguistic values
28+
__c)__ Meaning functions
29+
30+
2. Decide on wich operators to use for each operator(and, or, union, intersection, etc) in your logic
31+
32+
3. Use __fuzzyRule.py__ computeRules function
33+
34+
---
35+
36+
### How to define rules
37+
38+
The rules are executed from left to right.
39+
> A and B or C -> [ [A, B, C], [and, or] ]
40+
> A or B and C -> [ [ [A, B], C], [or, and] ]
41+
> A and B or C and D -> [ [ [A, B], [C, D]], [and, or, and] ]
42+
> A and (B or C) -> [ [A, [B, C] ], [and, or]]
43+
> A and (B or C or D) and D -> [ [A, [B, C, D], D], [and, or, or, and] ]
44+
---
45+
46+
### Example
47+
48+
```python
49+
BASE_VARIABLES = List[float]
50+
MEANING = List[Dict[str,float]]
51+
FUZZY_VARS = List[FuzzyVar]
52+
FUZZY_RULES = List[Tuple[List[Any '''float or list'''],]]
53+
```

test.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from fuzzyVar import FuzzyVar
2+
from math import pi, sin, cos
3+
from typing import Dict, List, Tuple, Any, Callable, NoReturn
4+
from fuzzyRule import compute_rule
5+
from operators import Operators
6+
7+
8+
9+
# type definitions
10+
BASE_VALUES = List[float] # variable base values
11+
MEANING = List[Dict[str, float]] # variable meaning values
12+
FUZZY_VARS = List[FuzzyVar] # FuzzyVarObjects
13+
FUZZY_RULES = List[Tuple[List[Any],List[Callable[[float, float], float]]]] # list [([var1,[var2_1,var2_2], var3], [op1_2, op2, op2_3])]
14+
VAR_DICT = Dict[str,int] # dictionary of fuzzy variable names to meaning/fuzzyVar/baseValue index
15+
OP = Operators
16+
17+
VAR_DICT = {
18+
"A": 0.,
19+
"B": 1.
20+
}
21+
22+
BASE_VALUES = [4,56]
23+
24+
MEANING = [
25+
{
26+
"low":0.,
27+
"high":0.
28+
},{
29+
"none":0.,
30+
"some":0.,
31+
"every":0.
32+
}
33+
]
34+
35+
FUZZY_VARS = [
36+
FuzzyVar(["low", "high"], {
37+
"low": lambda x: 20 - x**3/2,
38+
"high": lambda x: x**3/5.
39+
}
40+
),
41+
FuzzyVar(["none", "some", "every"], {
42+
"none": lambda x: 1. if x <= 0. else 0.,
43+
"some": lambda x: cos(x * pi) * sin(x * pi),
44+
"every": lambda x: 1. if x == 1. else 0.
45+
})
46+
]
47+
48+
OP = Operators(0.5,0.5,0.5)
49+
50+
def calculate_base_meaning(meaning_list:List[Dict[str,float]]) -> NoReturn:
51+
for idx, var in enumerate(FUZZY_VARS):
52+
for name in var.values:
53+
meaning_list[idx][name] = var.get_meaning(name, BASE_VALUES[idx])
54+
55+
calculate_base_meaning(MEANING)
56+
# print(MEANING)
57+
58+
A = VAR_DICT["A"]
59+
B = VAR_DICT["B"]
60+
61+
FUZZY_RULES = [
62+
([A,B,[B,A]], [OP.bounded_difference, OP.bounded_sum, OP.drastic_product]),
63+
([A,B,[B,A]], [OP.drastic_sum, OP.dubois_prade_intersection, OP.einstein_product]),
64+
([A,B,[B,A]], [OP.einstein_sum, OP.hamacher_product, OP.hamacher_sum]),
65+
([A,B,[B,A]], [OP.hamacher_union, OP.maximum, OP.minimum]),
66+
([A,B,[B,A]], [OP.union, OP.yaeger_intersection, OP.yaeger_union])
67+
]
68+
69+
for x, y in FUZZY_RULES:
70+
# print(x, y)
71+
compute_rule(x, y)

0 commit comments

Comments
 (0)