Intercambiar entre diferentes solucionadores odeos scipy

He hecho un solucionador que puede intercambiar entre scipy.integrate.ode y scipy.integrate.odeint . Aquí está el código.

 def f(y,s,C,u,v): y0 = y[0] # u y1 = y[1] # u' y2 = y[2] # v y3 = y[3] # v' dy = np.zeros_like(y) dy[0] = y1 dy[2] = y3 C = C.subs({u:y0,v:y2}) dy[1] = -C[0,0][0]*dy[0]**2\ -2*C[0,0][1]*dy[0]*dy[2]\ -C[0,1][1]*dy[2]**2 dy[3] = -C[1,0][0]*dy[0]**2\ -2*C[1,0][1]*dy[0]*dy[2]\ -C[1,1][1]*dy[2]**2 return dy def solve(C,u0,s0,s1,ds,solver=None): from sympy.abc import u,v if solver == None: # use lsoda from scipy.integrate.odeint s = np.arange(s0,s1+ds,ds) print 'Running solver ...' return sc.odeint(f,u0,s,args=(C,u,v)) else: # use any other solver from scipy.integrate.ode r = sc.ode(f).set_integrator(solver) # vode,zvode,lsoda,dopri5,dop853 r.set_f_params(C,u,v) r.set_initial_value(u0) #t = [] y = [] print 'Running solver ...' while r.successful() and rt <= s1: r.integrate(rt + ds) y.append(ry)#; t.append(rt) return np.array(y) 

El problema que experimento es el siguiente. Si decido usar el solucionador de scipy.integrate.odeint , los parámetros de f deben especificarse en el orden tal como están en el código. Sin embargo, si decido usar los solucionadores de scipy.integrate.ode , tengo que cambiar el orden de los parámetros de la función f(y,s,C,u,v) a f(s,y,C,u,v) , de lo contrario me sale el error

 TypeError: 'float' object has no attribute '__getitem__' 

Si hago esto, entonces scipy.integrate.odeint genera el mismo error para f definido como f(s,y,C,u,v) . ¿Cómo puedo operar con una f unificada sin importar el orden de los parámetros?

Editar:

Para resumir el problema:

scipy.integrate.ode solucionadores de scipy.integrate.ode funcionan si la función f se define como f(s,y,C,u,v) , y el solucionador scipy.integrate.odeint funciona si la función f se define como f(y,s,C,u,v) . ¿Por qué ocurre esto y cómo puedo solucionarlo?

Editar:

Scipy – versión 0.16.0

¿Por qué ocurre esto y cómo puedo solucionarlo?

Se está produciendo debido a una desafortunada decisión de diseño de API tomada hace años. odeint y la clase ode requieren diferentes firmas para que el sistema sea resuelto.

Puede arreglarlo agregando un envoltorio que cambie el orden de los dos primeros argumentos cuando use, por ejemplo, la clase ode . Por ejemplo, podrías cambiar esto:

  r = sc.ode(f).set_integrator(solver) 

a

  r = sc.ode(lambda t, x, *args: f(x, t, *args)).set_integrator(solver) 

Una mejor documentación de esta discrepancia está en progreso: https://github.com/scipy/scipy/pull/5151