Как вернуть ноль для отсутствующего одночлена в sympy

#python #sympy

#питон #сочувствую

Вопрос:

Я хотел бы вернуть ноль за отсутствующий одночлен, но не смог найти никаких указателей в документации sympy. Мое намерение состоит в том, чтобы построить разреженный массив из нескольких выражений. Есть ли простой способ сделать это? МВЕ:

 import sympy x, y, z = sympy.symbols('x, y, z') func_1 = 3   x   5 * y   2 * z func_2 = 1   x   2 * y  expr_2 = [func_1, func_2] func_vars = [x, y, z]  eqs = sympy.parallel_poly_from_expr(expr_2, func_vars) [[eqn.coeff_monomial(m) for m in eqn.monoms()][:-1] for eqn in eqs[0]]  # gt;gt;gt; [[1, 5, 2], [1, 2]] # expected [[1,5,2],[1,2,0]]  

Обновлено MWE с использованием indexedbase с нелинейной переменной на основе предложений smichr:

 def get_coeffs(coeff_dict, func_vars):  c = coeff_dict  for i in list(c.keys()):  b, _ = i.as_base_exp()  if b == i:  continue  if b in c:  raise ValueError('multiple generators with %s' % b)  if any(k.has(b) for k in c):  raise ValueError('cross terms detected with %s' % b)  c[b] = c[i]    return [coeff_dict[val] for val in func_vars]    x = sympy.IndexedBase('x') func_1 = 3   x[0]**2   5 * x[1]   2 * x[2] func_2 = 1   x[0]   2 * x[1]  expr_2 = [func_1, func_2] func_vars = [x[0], x[1], x[2]]   ([get_coeffs(i.as_coefficients_dict(), func_vars) for i in expr_2]) # I get [[1, 5, 2], [1, 2, 0]]  

Комментарии:

1. Я отмечаю, что ваши многочлены линейны в трех генераторах, что говорит о том, что вы вообще не хотите использовать многочлены (возможно, сделайте шаг назад и объясните, почему вы вообще хотите использовать многочлены). Если вы действительно хотите использовать многочлены, то как бы вы в целом решили, когда существуют нетривиальные одночлены, например x**2*y , какими должны быть записи в выходном списке?

2. В основном я пытаюсь воспроизвести вывод функции Mathematica «Cofficientarrays», которая выдает массивы коэффициентов переменных vars в полиномах полиномов. Это дает список, содержащий разреженные объекты. Это также говорит о том, что для нелинейных уравнений m[i] не являются уникальными. Cofficientarrays по умолчанию присваивает ненулевые коэффициенты только одночленам, в которых переменные отображаются в том же порядке, что и vars.

Ответ №1:

Если вы работаете с линейными уравнениями, то linear_eq_to_matrix можете работать с необработанными (неполигональными) выражениями, чтобы получить матрицу коэффициентов:

 gt;gt;gt; linear_eq_to_matrix([i.as_expr() for i in eqs[0]],[x,y,z]) (Matrix([ [1, 5, 2], [1, 2, 0]]), Matrix([ [-3], [-1]]))  

Этот as_coefficients_dict метод мог бы быть лучшим выбором. И если у вас есть полномочия какой-либо переменной, то результирующий словарь может быть изменен для хранения оснований полномочий с тем же коэффициентом.

 gt;gt;gt; x=IndexedBase('x') gt;gt;gt; eq=3   x[0]**2   5 * x[1]   2 * x[2] gt;gt;gt; eq.as_coefficients_dict() defaultdict(lt;class 'int'gt;, {1: 3, x[0]**2: 1, x[2]: 2, x[1]: 5}) gt;gt;gt; c=_ gt;gt;gt; for i in list(c.keys()): ... c[i.as_base_exp()[0]] = c[i] # set values bases of powers ... gt;gt;gt; [_[x[i]] for i in range(4)] # default dict will supply 0 [1, 5, 2, 0]  

Комментарии:

1. Это похоже на то, что я хочу, но выдает ошибку, например «Ожидаю символа, но получил x[0]», когда я создаю базу данных с индексом » x » и использую x[0], x[1], x[2] вместо x, y, z. Подход, который я использовал, все еще работает в этом сценарии, но функция linear_eq_to_matrix выдает ошибку. Есть какие-нибудь предложения о том, как поступить в таком случае?

2. symeqs = Tuple(*eqs[0]).xreplace(reps) где reps = dict(zip((x[0], x[1], ....), numbered_symbols('s'))) тогда кормить symeqs и list(reps.values()) linear_eq_to_matrix куда .

3. Я попробовал это на более сложном линейном уравнении, и это сработало.

4. Привет, смичр, я подумал, что должен спросить, есть ли способ использовать этот подход, даже если у меня есть нелинейный термин, такой как x[0]**2, такой, что он игнорирует нелинейность и все равно возвращает коэффициент 3 x[0]**2 5 * x[1] 2 * x[2] как 1

5. абсолютно!!!. это была функция, в которой я нуждался. Gracias!

Ответ №2:

Если это просто обычный список, вы можете просто обработать его после обработки. Чтобы дополнить 2D-список x буквами 0 s с правой стороны, вы можете просто сделать это:

 width = max(map(len, x)) for row in x:  row.extend([0] * (width - len(row)))  

В принципе, вы получаете ширину всего объекта, находя максимальную ширину всех строк. Затем для каждой строки вы просто вставляете столько 0 букв s, сколько требуется после нее, чтобы она была правильной ширины.