How to write dual Lagrange equation in Python using sympy? - python

from sympy import symbols
import numpy as np
x = np.array([[0.466,0,0,0,0,-0.466,0,0,0,0,0.466,0,0,0,0,0.590], [0.377,0,0,0,0,-0.377,0,0,0,0,0.377,0,0,0,0,0.755], [0.18,0,0,0,0,-0.18,0,0,0,0,0.18,0,0,0,0,0.949]])
y = np.array([-1, -1, 1])
def lagrange_dual(x, t):
result = 0
alpha = symbols('alpha')
for i in range(3):
for k in range(3):
result = result + alpha[i]*alpha[k]*t[i]*t[k]*np.dot(x[i, :], x[k, :])
result = 0.5*result - sum(alpha)
return result
print(lagrange_dual(x, y))
I'm trying to write the Lagrange form of svm in python but I get this error how can I solve it?
TypeError Traceback (most recent call last)
<ipython-input-59-372723adcf7d> in <module>
32
33 return result
---> 34 print(lagrange_dual(dat, labels))
35
36
<ipython-input-59-372723adcf7d> in lagrange_dual(x, t)
28 for i in range(3):
29 for k in range(3):
---> 30 result = result + alpha[i]*alpha[k]*t[i]*t[k]*np.dot(x[i, :], x[k, :])
31 result = 0.5*result - sum(alpha)
32
TypeError: 'Symbol' object is not subscriptable
the main goal is to achieve out put of this function for n data

I believe that this should give you what you were looking for.
Here is the expression:
import sympy as sp
import numpy as np
x = np.array([[0.466,0,0,0,0,-0.466,0,0,0,0,0.466,0,0,0,0,0.590], [0.377,0,0,0,0,-0.377,0,0,0,0,0.377,0,0,0,0,0.755], [0.18,0,0,0,0,-0.18,0,0,0,0,0.18,0,0,0,0,0.949]])
t = np.array([-1, -1, 1]) # not sure what this was for?
y = _ ### define y
a = _ ### define alpha
m = _ ### define m
# define the sympy symbols
m_sym = sp.Symbol("m")
i, j = sp.symbols("i j", cls=sp.Idx)
a_sym = sp.IndexedBase("a")
x_sym = sp.MatrixSymbol("x", x.shape[0], x.shape[1])
y_sym = sp.IndexedBase("y")
# define the expression
expr = sp.Sum(a_sym[i], (i, 0, m_sym)) - 0.5 * sp.Sum(
sp.Sum(
a_sym[i] * a_sym[j] * y_sym[i] * y_sym[j] *
sp.DotProduct(x_sym[i, :], x_sym[j, :]),
(i, 1, m_sym),
),
(j, 1, m_sym),
)
Then if we print the expression, we get:
>>> sp.pprint(expr)
m m m
___ ___ ___
╲ ╲ ╲
╲ ╲ ╲
╱ a[i] - 0.5⋅ ╱ ╱ a[i]⋅a[j]⋅y[i]⋅y[j]⋅x[i:i + 1, :]⋅x[j:j + 1, :]
╱ ╱ ╱
‾‾‾ ‾‾‾ ‾‾‾
i = 1 j = 1 i = 1
You can then turn this expression into a function and evaluate it using sp.lambdify. I don't have your variables for evaluation, so I'm just going to fill it with the dummy variables that I created above.
func = sp.lambdify((a_sym, x_sym, y_sym, m), expr)
func(a, x, y, m) # will produce your answer

To put it shortly, the error means one of the items you're trying to call isn't an array. Try adding each item in the equation seperately, so you can see what the issue is. Ex: AlphaI = alpha[i], etc.
Only add/multiply at the end.
Hope this helps!

Related

Is there a way to calculate the half range Fourier series in SymPy?

For example, if I want the Fourier series of the function f(x) = x(π-x) on [0, π], I can calculate the coefficients of the sine series:
which works by considering f(x) in a half range Fourier series, the half interval [0, π] extended to [-π, 0] by taking the extension of f(x) to be an odd function (so I don't need the cosine terms in the full Fourier series expansion).
Using SymPy, however, I get a cosine series:
import sympy as sp
x = sp.symbols('x', real=True)
f = x * (sp.pi - x)
s = sp.fourier_series(f, (x, 0, sp.pi))
s.truncate(4)
-cos(2*x) - cos(4*x)/4 - cos(6*x)/9 + pi**2/6
Even constructing a Piecewise function with the correct parity doesn't work:
p = sp.Piecewise((-f, x < 0), (f, x >= 0))
ps = sp.fourier_series(p, (x, 0, sp.pi))
ps.truncate(4)
-cos(2*x) - cos(4*x)/4 - cos(6*x)/9 + pi**2/6
The cosine series sort-of approximates f(x) but not nearly as well as the sine one. Is there any way to force SymPy to do what I did with paper and pen?
Integrating directly as proposed in the first answer by #Oscar is a simple solution.
It is interesting anyway to understand why your approach is not working.
To get an odd function, for negative x values, we need to use
fneg = x * (sp.pi + x) (= -f(-x))
Then, to calculate the coefficients, you need to integrate from -PI to PI.
Code
import sympy as sp
x = sp.symbols('x', real=True)
f = x * (sp.pi - x)
fneg = x * (sp.pi + x)
p = sp.Piecewise((fneg, x < 0), (f, x >= 0))
ps = sp.fourier_series(p, (x, -sp.pi, sp.pi))
print ('ps = ', ps.truncate(4))
Result:
ps = 8*sin(x)/pi + 8*sin(3*x)/(27*pi) + 8*sin(5*x)/(125*pi) + 8*sin(7*x)/(343*pi)
You can compute the series coefficients directly:
In [52]: f
Out[52]: x⋅(π - x)
In [53]: n = symbols('n', integer=True)
In [54]: bn = 2/pi*integrate(f*sin(n*x), (x, 0, pi))
In [55]: bn
Out[55]:
⎛⎧ n ⎞
⎜⎪ 2⋅(-1) 2 ⎟
⎜⎪- ─────── + ── for n ≠ 0⎟
2⋅⎜⎨ 3 3 ⎟
⎜⎪ n n ⎟
⎜⎪ ⎟
⎝⎩ 0 otherwise⎠
──────────────────────────────
π
In [56]: f_approx = summation(bn*sin(n*x), (n, 0, 5))
In [57]: f_approx
Out[57]:
8⋅sin(x) 8⋅sin(3⋅x) 8⋅sin(5⋅x)
──────── + ────────── + ──────────
π 27⋅π 125⋅π
In [58]: plot(f_approx, f, (x, -pi, 2*pi))

How to solve an equation that contains sigma sum to find the upper limit of sigma in Python

I want to find an integer value from a sigma contained equation with two variables like this post
where x (a real decimal value) range is between two limits e.g. known_xmin_value <= x < known_xmax_value. 1 is the lower limit of k (which is the integer) but don't know the upper limit (which is the goal to be derived from the solution); Perhaps just could be guess that it will be lower than 2000000. Is it possible to find the integer for k? How?
from sympy import Sum, solve
from sympy.abc import k, x
known_value = 742.231 # just for example
known_xmin_value = 3.652 # just for example
solve(-known_value + Sum((x + (k - 1) * (x - known_xmin_value)) ** 3, (k, 1, integer_unknown_limit)), x)
SymPy can compute the sum symbolically:
from sympy import *
from sympy import Sum, solve
from sympy.abc import k, x, y
# Use exact rational numbers
known_value = Rational('742.231') # just for example
known_xmin_value = Rational('3.652') # just for example
sum_value = Sum((x + (k - 1) * (x - known_xmin_value)) ** 3, (k, 1, y))
This is the summation and its result computed using doit:
In [22]: sum_value
Out[22]:
y
____
╲
╲ 3
╲ ⎛ ⎛ 913⎞⎞
╱ ⎜x + (k - 1)⋅⎜x - ───⎟⎟
╱ ⎝ ⎝ 250⎠⎠
╱
‾‾‾‾
k = 1
In [23]: sum_value.doit()
Out[23]:
⎛ 2 ⎞ ⎛ 2 ⎞ ⎛ 3 2 ⎞ ⎛ 4 3 2⎞ ⎛ 2 ⎞
761048497⋅y ⎛2500707⋅x 2283145491⎞ ⎜y y⎟ ⎜2739⋅x 2500707⋅x 2283145491⎟ ⎜y y y⎟ ⎜y y y ⎟ ⎜ 3 2739⋅x 2500707⋅x 761048497⎟
─────────── + ⎜───────── - ──────────⎟⋅⎜── + ─⎟ + ⎜─────── - ───────── + ──────────⎟⋅⎜── + ── + ─⎟ + ⎜── + ── + ──⎟⋅⎜x - ─────── + ───────── - ─────────⎟
15625000 ⎝ 62500 15625000 ⎠ ⎝2 2⎠ ⎝ 250 31250 15625000 ⎠ ⎝3 2 6⎠ ⎝4 2 4 ⎠ ⎝ 250 62500 15625000⎠
This is a quartic polynomial in y so the equation can be solved explicitly in radicals giving 4 symbolic expressions for the roots:
In [24]: s1, s2, s3, s4 = solve(sum_value.doit() - known_value, y)
In [25]: print(s1)
(-250*x*sqrt(62500*x**2/(62500*x**2 - 456500*x + 833569) - 456500*x/(62500*x**2 - 456500*x + 833569) - 1000*sqrt(833569*x**2 + 185557750*x - 677656903)/(62500*x**2 - 456500*x + 833569) + 833569/(62500*x**2 - 456500*x + 833569)) - 250*x + 913*sqrt(62500*x**2/(62500*x**2 - 456500*x + 833569) - 456500*x/(62500*x**2 - 456500*x + 833569) - 1000*sqrt(833569*x**2 + 185557750*x - 677656903)/(62500*x**2 - 456500*x + 833569) + 833569/(62500*x**2 - 456500*x + 833569)) - 913)/(500*x - 1826)
For any particular value of x probably none of these 4 roots will be equal to an integer though.
Since you are looking for a numerical solution, a naive approach would be a brute force over a set of integer_unknown_limit and use numerical root finding algorithms. For example:
from sympy import *
from scipy.optimize import root
import matplotlib.pyplot as plt
x, k, integer_unknown_limit = symbols("x, k, u")
known_value = 742.231 # just for example
known_xmin_value = 3.652 # just for example
expr = -known_value + Sum((x + (k - 1) * (x - known_xmin_value)) ** 3, (k, 1, integer_unknown_limit))
f = lambdify([x, integer_unknown_limit], expr)
res = {}
# NOTE: this loop may take a few minutes, depending on the machine.
# I suggest to lower the upper limit
for ul in range(1, 1000):
print(ul)
try:
r = root(f, 2, args=(ul,))
if r.success:
res[ul] = r.x[0]
except:
pass
plt.figure()
plt.plot(list(res.keys()), res.values())
plt.xlabel("u (upper limit)")
plt.ylabel("x where f(x)=0")
plt.title("f(x) = $%s$" % latex(expr))
plt.show()
As you can see, for each upper limit value in the considered subset, the expression is satisfied at some value of x.
EDIT: note that the same can be done with sympy's nsolve. Just replace the for loop with:
for ul in range(1, 1000):
print(ul)
try:
res[ul] = nsolve(expr.subs(integer_unknown_limit, ul), x, 1)
except:
pass

The diff function in sympy doesn't return a number?

I'm a newbie learning python. I have a question, can you guys help me? This is my code:
from sympy import *
def test(f, g, a):
f1 = f.subs(x, g)
df1 = diff(f1, x).subs(x, a)
return df1
print(test((2*(x**2) + abs(x + 1)), (x - 1), -1))
Result: -Subs(Derivative(re(x), x), x, -1) - 8
I'm taking the derivative of f(g(x)) with: f = 2(x^2) + abs(x + 1), g = x - 1 and x = -1. When I use diff to calculate the result is -Subs(Derivative(re(x), x), x, -1) - 8, but when I use the formula lim x->x0 (f(x) - f(x0))/(x - x0) I got result is -9. I also tried using a calculator to calculate and the result -9 is the correct result. Is there a way to make diff return -9? Anyone have any help or can give some pointers?
Thanks!
Whenever I see a re or im appear when I didn't expect them, I am inclined to make the symbols real:
>>> from sympy import *
>>> def test(f, g, a):
... f1 = f.subs(x, g)
... df1 = diff(f1, x).subs(x, a)
... return df1
...
>>> var('x',real=True)
x
>>> print(test((2*(x**2) + abs(x + 1)), (x - 1), -1))
-9
Since I'm still a relative beginner to sympy I like to view intermediate results (I even like to do that with numpy which I know much better). Running in isympy:
In [6]: diff(f1,x)
Out[6]:
⎛ d d ⎞
⎜re(x)⋅──(re(x)) + im(x)⋅──(im(x))⎟⋅sign(x)
⎝ dx dx ⎠
4⋅x - 4 + ───────────────────────────────────────────
x
That expression contains unevaluate d/dx and the distinction between the real and imaginary parts of x.
Restricting x to real as suggested in the other answer produces:
In [19]: diff(exp,x)
Out[19]: 4⋅x + sign(x + 1)

Is it possible to force SymPy to either compute an integral, or tell me why it cannot compute the integral?

I'm trying to compute the integral, specifically, the Laplace transform, of a piecewise function.
w_k = k*t, 0 <= t <= 1/k
1, otherwise
So I attempted to integrate it as follows:
from sympy import *
t, k = symbols('t k', positive=True)
w_k = Piecewise((k*t, (0 <= t)&(t <= 1/k)), (1, True))
integrate(w_k * exp(-s*t), (t, 0, oo)).doit()
Out:
∞
⌠
⎮ ⎧ -s⋅t 1
⎮ ⎪k⋅t⋅ℯ for t ≤ ─
⎮ ⎪ k
⎮ ⎨ dt
⎮ ⎪ -s⋅t
⎮ ⎪ ℯ otherwise
⎮ ⎩
⌡
0
Using laplace_transform gives me the same result.
I'm aware that sometimes certain conditions need to be fulfilled for the function to be possible to integrate by SymPy, but I'm really not sure what other than the positive variables is needed for this function. Is there any way to force SymPy to either compute the integral, or explain why it isn't possible?
Try this:
import math
from sympy import *
s = Symbol('s', positive=True)
t = Symbol('t', positive=True)
k = Symbol('k', positive=True)
function = Piecewise((k*t, (0 <= t)&(t <= 1/k)), (1, True))
result = integrate(function * exp(-s*t), (t, 0, math.inf))
Output:
k/s**2 + exp(-s/k)/s + (-k - s)*exp(-s/k)/s**2

Unexpected result in integral calculation

Basically not getting the expected result,
I am getting the following
exp(-infinity*sign(a**2)))
I tried the following
from sympy import *
import sympy as sp
x = sp.Symbol('x')
a = sp.Symbol('a')
def f(x,a):
return (a-x)**2/(a**2)
sp.exp(-1*sp.integrate(f(x,a),(x,0,oo)))
Result should be
(3a**2 - 3*a + 1)/(3a**2)
I don't know why you expect a finite result here:
In [20]: Integral((a-x)**2, (x, 0 ,oo))
Out[20]:
∞
⌠
⎮ 2
⎮ (a - x) dx
⌡
0
In [21]: Integral((a-x)**2, (x, 0 ,oo)).doit()
Out[21]: ∞

Categories