Simplifying sums of symbolic min terms - python

I'm new to SymPy, so this might actually be easy, but I couldn't find anything in the documentation that quite matched. I'm trying to simplify the following expression:
>>> from sympy import *
>>> i, N = symbols('i N', integer=True, negative=False)
>>> summation(Min(N-8*i, 8), (i, 0, ceiling(N/8)-1)).simplify()
Sum(Min(8, N - 8*i), (i, 0, ceiling(N/8) - 1))
This could simplify to just N (and is true in general for a positive k, in place of 8). Is there some way I can get this to happen?

Related

Evaluating a sum in SymPy

I want to evaluate the sum
using Python and SymPy, I'm relatively new using SymPy and the first thing I tried was
from sympy import exp, oo, summation, symbols
n, x = symbols('n,x')
summation(exp(-n*x), (n, 1, oo))
But it doesn't work, it just returns the unevaluated sum.
I can make it work using
from sympy import exp, oo, summation, symbols
n, x = symbols('n,x')
f = exp(-x)
summation(x**(-n), (n, 1, oo)).subs(x,f)
But I would like to know if it is possible to make it work without need to break the expression into x^n and then substitute x by e^-x.
Thank you
Try using the following:
x , n = smp.symbols('x n')
smp.Sum(smp.exp(-n*x),(n, 1, smp.oo))

Is there a simple way to get all discontinuities of a function in a certain domain with sympy?

Given an expression in sympy, is there a way to find all discontinuities in a given interval? For instance, given 1/(x^2-1) from -2 to 2, it would return -1 and 1. It doesn't have to be symbolic. A numerical solution may actually work better for my purposes.
You can use the singularities module for this.
In [ ]: from sympy import *
In [ ]: init_printing()
In [ ]: x = symbols('x')
In [ ]: singularities(1/(x**2 - 1), x)
Out[ ]: (-1, 1) # A tuple of SymPy objects
Reference: http://docs.sympy.org/latest/modules/calculus/index.html#sympy.calculus.singularities.singularities
I don't think that there's any specific method in SymPy to do this; it might be very difficult to do in full generality (i.e. for any possible function, in any number of variables, including those with infinite discontinuities).
If you're working with relatively simple expressions in one real variable, such as the example in your question, then one approach could be to compute the expression as a ratio of two expressions and then solve the denominator expression.
>>> expr
1/(x**2 - 1)
>>> n, d = expr.as_numer_denom()
>>> sympy.solve(d)
[-1, 1]
Another small example:
>>> expr2 = 1/(sympy.sin(x)) + 4/(x**2 - 3)
>>> expr2
1/sin(x) + 4/(x - 3)
>>> n, d = expr2.as_numer_denom()
>>> sympy.solve(d)
[0, -sqrt(3), sqrt(3), pi]
Obviously in this case SymPy does not list every multiple of pi as a solution; you'll have to process the list to generate solutions that lie in your desired domain.

Symbolic conditional sum

Is there a way to calculate, or at least state properly, a symbolic sum which iterates over a sequence conditionally?
For example, if a(n) is a sequence (of reals) and c(n) is a "condition" (boolean function defined on the integers), then I wish to compute, or at least state, the sum over all a(n)'s for which c(n).
Formally, I'd like to do something like this:
n = Symbol('n', integer=True, positive=True)
a = 1 / n**2
c = Eq(n%3, 1)
## s = Sum(a, (n, 0, oo), condition=c)
So s should be the following sum:
1/1 + 1/16 + 1/49 + 1/100 + 1/169 + ...
Of course, in this case I can define s manually, but I wonder whether I can do it automatically somehow.
Edit:
By manually I mean
Sum(1/(3*n+1)**2, (n, 0, oo))
This can be evaluated (and it is about 1.12173301393634).
An attempt I've made (which failed) is as follows:
Sum(Eq(n%3, 1) * (1/n**2), (n, 0, oo))
Trying to evaluate this using .evalf() resulted
AttributeError: 'BooleanFalse' object has no attribute '_eval_evalf'
Edit (2):
Here's another attempt, which yields a wrong result:
p = Piecewise((1/(n**2), Eq(n%3, 1)), (0, True))
Sum(p, (n, 0, oo)).evalf()
## returns 1.00000000000000
Either I've done something wrong, or this is a sympy bug.
Using a Piecewise is definitely the correct way to do this. The wrong result is a bug in SymPy, which you should report at https://github.com/sympy/sympy/issues/new. Your second method won't work because in SymPy booleans are not implicitly integers (True and False are not 1 and 0).
Or avoid piecewise by defining your function as 1/(3*n+1)**2
>>> Sum((3*n + 1)**(-2), (n, 0, oo))
Sum((3*n + 1)**(-2), (n, 0, oo))
>>> print filldedent(_.doit())
exp(-4*I*pi/3)*polylog(2, exp_polar(4*I*pi/3))/3 + pi**2/18 +
exp(-2*I*pi/3)*polylog(2, exp_polar(2*I*pi/3))/3
>>> Sum((3*n + 1)**(-2), (n, 0, oo)).n()
1.12173301393634
You can see that the remapping works by using Symbol-trickery. e.g. the 1st 6 terms:
>>> Add(*[(1/n).subs(n,Symbol(str((3*i+1)**2))) for i in range(5)])
1/49 + 1/169 + 1/16 + 1/100 + 1/1
If it's a linear sequence then you could use Integal's transform method to do the transformation for you:
>>> i=Integral(1/x**2,(x,1,oo))
>>> i.transform(x,3*x - 2)
Integral(3/(3*x - 2)**2, (x, 1, oo))
>>> (Sum(*_.args)/3).n(3) # divide by 3 to handle renorm
1.12

Manual fft not giving me same results as fft

import numpy as np
import matplotlib.pyplot as pp
curve = np.genfromtxt('C:\Users\latel\Desktop\kool\Neuro\prax2\data\curve.csv',dtype = 'float', delimiter = ',')
curve_abs2 = np.empty_like(curve)
z = 1j
N = len(curve)
for i in range(0,N-1):
curve_abs2[i] =0
for k in range(0,N-1):
curve_abs2[i] += (curve[i]*np.exp((-1)*z*(np.pi)*i*((k-1)/N)))
for i in range(0,N):
curve_abs2[i] = abs(curve_abs2[i])/(2*len(curve_abs2))
#curve_abs = (np.abs(np.fft.fft(curve)))
#pp.plot(curve_abs)
pp.plot(curve_abs2)
pp.show()
The code behind # gives me 3 values. But this is just ... different
Wrong ^^ this code: http://www.upload.ee/image/3922681/Ex5problem.png
Correct using numpy.fft.fft(): http://www.upload.ee/image/3922682/Ex5numpyformulas.png
There are several problems:
You are assigning complex values to the elements of curve_abs2, so it should be declared to be complex, e.g. curve_abs2 = np.empty_like(curve, dtype=np.complex128). (And I would recommend using the name, say, curve_fft instead of curve_abs2.)
In python, range(low, high) gives the sequence [low, low + 1, ..., high - 2, high - 1], so instead of range(0, N - 1), you must use range(0, N) (which can be simplified to range(N), if you want).
You are missing a factor of 2 in your formula. You could fix this by using z = 2j.
In the expression that is being summed in the inner loop, you are indexing curve as curve[i], but this should be curve[k].
Also in that expression, you don't need to subtract 1 from k, because the k loop ranges from 0 to N - 1.
Because k and N are integers and you are using Python 2.7, the division in the expression (k-1)/N will be integer division, and you'll get 0 for all k. To fix this and the previous problem, you can change that term to k / float(N).
If you fix those issues, when the first double loop finishes, the array curve_abs2 (now a complex array) should match the result of np.fft.fft(curve). It won't be exactly the same, but the differences should be very small.
You could eliminate that double loop altogether using numpy vectorized calculations, but that is a topic for another question.

Mathematica to Python

How can this Mathematica code be ported to Python? I do not know the Mathematica syntax and am having a hard time understanding how this is described in a more traditional language.
Source (pg 5): http://subjoin.net/misc/m496pres1.nb.pdf
This cannot be ported to Python directly as the definition a[j] uses the Symbolic Arithmetic feature of Mathematica.
a[j] is basically the coefficient of xj in the series expansion of that rational function inside Apart.
Assume you have a[j], then f[n] is easy. A Block in Mathematica basically introduces a scope for variables. The first list initializes the variable, and the rest is the execution of the code. So
from __future__ import division
def f(n):
v = n // 5
q = v // 20
r = v % 20
return sum(binomial(q+5-j, 5) * a[r+20*j] for j in range(5))
(binomial is the Binomial coefficient.)
Using the proposed solutions from the previous answers I found that sympy sadly doesn't compute the apart() of the rational immediatly. It somehow gets confused. Moreover, the python list of coefficients returned by *Poly.all_coeffs()* has a different semantics than a Mathmatica list. Hence the try-except-clause in the definition of a().
The following code does work and the output, for some tested values, concurs with the answers given by the Mathematica formula in Mathematica 7:
from __future__ import division
from sympy import expand, Poly, binomial, apart
from sympy.abc import x
A = Poly(apart(expand(((1-x**20)**5)) / expand((((1-x)**2)*(1-x**2)*(1-x**5)*(1-x**10))))).all_coeffs()
def a(n):
try:
return A[n]
except IndexError:
return 0
def f(n):
v = n // 5
q = v // 20
r = v % 20
return sum(a[r+20*j]* binomial(q+5-j, 5) for j in range(5))
print map(f, [100, 50, 1000, 150])
The symbolics can be done with sympy. Combined with KennyTM's answer, something like this might be what you want:
from __future__ import division
from sympy import Symbol, apart, binomial
x = Symbol('x')
poly = (1-x**20)**5 / ((1-x)**2 * (1-x**2) * (1-x**5) * (1-x**10))
poly2 = apart(poly,x)
def a(j):
return poly2.coeff(x**j)
def f(n):
v = n // 5
q = v // 20
r = v % 20
return sum(binomial(q+5-j, 5)*a(r+20*j) for j in range(5))
Although I have to admit that f(n) does not work (I'm not very good at Python).

Categories

Resources