How to estimate coefficients for a+xb=c? - python

I am trying to find the right python or R package/function to approximate x in the equation a + xb = c.
a, b, and c are tuples/vectors, so if I have:
a = (1,2,1)
b = (2,3,2)
c = (5,8,5)
then I would like the function to give me x = 2.
I feel like some form of least squares approach might be the right way to go, but I cannot seem to find a function that does this. Maybe I am looking with the wrong terms, because it seems like such an obvious thing, I don't know.

You can use Sympy for Python , here how it works :
from sympy.solvers import solve
from sympy import Symbol
x = Symbol('x')
solve(x**2 - 1, x)
[-1, 1] # output

Related

System of First Order ODEs in Python

I have seen how to solve systems of ODEs in Python, but all of the examples I have seen were "standard" equations. What I mean by standard is that the equations do not say "derivative of one function = expression that contains derivative of another function".
Here is a sample system I am trying to solve numerically. Initial conditions are x(0) = 5, y(0) = 3, z(0) = 2, and all initial derivatives are 0:
x'(t) + 4y(t) = -3y'(t)
y'(t) + ty(t) = -2z'(t)
z'(t) = -2y(t) + x'(t)
I am not 100% sure how to code this. Here is what I have tried:
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
import math
def ODESystem(f,t):
x = f[0]
y = f[1]
z = f[2]
Now, what do I define first: dydt, dxdt or dzdt. Is there a way for me to define one expression that "hangs around" before I use it to define another expression?
You do not need to solve anything manually, you can just as well do
def ODESystem(f,t):
x,y,z = f
return np.linalg.solve([[1,3,0],[0,1,2],[-1,0,1]], [-4, -t, -2])*y
Nevermind; I am stupid. I can keep on substituting into the third equation until I get an equation for z'(t) that does not include any other derivatives.

Sympy - get scalar out of vector, reference frame module

I have a very simple code, with a simple problem. I can't find the answers and tried everything that seemed logic to me. Anyways I have the code:
import sympy as sp
from sympy.physics.vector import *
N = ReferenceFrame('N')
f = 1*N.x+2*N.y
So f should now be a vector storing the values (1,2). x and y being 1 and 2 respectively. I made the setup as simple as possible.
I now want to extract the different scalars from the vector f. I'm looking for:
>>> f.some_function_or_whatever(N.y)
2
Input is greatly appreciated
For x, y, z coefficients set i to 0, 1, 2 respectively in the following line
f.to_matrix(N)[i]

Using scipy.linalg.solve with symmetric coefficient matrix (assume_a='sym')

I am trying to solve a system of linear equations A * x = b for the unknown x using scipy's linalg.solve function. Here is an example that works fine:
import numpy as np
import scipy.linalg as linalg
A = np.array([[ 0.18666667, 0.06222222, -0.01777778],
[ 0.01777778, 0.18666667, 0.01777778],
[-0.01777778, 0.06222222, 0.18666667]])
b = np.array([0.26666667, -0.26666667, -0.4])
x = linalg.solve(A, b, assume_a='gen')
It results in x = [1.77194417, -1.4555256, -1.48892533], which is a correct solution. This can be verified by computing A.dot(x), which results in [0.26666667, -0.26666667, -0.4]. As this is the same as b, the solution is correct.
However, the matrix of coefficients A is symmetrical, i.e., the values above and below the main diagonal are the same. If I understand the documentation correctly, for solving such a problem more efficiently, the solve function allows to set the argument assume_a='sym'. Unfortunately, using the following code (given the same A and b) results in an incorrect solution being found:
x = linalg.solve(A, b, assume_a='sym')
It results in x = [1.88811181, -1.88811181, -1.78321672], which is different from the solution above. Computing A.dot(x) results in [0.26666667, -0.35058274, -0.48391607]. As this is different from b, the solution seems to be incorrect.
I am wondering, if there is any problem with my code, or if my understanding of symmetric matrices or the expected result is simply wrong!? Maybe the matrix must satisfy additional constraints to be used together with assume_a='sym'?
I appreciate your answers. Thanks in advance!
In think it won't happen. I provide a short answer about it.
Non-symmetric A
import numpy as np
import scipy.linalg as linalg
A = np.array([[ 0.18666667, 0.06222222, -0.01777778],
[ 0.01777778, 0.18666667, 0.01777778],
[-0.01777778, 0.06222222, 0.18666667]])
b = np.array([0.26666667, -0.26666667, -0.4])
x = linalg.solve(A, b, assume_a='gen')
np.allclose(A # x,b)
Out:
True
Which shows the solver works well.
Symmetric A
# use you upper triangular A to get a symmetric matrix
A_symm = (np.triu(A) + np.triu(A).T -np.diag(A.diagonal()))
# solve the equations
x = linalg.solve(A_symm, b, assume_a='sym')
np.allclose(A_symm # x,b)
Out:
True
It still works.
If you pass a non-symmetric matrix A to the solver , and then specify the assume_a = 'sym', solver will only use upper triangular matrix of A, see below:
x = linalg.solve(A, b, assume_a='sym')
np.allclose(A # x,b),x
Out:
(False, array([ 1.88811181, -1.88811181, -1.78321672]))
The result shows that solver works "wrong", but the result x is the same with result of linalg.solve(A_symm, b, assume_a='sym')

How to combine polynomials in matrix operations in Sympy?

I'm doing some matrix operations, sometimes involving matrices whose entries have constant values.
But for some reason, I cannot get the matrix operation to combine the results into a single polynomial, even when the result is simple. for example, consider the following:
from sympy.matrices import *
import sympy
x= sympy.symbol.symbols('x')
Poly_matrix = sympy.Matrix([[sympy.Poly(x, x)],[sympy.Poly(x, x)]])
constant_matrix = sympy.Matrix([[0,1]])
constant_matrix_poly = constant_matrix.applyfunc(lambda val: sympy.Poly(val, x))
# this doesn't combine them
result1 = constant_matrix * Poly_matrix
print result1
>>>> Matrix([[Poly(0, x, domain='ZZ') + Poly(x, x, domain='ZZ')]])
# even THIS doesn't combine them when I convert the constants to Polynomials
result = constant_matrix_poly * Poly_matrix
print result
>>>> Matrix([[Poly(0, x, domain='ZZ') + Poly(x, x, domain='ZZ')]])
The problem with this, is that when I try to extract the expression, and turn this result into a different polynomial, I get the following error:
# This is where the trouble starts
sympy.Poly(result[0].as_expr(), x)
sympy.Poly(result1[0].as_expr(), x)
And the resulting error is a long traceback, ending with:
PolynomialError: Poly(x, x, domain='ZZ') contains an element of the set of generators.
To be even more specific, it has trouble with result[0].as_expr() because it cannot convert it to an expression using as_expr(), even though it is still an object of type Poly, so it can still use the method as_expr().
Why is it that these polynomials do not automatically get combined into one?
Or is there another way for me to call sympy.Poly(result[0].as_expr(), x)?
EDIT: Here are some questions with a similar error (although sometimes caused by something different):
sympy: PolynomialError: cos(a) contains an element of the generators set
Sympy Error when using POLY with SQRT
I stumbled upon this issue some time ago while running some code from a post. After looking into the source code of the matrix multiplication function _eval_matrix_mul on line 174 of dense.py, it turns out that sympy.Add is used to perform addition during the computation process rather than the + operator. Therefore Poly.add is not invoked and a new expression is created for addition every time.
Further inspection into the source code reveals that there is a PolyMatrix class that rewrites the matrix multiplication functions for polynominals. This class does work as expected as shown in the following. However, it does not show up anywhere in the documentation for unknown reasons so use it with caution. The docstring in the linked source code provides basic documentation for the class.
from sympy import Poly
from sympy.abc import x
from sympy.polys.polymatrix import PolyMatrix
mat = PolyMatrix([[Poly(x, x)], [1]])
const_mat = PolyMatrix([[4, 3]])
print(mat.shape, const_mat.shape)
print(mat.T * mat)
print(mat * mat.T)
print(2 * mat)
print(2 * mat + const_mat.T)
Output:
(2, 1) (1, 2)
Matrix([[Poly(x**2 + 1, x, domain='ZZ')]])
Matrix([[Poly(x**2, x, domain='ZZ'), Poly(x, x, domain='ZZ')], [Poly(x, x, domain='ZZ'), 1]])
Matrix([[Poly(2*x, x, domain='ZZ')], [2]])
Matrix([[Poly(2*x + 4, x, domain='ZZ')], [5]])
Another alternative approach is to use Expr.collect which has the same functionality as sympy.collect, as shown in the following:
from sympy import Poly, Matrix
from sympy.abc import x
mat = Matrix([[Poly(x, x)], [1]])
result = mat.T * mat
simplified = result.applyfunc(lambda p: p.collect(x))
print(simplified)
Output:
Matrix([[Poly(x**2 + 1, x, domain='ZZ')]])
If all you want is the characteristic polynomial, use charpoly. This is more efficient than eigenvals, because sometimes symbolic roots can be expensive to calculate.
Sample
lamda = symbols('lamda')
p = M.charpoly(lamda)
factor(p)
2
(λ - 5) ⋅(λ - 3)⋅(λ + 2)
Source
Here is one way to do this:
# even though this prints as two terms (which is kind of weird)
print result[0].as_expr()
#...this collapses it into one
exec('poly_expr = '+str(result[0].as_expr()))
print poly_expr
#...which allows the expressions to be combined
Poly(poly_expr, x)
However, this seems like a very hackish solution. Is there an easier way to do this?

How to solve equation with two matrices in python?

I need to find matrix A that A*B*A = B*A*B, and A^2 =1 if B =(1,0,0)(0,-1,0)(0,0,1)
I tried that do it in sympy:sympy.solve(A*B*A - B*A*A)
import sympy as sp
a,b,c,d,e,f,g,h,k = sp.symbols('a b c d e f g h k')
B = sp.Matrix([[1,0,1],[0,-1,0],[0,0,1]])
A = sp.Matrix([[a,b,c],[d,e,f],[g,h,k]])
sp.solve([A*B*A - B*A*B,B**2-sp.eye(3)])
and also I tried numpy.linalg, but I don't have any results
First of all, linalg will not help, as this is not a linear problem: unknown A gets multiplied by itself. You want to solve a system of 18 quadratic equations with 9 unknowns. For a generic system we'd expect no solutions, but there is a lot of structure here.
In my version of SymPy (1.1.1) direct attempts to solve even one of the matrix equations A*B*A=B*A*B or A*A=I fail to finish in reasonable time. So let's follow the advice of saintsfan342000 and approach the problem numerically, as a minimization problem. This is how I did it:
import numpy as np
from scipy.optimize import minimize
B = np.array([[1,0,0], [0,-1,0], [0,0,1]])
def func(A, B):
A = A.reshape((3, 3))
return np.linalg.norm(A.dot(B).dot(A)-B.dot(A).dot(B))**2 + np.linalg.norm(A.dot(A)-np.eye(3))**2
while True:
guess = np.random.uniform(-2, 2, size=(9,))
res = minimize(func, guess, args=(B,))
if res.fun < 1e-15:
A = res.x.reshape((3, 3))
print(A)
The function to minimize is the sum of squares of Frobenius norms of A*B*A-B*A*B and A*A-I. I put minimization in a loop because there are some local minima where minimize will get stuck; so when the minimal value found is not sufficiently close to zero, I ignore the result and start over. After running for a while, the script will print a bunch of matrices like
[[ 0.70386835 0.86117949 -1.40305355]
[ 0.17193376 0.49999999 0.81461157]
[-0.25409118 0.73892171 -0.20386834]]
which all share two important features:
the central element A[1,1] is 1/2
the trace of the matrix (the sum of diagonal elements) is 1.
Let's use this information to help SymPy solve the system. I still don't want to throw both equations at it, so I try to get one at a time.
from sympy import *
var('a:h') # a quick way to declare a bunch of symbols
B = Matrix([[1, 0, 0], [0, -1, 0], [0, 0, 1]])
A = Matrix([[a, b, c], [d, S(1)/2, f], [g, h, S(1)/2-a]]) # S(1)/2 is a way to get rational 1/2 instead of decimal 0.5
print(solve(A*B*A - B*A*B))
print(solve(A*A - eye(3)))
Now solve succeeds and prints the following:
[{b: h*(4*f*h - 3)/(2*g), d: -g/(2*h), a: 2*f*h - 1/2, c: -f*h*(4*f*h - 3)/g}]
[{b: h*(4*f*h - 3)/(2*g), d: -g/(2*h), a: 2*f*h - 1/2, c: -f*h*(4*f*h - 3)/g}]
Whoa! With the two constraints that we found numerically, both matrix equations are equivalent! I did not expect that. So we already have the solution:
A = Matrix([[2*f*h - S(1)/2, h*(4*f*h - 3)/(2*g), -f*h*(4*f*h - 3)/g], [-g/(2*h), S(1)/2, f], [g, h, 1 - 2*f*h]])
for arbitrary f, g, h.
Note: A=B is a trivial solution, which was excluded above by the requirement of A[1,1]=1/2. I imagine this was the intent; it appears you were looking for faithful 3-dimensional representations of the symmetric group S3.

Categories

Resources