2017-01-22 8 views
11

здания на примере я нашел here, я пытаюсь создать функцию из диагональной матрицы, которая была создана с использованием sumpy.diagSymPy: создание функции Numpy с диагональной матрицы, которая принимает массив Numpy

myM = Matrix([ 
[x1, 4, 4], 
[4, x2, 4], 
[4, 4, x3]]) 

Там, где это было создано с помощью этой подпрограммы, например:

import sympy as sp 
import numpy as np 

x1 = sp.Symbol('x1') 
x2 = sp.Symbol('x2') 
x3 = sp.Symbol('x3') 
X = sp.Matrix([x1, x2, x3]) 

myM = 4 * sp.ones(3, 3) 
sp.diag(*X) + myM - sp.diag(*np.diag(myM)) 

теперь я хотел бы создать функцию, используя lambdify из ufuncify, что занимает numpy.array или длина 3 (например, np.array([0.1,0.2,0.3])) в качестве входного сигнала, и выдает выходной сигнал в виде матрицы в соответствии с myM

myM = Matrix([ 
[0.1, 4, 4], 
[4, 0.2, 4], 
[4, 4, 0.3]]) 

В конце концов, мне нужно, чтобы создать матрицу Якоби символически с помощью этого метода: Jacobian И как функциональная форма может изменяться в процессе расчета, то вычисление символом Якоби было бы очень полезно.

ответ

10

Создание числовой матрицы 3 на 3 от числового вектора на самом деле не является символом SymPy, поскольку символы не задействованы. Рассмотрим следующее, где аргумент d представляет собой массив, содержащий диагональные элементы.

def mat(d): 
    return np.diag(d-4) + 4 

Вышеуказанная функция возвращает массив 2d NumPy. Чтобы вернуть матрицу SymPy вместо этого использовать

def mat(d): 
    return sp.Matrix(np.diag(d-4) + 4) 

Когда д имеет очень малые значения, вычитание с последующим добавлением может привести к потере точности: например, (1e-20 - 4) + 4 оценивает к нулю. Более безопасная альтернатива

def mat(d): 
    diagmat = np.diag(d) 
    return diagmat + np.fromfunction(lambda i, j: (i != j)*4, diagmat.shape) 
+0

Не совсем то, что я имел в виду, но я Я использую его, поэтому спасибо – Ohm

5

вы можете .subs() значения с плавающей точкой в ​​соответствующие символы:

import sympy as sp 
import numpy as np 

x1 = sp.Symbol('x1') 
x2 = sp.Symbol('x2') 
x3 = sp.Symbol('x3') 
X = sp.Matrix([x1, x2, x3]) 

myM = 4 * sp.ones(3, 3) 
smyM=sp.diag(*X) + myM - sp.diag(*np.diag(myM)) 

fcoefs = [(a, f) for a, f in (zip([x1, x2, x3], np.array([0.1,0.2,0.3])))] 

fmyM = smyM.subs(fcoefs) 

smyM 
Out[105]: 
Matrix([ 
[x1, 4, 4], 
[ 4, x2, 4], 
[ 4, 4, x3]]) 

fmyM 
Out[106]: 
Matrix([ 
[0.1, 4, 4], 
[ 4, 0.2, 4], 
[ 4, 4, 0.3]]) 

, кажется, быть прекрасным sympy.matrices.dense.MutableDenseMatrix Матрица после:

fmyM @ myM 
Out[107]: 
Matrix([ 
[32.4, 32.4, 32.4], 
[32.8, 32.8, 32.8], 
[33.2, 33.2, 33.2]]) 

может потребоваться преобразование к np.array для полного использования с numpy

Ниже приведена часть моего кода, показывающего mo повторно рисунка я использовал:

def ysolv(coeffs): 
    x,y,a,b,c,d,e = symbols('x y a b c d e') 
    ellipse = a*y**2 + b*x*y + c*x + d*y + e - x**2 
    y_sols = solve(ellipse, y) 
    print(*y_sols, sep='\n') 

    num_coefs = [(a, f) for a, f in (zip([a,b,c,d,e], coeffs))] 
    y_solsf0 = y_sols[0].subs(num_coefs) 
    y_solsf1 = y_sols[1].subs(num_coefs) 

    f0 = lambdify([x], y_solsf0) 
    f1 = lambdify([x], y_solsf1) 
    return f0, f1 

f0, f1 = ysolv(t[0]) 

y0 = [f0(x) for x in xs] 
y1 = [f1(x) for x in xs] 
...  

от: https://stackoverflow.com/a/41232062/6876009 (да, мой «feeloutXrange» есть хак так плохо было показано)