I'm trying to plot the batman equation. A solution in sympy or matplotlib will be great (sage isn't cool because I'm using windows). The problem is that if I comment out certain parts the part of the figure appears but with all the F *= parts, I get a blank plot.
import matplotlib.pyplot
from numpy import arange
from numpy import meshgrid
from numpy import sqrt
from numpy import real
delta = 0.01
xrange = arange(-7.0, 7.0, delta)
yrange = arange(-3.0, 3.0, delta)
x, y = meshgrid(xrange,yrange)
F = 1
F *= (((x/7) ** 2) * sqrt(abs(abs(x) - 3)/(abs(x) - 3)) + ((y / 3) ** 2) * sqrt(abs(y + (3 * sqrt(33)) / 7)/(y + (3 * sqrt(33)) / 7)) - 1)
F *= (abs(x/2) - ((3 * sqrt(33) - 7)/112) * x**2 - 3 + sqrt(1 - (abs(abs(x) - 2) - 1) ** 2 ) - y)
F *= (9 * sqrt(abs((abs(x) - 1) * (abs(x) - 3/4))/((1 - abs(x)) * (abs(x) - 3/4))) - 8 * abs(x) - y)
F *= (3 * abs(x) + 0.75 * sqrt(abs((abs(x) - 3/4) * (abs(x) - 1/2))/((3/4 - abs(x)) * (abs(x) - 1/2))) - y)
F *= ((9/4) * sqrt(abs((x - 1/2) * (x + 1/2))/((1/2 - x) * (1/2 + x))) - y)
F *= ((6 * sqrt(10)) / 7 + (3/2 - abs(x)/2) * sqrt(abs(abs(x) - 1)/(abs(x) - 1)) - ((6 * sqrt(10))/ 14) * sqrt(4 - (abs(x) - 1) ** 2 ) - y)
G = 0
matplotlib.pyplot.contour(x, y, (F - G), [0])
matplotlib.pyplot.show()
What's going on here? If the graph is zero for one multiplicand, it should still be so no matter which other multiplicands I throw in there.
source of the batman equation: http://www.reddit.com/r/pics/comments/j2qjc/do_you_like_batman_do_you_like_math_my_math/
The parameter of sqrt is negative for many points, so the finally products are all NaN. You can plot every factor as following:
from __future__ import division # this is important, otherwise 1/2 will be 0
import matplotlib.pyplot
from numpy import arange
from numpy import meshgrid
from numpy import sqrt
from numpy import real
delta = 0.01
xrange = arange(-7.0, 7.0, delta)
yrange = arange(-3.0, 3.0, delta)
x, y = meshgrid(xrange,yrange)
F1 = (((x/7) ** 2) * sqrt(abs(abs(x) - 3)/(abs(x) - 3)) + ((y / 3) ** 2) * sqrt(abs(y + (3 * sqrt(33)) / 7)/(y + (3 * sqrt(33)) / 7)) - 1)
F2 = (abs(x/2) - ((3 * sqrt(33) - 7)/112) * x**2 - 3 + sqrt(1 - (abs(abs(x) - 2) - 1) ** 2 ) - y)
F3 = (9 * sqrt(abs((abs(x) - 1) * (abs(x) - 3/4))/((1 - abs(x)) * (abs(x) - 3/4))) - 8 * abs(x) - y)
F4 = (3 * abs(x) + 0.75 * sqrt(abs((abs(x) - 3/4) * (abs(x) - 1/2))/((3/4 - abs(x)) * (abs(x) - 1/2))) - y)
F5 = ((9/4) * sqrt(abs((x - 1/2) * (x + 1/2))/((1/2 - x) * (1/2 + x))) - y)
F6 = ((6 * sqrt(10)) / 7 + (3/2 - abs(x)/2) * sqrt(abs(abs(x) - 1)/(abs(x) - 1)) - ((6 * sqrt(10))/ 14) * sqrt(4 - (abs(x) - 1) ** 2 ) - y)
for f in [F1,F2,F3,F4,F5,F6]:
matplotlib.pyplot.contour(x, y, f, [0])
matplotlib.pyplot.show()
the result plot:
I know this might seem lame, but how about creating a list of x values, and then computing the value of "batman" at each of those positions, and storing in another list. You could define a function "batman" which computes the y value for each x value you pass in.
Then just plot those lists with matplotlib.
EDIT: Since you've made numpy arrays already to store the results, you could use those when computing the y values.
I'm not even sure how this equation would work, since I see divisions by zero arising in the first term (under the first square root, when abs(x) = 3), and imaginary numbers showing up in the last term (under the last square root, when {abs(x)-1}^2 > 4, ie x > 3 or x < -3).
What am I missing here? Is only the real part of the result used, and are divisions by zero ignored or approximated?
Running this, I do indeed see lots of RunTimeWarnings, and it is not unlikely matplotlib would get totally confused what numbers to work with (NaNs, Infs; trying print F at the end). Looks like it still manages when there's only a relatively low number of NaNs or Infs, which would explain that you're seeing part of the figure.
I'd think matplotlib's contour is fine, just confused by the input.
Related
So I am trying to write a python program to calculate 4 unknowns (x, y, z, d) given a system of 4 non-linear equations. I am using the multivariate newton method.
However, the problem I have at the moment is that when I start my program, I do not get any output. The program runs (red square is going), but nothing is outputted.
There are some holes perhaps in my program, was hoping you could give some pointers.
Many thanks.
from autograd import jacobian
import autograd.numpy as np
import numpy.linalg
import sys
tolerance = 0.0001
sys.setrecursionlimit(10000);
def functionmatrix(x0):
f1 = pow((x0[0] - 1560), 2) + pow((x0[1] - 6540), 2) + pow((x0[2] - 20140), 2) - (2.9*10**3*pow((0.07074 - x0[3]), 2))
f2 = pow((x0[0] - 18760), 2) + pow((x0[1] - 2750), 2) + pow((x0[2] - 18610), 2) - (2.9*10**3*pow((0.07220 - x0[3]), 2))
f3 = pow((x0[0] - 17610), 2) + pow((x0[1] - 14630), 2) + pow((x0[2] - 13480), 2) - (2.9*10**3*pow((0.07690 - x0[3]), 2))
f4 = pow((x0[0] - 19170), 2) + pow((x0[1] - 610), 2) + pow((x0[2] - 18390), 2) - (2.9*10**3*pow((0.07242 - x0[3]), 2))
functionmatrix = np.array([f1, f2, f3, f4]).reshape(4,1)
return functionmatrix
def jacobianmatrix(x0):
f1 = pow((x0[0] - 1560), 2) + pow((x0[1] - 6540), 2) + pow((x0[2] - 20140), 2) - (2.9*10**3*pow((0.07074 - x0[3]), 2))
f2 = pow((x0[0] - 18760), 2) + pow((x0[1] - 2750), 2) + pow((x0[2] - 18610), 2) - (2.9*10**3*pow((0.07220 - x0[3]), 2))
f3 = pow((x0[0] - 17610), 2) + pow((x0[1] - 14630), 2) + pow((x0[2] - 13480), 2) - (2.9*10**3*pow((0.07690 - x0[3]), 2))
f4 = pow((x0[0] - 19170), 2) + pow((x0[1] - 610), 2) + pow((x0[2] - 18390), 2) - (2.9*10**3*pow((0.07242 - x0[3]), 2))
jacobianmatrix = np.array([jacobian(f1), jacobian(f2), jacobian(f3), jacobian(f4)]).reshape(4,1)
inversejacobian = np.linalg.inv(jacobianmatrix)
return inversejacobian
def determinevalues():
euclideandistance = 100
iteration = 0
tolerance = 0.00000001
maxiterations = 1000
x0 = np.array([0,0,6370,0], dtype = float).reshape(4,1)
while(np.any(abs(euclideandistance) > tolerance) and iteration < maxiterations):
outputfunctionmatrix = functionmatrix(x0)
outputjacobianmatrix = jacobianmatrix(x0)
newxvalues = x0 - np.linalg.solve(outputfunctionmatrix, outputjacobianmatrix)
iteration = iteration + 1
x0 = newxvalues
euclideandistance = np.linalg.norm(newxvalues - x0)
def main():
determinevalues()
main()
I run it in my side and the determinate() function cause an error due to the recursion. But, there are also many things to work on.
First, you should used appropriated librairies, the Harvard autograd library (link), has already grad and jacobian implementation. You problem can be simply resolve with this sample (link) :
import autograd.numpy as np
import autograd
def newton(f, x0, tol=0.0001, maxiter=10000):
g = autograd.jacobian(f)
h = autograd.hessian(f)
x = x0
for _ in range(maxiter):
# ==========================
# EDITED
gx = np.squeeze(g(x))
hx = np.squeeze(h(x))
delta = np.linalg.multi_dot([np.linalg.inv(hx), gx])
# ==========================
x = x - delta
if np.linalg.norm(delta) < tol:
break
return x
def main():
def f(x):
return np.array([[(x[0] - 1560) ** 2 + (x[1] - 6540) ** 2 + (x[2] - 20140) ** 2 - (2.9 * 10 ** 3 * (0.07074 - x[3]) ** 2)],
[(x[0] - 18760) ** 2 + (x[1] - 2750) ** 2 + (x[2] - 18610) ** 2 - (2.9 * 10 ** 3 * (0.0722 - x[3]) ** 2)],
[(x[0] - 17640) ** 2 + (x[1] - 14630) ** 2 + (x[2] - 13480) ** 2 - (2.9 * 10 ** 3 * (0.0769 - x[3]) ** 2)],
[(x[0] - 19170) ** 2 + (x[1] - 610) ** 2 + (x[2] - 18390) ** 2 - (2.9 * 10 ** 3 * (0.07242 - x[3]) ** 2)]])
x0 = np.array([0., 0., 6730., 0.])
print(newton(f, x0))
if __name__ == '__main__':
main()
Since you are in matrix alegra not linear, you just need to replace autograd.grad(f) by autograd.jacobian(f). I don't know if the system will converge though! You could rebuild jacobian and hessian function if you want to do it yourself.
EDIT :
There is an error in my code, jacobian and hessian need be reshaped before the calculation and we need to use, as you already used in your previous code, np.linalg.multi_dot() function.
I did the best fit for my Gaussian curve with Python. Once I have the best fit curve, I would like to know for a given Y value, the correspondent X values.
Since it is a Gaussian curve, I should have two values of X for a given Y ( less than the max value of Y).
How could I do it on Python?
Thank you
Let's take for instance your Gaussian : g(x) = a * exp(-(x - x0) ** 2 / (2 * sigma ** 2)) with a, x0 and sigma being your found parameters from the fit.
And now you want to find y such as y = g(x)
<=> y = a * exp(-(x - x0) ** 2 / (2 * sigma ** 2))
<=> ln|y/a| = -(x - x0) ** 2 / (2 * sigma ** 2))
<=> - ln|y/a| * (2 * sigma ** 2)) =(x - x0) ** 2
<=> sqrt(- ln|y/a| * (2 * sigma ** 2))) = +/- (x - x0)
<=> x = +/- (x0 + sqrt(- ln|y/a| * (2 * sigma ** 2))))
Then, you can use:
def inv_gaus(y, a, x0, sigma):
x = x0 + np.sqrt(-2 * np.log(y / a) * sigma ** 2)
return -x, x
And therefore you have 2 x for one y :)
So for this internship I am doing, I need to use the integral of (x^(9/2))/((1-x)^2) as part of an equation I am graphing. However, the variable that I am graphing along the x axis appears in both limits of integration. Since I am a complete and total novice at python, my code is atrocious, but I ended up copy+pasting the indefinite integral twice, plugging in the limits of integration, and subtracting. How can I make the code better?
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
x = np.arange(0,2.5,0.00001)
zs = 8
zr = 6
rbub = 5
sig = 2.5
XHI = 0.5
sigma = 10**-sig
L = 10**-3
zb = zs - (((1 + zs)/8)**(3/2)) * (0.0275) * (rbub/10)
a = (1+zr)/((1+zs)*(x+1))
b = (1+zb)/((1+zs)*(x+1))
def f(x):
ans = 0.000140092
ans = ans * ((1+zs)**(3/2))
ans = ans * ((x+1)**(3/2))
ans = ans * XHI
return ans * ((9/2)*(np.log(1-np.sqrt(b)) - np.log(np.sqrt(b)+1)) + (1/35 * (1/(b-1)) * (10*(b**(9/2)) + 18*(b**(7/2)) + 42*(b**(5/2)) + 210*(b**(3/2)) - 315*(b**(1/2))) - ((9/2)*(np.log(1-np.sqrt(a)) - np.log(np.sqrt(a)+1)) + (1/35 * (1/(a-1)) * (10*(a**(9/2)) + 18*(a**(7/2)) + 42*(a**(5/2)) + 210*(a**(3/2)) - 315*(a**(1/2)))))))
Here is one take. Of course, I have no idea what this is doing. You should be in a much better position to add comments / sensible variable names, as others have pointed out. Still, here is what you could do.
First, run a code formatter to make the code more human-friendly.
def f(x):
ans = 0.000140092
ans = ans * ((1 + zs) ** (3 / 2))
ans = ans * ((x + 1) ** (3 / 2))
ans = ans * XHI
return ans * (
(9 / 2) * (np.log(1 - np.sqrt(b)) - np.log(np.sqrt(b) + 1))
+ (
1
/ 35
* (1 / (b - 1))
* (
10 * (b ** (9 / 2))
+ 18 * (b ** (7 / 2))
+ 42 * (b ** (5 / 2))
+ 210 * (b ** (3 / 2))
- 315 * (b ** (1 / 2))
)
- (
(9 / 2) * (np.log(1 - np.sqrt(a)) - np.log(np.sqrt(a) + 1))
+ (
1
/ 35
* (1 / (a - 1))
* (
10 * (a ** (9 / 2))
+ 18 * (a ** (7 / 2))
+ 42 * (a ** (5 / 2))
+ 210 * (a ** (3 / 2))
- 315 * (a ** (1 / 2))
)
)
)
)
)
Right away you see some symemtry. This chunk
10 * (b ** (9 / 2))
+ 18 * (b ** (7 / 2))
+ 42 * (b ** (5 / 2))
+ 210 * (b ** (3 / 2))
- 315 * (b ** (1 / 2))
is a dot product of some weights and a b raised to a vector of powers. If b were scalar, we could write it as np.dot(weights, np.sqrt(b) ** powers). Maybe we would even score some optimization points from using integral powers.
Putting thigs together, we can get something like this:
weights = np.array([10, 18, 42, 210, -315])
powers = np.array([9, 7, 5, 3, 1])
def log_term(x):
return (9 / 2) * (np.log(1 - np.sqrt(x)) - np.log(np.sqrt(x) + 1))
def dot_term(x):
return (1 / 35) * 1 / (x - 1) * np.dot(np.sqrt(x)[..., None] ** powers, weights)
def integrate(x):
return log_term(x) + dot_term(x)
factor1 = integrate(b) - integrate(a)
factor2 = 0.000140092 * ((1 + zs) ** (3 / 2)) * XHI
factor = factor1 * factor2
def f(x):
return factor * ((x + 1) ** (3 / 2))
With better variable names and comments this could almost be readable.
Side comment. Both in your original code and in this version, you define x in the body of your script. You also define several variables as a function of x, such as a and b.
Python scoping rules mean that these variables will not change if you pass a different x to f. If you want all of your variables to change with x, you should move the definitions inside the function.
Using good variable names will help a lot for who gonna read the code or even for you, and comments will help too.
For the rest, it is a equation, there is no good way of putting it.
I made a Matlab function and I would like to convert it to Python to use with my web application.
I converted (.m file to .py file) almost everything using OMPC.
However, I can't make the solve() function to work (I am using the sympy library).
This is the Matlab line:
SBC = solve(sqrt((xa-x)^(2)+(ya-y)^(2))-sqrt((xb-x)^(2)+(yb-y)^(2))-D12==0,sqrt((xa-x)^(2)+(ya-y)^(2))-sqrt((xc-x)^(2)+(yc-y)^(2))-D13==0,[x,y]);
And this is the Python line where x and y are symbols (with x = Symbol('x') and y = Symbol('y')) :
sbc = solve(
sqrt((xa - x) ** (2) + (ya - y) ** (2))
- sqrt((xb - x) ** (2) + (yb - y) ** (2))
- D12 == 0,
sqrt((xa - x) ** (2) + (ya - y) ** (2))
- sqrt((xc - x) ** (2) + (yc - y) ** (2))
- D13 == 0,
[x, y]
)
With this Python code, I am getting False instead of a result (it works great with the Matlab code).
Am I missing something?
EDIT:
And with this, I am getting [] :
# -*- coding: utf-8 -*-
from sympy import *
def alg(xa=None, ya=None, za=None, Ta=None, xb=None, yb=None, zb=None, Tb=None, xc=None, yc=None, zc=None, Tc=None, xd=None, yd=None, zd=None, Td=None, RSSIA=None, RSSIB=None, RSSIC=None, RSSID=None, txPower=None, n=None):
n = 2
c = 3 * 10 ** 8
TOA12 = Ta - Tb
TOA13 = Ta - Tc
TOA14 = Ta - Td
D12 = TOA12 * c
D13 = TOA13 * c
D14 = TOA14 * c
x, y = symbols('x y')
eqs = [sqrt((xa - x) ** (2) + (ya - y) ** (2)) - sqrt((xb - x) ** (2) + (yb - y) ** (2)) - D12,
sqrt((xa - x) ** (2) + (ya - y) ** (2)) - sqrt((xc - x) ** (2) + (yc - y) ** (2)) - D13]
print solve(eqs, [x, y])
alg(3,1,0,21.8898790015,4,6,0,21.8898790005,10,4,0,21.88987900009,9,0.5,0,21.889879000105,23.9,23.85,23.9,23.95,24,1)
There is only one small change required in order to make it work. The reason why you receive False is that you use the == 0 in your function definition. In sympy, it is generally assumed that your functions evaluate to 0. To give an example taken from here:
If you want to solve the equations x+5y=2, -3x+6y=15 then you would do it as follows:
from sympy import *
x, y = symbols('x y')
solve([x + 5*y - 2, -3*x + 6*y - 15], [x, y])
which gives you
{x: -3, y: 1}
Note that the equations are passed in a way that they evaluate to 0.
If you run it like you did
solve([x + 5*y - 2 == 0, -3*x + 6*y - 15 == 0], [x, y])
then also False is returned.
So for your example, the following would work:
from sympy import *
x, y, xa, xb, xc, ya, yb, yc, D12, D13 = symbols('x y xa xb xc ya yb yc D12 D13')
eqs = [sqrt((xa - x) ** (2) + (ya - y) ** (2)) - sqrt((xb - x) ** (2) + (yb - y) ** (2)) - D12,
sqrt((xa - x) ** (2) + (ya - y) ** (2)) - sqrt((xc - x) ** (2) + (yc - y) ** (2)) - D13]
solve(eqs, [x, y])
Unfortunately, that does not run through on my private computer (my Python gets killed; apparently that is hard to solve) so I just tested it for a simpler version to demonstrate the principle:
eqs2 = [sqrt(xa - x) - D12,
(yc - y) ** (2) - D13]
solve(eqs2, [x, y])
which then gives you the expected output:
[(-D12**2 + xa, -sqrt(D13) + yc), (-D12**2 + xa, sqrt(D13) + yc)]
Hope you have more luck on your machine to solve these complicated functions. But this post explains why you receive the False.
EDIT
With your modified code, you can get a solution if you decrease the precision of your parameters D12 and D13. Here is the solution you then get:
[sqrt((-x + 3)**2 + (-y + 1)**2) - sqrt((-x + 4)**2 + (-y + 6)**2) - 0.3, sqrt((-x + 3)**2 + (-y + 1)**2) - sqrt((-x + 10)**2 + (-y + 4)**2) - 0.42]
[{x: 6.45543078993649, y: 3.14390310591109}, {x: 6.67962865117349, y: 2.61399193301427}]
Are these the same you receive for the Matlab simulations?
Here is the modified code; please note that I force the output to be in form of a dictionary and also print the equations (I round to two decimals but it also works with 4; you can play with that):
from sympy import *
def alg(xa=None, ya=None, za=None, Ta=None, xb=None, yb=None, zb=None, Tb=None, xc=None, yc=None, zc=None, Tc=None, xd=None, yd=None, zd=None, Td=None, RSSIA=None, RSSIB=None, RSSIC=None, RSSID=None, txPower=None, n=None):
n = 2
c = 3 * 10 ** 8
TOA12 = Ta - Tb
TOA13 = Ta - Tc
TOA14 = Ta - Td
D12 = round(TOA12 * c, 2)
D13 = round(TOA13 * c, 2)
# D14 = TOA14 * c
# x, y, D12, D13 = symbols('x y D12 D13')
x, y = symbols('x y')
eqs = [sqrt((xa - x) ** (2) + (ya - y) ** (2)) - sqrt((xb - x) ** (2) + (yb - y) ** (2)) - D12,
sqrt((xa - x) ** (2) + (ya - y) ** (2)) - sqrt((xc - x) ** (2) + (yc - y) ** (2)) - D13]
print eqs
print solve(eqs, x, y, dict=True)
alg(3,1,0,21.8898790015,4,6,0,21.8898790005,10,4,0,21.88987900009,9,0.5,0,21.889879000105,23.9,23.85,23.9,23.95,24,1)
import numpy as np
from scipy.optimize import fsolve
musun = 132712000000
T = 365.25 * 86400 * 2 / 3
e = 581.2392124070273
def f(x):
return ((T * musun ** 2 / (2 * np.pi)) ** (1 / 3) * np.sqrt(1 - x ** 2)
- np.sqrt(.5 * musun ** 2 / e * (1 - x ** 2)))
x = fsolve(f, 0.01)
f(x)
print x
What is wrong with this code? It seems to not work.
Because sqrt returns NaN for negative argument, your function f(x) is not calculable for all real x. I changed your function to use numpy.emath.sqrt() which can output complex values when the argument < 0, and returns the absolute value of the expression.
import numpy as np
from scipy.optimize import fsolve
sqrt = np.emath.sqrt
musun = 132712000000
T = 365.25 * 86400 * 2 / 3
e = 581.2392124070273
def f(x):
return np.abs((T * musun ** 2 / (2 * np.pi)) ** (1 / 3) * sqrt(1 - x ** 2)
- sqrt(.5 * musun ** 2 / e * (1 - x ** 2)))
x = fsolve(f, 0.01)
x, f(x)
Then you can get the right result:
(array([ 1.]), array([ 121341.22302275]))
the solution is very close to the true root, but f(x) is still very large because f(x) has a very large factor: musun.
fsolve() returns the roots of f(x) = 0 (see here).
When I plotted the values of f(x) for x in the range -1 to 1, I found that there are roots at x = -1 and x = 1. However, if x > 1 or x < -1, both of the sqrt() functions will be passed a negative argument, which causes the error invalid value encountered in sqrt.
It doesn't surprise me that fsolve() fails to find roots that are at the very ends of the valid range for the function.
I find that it is always a good idea to plot the graph of a function before trying to find its roots, as that can indicate how likely (or in this case, unlikely) it is that the roots will be found by any root-finding algorithm.