Rewriting a symbolic expression as linear combination of others - sympy

I am trying to solve something which may not actually be too complicated (mathematically), but I'm a bit lost and want to do this wich SymPy's aid. I
Given are two variables X, Y (these are symbolic, I do not have access to any values) and known constants a, b, ..., g. In a piece of existing software that I cannot change, from these
X' = a * X + b
Y' = c * Y + d
Z' = e * X * Y + f
are calculated. In another different piece of existing software that I cannot change,
I have different values, a similar calculation is done. I am greatly simplifying this for purposes of this question, but to get the idea:
X' and Y' like above
Z_ = (a * x + b) * ( c * y + d) - g
To bridge between Z' and Z_, I want to express z_ as a linear combination of X', Y', Z', and 1:
Z_ == 𝛂 * X' + 𝛃 * Y' + 𝛄 * Z' + 𝛅.
How can I solve this for 𝛂, 𝛃, 𝛄, 𝛅 with Sympy?
I know I could probably avoid Sympy, expressing each of the variables X', Y', Z', Z_ as linear combinations of X, Y, X*Y, and 1, and doing matrix algebra But since my problem actually is more complicated and its details likely to change in the future, I would really appreciate some software assistance.

Related

Convert a Sage multivariate polynomial into a univariate one

I am trying to implement Schoof's algorithm in Sage.
I have multivariate polynomials f(x, y) with coefficients in
a finite field F_q, for which the variable y only appears
in even powers (for example f(x, y) = x * y^4 + x^3 * y^2 + x).
Furthermore, using an equation y^2 = x^3 + A * x + B,
I want to replace powers of y^2 in the polynomial with
corresponding powers of x^3 + A * x + B,
so that the polynomial depends only on x.
My idea was this:
J = ideal(f, y ** 2 - (x ** 3 + A * x + B))
f = R(J.elimination_ideal(y).gens()[0])
(R is a univariate polynomial ring).
My problem is, sometimes it works, sometimes it does not
(I don't know why).
Is there a better solution or standard solution?
For counting points on elliptic curves,
the following resources might be useful:
SageMath constructions: algebraic geometry: point couting on curves
SageMath thematic tutorial on Schoof-Elkies-Atkin point counting
Regarding polynomials, consider providing
an example that works and one that fails.
That might help analyse the problem and answer the question.
Note that Ask Sage
has more experts ready to answer SageMath questions.

get coefficient of a monomial in a sympy expression

I have a sympy expression like so:
exp_str = '3 * x**2*y + 4*a**2 * x*y + 9*b * x'
my_expr = sp.parsing.sympy_parser.parse_expr(exp_str)
and I want to get the coefficient of x*y, which should be 4*a**2.
Is there a function that I can pass my_expr to along with a list of variables I want my polynomial to be over? For example, I would need to pass this function x and y so that it knows x and y are variables and that a and b are coefficients.
If there is no such function, and recommendations on how to write code to do this would be appreciated. Thanks
There is a coeff method of sympy expressions:
In [28]: x, y, a, b = symbols('x, y, a, b')
In [29]: expr = 3 * x**2*y + 4*a**2 * x*y + 9*b * x
In [30]: expr.coeff(x*y)
Out[30]:
2
4⋅a
https://docs.sympy.org/latest/modules/core.html?highlight=coeff#sympy.core.expr.Expr.coeff
You might find it useful though to work with expressions as structured polynomials e.g.:
In [31]: p = Poly(expr, [x, y])
In [32]: p
Out[32]: Poly(3*x**2*y + 4*a**2*x*y + 9*b*x, x, y, domain='ZZ[a,b]')
In [33]: p.coeff_monomial(x**2 * y)
Out[33]: 3
In [34]: p.coeff_monomial(x * y)
Out[34]:
2
4⋅a
https://docs.sympy.org/latest/modules/polys/basics.html

Using Sympy to Solve Inverse Kinematic

I want to solve simple 2D inverse kinematic problem with Sympy. I know forward kinematic equation of x and y position.
x = l1*cos(theta1) + l2*cos(theta1+theta2)
y = l1*sin(theta1) + l2*sin(theta1+theta2)
How to solve theta1 and theta2 value with Sympy if I know those two equations?
I don't think there is a solution to those equations, but if there were you could use the follwing method:
import sympy as sp
# Define symbols
theta1, theta2, l1, l2, x, y = sp.symbols("theta1 theta2 l1 l2 x y")
# Define equations, rearranged so expressions equal 0
eq1 = l1 * sp.cos(theta1) + l2 * sp.cos(theta1 + theta2) - x
eq2 = l1 * sp.sin(theta1) + l2 * sp.sin(theta1 + theta2) - y
# Solve for theta1 & theta2
solution = sp.solve([eq1, eq2], [theta1, theta2], dict=True)
print(solution)
I was trying to use the sympy nonlinsolve solver for a similar inverse kinematics problem but noticed this comment in the docs:
Currently nonlinsolve is not properly capable of solving the system of equations having trigonometric functions. solve can be used for such cases (but does not give all solution)

Why my Gradient is wrong (Coursera, Logistic Regression, Julia)?

I'm trying to do Logistic Regression from Coursera in Julia, but it doesn't work.
The Julia code to calculate the Gradient:
sigmoid(z) = 1 / (1 + e ^ -z)
hypotesis(theta, x) = sigmoid(scalar(theta' * x))
function gradient(theta, x, y)
(m, n) = size(x)
h = [hypotesis(theta, x[i,:]') for i in 1:m]
g = Array(Float64, n, 1)
for j in 1:n
g[j] = sum([(h[i] - y[i]) * x[i, j] for i in 1:m])
end
g
end
If this gradient used it produces the wrong results. Can't figure out why, the code seems like the right one.
The full Julia script. In this script the optimal Theta calculated using my Gradient Descent implementation and using the built-in Optim package, and the results are different.
The gradient is correct (up to a scalar multiple, as #roygvib points out). The problem is with the gradient descent.
If you look at the values of the cost function during your gradient descent, you will see a lot of NaN,
which probably come from the exponential:
lowering the step size (e.g., to 1e-5) will avoid the overflow,
but you will have to increase the number of iterations a lot (perhaps to 10_000_000).
A better (faster) solution would be to let the step size vary.
For instance, one could multiply the step size by 1.1
if the cost function improves after a step
(the optimum still looks far away in this direction: we can go faster),
and divide it by 2 if it does not (we went too fast and ended up past the minimum).
One could also do a line search in the direction of the gradient to find the best step size
(but this is time-consuming and can be replaced by approximations, e.g., Armijo's rule).
Rescaling the predictive variables also helps.
I tried comparing gradient() in the OP's code with numerical derivative of cost_j() (which is the objective function of minimization) using the following routine
function grad_num( theta, x, y )
g = zeros( 3 )
eps = 1.0e-6
disp = zeros( 3 )
for k = 1:3
disp[:] = theta[:]
disp[ k ]= theta[ k ] + eps
plus = cost_j( disp, x, y )
disp[ k ]= theta[ k ] - eps
minus = cost_j( disp, x, y )
g[ k ] = ( plus - minus ) / ( 2.0 * eps )
end
return g
end
But the gradient values obtained from the two routines do no seem to agree very well (at least for the initial stage of minimization)... So I manually derived the gradient of cost_j( theta, x, y ), from which it seems that the division by m is missing:
#/ OP's code
# g[j] = sum( [ (h[i] - y[i]) * x[i, j] for i in 1:m ] )
#/ modified code
g[j] = sum( [ (h[i] - y[i]) * x[i, j] for i in 1:m ] ) / m
Because I am not very sure if the above code and expression are really correct, could you check them by yourself...?
But in fact, regardless of whether I use the original or corrected gradients, the program converges to the same minimum value (0.2034977016, almost the same as obtained from Optim), because the two gradients differ only by a multiplicative factor! Because the convergence was very slow, I also modified the stepsize alpha adaptively following the suggestion by Vincent (here I used more moderate values for acceleration/deceleration):
function gradient_descent(x, y, theta, alpha, n_iterations)
...
c = cost_j( theta, x, y )
for i = 1:n_iterations
c_prev = c
c = cost_j( theta, x, y )
if c - c_prev < 0.0
alpha *= 1.01
else
alpha /= 1.05
end
theta[:] = theta - alpha * gradient(theta, x, y)
end
...
end
and called this routine as
optimal_theta = gradient_descent( x, y, [0 0 0]', 1.5e-3, 10^7 )[ 1 ]
The variation of cost_j versus iteration steps is plotted below.

Finding Y given X on a Cubic Bezier Curve?

I need a method that allows me to find the Y-coordinate on a Cubic Bezier Curve, given an x-coordinate.
I've come across lots of places telling me to treat it as a cubic function then attempt to find the roots, which I understand. HOWEVER the equation for a Cubic Bezier curve is (for x-coords):
X(t) = (1-t)^3 * X0 + 3*(1-t)^2 * t * X1 + 3*(1-t) * t^2 * X2 + t^3 * X3
What confuses me is the addition of the (1-t) values. For instance, if I fill in the X values with some random numbers:
400 = (1-t)^3 * 100 + 3*(1-t)^2 * t * 600 + 3*(1-t) * t^2 * 800 + t^3 * 800
then rearrange it:
800t^3 + 3*(1-t)*800t^2 + 3*(1-t)^2*600t + (1-t)^3*100 -400 = 0
I still don't know the value of the (1-t) coefficients. How I am I supposed to solve the equation when (1-t) is still unknown?
There are three common ways of expressing a cubic bezier curve.
First x as a function of t
x(t) = sum( f_i(t) x_i )
= (1-t)^3 * x0 + 3*(1-t)^2 * t * x1 + 3*(1-t) * t^2 * x2 + t^3 * x3
Secondly y as a function of x
y(x) = sum( f_i(x) a_i )
= (1-x)^3 * y0 + 3*(1-x)^2 * x * y1 + 3*(1-x) * x^2 * y2 + x^3 * y3
These first two are mathematically the same, just using different names for the variables.
Judging by your description "find the Y-coordinate on a Cubic Bezier Curve, given an x-coordinate on it." I'm guessing that you've got a question using the second equation are are trying to rearrange the first equation to help you solve it, where as you should be using the second equation. If thats the case, then no rearranging or solving is required - just plug your x value in and you have the solution.
Its possible that you have an equation of the third kind case, which is the ugly and hard case.
This is both the x and y parameters are cubic Beziers of a third variable t.
x(t) = sum( f_i(t) x_i )
y(t) = sum( f_i(t) y_i )
If this is your case. Let me know and I can detail what you need to do to solve it.
I think this is a fair CS question, so I'm going to attempt to show how I solved this. Note that a given x may have more than 1 y value associated with it. In the case where I needed this, that was guaranteed not to be the case, so you'll have to figure out how to determine which one you want.
I iterated over t generating an array of x and y values. I did it at a fairly high resolution for my purposes. (I was looking to generate an 8-bit look-up table, so I used ~1000 points.) I just plugged t into the bezier equation for the next x and the next y coordinates to store in the array. Once I had the entire thing generated, I scanned through the array to find the 2 nearest x values. (Or if there was an exact match, used that.) I then did a linear interpolation on that very small line segment to get the y-value I needed.
Developing the expression further should get you rid of the (1 - t) factors
If you run:
expand(800*t^3 + 3*(1-t)*800*t^2 + 3*(1-t)^2*600*t + (1-t)^3*100 -400 = 0);
In either wxMaxima or Maple (you have to add the parameter t in this one though), you get:
100*t^3 - 900*t^2 + 1500*t - 300 = 0
Solve the new cubic equation for t (you can use the cubic equation formula for that), after you got t, you can find x doing:
x = (x4 - x0) * t (asuming x4 > x0)
Equation for Bezier curve (getting x value):
Bx = (-t^3 + 3*t^2 - 3*t + 1) * P0x +
(3*t^3 - 6*t^2 + 3*t) * P1x +
(-3*t^3 + 3*t^2) * P2x +
(t^3) * P3x
Rearrange in the form of a cubic of t
0 = (-P0x + 3*P1x - 3*P2x + P3x) * t^3+
(3*P0x - 6*P1x + 3*P2x) * t^2 +
(-3*P0x + 3*P1x) * t +
(P0x) * P3x - Bx
Solve this using the cubic formula to find values for t. There may be multiple real values of t (if your curve crosses the same x point twice). In my case I was dealing with a situation where there was only ever a single y value for any value of x. So I was able to just take the only real root as the value of t.
a = -P0x + 3.0 * P1x - 3.0 * P2x + P3x;
b = 3.0 * P0x - 6.0 * P1x + 3.0 * P2x;
c = -3.0 * P0x + 3.0 * P1x;
d = P0x;
t = CubicFormula(a, b, c, d);
Next put the value of t back into the Bezier curve for y
By = (1-t)^3 * P0x +
3t(1-t)^2 * P1x +
3t^2(1-t) * P2x +
t^3 * P3x
So I've been looking around for some sort of method to allow me to find the Y-coordinate on a Cubic Bezier Curve, given an x-coordinate on it.
Consider a cubic bezier curve between points (0, 0) and (0, 100), with control points at (0, 33) and (0, 66). There are an infinite number of Y's there for a given X. So there's no equation that's going to solve Y given X for an arbitrary cubic bezier.
For a robust solution, you'll likely want to start with De Casteljau's algorithm
Split the curve recursively until individual segments approximate a straight line. You can then detect whether and where these various line segments intercept your x or whether they are vertical line segments whose x corresponds to the x you're looking for (my example above).