5
5
adding logical operaitons for easier handling.
6
6
"""
7
7
8
- from logging import warn
9
8
from typing import Callable
10
9
11
10
import matplotlib .pyplot as plt
17
16
18
17
class FuzzyWarning (UserWarning ):
19
18
"""Extra Exception so that user code can filter exceptions specific to this lib."""
20
-
21
19
pass
22
20
23
21
@@ -71,19 +69,11 @@ def __init__(
71
69
self ._res = res
72
70
self ._sets = {} if sets is None else sets # Name: Set(Function())
73
71
74
- def __call__ (self , X ):
72
+ def __call__ (self , x ):
75
73
"""Pass a value to all sets of the domain and return a dict with results."""
76
- if isinstance (X , np .ndarray ):
77
- if any (not (self ._low <= x <= self ._high ) for x in X ):
78
- raise FuzzyWarning ("Value in array is outside of defined range!" )
79
- res = {}
80
- for s in self ._sets .values ():
81
- vector = np .vectorize (s .func , otypes = [float ])
82
- res [s ] = vector (X )
83
- return res
84
- if not (self ._low <= X <= self ._high ):
85
- warn (f"{ X } is outside of domain!" )
86
- return {s : s .func (X ) for name , s in self ._sets .items ()}
74
+ if not (self ._low <= x <= self ._high ):
75
+ raise FuzzyWarning (f"{ x } is outside of domain!" )
76
+ return {name : s .func (x ) for name , s in self ._sets .items ()}
87
77
88
78
def __str__ (self ):
89
79
"""Return a string to print()."""
@@ -195,7 +185,7 @@ class Set:
195
185
name = None # these are set on assignment to the domain! DO NOT MODIFY
196
186
domain = None
197
187
198
- def __init__ (self , func : Callable , * , name = None , domain = None ):
188
+ def __init__ (self , func : Callable , * , name : str | None = None , domain : Domain | None = None ):
199
189
self .func = func
200
190
self .domain = domain
201
191
self .name = name
@@ -334,7 +324,7 @@ def dilated(self):
334
324
335
325
def multiplied (self , n ):
336
326
"""Multiply with a constant factor, changing all membership values."""
337
- return Set (lambda x : self .func (x ) * n , domain = self )
327
+ return Set (lambda x : self .func (x ) * n , domain = self . domain )
338
328
339
329
def plot (self ):
340
330
"""Graph the set in the given domain."""
@@ -350,19 +340,18 @@ def array(self):
350
340
raise FuzzyWarning ("No domain assigned." )
351
341
return np .fromiter ((self .func (x ) for x in self .domain .range ), float )
352
342
353
- @property
354
343
def center_of_gravity (self ):
355
344
"""Return the center of gravity for this distribution, within the given domain."""
356
- if self .__center_of_gravity is not None :
357
- return self .__center_of_gravity
358
345
346
+ assert self .domain is not None , "No center of gravity with no domain."
359
347
weights = self .array ()
360
348
if sum (weights ) == 0 :
361
349
return 0
362
- cog = np .average (np . arange ( len ( weights )) , weights = weights )
350
+ cog = np .average (self . domain . range , weights = weights )
363
351
self .__center_of_gravity = cog
364
352
return cog
365
353
354
+
366
355
def __repr__ (self ):
367
356
"""
368
357
Return a string representation of the Set that reconstructs the set with eval().
@@ -410,6 +399,7 @@ class Rule:
410
399
"""
411
400
412
401
def __init__ (self , conditions , func = None ):
402
+ print ("ohalala" )
413
403
self .conditions = {frozenset (C ): oth for C , oth , in conditions .items ()}
414
404
self .func = func
415
405
@@ -444,30 +434,43 @@ def __call__(self, args: "dict[Domain, float]", method="cog"):
444
434
assert isinstance (
445
435
args , dict
446
436
), "Please make sure to pass in the values as a dictionary."
447
- if method == "cog" :
448
- assert (
449
- len ({C .domain for C in self .conditions .values ()}) == 1
450
- ), "For CoG, all conditions must have the same target domain."
451
- actual_values = {
452
- f : f (args [f .domain ]) for S in self .conditions .keys () for f in S
453
- }
454
-
455
- weights = []
456
- for K , v in self .conditions .items ():
457
- x = min ((actual_values [k ] for k in K if k in actual_values ), default = 0 )
458
- if x > 0 :
459
- weights .append ((v , x ))
460
-
461
- if not weights :
462
- return None
463
- target_domain = list (self .conditions .values ())[0 ].domain
464
- index = sum (v .center_of_gravity * x for v , x in weights ) / sum (
465
- x for v , x in weights
466
- )
467
- return (target_domain ._high - target_domain ._low ) / len (
468
- target_domain .range
469
- ) * index + target_domain ._low
470
-
437
+ match method :
438
+ case "cog" :
439
+ assert (
440
+ len ({C .domain for C in self .conditions .values ()}) == 1
441
+ ), "For CoG, all conditions must have the same target domain."
442
+ actual_values = {
443
+ f : f (args [f .domain ]) for S in self .conditions .keys () for f in S
444
+ }
445
+
446
+ weights = []
447
+ for K , v in self .conditions .items ():
448
+ x = min ((actual_values [k ] for k in K if k in actual_values ), default = 0 )
449
+ if x > 0 :
450
+ weights .append ((v , x ))
451
+
452
+ if not weights :
453
+ return None
454
+ target_domain = list (self .conditions .values ())[0 ].domain
455
+ index = sum (v .center_of_gravity * x for v , x in weights ) / sum (
456
+ x for v , x in weights
457
+ )
458
+ return (target_domain ._high - target_domain ._low ) / len (
459
+ target_domain .range
460
+ ) * index + target_domain ._low
461
+
462
+ case "centroid" :
463
+ raise NotImplementedError ("Centroid method not implemented yet." )
464
+ case "bisector" :
465
+ raise NotImplementedError ("Bisector method not implemented yet." )
466
+ case "mom" :
467
+ raise NotImplementedError ("Middle of max method not implemented yet." )
468
+ case "som" :
469
+ raise NotImplementedError ("Smallest of max method not implemented yet." )
470
+ case "lom" :
471
+ raise NotImplementedError ("Largest of max method not implemented yet." )
472
+ case _:
473
+ raise ValueError ("Invalid method." )
471
474
472
475
def rule_from_table (table : str , references : dict ):
473
476
"""Turn a (2D) string table into a Rule of fuzzy sets.
0 commit comments