1

I'm new to python, in this case, I want to put my function into 2d arrays, so I can plot the function. Here is my triangle function, I'm using it for fuzzy logic:

def triangle (z,a,b,c):
    if (z<=a) | (z>=c):
        y = 0
    elif (a<=z) & (z<=b):
        y = (z-a) / (b-a)
    elif (b<=z) & (z<=c):
        y = (b-z) / (c-b)
    return y

and I'm trying to make the array using numpy, np.linspace but I can't get it done, I've tried to use the fuzzy library, but nothing works.

Praveen
  • 6,872
  • 3
  • 43
  • 62
prasta
  • 11
  • 1
  • 3
  • Which array are you trying to convert using linspace? What error do you get when you try to do this? – Praveen Oct 10 '16 at 04:50
  • 1
    Please show an example *input* - ```z,a,b,c```; and the desired output. Is [this the function](http://www.dma.fi.upm.es/recursos/aplicaciones/logica_borrosa/web/fuzzy_inferencia/funpert_en.htm#triangular) you are referring to? – wwii Oct 10 '16 at 05:02
  • Check out [numpy.triu](http://docs.scipy.org/doc/numpy/reference/generated/numpy.triu.html), and possibly a [similar post](http://stackoverflow.com/questions/8905501/extract-upper-lower-triangular-part-of-a-numpy-matrix) – Aziz Alto Oct 10 '16 at 05:59
  • yeah z is the value between a and c, its like the crisp value in fuzzy logic, so im gonna try ur code for, thanks for helping – prasta Oct 10 '16 at 06:10
  • @AzizAlto - how would you use numpt.triu in the OP's function? – wwii Oct 10 '16 at 15:01

1 Answers1

2

Looks like a, b, c are constants and z is a np.linspace between a, and c.

You can make use of Boolean Indexing , SciPy cookbook/Indexing

a = 1
b = 2
c = 3

def triangle (z, a = a, b = b, c = c):
    y = np.zeros(z.shape)
    y[z <= a] = 0
    y[z >= c] = 0
    first_half = np.logical_and(a < z, z <= b)
    y[first_half] = (z[first_half]-a) / (b-a)
    second_half = np.logical_and(b < z, z < c)
    y[second_half] = (c-z[second_half]) / (c-b)
    return y

z = np.linspace(a, c, num = 51)
y = triangle(z, a, b, c)

q = np.vstack((z, y)) # shape = (2, 50) ... [[z, z, z, ...], [y, y, y, ...]]
q =  q.T # shape = (50, 2) ... [[z, y], [z, y], ....]

enter image description here


When you use a numpy ndarray in a comparison expression the result is a boolean array:

>>> q = np.linspace(0, 20, num = 50)
>>> print(q)
[  0.           0.40816327   0.81632653   1.2244898    1.63265306
   2.04081633   2.44897959   2.85714286   3.26530612   3.67346939
   4.08163265   4.48979592   4.89795918   5.30612245   5.71428571
   6.12244898   6.53061224   6.93877551   7.34693878   7.75510204
   8.16326531   8.57142857   8.97959184   9.3877551    9.79591837
  10.20408163  10.6122449   11.02040816  11.42857143  11.83673469
  12.24489796  12.65306122  13.06122449  13.46938776  13.87755102
  14.28571429  14.69387755  15.10204082  15.51020408  15.91836735
  16.32653061  16.73469388  17.14285714  17.55102041  17.95918367
  18.36734694  18.7755102   19.18367347  19.59183673  20.        ]
>>> print(q < 5)
[ True  True  True  True  True  True  True  True  True  True  True  True
  True False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False]
>>> print(q > 15)
[False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False  True  True  True  True  True  True  True  True  True  True  True
  True  True]
>>> print(np.logical_and(q > 5, q < 15))
[False False False False False False False False False False False False
 False  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True False False False False False False False False False False False
 False False]
>>> 

You can use a boolean array to select portions of an array that meet your condition:

>>> q[np.logical_and(q > 7, q < 11)]
array([  7.34693878,   7.75510204,   8.16326531,   8.57142857,
         8.97959184,   9.3877551 ,   9.79591837,  10.20408163,  10.6122449 ])
>>> 

When you use boolean indexing in an assignment statement the right-hand-side is only assigned to the indices where the comparison is True:

>>> q[np.logical_and(q > 7, q < 11)] = -1
>>> print(q)
[  0.           0.40816327   0.81632653   1.2244898    1.63265306
   2.04081633   2.44897959   2.85714286   3.26530612   3.67346939
   4.08163265   4.48979592   4.89795918   5.30612245   5.71428571
   6.12244898   6.53061224   6.93877551  -1.          -1.          -1.          -1.
  -1.          -1.          -1.          -1.          -1.          11.02040816
  11.42857143  11.83673469  12.24489796  12.65306122  13.06122449
  13.46938776  13.87755102  14.28571429  14.69387755  15.10204082
  15.51020408  15.91836735  16.32653061  16.73469388  17.14285714
  17.55102041  17.95918367  18.36734694  18.7755102   19.18367347
  19.59183673  20.        ]
>>> 
wwii
  • 23,232
  • 7
  • 37
  • 77
  • so if i got 2 function triangle and trapezoid, and i want to plot it into one graph and of course the length of x axis is not limited by the value of c, example : the length of the x axis is 20, the triangle and trapezoid function have its own a,b,c, how to do it? its like fuzzy logic membership function graph – prasta Oct 10 '16 at 08:12
  • @prasta - If you want ```z``` to have a *larger* range then change the [numpy.linspace](http://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html#numpy-linspace) start and stop arguments when you make ```z```. You will need to write a trapezoid function by adapting the triangle function. – wwii Oct 10 '16 at 14:49
  • @prasta - Just pass the appropriate arguments to the functions. You could also create functions from, ```triangle``` and ```trapezoid```, with fixed ```a, b, c``` arguments using [```functools.partial```](https://docs.python.org/3/library/functools.html#functools.partial). You can create as many of those partial functions as you need with differing ```a, b, c``` values and just pass ```z``` to the partial functions. – wwii Oct 10 '16 at 14:55
  • so, ive try to change the start and stop function from the numpy.linspace to np.linspace(0, 20, num=51) , and then i cant get my triangle to have 1.0 value, its only have until 0.9. its not reach to the top of the graph – prasta Oct 11 '16 at 02:40
  • @prasta, linspace will give you ```num``` equally spaced points between ```start``` and ```stop``` so you aren't guaranteed to get a value equal to ```b```. If you make ```num``` large enough, you should get points sufficiently close to ```b```, or maybe play around with the start and stop values. Do you understand how your function works? You should spend some time reading the numpy docs, and play around with linspace and boolean indexing so you can understand how it works - then you can adjust the code to suit your needs. – wwii Oct 11 '16 at 03:28
  • yeah, i need more read on the numpy docs, and ive already solved it somehow, thank you so much – prasta Oct 11 '16 at 15:18