I am taking a course on Fuzzy Systems and I take my notes on my computer. This means that I have to draw graphs on my computer from time to time. Since these graphs are quite well defined, I feel that plotting them with numpy
would be a good idea (I take notes with LaTeX, and I'm pretty quick on the python shell, so I figure I can get away with this).
The graphs for fuzzy membership functions are highly piecewise, for example:
In order to plot this, I tried the following code for a numpy.piecewise
(which gives me a cryptic error):
In [295]: a = np.arange(0,5,1)
In [296]: condlist = [[b<=a<b+0.25, b+0.25<=a<b+0.75, b+0.75<=a<b+1] for b in range(3)]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-296-a951e2682357> in <module>()
----> 1 condlist = [[b<=a<b+0.25, b+0.25<=a<b+0.75, b+0.75<=a<b+1] for b in range(3)]
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [297]: funclist = list(itertools.chain([lambda x:-4*x+1, lambda x: 0, lambda x:4*x+1]*3))
In [298]: np.piecewise(a, condlist, funclist)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-298-41168765ae55> in <module>()
----> 1 np.piecewise(a, condlist, funclist)
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/lib/function_base.pyc in piecewise(x, condlist, funclist, *args, **kw)
688 if (n != n2):
689 raise ValueError(
--> 690 "function list and condition list must be the same")
691 zerod = False
692 # This is a hack to work around problems with NumPy's
ValueError: function list and condition list must be the same
At this point, I'm fairly confused as to how to plot this function. I don't really understand the error message, which is further impeding my efforts to debug this.
Ultimately, I am looking to plot and export this function into an EPS file, so I'd appreciate any help along those lines as well.
In general, numpy arrays are very good at doing sensible things when you just write the code as if they were just numbers. Chaining comparisons is one of the rare exceptions. The error you're seeing is essentially this (obfuscated a bit by piecewise
internals and ipython error formatting):
>>> a = np.array([1, 2, 3])
>>> 1.5 < a
array([False, True, True], dtype=bool)
>>>
>>> 1.5 < a < 2.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>>
>>> (1.5 < a) & (a < 2.5)
array([False, True, False], dtype=bool)
>>>
You can alternatively use np.logical_and
, but bitwise and
works just fine here.
As far as plotting is concerned, numpy itself doesn't do any. Here's an example with matplotlib:
>>> import numpy as np
>>> def piecew(x):
... conds = [x < 0, (x > 0) & (x < 1), (x > 1) & (x < 2), x > 2]
... funcs = [lambda x: x+1, lambda x: 1,
... lambda x: -x + 2., lambda x: (x-2)**2]
... return np.piecewise(x, conds, funcs)
>>>
>>> import matplotlib.pyplot as plt
>>> xx = np.linspace(-0.5, 3.1, 100)
>>> plt.plot(xx, piecew(xx))
>>> plt.show() # or plt.savefig('foo.eps')
Notice that piecewise
is a capricious beast. In particular, it needs its x
argument to be an array, and won't even try converting it if it isn't (in numpy
parlance: x
needs to be an ndarray
, not an array_like
):
>>> piecew(2.1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in piecew
File "/home/br/.local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 690, in piecewise
"function list and condition list must be the same")
ValueError: function list and condition list must be the same
>>>
>>> piecew(np.asarray([2.1]))
array([ 0.01])