2014-02-12 4 views
1

Имея функцию f (x, y, z), мне нужно решить ограничение f (x, y, z) = 0, а затем построить его. Я пытался найти для каждой пары (у, г) значения х, для которых F (х, у, г) = 0:Python fsolve() жалуется на форму. Зачем?

from numpy import * 
from scipy.optimize import fsolve 

def func(x,y,z): 
    return x+y+z 

y = linspace(0,1,100) 
z = linspace(0,1,100) 
x0 = zeros((y.size,z.size)) + 0.5 # the initial guess 
yz = (y[:,newaxis],z[newaxis,:]) # the other parameters 
x, info, iterations, message = fsolve(func,x0,yz) 
contour(y,z,x) 

Python (2.7.5) говорит «TypeError: fsolve: есть несоответствие между формой ввода и вывода аргумента «func» «func».

Но если я проверить это сам, это дает ту же форму:

func(x0,y[:,newaxis],z[:,newaxis]).shape == x0.shape 

возвращает True.

Почему fsolve() жалуется?

+0

это не тот же вызов функции. что если вы проверите 'func (x0, y [:, newaxis], z [:, newaxis]). shape == x0.shape'? Не видя кода 'func', отладка этого для вас может быть сложной. – M4rtini

+0

Да, вы правы, я только что осознал это и собирался изменить его в вопросе. Я попробовал, и он также дает ту же форму. – Amenhotep

+0

Функция представляет собой длинную часть программы, но такое же поведение происходит с одной функцией линии def func (x, y, z): return x + y + z; Я не думаю, что это из-за функции. – Amenhotep

ответ

2

fsolve ожидает аргумент x, а возвращаемое значение func является скалярным или одномерным массивом. Вам нужно будет изменить свой код для работы с плоскими значениями x. Например.

def func(x, y, z): 
    x = x.reshape(y.size, z.size) 
    return (x + y + z).ravel() 

и что-то подобное для вызова fsolve:

sol, info, ier, mesg = fsolve(func, x0.ravel(), args=yz, full_output=True) 
x = sol.reshape(y.size, z.size) 
+0

Да, теперь fsolve() больше не жалуется, но для завершения требуется много времени. Для матрицы 10 x 10 она работает, но для простой матрицы 100 x 100 она работает через 10 минут. Возможно, fsolve() не самый лучший вариант для моей проблемы. В таких случаях я напишу еще один вопрос об общей стратегии. Спасибо за ваш ответ. – Amenhotep

+0

100x100 матрица - это 10000 переменных, что слишком много для fsolve. См. [Scipy.optimize учебник по большим проблемам] (http://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html#root-finding-for-large-problems). –

2

Вот сравнение с krylov метода рекламируемый в scipy.optimize tutorial:

from numpy import linspace, zeros, newaxis 
import time 
from scipy.optimize import root 

def func(x,y,z): 
    x = x.reshape(y.size, z.size) 
    f = x + y + z 
    f = f.ravel() 
    return f 

n = 50 
y = linspace(0,1,n) 
z = linspace(0,1,n) 
x0 = zeros((y.size,z.size)) + 0.5 # the initial guess 
yz = (y[:,newaxis],z[newaxis,:]) # the other parameters 

start = time.time() 
sol1 = root(func, x0.ravel(), args=yz, method='hybr', tol=1e-7) # same as fsolve 
x1 = sol1.x.reshape(y.size, z.size) 
print("(fsolve) time taken (sec): %g" % (time.time() - start,)) 
print("(fsolve) successful: %r (%s)" % (sol1.success, sol1.message)) 
print("(fsolve) max error: %g" % (abs(func(x1, *yz)).max(),)) 

start = time.time() 
sol2 = root(func, x0.ravel(), args=yz, method='krylov', tol=1e-9) 
x2 = sol2.x.reshape(y.size, z.size) 
print("(krylov) time taken (sec): %g" % (time.time() - start,)) 
print("(krylov) successful: %r (%s)" % (sol2.success, sol2.message)) 
print("(krylov) max error: %g" % (abs(func(x2, *yz)).max(),)) 

Печать

 
(fsolve) time taken (sec): 26.9296 
(fsolve) successful: False (The iteration is not making good progress, as measured by the 
    improvement from the last ten iterations.) 
(fsolve) max error: 1.52656e-16 
(krylov) time taken (sec): 0.0173709 
(krylov) successful: True (A solution was found at the specified tolerance.) 
(krylov) max error: 1.11022e-16 
+0

Ничего себе! Спасибо! – Amenhotep

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