Как сгенерировать символический многомерный многочлен заданного измерения в SymPy?

1

Я хочу использовать ряд мощности для аппроксимации некоторых PDE. На первом этапе мне нужно создать символические многомерные многочлены, заданные numpy ndarray.

Рассмотрим следующий полином:

Изображение 174551

Я хочу взять m мерный ndarray из D=[d1,...,dm] где dj - целые неотрицательные числа, и создать символический многомерный многочлен в виде символического выражения. Символическое выражение состоит из одночленов вида:

Изображение 174551

Fo, если D=[2,3] выход должен быть

Изображение 174551

Для этого конкретного случая я мог гнездятся два for loops и добавить выражения. Но я не знаю, что делать для D с произвольной длиной. Если бы я мог генерировать D мерные ndarrays из A и X без использования для циклов, тогда я мог бы использовать np.sum(np.multiply(A,X)) как скалярное произведение Фробениуса, чтобы получить то, что мне нужно.

Теги:
numpy
sympy
polynomial-math

1 ответ

2

Я бы использовал symarray и itertools.product для этого:

from sympy import *
import itertools
D = (3, 4, 2, 3)
a = symarray("a", D)
x = symarray("x", len(D))
prod_iterator = itertools.product(*map(range, D))
result = Add(*[a[p]*Mul(*[v**d for v, d in zip(x, p)]) for p in prod_iterator])

В результате

a_0_0_0_0 + a_0_0_0_1*x_3 + a_0_0_0_2*x_3**2 + a_0_0_1_0*x_2 + a_0_0_1_1*x_2*x_3 + a_0_0_1_2*x_2*x_3**2 + a_0_1_0_0*x_1 + a_0_1_0_1*x_1*x_3 + a_0_1_0_2*x_1*x_3**2 + a_0_1_1_0*x_1*x_2 + a_0_1_1_1*x_1*x_2*x_3 + a_0_1_1_2*x_1*x_2*x_3**2 + a_0_2_0_0*x_1**2 + a_0_2_0_1*x_1**2*x_3 + a_0_2_0_2*x_1**2*x_3**2 + a_0_2_1_0*x_1**2*x_2 + a_0_2_1_1*x_1**2*x_2*x_3 + a_0_2_1_2*x_1**2*x_2*x_3**2 + a_0_3_0_0*x_1**3 + a_0_3_0_1*x_1**3*x_3 + a_0_3_0_2*x_1**3*x_3**2 + a_0_3_1_0*x_1**3*x_2 + a_0_3_1_1*x_1**3*x_2*x_3 + a_0_3_1_2*x_1**3*x_2*x_3**2 + a_1_0_0_0*x_0 + a_1_0_0_1*x_0*x_3 + a_1_0_0_2*x_0*x_3**2 + a_1_0_1_0*x_0*x_2 + a_1_0_1_1*x_0*x_2*x_3 + a_1_0_1_2*x_0*x_2*x_3**2 + a_1_1_0_0*x_0*x_1 + a_1_1_0_1*x_0*x_1*x_3 + a_1_1_0_2*x_0*x_1*x_3**2 + a_1_1_1_0*x_0*x_1*x_2 + a_1_1_1_1*x_0*x_1*x_2*x_3 + a_1_1_1_2*x_0*x_1*x_2*x_3**2 + a_1_2_0_0*x_0*x_1**2 + a_1_2_0_1*x_0*x_1**2*x_3 + a_1_2_0_2*x_0*x_1**2*x_3**2 + a_1_2_1_0*x_0*x_1**2*x_2 + a_1_2_1_1*x_0*x_1**2*x_2*x_3 + a_1_2_1_2*x_0*x_1**2*x_2*x_3**2 + a_1_3_0_0*x_0*x_1**3 + a_1_3_0_1*x_0*x_1**3*x_3 + a_1_3_0_2*x_0*x_1**3*x_3**2 + a_1_3_1_0*x_0*x_1**3*x_2 + a_1_3_1_1*x_0*x_1**3*x_2*x_3 + a_1_3_1_2*x_0*x_1**3*x_2*x_3**2 + a_2_0_0_0*x_0**2 + a_2_0_0_1*x_0**2*x_3 + a_2_0_0_2*x_0**2*x_3**2 + a_2_0_1_0*x_0**2*x_2 + a_2_0_1_1*x_0**2*x_2*x_3 + a_2_0_1_2*x_0**2*x_2*x_3**2 + a_2_1_0_0*x_0**2*x_1 + a_2_1_0_1*x_0**2*x_1*x_3 + a_2_1_0_2*x_0**2*x_1*x_3**2 + a_2_1_1_0*x_0**2*x_1*x_2 + a_2_1_1_1*x_0**2*x_1*x_2*x_3 + a_2_1_1_2*x_0**2*x_1*x_2*x_3**2 + a_2_2_0_0*x_0**2*x_1**2 + a_2_2_0_1*x_0**2*x_1**2*x_3 + a_2_2_0_2*x_0**2*x_1**2*x_3**2 + a_2_2_1_0*x_0**2*x_1**2*x_2 + a_2_2_1_1*x_0**2*x_1**2*x_2*x_3 + a_2_2_1_2*x_0**2*x_1**2*x_2*x_3**2 + a_2_3_0_0*x_0**2*x_1**3 + a_2_3_0_1*x_0**2*x_1**3*x_3 + a_2_3_0_2*x_0**2*x_1**3*x_3**2 + a_2_3_1_0*x_0**2*x_1**3*x_2 + a_2_3_1_1*x_0**2*x_1**3*x_2*x_3 + a_2_3_1_2*x_0**2*x_1**3*x_2*x_3**2

Примечания:

  1. symarray зависит от NumPy, но это, похоже, не является проблемой для вас. Если бы это было так, я бы создал символы один за другим, используя itertools.product
  2. Формат Add(*[...]) более эффективен, чем sum([...]) для формирования символических сумм с большим количеством терминов, см. Вопрос № 13945 SymPy.
  • 0
    здорово. Я проверю это и вернусь. в то же время другие также предлагают решения здесь и здесь . Вам тоже может понравиться их увидеть.
  • 0
    Отсюда я нашел product(*map(range, D)) который кажется быстрее, чем product(*[range(d) for d in D]) . Как ты думаешь?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню