FuzzPy is a python library that exposes specialized datatypes to deal with a wide range of fuzzy number types, fuzzy sets, and fuzzy graphs. Binary operations against each type, such as set unions and intersections, can be performed using some of python’s native binary operators (|, &, ==), or specialized methods if you wish to deviate from the default functions for these computations.
FuzzPy also provides several helper methods such as kernel and neighbors isolation, alpha-cuts, cardinality testing, shortest-path computation, and minimum spanning trees. A powerful visualization framework also allows you to quickly create and save visualizations for your data.
In this post, we will examine fuzzy sets and fuzzy graphs, and see how one can use FuzzPy to work with these types, providing examples for each. In the next post of this series, we will examine the different types of fuzzy numbers, generate visualizations, and explore advanced concepts such as automatic fuzzification, and importing graph data from fuzzy adjacency matrices.
Fuzzy Sets
A fuzzy set is simply a set in which each element has an associated degree of membership into the set. This membership value is called -value of the element. A
-value of zero indicates that the element does not belong to the set, while any value between zero (exclusive) and one (inclusive), indicates that the element is, to a certain degree, a set member.
Creating a fuzzy set with FuzzPy is just a matter of creating a new FuzzySet object, then either calling the add(FuzzyElement(value, mu)) method for each element to import, or using the update(elements) method, providing it with a list of FuzzyElement(value, tuples for bulk import.-value)
from fuzz import FuzzySet, FuzzyElement # Create two lists of FuzzyElements elements_a = [(1, 0.3), (2, 0.5), (3, 0.7), (4, 0.9)] elements_b = [(3, 0.8), (6, 0.6), (1, 0.4), (8, 0.2)] elements_a = [FuzzyElement(x[0], x[1]) for x in elements_a] elements_b = [FuzzyElement(x[0], x[1]) for x in elements_b] # Create two fuzzy sets set_a = FuzzySet() set_b = FuzzySet() set_a.update(elements_a) set_b.update(elements_b) |
We’ve just created a couple fuzzy sets with four elements each. Notice that two of the elements are common to both set_a and set_b (albeit with different -values). We can now perform several operations against these sample sets. Save the code above in a file called
example.py and fire up the python interpreter to test fuzzy set functionality against our sets:
>>> from example import * >>> # Set Difference ... >>> set_a - set_b FuzzySet([FuzzyElement(2, 0.500000), FuzzyElement(4, 0.900000)]) >>> set_b - set_a FuzzySet([FuzzyElement(8, 0.200000), FuzzyElement(6, 0.600000)]) # Set Union ... >>> set_a | set_b FuzzySet([FuzzyElement(1, 0.400000), FuzzyElement(2, 0.500000), FuzzyElement(3, 0.800000), FuzzyElement(4, 0.900000), FuzzyElement(6, 0.600000), FuzzyElement(8, 0.200000)]) # Set Intersection ... >>> set_a & set_b FuzzySet([FuzzyElement(1, 0.300000), FuzzyElement(3, 0.700000)]) |
Fuzzy graphs
In a fuzzy graph or digraph, each vertice and each edge can be associated with a -value. The
-value of a vertice indicates the vertice’s degree of membership into the graph, while an edge or arc’s
-value indicates the degree of connectivity between the head and tail vertices.
The creation of fuzzy graphs is also pretty straightforward: create a set or fuzzy set (see above), then feed that set to the fuzz.Graph constructor, along with the directed boolean value to specify whether you’d like to create a graph or a digraph. You can then use the fuzz.Graph.connect(head, tail, mu) method to add edges to the graph:
import fuzz # Create two sets of vertices set_a = set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) set_b = set([11, 12, 13, 14, 15, 16, 17, 18, 19, 20]) # Create our graph objects graph_a = fuzz.FuzzyGraph(viter=set_a, directed=False) graph_b = fuzz.FuzzyGraph(viter=set_b, directed=True) # Create some arcs in graph_a graph_a.connect(1, 3, 0.5) graph_a.connect(3, 6, 0.06) graph_a.connect(2, 8, 0.2) graph_a.connect(4, 1, 0.9) # And some in graph_b graph_b.connect(11, 19, 0.9) graph_b.connect(14, 12, 0.3) graph_b.connect(15, 14, 0.5) |
Save the code above in a file named graphs.py and fire up your python interpreter so we can experiment with graph operations:
>>> from graphs import * >>> # Retrieve the mu value of the edge between 1 and 3 ... >>> graph_a.mu(3, 1) 0.5 >>> # Retrieve an alpha-cut of graph_b against mu-value of 0.5 ... >>> graph_b.alpha(0.5) Graph(viter = set([11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), eiter = set([(15, 14), (11, 19)]), directed = True) >>> # Is graph_a a subgraph of graph_b? (no) ... graph_a.issubgraph(graph_b) False >>> # Detect adjacent (connected) vertices ... >>> graph_a.adjacent(1, 2) False >>> graph_a.adjacent(1, 3) True >>> # Find all the neighbours of the vertex with value 3 ... >>> graph_a.neighbors(3) set([1, 6]) >>> # Find the shortest path to all vertices using 6 as origin ... >>> graph_a.dijkstra(6) {1: 3, 2: None, 3: 6, 4: 1, 5: None, 6: None, 7: None, 8: None, 9: None, 10: None} >>> # Find the minimum spanning tree of graph_a ... >>> graph_a.minimum_spanning_tree() Graph(viter = set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), eiter = set([(2, 8), (1, 3), (4, 1), (3, 6)]), directed = False) |
There are a few more operations available for both crisp and fuzzy graphs/digraphs. You should consult the API doc for a comprehensive list.
You should also consult the examples provided as part of the module on GitHub to see FuzzPy in action.
Related posts:
I think the idea is really great, but I’m confused by some of the results, especially the “calculus” involving these mu values are not explicitly mentioned anywhere. They seem to be inspired by probabilities, but then results like these are inconsistent with the probabilistic framwork:
>>> set_a | set_b
FuzzySet([FuzzyElement(1, 0.400000), FuzzyElement(2, 0.500000), FuzzyElement(3, 0.800000), FuzzyElement(4, 0.900000), FuzzyElement(6, 0.600000), FuzzyElement(8, 0.200000)])
Again, because the “mu calculus” is not defined explicitly, it’s hard for me to tell that the answer is “wrong”, but if we were using probabilities, the probability of 1 being in the set is not going to be simply the max of the two values (which is what appears to be happening).
I think it would be better to use probabilities (de Finetti’s theorem and all that), and I’m going to try to implement that in CommonLisp. Thanks for the great idea.
@Kanak:
When you say “mu calculus” I deduce that you are referring to the definitions of the fuzzy union and fuzzy intersection operators. The standard definitions for these (as widely used in the literature) are in fact the maximum and minimum of the mu values, respectively. This is explicitly specified in the sense that the API documentation and code refer to the operators as such. Other t-conorms and t-norms exist for different union and intersection operations, and in fact FuzzPy implements 3 other types for both union and intersection (there are many more in the literature and it wouldn’t be difficult to add them).
Fuzzy sets model a fundamentally different kind of uncertainty than do probabilities, but you could use the algebraic sum t-conorm and algebraic product t-norm (for union and intersection, respectively) to obtain results consistent with probability theory. You can call the
unionandintersectionmethods directly, specifying thenormkeyword argument asFuzzySet.NORM_ALGEBRAICin both cases.In general, it sounds like you’re not familiar with fuzzy sets? The seminal 1965 paper by Zadeh (entitled, appropriately enough, “Fuzzy Sets”) is a perfect place to start. I also suggest Fuzzy Set Theory: Foundations and Applications by Klir, St. Clair, and Yuan as a lightweight introduction.
Aaron,
Thank you very much for your detailed reply (and links to references). I was definitely thinking solely in terms of probability (which is why the max result was so confusing), but your explanation was very helpful. I’ll definitely be reading the book (and playing with your module) to learn more about what appears to be a very useful and fascinating topic.
[...] Mad Python Watch out.. he’s angry Skip to content HomeRésumé (PDF)Contact ← Fuzzy Mathematics with FuzzPy (Part 1) [...]
[...] Fuzzy Mathematics und Fuzzy Graphs. Es gibt ein nettes Tutorial, Fuzzy Mathematics with FuzzPy (Teil 1, Teil 2), das über die Startschweirigkeiten hinweghilft. [Peter van I. per [...]
[...] Fuzzy Mathematics with FuzzPy (Part 1) | Mad Python – Python module to work with fuzzy numbers, sets, and graphs. Integrated with GraphViz for visualization. [...]
Great work – embedding Labjack hardware control via Python in FuzzyPy allows to go SCADA…
A full fledged manual however would be appreciated for beginners…
Great work Mr. Mavrinac, congratulations.