Skip to content

Commit aa69aae

Browse files
committed
fixed all complaints of pydocstyle
1 parent 726fef7 commit aa69aae

File tree

7 files changed

+99
-52
lines changed

7 files changed

+99
-52
lines changed

fuzzy/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""File to indicate that this is a package."""

fuzzy/classes.py

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11

2+
"""
3+
Domain and Set classes for fuzzy logic.
4+
5+
Primary abstractions for recursive functions for better handling.
6+
"""
7+
28
import matplotlib.pyplot as plt
39
from numpy import arange, fromiter, array_equal, less_equal, greater_equal, less, greater
410
import numpy as np
@@ -9,6 +15,8 @@
915
from .combinators import MAX, MIN, product, bounded_sum, simple_disjoint_sum
1016

1117
class FuzzyWarning(UserWarning):
18+
"""Extra Exception so that user code can filter exceptions specific to this lib."""
19+
1220
pass
1321

1422

@@ -48,9 +56,11 @@ class Domain:
4856
>>> temp(3) == {"hot": 0, "cold": 1}
4957
True
5058
"""
59+
5160
_allowed_attrs = ['name', 'low', 'high', 'res', '_sets']
5261

5362
def __init__(self, name, low, high, *, res=1, sets:dict=None):
63+
"""Define a domain."""
5464
assert low < high, "higher bound must be greater than lower."
5565
assert res > 0, "resolution can't be negative or zero"
5666
self.name = name
@@ -62,32 +72,38 @@ def __init__(self, name, low, high, *, res=1, sets:dict=None):
6272

6373

6474
def __call__(self, x):
75+
"""Pass a value to all sets of the domain and return a dict with results."""
6576
if not(self.low <= x <= self.high):
6677
warn(f"{x} is outside of domain!")
6778
memberships = {name: s.func(x) for
6879
name, s, in self._sets.items()}
6980
return memberships
7081

7182
def __str__(self):
83+
"""Return a string to print()."""
7284
return self.name
7385

7486
def __repr__(self):
87+
"""Return a string so that eval(repr(Domain)) == Domain."""
7588
return f"Domain('{self.name}', {self.low}, {self.high}, res={self.res}, sets={self._sets})"
7689

7790
def __eq__(self, other):
91+
"""Test equality of two domains."""
7892
return all([self.name == other.name,
7993
self.low == other.low,
8094
self.high == other.high,
8195
self.res == other.res,
8296
self._sets == other._sets])
8397

8498
def __getattr__(self, name):
99+
"""Get the value of an attribute."""
85100
if name in self._sets:
86101
return self._sets[name]
87102
else:
88103
raise AttributeError(f"{name} is not a set or attribute")
89104

90105
def __setattr__(self, name, value):
106+
"""Define a set within a domain or assign a value to a domain attribute."""
91107
# it's a domain attr
92108
if name in self._allowed_attrs:
93109
object.__setattr__(self, name, value)
@@ -100,6 +116,7 @@ def __setattr__(self, name, value):
100116
value.name = name
101117

102118
def __delattr__(self, name):
119+
"""Delete a fuzzy set from the domain."""
103120
if name in self._sets:
104121
del self._sets[name]
105122
else:
@@ -123,13 +140,13 @@ def min(self, x):
123140
return min(f(x) for f in self._sets.values())
124141

125142
def max(self, x):
126-
"""Standard way to get the max over all membership funcs.
127-
"""
143+
"""Standard way to get the max over all membership funcs."""
128144
return max(f(x) for f in self._sets.values())
129145

130146
class Set:
131147
"""
132148
A fuzzyset defines a 'region' within a domain.
149+
133150
The associated membership function defines 'how much' a given value is
134151
inside this region - how 'true' the value is.
135152
@@ -142,10 +159,12 @@ class Set:
142159
Note that most checks are merely assertions that can be optimized away.
143160
DO NOT RELY on these checks and use tests to make sure that only valid calls are made.
144161
"""
162+
145163
_domain = None
146164
_name = None
147165

148166
def __init__(self, func:callable, *, domain=None, name=None):
167+
"""Initialize the set."""
149168
assert callable(func) or isinstance(func, str)
150169
# if func is a str, we've got a pickled function via repr
151170

@@ -197,27 +216,35 @@ def fset(self, value):
197216
del domain_
198217

199218
def __call__(self, x):
219+
"""Call the function of the set (which can be of any arbitrary complexity)."""
200220
return self.func(x)
201221

202222
def __invert__(self):
223+
"""Return a new set with modified function."""
203224
return Set(inv(self.func))
204225

205226
def __and__(self, other):
227+
"""Return a new set with modified function."""
206228
return Set(MIN(self.func, other.func))
207229

208230
def __or__(self, other):
231+
"""Return a new set with modified function."""
209232
return Set(MAX(self.func, other.func))
210233

211234
def __mul__(self, other):
235+
"""Return a new set with modified function."""
212236
return Set(product(self.func, other.func))
213237

214238
def __add__(self, other):
239+
"""Return a new set with modified function."""
215240
return Set(bounded_sum(self.func, other.func))
216241

217242
def __xor__(self, other):
243+
"""Return a new set with modified function."""
218244
return Set(simple_disjoint_sum(self.func, other.func))
219245

220246
def __pow__(self, power):
247+
"""Return a new set with modified function."""
221248
#FYI: pow is used with hedges
222249
return Set(lambda x: pow(self.func(x), power))
223250

@@ -259,16 +286,19 @@ def __gt__(self, other):
259286
return all(greater(self.array(), other.array()))
260287

261288
def __len__(self):
289+
"""Number of membership values in the set, defined by bounds and resolution of domain."""
262290
if self.domain is None:
263291
raise FuzzyWarning("No domain.")
264292
return len(self.array())
265293

266294
def cardinality(self):
295+
"""The sum of all values in the set."""
267296
if self.domain is None:
268297
raise FuzzyWarning("No domain.")
269298
return sum(self.array())
270299

271300
def relative_cardinality(self):
301+
"""Relative cardinality is the sum of all membership values by number of all values."""
272302
if self.domain is None:
273303
raise FuzzyWarning("No domain.")
274304
if len(self) == 0:
@@ -278,6 +308,8 @@ def relative_cardinality(self):
278308

279309
def concentrated(self):
280310
"""
311+
Alternative to hedge "very".
312+
281313
Returns an new array that has a reduced amount of values the set includes and to dampen the
282314
membership of many values.
283315
TODO: implement this as a new set?
@@ -288,8 +320,11 @@ def concentrated(self):
288320

289321
def intensified(self):
290322
"""
291-
Returns a new array where the membershi of values are increased that
323+
Alternative to using hedges.
324+
325+
Returns a new array where the membership of values are increased that
292326
already strongly belong to the set and dampened the rest.
327+
293328
TODO: implement this as a new set?
294329
"""
295330
return NotImplemented
@@ -298,30 +333,32 @@ def intensified(self):
298333
else:
299334
return 1 - 2(1 - x**2)
300335

301-
def dilatated(self):
302-
"""Expands the set with more values and already included values are enhanced.
303-
TODO: implement this as a new set?"""
336+
def dilated(self):
337+
"""Expand the set with more values and already included values are enhanced.
338+
339+
TODO: implement this as a new set?
340+
"""
304341
return NotImplemented
305342
return x ** 1./2.
306343

307-
def multiplication(self, n):
308-
"""Set is multiplied with a constant factor, which changes all membership values.
309-
TODO: implement this as a new set?"""
344+
def multiplied(self, n):
345+
"""Multiply with a constant factor, changing all membership values.
346+
347+
TODO: implement this as a new set?
348+
"""
310349
return NotImplemented
311350
return x * n
312351

313352
def plot(self):
314-
"""Graph the set.
315-
Use the bounds and resolution of the domain to display the set
316-
unless specified otherwise.
317-
"""
353+
"""Graph the set in the given domain."""
318354
if self.domain is None:
319355
raise FuzzyWarning("No domain assigned, cannot plot.")
320356
R = self.domain.range()
321357
V = [self.func(x) for x in R]
322358
plt.plot(R, V)
323359

324360
def array(self):
361+
"""Return an array of all values for this set within the given domain."""
325362
if self.domain is None:
326363
raise FuzzyWarning("No domain assigned.")
327364
return fromiter((self.func(x) for x in self.domain.range()),
@@ -350,13 +387,14 @@ def create_function_closure():
350387
return f"Set({self.func}, domain={self.domain}, name={self.name})"
351388

352389
def __str__(self):
390+
"""Return a string for print()."""
353391
if self.name is None and self.domain is None:
354392
return f"dangling Set({self.func})"
355393
else:
356394
return f"{self.domain}.{self.name}"
357395

358396
def normalized(self):
359-
"""Returns a set *in this domain* whose max value is 1."""
397+
"""Return a set *in this domain* whose max value is 1."""
360398
if self.domain is None:
361399
raise FuzzyWarning("Can't normalize without domain.")
362400
else:

fuzzy/combinators.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11

22
"""
3-
-----------
4-
COMBINATORS
5-
-----------
6-
Linguistic terms (membership functions of two different FuzzySets of the same domain)
7-
are combined.
3+
Combine two linguistic terms.
84
9-
a and b are functions.
5+
a and b are functions of two sets of the same domain.
106
117
Since these combinators are used directly in the Set class to implement logic operations,
128
the most obvious use of this module is when subclassing Set to make use of specific combinators
@@ -70,6 +66,7 @@ def f(x):
7066

7167
def hamacher_product(a, b):
7268
"""AND variant.
69+
7370
(xy) / (x + y - xy) for x, y != 0
7471
0 otherwise
7572
"""
@@ -80,6 +77,7 @@ def f(z):
8077

8178
def hamacher_sum(a, b):
8279
"""OR variant.
80+
8381
(x + y - 2xy) / (1 - xy) for x,y != 1
8482
1 otherwise
8583
"""
@@ -106,7 +104,10 @@ def f(x):
106104

107105

108106
def gamma_op(g):
109-
"""A 'compensatoric' operator, combining AND with OR by a weighing factor g.
107+
"""Combine AND with OR by a weighing factor g.
108+
109+
This is called a 'compensatoric' operator.
110+
110111
g (gamma-factor)
111112
0 < g < 1 (g == 0 -> AND; g == 1 -> OR)
112113
@@ -123,7 +124,8 @@ def f(z):
123124
return e
124125

125126
def simple_disjoint_sum(a, b):
126-
"""Implements a simple fuzzy XOR operation.
127+
"""Simple fuzzy XOR operation.
128+
127129
(A AND ~B) OR (~A AND B)
128130
"""
129131
def f(z):

0 commit comments

Comments
 (0)