2015-02-06 2 views
1

Я застреваю в проблеме, которую я упростил ниже.SciPy не может преобразовать комплекс в float

Итак, у меня есть функция (матрица), которая возвращает собственные значения матрицы.

Вторая функция (производная) находит производные собственных значений по дельта. Собственная производная функция SciPy очень медленная, поэтому я использовал метод сложных разностей.

Затем я беру двойной интеграл подынтегрального выражения по r и theta. Вместо того, чтобы брать двойной интеграл, я решаю дифференциальное уравнение г, взяв одномерный интеграл по тете, что делает вычисления более быстрыми.

И, наконец, интегральные работы. Однако, если я попытаюсь найти конкретную дельту, которая удовлетворяет уравнению, она дает ошибку: невозможно преобразовать комплекс в float, который я не понимаю, откуда приходит мнимое число.

Я новичок в мире Python, любая помощь будет весьма признательна. Спасибо.

from scipy.integrate import quad 
from numpy import linalg as LA 
import numpy as np 
from pylab import * 

from scipy.integrate import odeint 
from scipy.integrate import ode 
from scipy.optimize import fsolve 


#This routine is for the matrix and returns the eigenvalues 
def matrix(r, theta, delta1, delta2): 

    mat = np.array([[r**2-1,r*np.cos(theta),0,delta1],r*np.cos(theta),r**2 - 1, -delta1,0],[0,-delta2,-r**2+1,-r*np.cos(theta)],[delta2,0,-r*np.cos(theta),-r**2+1]]) 
    return np.sort(LA.eigvals(mat))[2:4] 

#This routine takes the derivatives of eigenvalues with respect to the parameter delta. I set delta1 = delta2. 
def deriv(r, theta, delta): 

    h = 0.00000000001 

    return np.imag(matrix(r, theta, delta, delta+h*1j))/h 

#This is the integrand that we need to integrate over r and theta 
def integrand(theta,r, beta, delta): 
    ee = matrix(r, theta, delta, delta) 
    dd = deriv(r, theta, delta) 
    return (np.tanh(0.5*beta*ee[0])*dd[0]+np.tanh(0.5*beta*ee[1])*dd[1])*r*r*np.sin(theta) 

#Just integrate over theta 
def polarint(y,r,beta,delta): 
    return quad(integrand,0,np.pi,args = (r,beta,delta))[0] 

#Instead of integrating directly over r, solve the differential equation. 
#Lambda is the range of r. 
def givesclen(delta, beta, lam): 
    y0 = 0 
    t_out = np.linspace(0, lam, 2500); 
    rt = odeint(polarint,y0,t_out,args=(beta,delta)) 
    temp = (rt[-1]/delta)/(4*np.pi**2)-t_out[-1]/(2*np.pi**2) 
    return temp[0] 

#The goal is to find the delta; given sl, lam, beta 
#Such that the result of the integration is equal to sl 
def equationgap(delta, beta, lam,sl): 
    return givesclen(delta, beta, lam)*4*np.pi - sl 

#Test if the equationgap works, the result should be close to zero! 
print equationgap(.5,40,500,.1744) 

#Now use the fsolve function should find the delta to be .5! 
#beta = 40 
#lam = 500 
#sl = 0.174 
#fsolve(equationgap,.6,args = (beta, lam, sl)) 

Edit:

Сообщение об ошибке:

Traceback (most recent call last): 
File "test.py", line 38, in polarint 
return quad(integrand,0,np.pi,args = (r,beta,delta))[0] 
File "/usr/local/anaconda/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 281, in quad 
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points) 
File "/usr/local/anaconda/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 345, in _quad 
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit) 
File "test.py", line 30, in integrand 
dd = deriv(r, theta, delta) 
File "test.py", line 22, in deriv 
return np.imag(matrix(r, theta, delta, delta+h*1j))/h 
File "test.py", line 14, in matrix 
mat = np.array([[r**2-1,r*np.cos(theta),0,delta1],[r*np.cos(theta),r**2 - 1, -delta1,0],[0,-delta2,-r**2+1,-r*np.cos(theta)],[delta2,0,-r*np.cos(theta),-r**2+1]]) 
TypeError: can't convert complex to float 
+0

Ваш вызов 'np.imag' преобразуется в сложный. Почему это там? –

+0

Это для взятия производной, взятой отсюда: http://blogs.mathworks.com/cleve/2013/10/14/complex-step-differentiation/ – gurluk

+0

В python существует множество производных подпрограмм. Вы смешиваете код MATLAB? В любом случае, np.imag означает взять воображаемую сторону. Если вы вызовете эту функцию, она преобразует свой аргумент в сложную функцию. Я не знаю, какая производная она должна быть. –

ответ

0

Я могу произвести ваше сообщение об ошибке с:

x = np.ones((3,)) 
x[1] = 1 + 1j 

x является dtype=float массив. Попытка вставить сложное значение вызывает ошибку.

Если ошибка производится в оценке:

mat = np.array([[r**2-1,r*np.cos(theta),0,delta1], 
       [r*np.cos(theta),r**2 - 1, -delta1,0], 
       [0,-delta2,-r**2+1,-r*np.cos(theta)], 
       [delta2,0,-r*np.cos(theta),-r**2+1]]) 

вопрос - какие значения r, theta, delta1, delta2 может произвести эту ошибку. Когда 1-й 3 - реальные скаляры и последний комплекс, я получаю комплексный массив (4,4). Я подозреваю, что одна из этих переменных - это то, что мы не делаем.


Я shortend pv сек минимальный пример:

np.array([1, np.array([1j])]) # error 
np.array([[1],np.array([1j])]) # ok 

коммутаторе порядок терминов, и результат отличается:

np.array([np.array([1j]),1]) 
# array([array([ 0.+1.j]), 1], dtype=object) 

Очевидно, что ошибка является результатом попытки для создания большего массива из комбинации скаляров и массивов, один из которых является сложным. Сообщение об ошибке является неясным и, вероятно, результатом непредвиденной проблемы. Это может быть достойно отчета об ошибке.

И решение состоит в том, чтобы либо преобразовать все эти 0 s в списки [0], либо убедиться, что значение delta2 является скаляром, а не массивом.

+0

Спасибо. Позже я написал свои собственные подпрограммы, чтобы найти корни функций, и это работает. Забавно, что я пытался сделать fsolve работу в течение двух недель, и я написал свой собственный рабочий код, который делает то же самое, что fsolve через 2 часа :-) Я должен был начать с написания собственного кода с самого начала. – gurluk

1

Это минимальный код, который не удается

from numpy import array 
q = [[-1.0, 0.0, 0, array([ 0.6])], [0.0, -1.0, array([-0.6]), 0], [0, array([-0.6 -1.00000000e-11j]), 1.0, -0.0], [array([ 0.6 +1.00000000e-11j]), 0, -0.0, 1.0]] 
array(q) 

, который является своего рода странно.Однако обратите внимание, что есть массивы с одним элементом, смешанным с равными числами. Это можно обнаружить, просто распечатав объект, который вы даете array(), прежде чем давать его.

Чтобы это исправить, изменить дельта дельта [0] в функции вы даете fsolve:

def equationgap(delta, beta, lam,sl): 
    return givesclen(delta[0], beta, lam)*4*np.pi - sl 

, потому что остальная часть кода ожидает, что дельта является одним числом, а не массив. fsolve даст функции для оптимизации массива чисел, даже если есть только один.

+0

Благодарим вас за ответ. Однако это не решило проблему. Затем я изменил часть на 'return giveclen (np.real (delta), beta, lam) * 4 * np.pi - sl', но снова не помог. – gurluk

+0

Вышеупомянутое изменение, безусловно, делает ошибку, которую вы видите выше, уходит, если вы делаете это в коде, который вы указали выше. Вероятно, ваш собственный код отличается от того, что вы написали выше, но причина ошибки очень важна, поэтому вы должны попытаться самостоятельно адаптировать решение. (Изменение его на 'np.real (delta)' ничего не изменит, потому что оно все равно является массивом.) –

+0

Спасибо. Позже я написал свои собственные подпрограммы, чтобы найти корни функций, и это работает.Забавно, что я пытался сделать fsolve работу в течение двух недель, и я написал свой собственный рабочий код, который делает то же самое, что fsolve через 2 часа :-) Я должен был начать с написания собственного кода с самого начала. – gurluk