Related
I can be considered pretty much new to python and coding in general so forgive me for my ignorance.
I'm trying to solve a system of trigonometric functions in python, and I'm doing so using the solve command from sympy. However, this method returns only a finite number of solutions, two in this particular case.
I've read through the documentation and it seems that to get an expression for all the solutions solveset is to be used instead. However, I do not want all the solutions to be displayed, but rather only a finite amount which is contained within a certain range.
Here's the example:
from sympy import *
x, y = symbols('x, y')
eq1 = Eq(y - sin(x), 0)
eq2 = Eq(y - cos(x), 0)
sol = solve([eq1, eq2], [x, y])
print(sol)
which only returns the first two solutions in the positive x range.
How could I do to, for example, display all the solutions within the x range [-2pi, 2pi]?
I'd want them in explicit form rather than written in term of some multiplier since I then need to convert them into numerical form.
Thank you in advance.
SymPy can really take you down rabbit holes. I agree with kampmani's solution, only if you can easily solve for y on your own. However, in more general cases and in higher dimensions, his solution does not hold.
For example, the following will be slightly more tricky:
eq1 = Eq(z - x*y, 0)
eq2 = Eq(z - cos(x) - sin(y), 0)
eq3 = Eq(z + x*y, 0)
So here I am; killing a fly with a bazooka. The problem is that one was able to simplify the set of equations into a single equation with a single variable. But what if you can't do that (for example, if it was a larger system)?
In this case, one needs to use nonlinsolve to solve the system of equations. But this does not provide numeric solutions directly and does not have a domain argument.
So the following code unpacks the solutions. It goes through each tuple in the set of solutions and finds the numeric solutions for each component in the tuple. Then in order to get the full list, you need a Cartesian Product of each of those components. Repeat this for each tuple in the set of solutions.
The following should work for almost any system of equations in any dimension greater than 1. It produces numeric solutions in the cube whose boundaries are the domains variable.
from sympy import *
import itertools # used for cartesian product
x, y, z = symbols('x y z', real=True)
domains = [Interval(-10, 10), Interval(-10, 10), Interval(-10, 10)] # The domain for each variable
eq1 = z - x*y
eq2 = z - cos(x) - sin(y)
eq3 = z + x*y
solutions = nonlinsolve([eq1, eq2, eq3], [x, y, z]) # the recommended function for this situation
print("---------Solution set----------")
print(solutions) # make sure the solution set is reasonable. If not, assertion error will occur
_n = Symbol("n", integer=True) # the solution set often seems to contain these symbols
numeric_solutions = []
assert isinstance(solutions, Set) # everything that I had tried resulted in a FiniteSet output
for solution in solutions.args: # loop through the different kinds of solutions
assert isinstance(solution, Tuple) # each solution should be a Tuple if in 2D or higher
list_of_numeric_values = [] # the list of lists of a single numerical value
for i, element in enumerate(solution):
if isinstance(element, Set):
numeric_values = list(element.intersect(domains[i]))
else: # assume it is an Expr
assert isinstance(element, Expr)
if _n.name in [s.name for s in element.free_symbols]: # if n is in the expression
# change our own _n to the solutions _n since they have different hidden
# properties and they cannot be substituted without having the same _n
_n = [s for s in element.free_symbols if s.name == _n.name][0]
numeric_values = [element.subs(_n, n)
for n in range(-10, 10) # just choose a bunch of sample values
if element.subs(_n, n) in domains[i]]
elif len(element.free_symbols) == 0: # we just have a single, numeric number
numeric_values = [element] if element in domains[i] else []
else: # otherwise we just have an Expr that depends on x or y
# we assume this numerical value is in the domain
numeric_values = [element]
# note that we may have duplicates, so we remove them with `set()`
list_of_numeric_values.append(set(numeric_values))
# find the resulting cartesian product of all our numeric_values
numeric_solutions += itertools.product(*list_of_numeric_values)
# remove duplicates again to be safe with `set()` but then retain ordering with `list()`
numeric_solutions = list(set(numeric_solutions))
print("--------`Expr` values----------")
for i in numeric_solutions:
print(list(i)) # turn it into a `list` since the output below is also a `list`.
print("--------`float` values---------")
for i in numeric_solutions:
print([N(j) for j in i]) # could have been converted into a `tuple` instead
In particular, it produces the following output for the new problem:
---------Solution set----------
FiniteSet((0, ImageSet(Lambda(_n, 2*_n*pi + 3*pi/2), Integers), 0))
--------`Expr` values----------
[0, -5*pi/2, 0]
[0, -pi/2, 0]
[0, 3*pi/2, 0]
--------`float` values---------
[0, -7.85398163397448, 0]
[0, -1.57079632679490, 0]
[0, 4.71238898038469, 0]
It was a lot of effort and probably not worth it but oh well.
By using solveset you can restrict the solutions with domain argument. For evaluating numerical results use .evalf() or another similar method.
from sympy import Interval, symbols, solveset, sin, cos, pi
x = symbols('x')
sol = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
print(sol)
print(sol.evalf())
Output
FiniteSet(-7*pi/4, -3*pi/4, pi/4, 5*pi/4)
FiniteSet(-5.49778714378214, -2.35619449019234, 0.785398163397448, 3.92699081698724)
I hope this helps!
Thanks to the brilliant suggestion from #kampmani it is possible to achieve the desired result.
For start, the FiniteSet elements are not indexed and cannot be used, so the FiniteSet has to be converted into a list:
solx_array = []
#
#
#
solx = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
solx_array=list(solx)
The next step is to find the y coordinate of the intersection point given its x coordinate. The final code should look somewhat similar to this:
from sympy import Interval, symbols, solveset, sin, cos, pi
sol_array = []
x = symbols('x')
solx = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
solx_array=list(solx)
for i in range(len(solx_array)):
soly = cos(solx_array[i])
sol_array.append(str(solx_array[i] + soly))
for i in range(len(sol_array)):
print(sol_array[i])
Still don't know how to convert the results into numerical form though, any idea is very appreciated.
I don't understand what indexed objects in sympy are for. The documentation didn't help me understand the concept much.
For instance :
>>> from sympy import symbols, IndexedBase, Idx
>>> M = IndexedBase('M')
>>> i, j = symbols('i j', cls=Idx)
>>> M[i, j]
M[i, j]
What does this code do? What is M[i,j]?
All I understand is that an indexed object gives indices to individual sympy symbols .
I'm looking for a better explanation of indexed objects , along with it's relation to IndexedBase and idx
One-line explanation: they represent a symbolic array of undetermined, possibly infinite, size.
Suppose you want to work with n symbols, how would you do that? Easy enough if n is a given number, like 10. But it's just n, an unspecified integer number. Formulas like that appear in mathematics all the time: "add or multiply (something) over the indices i=1, ..., n".
For example, suppose I have a function in n-dimensional space Rn, such as f(x) = 1/distance(x, 0). The distance is, of course, the square root of the sum of squares of coordinates. And maybe I want to find some partial derivative of f. How to express all of this in SymPy? Like this:
from sympy import *
x = IndexedBase('x')
j, k, n = symbols('j k n', cls=Idx)
f = 1/sqrt(Sum(x[k]**2, (k, 1, n)))
print(f.diff(x[j]))
This computes the derivative of f with respect to the coordinate x[j]. The answer is
-Sum(2*KroneckerDelta(j, k)*x[k], (k, 1, n))/(2*Sum(x[k]**2, (k, 1, n))**(3/2))
which is correct (although perhaps the numerator could be simplified if we assume that j is in the range 1..n).
In the above example, x[j] is the coordinate with index j. In your example, M[i, j] could be the entry of some matrix at position i, j.
M is the name of symbolic array, its class is IndexedBase
i and j are indices of that array, their class is Idx
The above are the classes that you would instantiate yourself. The class of M[i, j] is Indexed but you don't create those objects by using class name, M[i, j] simply does that.
Two recent questions with examples of working with indexed objects:
Create an unknown number of programmatically defined variables
Sum of partial derivatives of a product over a symbolic number of variables
Indexed is primarily used for two use-cases:
Formulas with symbolic subscripts. For example, \sum_{i=1}^n a_i. You could just use Symbol('a_i'), but them the i is not symbolic and in any way related to Symbol('i'). So for instance, Sum(a_i, (i, 1, n)) will just give you n*a_i. Instead IndexedBase('a')[i] represents a different symbol for every value of i, and Sum(IndexedBase('a')[i], (i, 1, n)) effectively represents the above summation.
N-d arrays. This is especially useful for code generation, because the SymPy code printers for languages like C or Fortran will print Indexed objects as array lookups automatically, for instance
>>> a = IndexedBase('a')
>>> i = Idx('i', (1, n))
>>> ccode(a[i])
'a[i]'
>>> fcode(a[i])
' a(i)'
This makes it very easy to write array-based code symbolically using SymPy and generate fast code that computes it.
I need to repeatedly evaluate a polynomial of the form
f(x)=c(0)+c(1)*x+...+c(k-1)*x^(k-1) mod p
where k is an integer, p is a large prime number and c(0),...,c(p) are between 1 and p.
For my applications, k=10, p should be greater than 1000.
I would prefer to do this in Python and as fast as possible. I don't know enough about modulo arithmetic in Python to implement this efficiently (e.g. how to exploit that we can use Mersenne primes p=2^q-1 in which case about should use that multiplication is a register shift, avoid trouble by adding integers over different orders of magnitude,...).
Motivation: k-independent hashing, see https://en.wikipedia.org/wiki/K-independent_hashing. This seems to a very popular academic subject but I was not able to find any implementations for k>2.
In general, you can compute the value of a polynomial using the following construction:
def value(poly, x):
"""Evaluates a polynomial POLY for a given x.
The polynomial is expressed as a list of coefficients, with
the coefficient for x ** N at poly[N].
This means that x ** 2 + 2*x + 3 is expressed as [3, 2, 1].
"""
v = 0
# Bit messy, but we're basically generating the indexes of
# our polynomial coefficients from highest to lowest
for coeff in reverse(poly):
v = v * x + coeff
return v
To evaluate this modulo a value, we can simply change the inner loop to v = v * x + poly[ix] % p (and pass our modulus as the parameter p).
We can show that the example polynom (x^2 + 2x + 3) is computed correctly by unwinding the loop and see that what we have is (((1) * x + 2) * x + 3) (each parenthesis level is one iteration through the loop), this can be simplified to 1 * x * x + 2 * x + 3, which is clearly the expected polynomial.
By using this, we should never end up with an intermediate value larger than p * x.
I am translating my code from Python to Mathematica. I am trying to define a matrix, whose values depend on a variable chosen by the user, called kappa.
In Python the code looked like that:
def getA(kappa):
matrix = zeros((n, n), float)
for i in range(n):
for j in range(n):
matrix[i][j] = 2*math.cos((2*math.pi/n)*(abs(j-i))*kappa)
n = 5
return matrix
What I have done so far in Mathematica is the following piece of code:
n = 5
getA[kappa_] :=
A = Table[0.0, {n}, {n}];
For[i = 0, i < n, i++,
For[ j = 0, j < n, j++,
A[[i, j]] = 2*Cos[(2*pi/n)*(abs (j - i))*kappa]]];
b = getA[3]
But when I try to evaluate this matrix for a value of kappa equal to 3, I get the following error:
Set::partd: "Part specification A[[i,j]] is longer than depth of object.
How can I fix it?
Try something like this
n = 5;
A = Table[2*Cos[(2 \[Pi]/n) (Abs[ j - i]) \[Kappa]], {i, 1, n}, {j, 1, n}];
b = A /. \[Kappa]->3
I'll leave you to package this into a function if you want to.
You write that you are trying to translate Python into Mathematica; your use of For loops suggests that you are trying to translate to C-in-Mathematica. The first rule of Mathematica club is don't use loops.
Besides that you've made a number of small syntactical errors, such as using abs() where you should have had Abs[] (Mathematica's built-in functions all have names beginning with a capital letter, they wrap their arguments in [ and ], not ( and )), pi is not the name of the value of the ratio of a circle's diameter to its radius (it's called \[Pi]). Note too that I've omitted the multiplication operator which is often not required.
In your particular case, this would be the fastest and the most straightforward solution:
getA[κ_, n_] := ToeplitzMatrix[2 Cos[2 π κ Range[0, n - 1] / n]]
I want to solve the following problem with python, if possible with sympy.
Let n be a fixed positive number. Let p=(p_1,...p_n) be a fixed known vector of positive integers. Let d be a fixed, known positive integer. Let q=(q_1,...,q_n) be a vector of unknown nonnegative integers.
How can I get all the solutions of p.q=d?
Where . means dot product.
Actually I can solve this for each individual n. But I want to create a function
def F(n,p,d):
...
return result
Such that result is a, e.g., list of all solutions. Note that from the restrictions made above, there is a finite number of solutions for each triplet of data (n,p,d).
I can't figure a way to do this, so any suggestion will be appreciated.
Added.
Example: suppose n=3 (the case n=2 is trivial), p=(2,1,3), d=3. Then I would do something like
res=[]
for i in range (d):
for j in range (d):
k=d-p[0]*i-p[2]*j
if k>=0:
res.append([i,k,j])
Then res=[[0, 3, 0], [0, 0, 1], [1, 1, 0]] which is correct.
As you can imagine, the bigger n is, the more for loops I need if I want to follow the same idea. So I do not think this is a good way to do it for arbitrary n, say n=57 or whatever big enough...
Following the algorithm you provided:
from itertools import product
dot = lambda X, Y: sum(x * y for x, y in zip(X, Y))
p = [1, 2, 3, ...] # Whatever fixed value you have for `p`
d = 100 # Fixed d
results = []
for q in product(range(0, d+1), repeat=len(p)):
if dot(p, q) == d:
results.append(q)
However this is slightly inefficient since it is possible to determine prior to computing the entire dot product, whether k will be positive. So let's define the dot product like this:
def dot(X, Y, d):
total = 0
for x, y in zip(X, Y):
total += x * y
if total > d:
return -1
return total
Now, as soon as the total exceeds d, the calculation exits. You can also express this as a list comprehension:
results = [q for q in product(range(0, d+1), repeat=len(p)) if dot(p, q, d) == d]