Sympy - get scalar out of vector, reference frame module - python

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]

Related

How do i solve this equation for m using SciPy root function and how do i write it

```
import numpy as np
K = 1.38e-23
z = 8
J = 1.8e-21
T = 1
m = 0
```
these are just constants
m = np.tanh((z*J*m)/(K*T))
this is the equation
but I need to find it each m value for each T value so I'm not sure if a nested loop would be better where I loop through T and m because I've tried and is doesn't work proper I'm just not sure what to do so any help would be great. also T is in range 1 - 1501
I am not still sure what you really need.
If you do some optimization to find some min or max, you should have a look again might you provide less information to us than needed (for example you say m=0 but that gives answer 0 for any T. Might you want to have range of m and T. It's then another story.
Without scipy if you willing to calculate just a result of a function of two parameters, m and T, you can use linspace for example to set ranges and steps.
import numpy as np
import matplotlib.pyplot as plt
def func(T, m):
z = 8
K = 1.38e-23
J = 1.8e-21
return np.tanh((z*J*m)/(K*T))
xaxis = np.linspace(1, 1501, 1500)
yaxis = np.linspace(0, 10, 10)
result = func(xaxis[:,None], yaxis[None,:])
plt.plot(result)
And you get smth as below, few curves. But I set m in range, might you need another values there. Up to you. Check and go.

How to estimate coefficients for a+xb=c?

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

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')

I am beginner, and have a question related to plotting in Python

I am new to python.
I wanted to know the syntax for a problem
Suppose I want to plot a quantity x = (constant with a fixed given value) * ln (1+z) versus z (which varies from c to d)
How do I define the variables x and z, how do I input an 'ln' function
I have imported numpy, scipy and matplotlib, but do not know how to proceed thereafter
Since you already imported numpy, here is just another answer:
import numpy as np
import matplotlib.pyplot as plt
x_coeff = 10
c = 0
d = 100
z = [i for i in range(c, d)]
x = [x_coeff * np.log(1+v) for i, v in enumerate(z)]
plt.plot(z, x)
plt.show()
It's always better to check the documents, and give out your first try:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.log.html
You might also need to understand "list comprehension".
It's a beautiful and convenient way to create list in python.
For plotting a curve, you need two lists, one of them is domain on x axis and the other is range points on y-axis. first we take a constant as input,using python inbuilt input function and make sure that it is int, use math library and log function to do log as need.
import math
import matplotlib.pyplot as plt
a = int(input("enter a value for constant : "))
c,d = 0,100
xvals = list(range(c,d,1)) # start,end,step
print(xvals)
yvals = [a*math.log(1+x) for x in xvals]
print(yvals)
plt.plot(xvals,yvals)
plt.show()

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?

Categories

Resources