Наборы уровней функции с использованием "мин"

ОБНОВИТЬ

Подводя итоги моего первоначального поста, приведенного ниже, я испытываю трудности с отображением наборов уровней с участием функции min, например, следующей функции:

def f(x,y):
   return min(x,x-y,x**2,y+1)

Код, который я использую для построения наборов уровней:

import matplotlib.pyplot as plt
import numpy as np

plt.ion()
x_ = np.linspace(-180,180,num=40)
y_ = np.linspace(-180,180,num=40)
x,y = np.meshgrid(x_,y_)
levels = f(x,y)
c = plt.contour(x,y,levels,50)
plt.colorbar()
plt.show()

которая отлично работает для функции, включающей регулярные арифметические операции (+,-,**,*,/). Используя функцию fУ меня есть эта ошибка:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

указывая на обратную линию f, Как я могу построить наборы уровней моей функции f?


НАЧАЛЬНЫЙ ПОЧТА

Я пытаюсь построить наборы уровней двух функций f1 и f2, определенных следующим образом:

A = -73.95, 48.73
L=180


######## f1
def distance(a,b):
      """ a and b tuples """
      return np.sqrt((a[0]-b[0])**2+(a[1]-b[1])**2)

def f1(x,y):
       """ simple distance """
       p = x,y
       #print p
       return distance(p,A)

######## f2
def images(p):
        """ p tuple """
        #print "len(p) in images : "+str(len(p))+"\n"
        #print p
        pHC = (p[0],p[1]+L)
        pHR = (p[0]+L,p[1]+L)
        pHL = (p[0]-L,p[1]+L)
        pCR = (p[0]+L,p[1])
        pCL = (p[0]-L,p[1])
        pDC = (p[0],p[1]-L)
        pDR = (p[0]+L,p[1]-L)
        pDL = (p[0]-L,p[1]-L)
        return pHC,pHR,pHL,pCR,pCL,pDC,pDR,pDL
def minD(p,focal):
        """
        distance with images (p and focal are tuples)
        """
        #print p
        pHC,pHR,pHL,pCR,pCL,pDC,pDR,pDL = images(p)
        dHC = distance(focal,pHC)
        dHR = distance(focal,pHR)
        dHL = distance(focal,pHL)
        dCR = distance(focal,pCR)
        dCL = distance(focal,pCL)
        dDC = distance(focal,pDC)
        dDR = distance(focal,pDR)
        #print "len(dHC) : "+str(len(dHC))
        #print "len(dHC[0]) : "+str(len(dHC[0]))
        #print dHC
        d = min([dHC,dHR,dHL,dCR,dCL,dDC,dDR,dDL,distance(p,focal)])
        return d

def f2(phi,psi):
       p = phi,psi
       return minD(p,A)

Вот мой код для построения наборов уровней:

import matplotlib.pyplot as plt
import numpy as np

plt.ion()
x_ = np.linspace(-180,180,num=40)
y_ = np.linspace(-180,180,num=40)
x,y = np.meshgrid(x_,y_)
levels1 = f1(x,y)
#levels2 = f2(x,y)
c = plt.contour(x,y,levels,50)
#c = plt.contour(x,y,levels2,50)
plt.colorbar()
plt.show()

Мой сюжет кажется правильным с функцией f1 (по крайней мере, нет ошибок кода). Однако с функцией f2, У меня ошибка в строке перед последним из minD:

    d = min([dHC,dHR,dHL,dCR,dCL,dDC,dDR,dDL,distance(p,focal)])
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

С некоторыми отпечатками я мог обнаружить, что элементы списка, над которыми я выполняю мин (в minD функция) являются массивами в случае f2 а не отдельные элементы, как для f1, Как я могу построить наборы уровней функции f2?

2 ответа

Решение

Вы хотите вызвать numy версию min, а не версию python, которая ожидает числа в качестве входных данных и дает вам минимум из них - отсюда и происходит ValueError. Есть две версии в NumPy; np.min и np.minimum. np.min даст вам минимальное значение массива (таким образом, число), а np.minimum сделает точечный минимум массива (то есть другого массива). Вы хотите последнее.

К сожалению, я не думаю, что вы можете просто сделать np.minimum(array1, array2, array3), как описано выше, поэтому я думаю, что вам нужно вложить вызовы np.minimum. Хотя, если вы будете делать это часто, я думаю, вы можете создать функцию, которая вложит эти вызовы, чтобы вам было легче читать. Вот что я получил и похоже на работу:

def f(x,y):
    return np.minimum(np.minimum(np.minimum(x,x-y),x**2),y+1)

plt.figure()

x_ = np.linspace(-180, 180, num=200)
y_ = np.linspace(-180, 180, num=200)
x,y = np.meshgrid(x_, y_)

levels = f(x, y)

c = plt.contour(x, y, levels, 50)
plt.colorbar()

Это дает:

(обратите внимание, я увеличил число с 40 до 200, чтобы помочь matplotlib с негладкими частями)

В конце концов, я иду прямо и не использую meshgrid функция numpy:

x=np.linspace(-180,180,num=40)
y=np.linspace(-180,180,num=40)
levels=np.zeros((len(x),len(y)))
for i in range(len(x)):
    for j in range(len(y)):
        levels[i,j]=f2(x[i],y[j])
plt.contour(x,y,levels.T)

Это не оптимально во времени, как в случае с meshgrid функции, но я бы предпочел использовать это, чем понимать, что происходит с моими данными в meshgrid, У меня нет времени на это, к сожалению.

Выход:

Другие вопросы по тегам