Вызов функции с несколькими аргументами, сгенерированной 'lambdify' в массиве numpy - PullRequest
1 голос
/ 23 марта 2020

Я написал выражение f в SymPy, как показано в коде, а затем преобразовал в функцию, используя lambdify. Затем я векторизовал его, используя np.vectorize(f), чтобы иметь возможность применить его к массиву numpy.

import numpy as np
from math import exp
a = Symbol('a')
x = Symbol('x')
b = Symbol('b')
c = Symbol('c')

from sympy import *
f = exp(-(a+b+c)*x)*(4+exp(-(a+b)*x) -2*exp(-a*x) - 2*exp(-c*x))
f = lambdify([x,(a,b,c)], f)
vff = np.vectorize(f)

t = np.arange(0, 5, 0.01, dtype=np.float64)
y = vff(t, (1,1,1)) # (1,1,1) stands for (a,b,c)

Но при этом последняя строка выдает следующую ошибку.

TypeError: _lambdifygenerated() missing 1 required positional argument: '_Dummy_191'.

Я думаю, что синтаксис может быть неправильным. Я искал по inte rnet, но не смог найти правильный синтаксис. Может кто-нибудь сказать мне правильный синтаксис?

1 Ответ

0 голосов
/ 23 марта 2020
In [8]: print(f.__doc__)                                                                                             
Created with lambdify. Signature:

func(x, arg_1)

Expression:

(exp(x*(-a - b)) + 4 - 2*exp(-c*x) - 2*exp(-a*x))*exp(x*(-a - b - c))

Source code:

def _lambdifygenerated(x, _Dummy_166):
    [a, b, c] = _Dummy_166
    return ((exp(x*(-a - b)) + 4 - 2*exp(-c*x) - 2*exp(-a*x))*exp(x*(-a - b - c)))

Импортированные модули:

f можно запустить с:

In [9]: f(np.arange(3),(1,1,1))                                                                                      
Out[9]: array([1.        , 0.13262366, 0.00861856])

Поскольку f работает с входом массива, я не думаю, что вам нужно vectorized form.

Я получу вашу ошибку, если позвоню vff с одним аргументом:

In [14]: vff(np.arange(3))                                                                                           
---------------------------------------------------------------------------
...
TypeError: _lambdifygenerated() missing 1 required positional argument: '_Dummy_166'

С 2 аргументами я получу другую ошибку:

In [15]: vff(np.arange(3),(1,1,1))                                                                                   
---------------------------------------------------------------------------
...
<lambdifygenerated-1> in _lambdifygenerated(x, _Dummy_166)
      1 def _lambdifygenerated(x, _Dummy_166):
----> 2     [a, b, c] = _Dummy_166
      3     return ((exp(x*(-a - b)) + 4 - 2*exp(-c*x) - 2*exp(-a*x))*exp(x*(-a - b - c)))

TypeError: 'numpy.int64' object is not iterable

Это потому, что vectorize передает скаляр 1 в качестве второго аргумента. vectorize передает скалярные кортежи в функцию, а не в массивы. Он разработан из функций, которые принимают скалярные аргументы, а не массивы или даже кортежи. Есть несколько способов обойти это, но имейте в виду, что vectorize - это , а не инструмент скорости.

Так как вы не хотите, чтобы vectorize повторял (a, b , c) аргумент, мы можем «исключить» его:

In [16]: vff = np.vectorize(f, excluded=[1])                                                                         

In [17]: vff(np.arange(3),(1,1,1))                                                                                   
Out[17]: array([1.        , 0.13262366, 0.00861856])

Это работает так же, как f (выше). Но это намного медленнее:

In [18]: timeit vff(np.arange(300),(1,1,1))                                                                          
5.29 ms ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [19]: timeit f(np.arange(300),(1,1,1))                                                                            
103 µs ± 41 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

vectorize даже медленнее, чем понимание списка:

In [20]: timeit np.array([f(i,(1,1,1)) for i in range(300)])                                                         
3.91 ms ± 6.17 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...