I am trying to solve a logarithmic function using Python. I am searching for an irrational number, so I wrote this bisection algorithm:
def racine(x):
a=0
b=x/2
c=(a+b)/2
while a!=b and a<c<b:
if c**2<x:
a=c
else:
b=c
c=(a+b)/2
return a, b
which seems to work, at least for finding irrational roots. However then I have a more complicated function:
ln(P)=A+B/T+C*ln(T)
where P, A, B and C are known constants. Isolating T, there is this:
T==e**((ln(P)-A-B/T)/C)
But this still can't be solved because T is on both sides. Can somebody see the way around it? For now I have this code, which clearly doesn't work.
def temperature(P):
A=18.19
B=-23180
C=-0.8858
T==e**((log(P)-A-B/T)/C)
return racine (T)
Thank you!
The answer should be to use the bisection method again.
a=small estimate
fa = f(a)
b=large estimate
fb = f(b)
while( b-a > 1e-12 ) {
c = (a+b)/2
fc = f(c)
if( fabs(fc) < 1e-12) return c;
if( (fc>0) == (fa>0) ) {
a = c; fa = fc
} else {
b = c; f = fc;
}
return (a+b)/2
For more efficient methods look up the regula falsi method in its Illinois variant.
If you have NumPy installed, you can find the temperature at a given pressure numerically, for example with scipy.optimize.newton. For example,
import numpy as np
from scipy.optimize import newton
A, B, C = 18.19, -23180, -0.8858
fr = lambda T, lnp: (A + B/T + C*np.log(T)) - lnp
def T(p):
return newton(fr, 1000, args=(np.log(p),))
In [1]: p1 = 10
In [2]: T1 = T(p1)
In [3]: T1
Out[3]: 2597.8167133280913
In [4]: np.exp(A + B/T1 + C*np.log(T1)) # check
Out[4]: 10.000000000000002
The initial guess value (here 1000) you might have to customize for your usage: I don't know your units.
Related
I'm fairly new to python and i'm working on a problem for a school project. I feel im making progress but i'm not sure what to do next. The question is:
Write a function that takes mass as input and returns its energy equivalent using Einstein’s famous E = mc 2 equation. Test it with at least 3 different mass values. Write the program so that it can take the mass in kilograms as a commandline argument.
import sys
import math
m = float(sys.argv)
c = float(299792458)
def einstein_equation(m, c):
result = m * (math.pow(c, 2))
return result
e = einstein_equation(m, c)
print e
just make it simple man, no need for sys.argv
and no need for math.pow
just:
c = float(7382)
def einstein_equation(m, c):
return m * (c*c)
for _ in range(3):
m = float(input("MASS : "))
e = einstein_equation(m, c)
print (e)
You don't need libary for powering and just add index for sys.argv
import sys
m = int(sys.argv[1])
c = 299792458
print(m*c**2)
I'm new to python but I been working on a code which can solve an integral equation which range is also changing according the unknown parameter. I tried to use Sympy solve function but it does not return any result. I solved the problem with a for loop, but its really slow, inefficient. I'm sure there must be a better solution, a solver. Maybe there is an other approach? I'am messing up something? I attach also the code.
import sympy as sy
from sympy.solvers import solve
alphasum = 1.707
Lky = 3.078
g = 8
Ep = 195
sigp1 = 1401.927
sigp0 = 1476
e = 2.718282
u = 0.05
k = 0.007
lsl = sy.Symbol('lsl')
def lefthand(g, Ep):
return g * Ep
def rigthhand(sigp1, sigp0, e, u, alphasum, Lky, k, lsl):
return (sigp1 - (-sigp1 + 2 * sigp0 - 2 * sigp0 * (1 - e ** (-u * (((alphasum / Lky) * lsl) + k * lsl)))))
equr = (sy.integrate(rigthhand(sigp1, sigp0, e, u, alphasum, Lky, k, lsl), (lsl, 0, lsl)))
equl = lefthand(g, Ep)
print(equr)
print (equl)
print (equr-equl)
result = solve(equr-equl, lsl,warn =True,check=False,minimal=True,quick=True,simplify=True,quartics=True)
print(result)
You can use nsolve to find numerical solutions:
In [11]: sympy.nsolve(equr-equl, lsl, 8)
Out[11]: 8.60275245116315
In [12]: sympy.nsolve(equr-equl, lsl, -4)
Out[12]: -4.53215114758428
When u is 0 your equation is linear and you can solve if for lsl; let this be an initial guess for the value of lsl at a larger value of u. Increase your value of u to the target value. Let's use capital U for the parameter we will control, replacing it with values closer and closer to u:
>>> U = Symbol('U')
>>> equr = (sy.integrate(rigthhand(sigp1, sigp0, e, U, alphasum, Lky, k, lsl), (lsl, 0, lsl)))
>>> equl = lefthand(g, Ep)
>>> z = equr-equl
>>> u0 = solve(z.subs(U,0),lsl)[0]
>>> for i in range(1,10): # get to u in 9 steps
... u0 = nsolve(z.subs(U,i*u/10.), u0)
>>> print(u0)
-4.71178322070344
Now define a larger value of u
>>> u = 0.3
>>> for i in range(1,10): # get to u in 9 steps
... u0 = nsolve(z.subs(U,i*u/10.), u0)
...
>>> u0
-2.21489271112540
Our intitial guess will (usually) be pretty good since it is exact when u is 0; if it fails then you might need to take more than 9 steps to reach the target value.
This is the Matlab code for Complexity Invariance Distance (Source)
Q and C are 1d-arrays with similar length.
function d = CID(Q, C)
CE_Q = sqrt(sum(diff(Q).^2));
CE_C = sqrt(sum(diff(C).^2));
d = sqrt(sum((Q - C).^2)) * (max(CE_Q,CE_C)/min(CE_Q,CE_C));
This is my pythonic translation:
def cid_dist(Q,C):
import numpy as np
CE_Q = np.sqrt(np.sum(np.diff(Q)**2))
CE_C= np.sqrt(np.sum(np.diff(C)**2))
d = np.sqrt(np.sum((Q - C)**2)) * (np.maximum(CE_Q,CE_C)/np.minimum(CE_Q,CE_C))
return d
Is it correct?
I have tried it in Octave. Both function return identical results.
I am using sympy to solve some equations and I am running into a problem. I have this issue with many equations but I will illustrate with an example. I have an equation with multiple variables and I want to solve this equation in terms of all variables but one is excluded. For instance the equation 0 = 2^n*(2-a) - b + 1. Here there are three variables a, b and n. I want to get the values for a and b not in terms of n so the a and b may not contain n.
2^n*(2-a) - b + 1 = 0
# Since we don't want to solve in terms of n we know that (2 - a)
# has to be zero and -b + 1 has to be zero.
2 - a = 0
a = 2
-b + 1 = 0
b = 1
I want sympy to do this. Maybe I'm just not looking at the right documentation but I have found no way to do this. When I use solve and instruct it to solve for symbols a and b sympy returns to me a single solution where a is defined in terms of n and b. I assume this means I am free to choose b and n, However I don't want to fix n to a specific value I want n to still be a variable.
Code:
import sympy
n = sympy.var("n", integer = True)
a = sympy.var("a")
b = sympy.var("b")
f = 2**n*(2-a) - b + 1
solutions = sympy.solve(f, [a,b], dict = True)
# this will return: "[{a: 2**(-n)*(2**(n + 1) - b + 1)}]".
# A single solution where b and n are free variables.
# However this means I have to choose an n I don't want
# to that I want it to hold for any n.
I really hope someone can help me. I have been searching google for hours now...
Ok, here's what I came up with. This seems to solve the type of equations you're looking for. I've provided some tests as well. Of course, this code is rough and can be easily caused to fail, so i'd take it more as a starting point than a complete solution
import sympy
n = sympy.Symbol('n')
a = sympy.Symbol('a')
b = sympy.Symbol('b')
c = sympy.Symbol('c')
d = sympy.Symbol('d')
e = sympy.Symbol('e')
f = sympy.sympify(2**n*(2-a) - b + 1)
g = sympy.sympify(2**n*(2-a) -2**(n-1)*(c+5) - b + 1)
h = sympy.sympify(2**n*(2-a) -2**(n-1)*(e-1) +(c-3)*9**n - b + 1)
i = sympy.sympify(2**n*(2-a) -2**(n-1)*(e+4) +(c-3)*9**n - b + 1 + (d+2)*9**(n+2))
def rewrite(expr):
if expr.is_Add:
return sympy.Add(*[rewrite(f) for f in expr.args])
if expr.is_Mul:
return sympy.Mul(*[rewrite(f) for f in expr.args])
if expr.is_Pow:
if expr.args[0].is_Number:
if expr.args[1].is_Symbol:
return expr
elif expr.args[1].is_Add:
base = expr.args[0]
power = sympy.solve(expr.args[1])
sym = expr.args[1].free_symbols.pop()
return sympy.Mul(sympy.Pow(base,-power[0]), sympy.Pow(base,sym))
else:
return expr
else:
return expr
else:
return expr
def my_solve(expr):
if not expr.is_Add:
return None
consts_list = []
equations_list = []
for arg in expr.args:
if not sympy.Symbol('n') in arg.free_symbols:
consts_list.append(arg)
elif arg.is_Mul:
coeff_list = []
for nested_arg in arg.args:
if not sympy.Symbol('n') in nested_arg.free_symbols:
coeff_list.append(nested_arg)
equations_list.append(sympy.Mul(*coeff_list))
equations_list.append(sympy.Add(*consts_list))
results = {}
for eq in equations_list:
var_name = eq.free_symbols.pop()
val = sympy.solve(eq)[0]
results[var_name] = val
return results
print(my_solve(rewrite(f)))
print(my_solve(rewrite(g)))
print(my_solve(rewrite(h)))
print(my_solve(rewrite(i)))
I'm stuck with one task on my learning path.
For the binomial distribution X∼Bp,n with mean μ=np and variance σ**2=np(1−p), we would like to upper bound the probability P(X≥c⋅μ) for c≥1.
Three bounds introduced:
Formulas
The task is to write three functions respectively for each of the inequalities. They must take n , p and c as inputs and return the upper bounds for P(X≥c⋅np) given by the above Markov, Chebyshev, and Chernoff inequalities as outputs.
And there is an example of IO:
Code:
print Markov(100.,0.2,1.5)
print Chebyshev(100.,0.2,1.5)
print Chernoff(100.,0.2,1.5)
Output
0.6666666666666666
0.16
0.1353352832366127
I'm completely stuck. I just can't figure out how to plug in all that math into functions (or how to think algorithmically here). If someone could help me out, that would be of great help!
p.s. and all libs are not allowed by task conditions except math.exp
Ok, let's look at what's given:
Input and derived values:
n = 100
p = 0.2
c = 1.5
m = n*p = 100 * 0.2 = 20
s2 = n*p*(1-p) = 16
s = sqrt(s2) = sqrt(16) = 4
You have multiple inequalities of the form P(X>=a*m) and you need to provide bounds for the term P(X>=c*m), so you need to think how a relates to c in all cases.
Markov inequality: P(X>=a*m) <= 1/a
You're asked to implement Markov(n,p,c) that will return the upper bound for P(X>=c*m). Since from
P(X>=a*m)
= P(X>=c*m)
it's clear that a == c, you get 1/a = 1/c. Well, that's just
def Markov(n, p, c):
return 1.0/c
>>> Markov(100,0.2,1.5)
0.6666666666666666
That was easy, wasn't it?
Chernoff inequality states that P(X>=(1+d)*m) <= exp(-d**2/(2+d)*m)
First, let's verify that if
P(X>=(1+d)*m)
= P(X>=c *m)
then
1+d = c
d = c-1
This gives us everything we need to calculate the uper bound:
def Chernoff(n, p, c):
d = c-1
m = n*p
return math.exp(-d**2/(2+d)*m)
>>> Chernoff(100,0.2,1.5)
0.1353352832366127
Chebyshev inequality bounds P(X>=m+k*s) by 1/k**2
So again, if
P(X>=c*m)
= P(X>=m+k*s)
then
c*m = m+k*s
m*(c-1) = k*s
k = m*(c-1)/s
Then it's straight forward to implement
def Chebyshev(n, p, c):
m = n*p
s = math.sqrt(n*p*(1-p))
k = m*(c-1)/s
return 1/k**2
>>> Chebyshev(100,0.2,1.5)
0.16