sympy - symbolic sum over symbolic number of elements
Asked Answered
E

2

9

What is the most appropriate way to express the following in SymPy:

A sum over samples 'x[i]' with 'i' going from concrete 0 to symbolic 'N'. 'x[i]' itself shall be symbolic, i.e. always appear as variable.

The goal is to use these expressions in a system of linear equations.

Example (trivial least squares approx.):

Given a set of samples (x[i], y[i]) which are supposed to lie on a line given by 'y = m*x + a'. That is, the estimated line is determined by 'm' and 'a'. The error between the samples and the estimated line may be given by

 error(m, a) = sum((m * x[i] + a - y[i]) ** 2, start_i=0, end_i=N)

Now, searching for the zero transitions in the derivatives 'd/dm error(m,a)' and 'd/da error(m,a)' delivers the minimal distance. How could I find the solution with sympy?

Evanesce answered 29/9, 2017 at 15:54 Comment(1)
Can you please edit your question to clarify: 1) I understand your situation such that the x[i] and N shall be abstract. How would your situation differ from solving a completely abstract linear equation system? Why do you need SymPy for this and what do you expect it to do for you? 2) If I misunderstood this somehow, why do the standard Python sum or sympy.Sum not work? — Ideally please give some example for the input, what you want to do with it, and what kind of result you would like to have.Lewis
Z
8

Given your later question, I assume you already figured most of it, but for clarity sake, samples are considered as function (makes sense, given sets are actually functions that cover the domain of the set [mostly over part of the integers]), so the notation is like x(i), and summation can be achieved with the summation function or Sum constructor (the first one is better, since it will expand automatically constant addends, like summation(x, (i, 0, n))).

>>> from sympy import *
>>> m, a, x, y, i, n = symbols('m a x y i n')
>>> err = summation((m * x(i) + a - y(i)) ** 2, (i, 0, n))
>>> pprint(err)
  n
 ___
 ╲
  ╲                      2
  ╱   (a + m⋅x(i) - y(i))
 ╱
 ‾‾‾
i = 0

After you provide the sum function the addend expression and the (index, lower bound, upper bound), you can move on to play with the sum:

>>> diff(err, m)
Sum(2*(a + m*x(i) - y(i))*x(i), (i, 0, n))
>>> diff(err, a)
Sum(2*a + 2*m*x(i) - 2*y(i), (i, 0, n))
Zea answered 2/10, 2017 at 11:36 Comment(3)
This throws a "TypeError: 'Symbol' object is not callable"Intrust
@Scott I wrote this answer almost 3 years ago. Maybe a newer version of sympy has deprecated default symbol subscription? (That'd be my first guess)Zea
@Scott m, a, i, n = symbols('m a x y i n') err, x, y = symbols('err x y', cls=Function) should fix the error.Fadeout
E
0

The actual solution is to used IndexedBased symbols and an integer symbol for the index of the summation, and the Sum instance with appropriate setup, i.e.

from sympy import symbols, IndexedBase, Sum, expand

x = IndexedBase('x')
y = IndexedBase('y')
n, m, a = symbols('n m a')
i = symbols('i', integer=True)

expr = Sum((m * x[i] + a - y[i]) ** 2, (i, 1, n)) 

From there, you can make any modifications as you would do on paper, namely for example:

print(expand(expr))
Evanesce answered 21/12, 2023 at 10:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.