Complete solutions of system of equations with python - python

I have the following system of equations and I'm trying to get the solution with sympy:
from sympy import *
x,y = symbols('x,y')
rea1 = (1.0*10**(-4)*(x+2)*(4*y+3*x+1)**3) - 1.3 * ((-2*y-x+1)*(-y-x+1)*(2*y+2*x+6)**2)
rea2 = (1.0*10**(-4)*(y+1)*(4*y+3*x+1)**4) - 2.99 * ((-2*y-x+1)**2*(-y-x+1)*(2*y+2*x+6)**2)
solu = solve([rea1,rea2],[x,y])
sol = nsolve([rea1,rea2],[x,y],[-0.1,1])
print(solu)
print(sol)
with results
[(-11.0, 8.0), (-3.0, 2.0), (-2.0, -1.0), (5.0, -4.0)]
and
Matrix([[1.32358494772278], [-0.324195048403443]])
However I know from Maxima the following solutions:
[[x=-11,y=8],
[x=-3,y=2],
[x=5,y=-4],
[x=-2,y=-1],
[x=1.3236,y=-0.3242],
[x=-2.0091,y=-0.98836],
[x=-3.8143,y=0.84582],
[x=3.004,y=-1.0016],
[x=-4.0297,y=0.9959],
[x=-8.4744,y=9.4724]]
How to get all the solutions with Python?

Okay, this is a second answer. I think I know why SymPy's main solvers don't seem to work for this case. I have written some better code to do this and posted it in the SymPy issue here:
https://github.com/sympy/sympy/issues/23637#issuecomment-1159205521
I'll also show it here:
from sympy import *
def solve_poly_numeric(polys, syms, exact=False, prec=None):
"""Solve a system of polynomials having rational coefficients."""
_, info = parallel_poly_from_expr(polys)
domain = info['domain']
if domain not in (ZZ, QQ):
raise ValueError("Poly should have rational coefficients")
# Compute a preliminary Groebner basis
gb = groebner(polys, syms)
# Handle inconsistent or infinite cases
if 1 in gb:
return []
elif not gb.is_zero_dimensional:
raise ValueError("Infinitely many solutions")
# Split the system by factorising the final polynomial
c, fms = factor_list(gb[-1])
gbs = []
for factor, m in fms:
gb_new = groebner(gb[:-1] + [factor], syms)
gbs.append(gb_new)
# Now solve each subsystem
solutions = []
for gbi in gbs:
solutions.extend(solve_separating(gbi))
# Make the solutions approximate (this is because otherwise you'll see
# complicated RootOf expressions).
if not exact:
solutions = [[s.evalf(prec) for s in sol] for sol in solutions]
return solutions
def solve_separating(gb):
syms = gb.gens
N = len(syms)
s = Dummy('s')
i = 0
while True:
eq_s = s - sum(j**i*syms[j] for j in range(N))
gb = groebner(list(gb) + [eq_s], syms + (s,))
if is_separated(gb):
return solve_rur(gb)
i += 1
def is_separated(gb):
"""Test if a Groebner basis is separated"""
for p in gb.polys[:-1]:
if sum(p.degree_list()[:-1]) != 1:
return False
return sum(gb.polys[-1].degree_list()[:-1]) == 0
def solve_rur(gb):
[sol] = linsolve(gb[:-1], gb.gens[:-1])
s = gb.gens[-1]
s_sols = set(gb.polys[-1].as_poly(s).all_roots())
return [sol.subs(s, s_sol) for s_sol in s_sols]
With that you get all the roots you were expecting:
In [100]: solve_poly_numeric([nsimplify(rea1), nsimplify(rea2)], [x, y])
Out[100]:
[[-2.0, -1.0], [5.0, -4.0], [-11.0, 8.0], [-3.0, 2.0], [-4.02970802196492, 0.995904370231472], [-8.
47443484879371, 9.47242621738025], [3.00401593628982, -1.00159247934001], [-3.81434166231536, 0.845
816419487192], [-2.00911635093861, -0.988359479355467], [1.32358494772277, -0.32419504840344]]

With a nonlinear system with multiple solutions, the trick is to make a guess near the solution. So nsolve((rea1,rea2),(x,y),(1.3,-0.3)) will give you a solution. But if you don't know that you have a solution there, how can you get it? One method is to use a "continuation parameter" whose value you can change from 0 to 1 to "shut off" the highly nonlinear part of the equation(s). In your case I replace 4*y+3*x+1 with z*(4*y+3*x+1) and solve for z=0
>>> from sympy import Tuple,nsimplify
>>> eqs = Tuple(*[nsimplify(i) for i in (rea1,rea2)]) # get rid of floats
>>> eqs = eqs.subs(4*y+3*x+1, z*(4*y+3*x+1)) # introduce continuation param
>>> z0 = solve(eqs.subs(z,0)); z0
[{x:1−2y}, {x:1−y}, {x:−y−3}]
With these three hints as to how x is related to y I then just fully turn on the non-linear term and hope that I am close enough as I calculate values of x for y values of interest -- and for that you have to have some idea of what you are looking for. I will just assume we are looking in the range of [-11,10] and collect the answers as they are obtained (and ignore failed attempts):
>>> saw = set()
>>> for yg in range(-11,11):
... for xs in z0:
... guess = xs[x].subs(y,yg),yg
... try:
... ans = nsolve(eqs.subs(z,1),(x,y),guess)
... except:continue
... saw.add((ans[0,0],ans[1,0]))
And let's see what we got:
>>> from sympy import Point
>>> for i in sorted({Point(i).n(3) for i in saw},key=lambda x:x[0]):print(i)
Point2D(-11.0, 8.0)
Point2D(-8.47, 9.47)
Point2D(-4.03, 0.996)
Point2D(-3.81, 0.846)
Point2D(-3.0, 2.0)
Point2D(-2.0, -1.0)
Point2D(1.32, -0.324)
Point2D(3.0, -1.0)
Point2D(5.0, -4.0)
Due to slight differences in the original solutions, 2 of the solutions appear to be duplicates; they were removed by evaluating to 3 digits of precision. Whether there is a different solution near (-2,-1) is something you would have to investigate. But using a guess near the solution already found would be a way to confirm that.

I'm not sure why solve fails here. That should be considered a bug and reported to the SymPy project on GitHub rather than here on SO.
You can get the solutions like this:
In [128]: eq1 = nsimplify(rea1)
In [129]: eq2 = nsimplify(rea2)
In [130]: r = resultant(eq1, eq2, x)
In [131]: rs = list(set(real_roots(r)))
In [132]: [root.n(5) for root in rs]
Out[132]: [-0.98836, 2.0, 0.9959, 8.0, -1.0016, 0.84582, -0.32419, 9.4724, -4.0, -1.0]
That's giving the values for y so it just remains to determine the corresponding values for x e.g.:
In [133]: xvals = nroots(eq1.subs(y, rs[0].n()))
In [134]: xvals
Out[134]: [-2.0148693245473, -2.00911635093857, 1.98822706053502, 2.97754996447177]
Only one of these values is correct (i.e. also satisfies eq2):
In [135]: [eq2.subs({y:rs[0], x:xval}).n(3) for xval in xvals]
Out[135]: [-0.00481, -2.55e-13, -0.0247, 0.00169]
Really solve should be able to handle all of this though so a bug should be raised.

Your case is a system of nonlinear equations. Sympy provides the solveset module for system of equations, depending on the system type.
You can try solveset.nonlinsolve()
https://docs.sympy.org/latest/modules/solvers/solveset.html#sympy.solvers.solveset.nonlinsolve

Related

Finding the minima/maxima of a multi-variable polynomial in python

I have the following polynomial equation that I would like to find the local minima and maxima for.
I defined the function as follows. It uses a flatten function to flatten the nested list, I'll include it for testing purposes (found it here http://rightfootin.blogspot.com/2006/09/more-on-python-flatten.html)
flatten list
from itertools import combinations
import math
def flatten(l, ltypes=(list, tuple)):
ltype = type(l)
l = list(l)
i = 0
while i < len(l):
while isinstance(l[i], ltypes):
if not l[i]:
l.pop(i)
i -= 1
break
else:
l[i:i + 1] = l[i]
i += 1
return ltype(l)
my polynomial
def poly(coefficients, factors):
#quadratic terms
constant = 1
singles = factors
products = [math.prod(c) for c in combinations(factors, 2)]
squares = [f**2 for f in factors]
sequence = flatten([constant, singles, products, squares])
z = sum([math.prod(i) for i in zip(coefficients, sequence)])
return z
The arguments it takes is a list of coefficients, for example:
coefs = [12.19764959, -1.8233151, 2.50952816,-1.56344375, 1.00003828, -1.72128301, -2.54254877, -1.20377309, 5.53510616, 2.94755653, 4.83759279, -0.85507208, -0.48007208, -3.70507208, -0.27007208]
And a list of factor or variable values:
factors = [0.4714, 0.4714, -0.4714, 0.4714]
Plug these in and it calculates the result of the polynomial. The reason I wrote it like this is because the number of variables (factors) changes from fit to fit, so I wanted to keep it flexible. I now want to find the combination of "factors" values within a certain range (let's say between -1 and 1) where the function reaches its maximum and minimum values. If the function was "hard coded" I could use scipy.optimize, but I can't figure out how to make it works as is.
Another option is a brute force grid search (which I use at the moment), but it's very slow as soon as you have more than 2 variables, especially with small step sizes. There may be no true minima/maxima where slope == 0 within the bounds, but as long as I can get the maximum and minimum values that is OK.
Ok, I figured it out. It was two really silly things:
the order of the arguments in the function had to be reversed, so that the first argument (the one I wanted to optimize for) were the "factors" or the X values, followed by the coefficients. That way an array of the same size could be used as the X0 and the coefficients could be used as args.
That wassn't enough, as the function would return an array if an array was the input. I just added a factors = list(factors) to the function itself to put it into the correct shape.
The new function:
def poly(factors, coefficients):
factors = list(factors)
#quadratic terms
constant = 1
singles = factors
products = [math.prod(c) for c in combinations(factors, 2)]
squares = [f**2 for f in factors]
sequence = flatten([constant, singles, products, squares])
z = sum([math.prod(i) for i in zip(coefficients, sequence)])
return z
And the optimization:
coefs = [4.08050532, -0.47042713, -0.08200181, -0.54184481, -0.18515675,
-0.96751856, -1.10814625, -1.7831592, 5.2763512, 2.83505438, 4.7082153,
0.22988773, 1.06488773, -0.70011227, 1.42988773]
x0 = [0.1, 0.1, 0.1, 0.1]
minimize(poly,x0 = x0, args = coefs, bounds = ((-1,1),(-1,1),(-1,1),(-1,1)))
Which returns:
fun: -1.6736636102536673
hess_inv: <4x4 LbfgsInvHessProduct with dtype=float64>
jac: array([-2.10611305e-01, 2.19138777e+00, -8.16990766e+00, -1.11022302e-07])
message: 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'
nfev: 85
nit: 12
njev: 17
status: 0
success: True
x: array([1., -1.,1., 0.03327357])

solving linear system 6x6 matrix using sympy

i am trying to solve a matrix that has 6x6 matrices as it's entries(elements)
i tried multiplying the inverse of gen to the solution matrix, but i don't trust the correctness of the answer am getting.
from sympy import Eq, solve_linear_system, Matrix,count_ops,Mul,horner
import sympy as sp
a, b, c, d, e,f = sp.symbols('a b c d e f')
ad = Matrix(([43.4,26.5,115,-40.5,52.4,0.921],
[3.78,62.9,127,-67.6,110,4.80],
[41.25,75.0,213,-88.9, 131, 5.88],
[-10.6,-68.4,-120,64.6,-132,-8.49],
[6.5,74.3,121,-72.8,179,29.7],
[1.2,30.7,49.7,-28.7,91,29.9]))
fb= Matrix(([1,0,0,0,0,0],
[0,1,0,0,0,0],
[0,0,1,0,0,0],
[0,0,0,1,0,0],
[0,0,0,0,1,0],
[0,0,0,0,0,1]))
ab = Matrix(([-0.0057],
[0.0006],
[-0.0037],
[0.0009],
[0.0025],
[0.0042]))
az = sp.symbols('az')
bz = sp.symbols('bz')
fz = sp.symbols('fz')
gen = Matrix(([az, fz, 0, 0, 0, 0,bz],
[fz,az,fz,0,0,0,bz],
[0,fz,az,fz,0,0,bz],
[0,0,fz,az,fz,0,bz],
[0,0,0,fz,az,fz,bz],
[0,0,0,0,fz,az,bz]))
answer = solve_linear_system(gen,a,b,c,d,e,f)
first_solution = answer[a]
df = count_ops(first_solution)
print(df,first_solution)
disolved = zip(first_solution.simplify().as_numer_denom(),(1,-1))
dft = Mul(*[horner(b)**e for b,e in disolved])
dff = count_ops(dft)
print(dff,dft)
_1st_solution = dft.subs({az:ad,fz:fb,bz:ab},simultaneous = True).doit()
print(_1st_solution)
when i ran my code it raised sympy.matrices.common.ShapeError
You have to be careful when using horner with expressions containing commutative symbols that are actually noncommutative (in your case because they represent matrices). Your dft expression is
(az**2*bz - bz*fz**2)/(az*(az*(az + fz) - 2*fz**2) - fz**3)
but should maybe be
(az**2 - fz**2)*(az*(az*(az + fz) - 2*fz**2) - fz**3)**(-1)*bz
You would have received a correct expression if you had created the symbols as noncommutative (as shown below).
But you can't use horner with non-commutative symbols, so I just rearranged the expression by hand; you will have to check to see that the ordering is right. As an alternative to doing the factoring by hand you might also try using factor_nc to help you -- but it won't handle horner like expression factoring:
>>> ax, bz, fz = symbols('az bz fz, commutative=False)
>>> (az**2*bz - fz**2*bz)
az**2*bz - fz**2*bz
>>> factor_nc(_)
(az**2 - fz**2)*bz

Find zeros of the characteristic polynomial of a matrix with Python

Given an N x N symmetric matrix C and an N x N diagonal matrix I, find the solutions of the equation det(λI-C)=0. In other words, the (generalized) eigenvalues of C are to be found.
I know few ways how to solve this in MATLAB using build-in functions:
1st way:
function lambdas=eigenValues(C,I)
syms x;
lambdas=sort(roots(double(fliplr(coeffs(det(C-I*x))))));
2nd way:
[V,D]=eig(C,I);
However, I need to use Python. There are similar function in NumPy and SymPy, but, according to docs (numpy, sympy), they take only one matrix C, as the input. Though, the result's different from the result produced by Matlab. Also, symbolic solutions produced by SymPy aren't helpful. Maybe I am doing something wrong? How to find solution?
Example
MATLAB:
%INPUT
I =
2 0 0
0 6 0
0 0 5
C =
4 7 0
7 8 -4
0 -4 1
[v,d]=eig(C,I)
%RESULT
v =
-0.3558 -0.3109 -0.5261
0.2778 0.1344 -0.2673
0.2383 -0.3737 0.0598
d =
-0.7327 0 0
0 0.4876 0
0 0 3.7784
Python 3.5:
%INPUT
I=np.matrix([[2,0,0],
[0,6,0],
[0,0,5]])
C=np.matrix([[4,7,0],[7,8,-4],[0,-4,1]])
np.linalg.eigh(C)
%RESULT
(array([-3., 1.91723747, 14.08276253]),
matrix(
[[-0.57735027, 0.60061066, -0.55311256],
[ 0.57735027, -0.1787042 , -0.79670037],
[ 0.57735027, 0.77931486, 0.24358781]]))
At least if I has positive diagonal entries you can simply solve a transformed system:
# example problem
>>> A = np.random.random((3, 3))
>>> A = A.T # A
>>> I = np.identity(3) * np.random.random((3,))
# transform
>>> J = np.sqrt(np.einsum('ii->i', I))
>>> B = A / np.outer(J, J)
# solve
>>> eval_, evec = np.linalg.eigh(B)
# back transform result
>>> evec /= J[:, None]
# check
>>> A # evec
array([[ -1.43653725e-02, 4.14643550e-01, -2.42340866e+00],
[ -1.75615960e-03, -4.17347693e-01, -8.19546081e-01],
[ 1.90178603e-02, 1.34837899e-01, -1.69999003e+00]])
>>> eval_ * (I # evec)
array([[ -1.43653725e-02, 4.14643550e-01, -2.42340866e+00],
[ -1.75615960e-03, -4.17347693e-01, -8.19546081e-01],
[ 1.90178603e-02, 1.34837899e-01, -1.69999003e+00]])
OP's example. IMPORTANT: must use np.arrays for I and C, np.matrix will not work.
>>> I=np.array([[2,0,0],[0,6,0],[0,0,5]])
>>> C=np.array([[4,7,0],[7,8,-4],[0,-4,1]])
>>>
>>> J = np.sqrt(np.einsum('ii->i', I))
>>> B = C / np.outer(J, J)
>>> eval_, evec = np.linalg.eigh(B)
>>> evec /= J[:, None]
>>>
>>> evec
array([[-0.35578356, -0.31094779, -0.52605088],
[ 0.27778714, 0.1343625 , -0.267297 ],
[ 0.23826117, -0.37371199, 0.05975754]])
>>> eval_
array([-0.73271478, 0.48762792, 3.7784202 ])
If I has positive and negative entries use eig instead of eigh and before taking the square root cast to complex dtype.
Differing from other answers, I assume that by the symbol I you mean the identity matrix, Ix=x.
What you want to solve, Cx=λIx, is the so-called standard eigenvalue problem,
and most eigenvalue solvers tackle the problem described in that format, hence the
Numpy function has the signature eig(C).
If your C matrix is a symmetric matrix and your problem is indeed a standard eigenvalue problem I'd recommend the use of numpy.linalg.eigh, that is optimized for this type of problems.
On the contrary if your problem is really a generalized eigenvalue problem, as, e.g., the frequency equation Kx=ω²Mx you could use scipy.linalg.eigh, that supports that type of problem statement for symmetric matrices.
eigvals, eigvecs = scipy.linalg.eigh(C, I)
With respect to the discrepancies in eigenvalues, the Numpy implementation gives no guarantees w/r to their ordering, so it could be just a different ordering, but if your problem is indeed a generalized problem (I not being the identity matrix...) the solution is of course different and you have to use the Scipy implementation of eigh.
If the discrepancies is within the eigenvectors, please remember that the eigenvectors are known within an arbitrary scale factor and, again, the ordering could be undefined (but, of course, their order is the same order in which you have the eigenvalues) — the situation is a little different for scipy.linalg.eigh because in this case the eigenvalues are sorted and the eigenvectors are normalized with respect to the second matrix argument (I in your example).
Ps: scipy.linalg.eigh behaviour (i.e., sorted eigenvalues and normalized eigenvectors) is so convenient for my use cases that I use to use it also to solve standard eigenvalue problems.
Using SymPy:
>>> from sympy import *
>>> t = Symbol('t')
>>> D = diag(2,6,5)
>>> S = Matrix([[ 4, 7, 0],
[ 7, 8,-4],
[ 0,-4, 1]])
>>> (t*D - S).det()
60*t**3 - 212*t**2 - 77*t + 81
Computing the exact roots:
>>> roots = solve(60*t**3 - 212*t**2 - 77*t + 81,t)
>>> roots
[53/45 + (-1/2 - sqrt(3)*I/2)*(312469/182250 + sqrt(797521629)*I/16200)**(1/3) + 14701/(8100*(-1/2 - sqrt(3)*I/2)*(312469/182250 + sqrt(797521629)*I/16200)**(1/3)), 53/45 + 14701/(8100*(-1/2 + sqrt(3)*I/2)*(312469/182250 + sqrt(797521629)*I/16200)**(1/3)) + (-1/2 + sqrt(3)*I/2)*(312469/182250 + sqrt(797521629)*I/16200)**(1/3), 53/45 + 14701/(8100*(312469/182250 + sqrt(797521629)*I/16200)**(1/3)) + (312469/182250 + sqrt(797521629)*I/16200)**(1/3)]
Computing floating-point approximations of the roots:
>>> for r in roots:
... r.evalf()
...
0.487627918145732 + 0.e-22*I
-0.73271478047926 - 0.e-22*I
3.77842019566686 - 0.e-21*I
Note that the roots are real.

(Python) Markov, Chebyshev, Chernoff upper bound functions

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

How to find every integer that is the closest to the antilogarithm (10base) for a series of n*0.1 (in Python)

In my algorithm I want to evaluate if the current integer n happens to be closest to the antilogarithm of any positive multiple of 0.1, so 0.1, 1.0, 1.1, 7.9, 21.5 etc.
Antilog?
AntiLog(x) = 10x
I found an online calculator that finds the antilog here: http://ncalculators.com/number-conversion/anti-log-logarithm-calculator.htm but nowhere I could find any examples of doing this in Python, or any other programming language.
If I can't use Python to find the antilog of a series of numbers I would have to resort to storing a list of antilog values in my program, for performance I'm might consider that anyways but nevertheless it would be great to figure out how to do this in code.
Update:
With the code from first answer I was able to do it, this code fully demonstrates all I was trying to do:
#!/usr/bin/python
import sys
import math
for x in xrange(1, 1000000):
target = round(math.log10(x),1)
int_antilog = int(10**target+0.5) #fast round() alternative
if (x == int_antilog):
print 'do something at call ' + str(x)
Python has a power operator that performs the exponentiation you want to do:
def antilog(x):
return 10 ** x
Examples:
>>> antilog(0.1)
1.2589254117941673
>>> antilog(3)
1000
>>> inputs = [0.1, 1.0, 1.1, 7.9, 21.5]
>>> outputs = [antilog(x) for x in inputs]
>>> print outputs
[1.2589254117941673, 10.0, 12.589254117941675, 79432823.47242822, 3.1622776601683794e+21]
Round and convert to integers in your favourite way, and you'll be good to go.
If k is the closest integer to 10 to a power that's a multiple of 0.1, then k ≈ 10ᵐʳ, where m is an integer and r=0.1, so ln k ≈ m r ln 10 and m ≈ ln k / (r ln 10) = log₁₀(k)/r. If u = log₁₀(k)/r, then the values of 10 to a power that's a multiple of 0.1 that are nearest to k are 10 to the power r times the floor of u or the ceiling of u, as expressed in the following code.
import math
def aloghilo(k):
u = 10*math.log10(k)
return (10**(math.floor(u)/10), 10**(math.ceil(u)/10))
def isantilog(k):
(lo,hi) = aloghilo(k)
return k==round(lo) or k==round(hi)
Here is an example of results, via the ipython interpreter:
In [13]: [aloghilo(k) for k in (20,30,40,50,60)]
Out[13]:
[(19.952623149688797, 25.118864315095795),
(25.118864315095795, 31.622776601683793),
(39.810717055349734, 50.11872336272722),
(39.810717055349734, 50.11872336272722),
(50.11872336272722, 63.09573444801933)]
In [14]: [isantilog(k) for k in (20,30,40,50,60)]
Out[14]: [True, False, True, True, False]

Categories