Как использовать Simpy Solver для решения уравнения, генерируемого соответствующими элементами из двух numpy .array? - PullRequest
0 голосов
/ 27 марта 2020

the equation

Как я знаю, если параметры в уравнении являются скалярами, решение уравнения выше реализуется как:

from sympy.solvers import solve
from sympy import Symbol
from math import sin, cos, sqrt

# ep, t, a are in short for epsilon, theta and alpha, respectively
ep = Symbol('ep')
a = 0.4798212489019141 
t = 39.603733
solve(abs(a)-abs((ep-1)(sin(t)**2 - ep*(1+sin(t)**2)/(ep*cos(t)+sqrt(ep-sin(t)**2))**2)), ep)

Вопрос есть, если эти параметры numpy .ndarray в 3-х измерениях, как реализовать этот расчет? В моем случае форма тета и альфа (5,277,232). Таким образом, выходные данные ep также должны иметь такую ​​же форму.

Ответы [ 2 ]

1 голос
/ 29 марта 2020

Когда я выбираю выражение проблемы отдельно, минимальный сегмент, который выдает вашу ошибку:

In [13]: sqrt(ep-sin(t)**2)                                                                    
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-1d595e0b7cc7> in <module>
----> 1 sqrt(ep-sin(t)**2)

/usr/local/lib/python3.6/dist-packages/sympy/core/expr.py in __float__(self)
    323         if result.is_number and result.as_real_imag()[1]:
    324             raise TypeError("can't convert complex to float")
--> 325         raise TypeError("can't convert expression to float")
    326 
    327     def __complex__(self):

TypeError: can't convert expression to float

Аргумент sqrt является выражением sympy (потому что ep является символом):

In [14]: ep-sin(t)**2                                                                          
Out[14]: ep - 0.892639513815489

math.sqrt требует ввода с плавающей запятой; это не может сделать символ c sqrt.

Если я заменю его на sympy sqrt:

In [16]: from sympy import sqrt                                                                

In [17]: sqrt(ep-sin(t)**2)                                                                    
Out[17]: 
  ________________________
╲╱ ep - 0.892639513815489 

Теперь, если я попробую все выражение:

In [18]: abs(a)-abs((ep-1)(sin(t)**2 - ep*(1+sin(t)**2)/(ep*cos(t)+sqrt(ep-sin(t)**2))**2))    
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-18-7d1c0e01daaf> in <module>
----> 1 abs(a)-abs((ep-1)(sin(t)**2 - ep*(1+sin(t)**2)/(ep*cos(t)+sqrt(ep-sin(t)**2))**2))

TypeError: 'Add' object is not callable

(ep-1) - симпатичное Add выражение. Из-за синтаксических правил python вы не можете (...)(...) подразумевать умножение. Вы должны быть явными:

In [19]: abs(a)-abs((ep-1)*(sin(t)**2 - ep*(1+sin(t)**2)/(ep*cos(t)+sqrt(ep-sin(t)**2))**2))   
Out[19]: 
                    │         ⎛                1.89263951381549⋅ep                           
0.479821248901914 - │(ep - 1)⋅⎜──────────────────────────────────────────────────── - 0.89263
                    │         ⎜                                                   2          
                    │         ⎜⎛                         ________________________⎞           
                    │         ⎝⎝0.327659100567207⋅ep - ╲╱ ep - 0.892639513815489 ⎠           

          ⎞│
9513815489⎟│
          ⎟│
          ⎟│
          ⎠│

In [20]: solve(abs(a)-abs((ep-1)*(sin(t)**2 - ep*(1+sin(t)**2)/(ep*cos(t)+sqrt(ep-sin(t)**2))**
    ...: 2)), ep)                                                                              
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
<ipython-input-20-944cce37e63b> in <module>
----> 1 solve(abs(a)-abs((ep-1)*(sin(t)**2 - ep*(1+sin(t)**2)/(ep*cos(t)+sqrt(ep-sin(t)**2))**2)), ep)

/usr/local/lib/python3.6/dist-packages/sympy/solvers/solvers.py in solve(f, *symbols, **flags)
   1032             if e.has(*symbols):
   1033                 raise NotImplementedError('solving %s when the argument '
-> 1034                     'is not real or imaginary.' % e)
   1035 
   1036         # arg

NotImplementedError: solving Abs((ep - 1)*(1.89263951381549*ep/(0.327659100567207*ep - sqrt(ep - 0.892639513815489))**2 - 0.892639513815489)) when the argument is not real or imaginary.

Похоже, вам нужно присвоить некоторые ограничения для переменной ep. (Мне не хватает эксперта sympy, чтобы сделать это без чтения документов.)

===

Если я уберу abs из выражения и уточню ep, я получаю числовое c решение:

In [57]: expr =a-(ep-1)*(sin(t)**2 - ep*(1+sin(t)**2)/(ep*cos(t)+sqrt(ep-sin(t)**2))**2)       

In [58]: ep =  Symbol('ep', real=True)                                                         

In [59]: solve(expr, ep)                                                                       
Out[59]: [56.1511793662046]

In [60]: expr.subs(ep, _[0])                                                                   
Out[60]: -1.65423230669148e-13

предположительно, которое можно повторить для других значений a и t. Метод итерации не должен иметь значения, поскольку шаг solve будет доминировать в это время.

1 голос
/ 27 марта 2020

Если вы хотите решить вышеприведенное уравнение для пар a и t, вы можете векторизовать свою функцию. Это позволяет помещать массивы произвольных форм и оценивать функцию для всех пар и сортировать ее в правильную форму.

Пример:

import numpy as np

def eps_solve(a, t):
    return a + t
eps_solve_vec = np.vectorize(eps_solve)

a = np.array([[[1, 1], [2, 2]], [[3, 4], [7, 8]]])
t = np.array([[[1, 2], [3, 4]], [[7, 0], [3, 1]]])
res = eps_solve_vec(a, t)
print(res, res.shape)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...