2015-10-13 10 views
3

UPDATEмножества уровня функции, используя «мин»

Чтобы подытожить мой первоначальный пост ниже, у меня есть трудности Plotting уровня функций, связанных с «мин», такие как следующие функции:

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?


ИСХОДНЫЙ POST

Я пытаюсь построить наборы уровня двух функций 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() 

Мой участок кажется правильным с весельем ction 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

Вы хотите вызвать Numpy версию мин, версия не питона, который ожидает номера в качестве входных данных и дает вам минимум из них - это то, где 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() 

Это дает:

enter image description here

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

+0

Я не знал о 'np.minimum'. Я пробовал только «np.min», и, конечно, у меня была такая же ошибка. Спасибо за ваш ответ. – dada

+1

Для тех, кто хотел бы знать, как автоматически встраивать 'np.minimum', используйте' reduce (np.minimum, [x, x-y, x ** 2, y + 1]) ' – dada

0

В конце концов, я буду просто и не используя 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. У меня нет времени для этого, к сожалению.

Выход: enter image description here

+1

Значит, вы хотите знать, что происходит с вашими данными в 'meshgrid'? Позвольте мне попытаться объяснить, как это работает. В двумерном случае он будет повторять первый массив по-разному, а второй по столбцу, так что в конце обе имеют одну и ту же форму '(len (x), len (y))'. Если вы затем передаете их (вы также можете представить себе их друг на друга), вы получите каждую комбинацию x, y пар. Это чрезвычайно избыточно, но поскольку данные хорошо выровнены для векторизованного вычисления, он даст вам аккуратное ускорение. – swenzel

Смежные вопросы