I am wondering if there is a way to have SymPy recognize that expressions such as Pow(positive, variable) will always be greater than zero (assuming real numbers).
from sympy import *
init_session()
StictLessThan(0, 1) # returns desired output
>>> False
StrictLessThan(0, x) # returns desired output
>>> 0 < x
StrictLessThan(0, 2**x) # returns undesired output, but not surprising
>>> 0 < 2**x
(2**x).is_comparable # From this I assume that I would have to define my own function
>>> False
some_function(0, 2**x) # does this exist built into the SymPy package?
>>> True
I am aware that I can make my own function to do this, but I am curious as to the built-in capabilities and limitations of SymPy.
def is_positive_exponential(exponential):
base, exponent = exponential.as_base_exp()
return True if base > 0 else False
Consider that when x = pi*I/log(2) (a complex number), the expression 2**x evaluates to -1 which is not positive.
If you tell SymPy that x is a real number, it will know that 2**x is positive.
x = Symbol('x', real=True)
StrictLessThan(0, 2**x) # returns True
See the list of possible assumptions. By default, Symbol('x') is assumed "commutative" but nothing else is assumed about it.
Related
Question
When evaluating arithmetic there are multiple steps (PEMDAS) taken during evaluation. I know you can evaluate an operation then round it, but at times you need to round your data to never exceed a certain precision throughout the evaluation. This brings me to my question: How can you round at every step during the evaluation instead of just at the end?
Examples
For our first example, we will be using the simple operation 0.125/0.375 and rounding to 2 decimals.
# This operation evaluates to 1/3
>>> 0.125/0.375
0.3333333333333333
# If we wanted to round it we could just do
>>> round(0.125/0.375, 2)
0.33
# But if we wanted to round at every step of PEMDAS the following would be necessary
>>> round(round(0.125, 2)/round(0.375, 2), 2)
0.32
# Same equation as above but written as (1/8)/(3/8)
>>> round(round(round(1, 2)/round(8, 2), 2)/round(round(3, 2)/round(8, 2), 2), 2)
0.32
As you can see you get a different result if rounding is performed at every step rather than just at the end.
Although being a bit cumbersome this approach does get the job done. Problems arise though when the equation is not hardcoded but rather received from the user:
# Rounding cannot be applied here in the same way that we did above
>>> eval(input("Arithmetic: "))
Arithmetic: (1/8)/(3/8)
0.3333333333333333
Use cases
This may seem pretty useless at first but can actually be very valuable for many things.
Here is a simple example where rounding at each step would be necessary for finding the holes of a function:
# undefined.py
from math import *
import numpy as np
function = input("Function in terms of x: ")
def is_undefined(x):
x = round(x, 2) # To deal with minor Python inaccuracies (ex: 1.000000000000001)
try:
eval(function)
return False
except ZeroDivisionError:
return True
undefined = [x for x in np.linspace(-5, 5, 1001) if is_undefined(float(x))]
print(undefined)
# Works perfectly!
>>> python undefined.py
Function in terms of x: (x**2)*(x-2)/(x-2)
[2.0]
# Unable to find the hole at x=pi
>>> python undefined.py
Function in terms of x: (x**2)*(2*x - 2*pi)/(x - pi)
[]
The decimal module provides a Decimal type which can be configured so that all arithmetic operations are rounded to a certain number of decimal places:
>>> import decimal as d
>>> d.setcontext(d.Context(prec=2))
>>> x = d.Decimal(0.125)
>>> y = d.Decimal(0.375)
>>> x / y
Decimal('0.33')
You can force rounding of the numbers before the division by using the unary + operation, which normally does nothing, but in this case it applies the precision from the current context, changing the result (to be more inaccurate, of course):
>>> (+x) / (+y)
Decimal('0.32')
So a solution for an expression from user input could be to replace all number literals and instances of the variable x with Decimal objects of the same values: here I've used a regular expression to do that, and to use a unary + to also force rounding before operations.
import decimal as d
import re
d.setcontext(d.Context(prec=2))
function = input("Function in terms of x: ")
function = re.sub(r'([0-9]+(\.[0-9]+)?|x)', r'(+d.Decimal(\1))', function)
# ...
Note there is no longer a need to write x = round(x, 2), because the expression itself forces x to be rounded.
You may be looking for symbolic math instead, such as Sympy, which can probably do what you're really looking for-
Specifically, not aliasing transcendental numbers (like pi and e) or waiting to reduce irreducible fractions into decimal space until asked to evaluate to a decimal
>>> from sympy import *
>>> expr = "(1/8)/(3/8)"
>>> simplify(expr) # precise value
1/3
>>> simplify(expr).evalf() # decimal aliasing
0.333333333333333
>>> N("(1/8)/(3/8)") # using sympy.N()
0.333333333333333
This can also be used to solve equations
>>> x = symbols("x", real=True)
>>> solve(x**2 - 1) # simple solution
[-1, 1]
>>> solve(x**2 - pi) # more complex solution
[-sqrt(pi), sqrt(pi)]
>>> [N(expr) for expr in solve(x**2 - pi)] # decimal approximation
[-1.77245385090552, 1.77245385090552]
This can also be used (perhaps evilly) with Python constructs
>>> [N(x * pi) for x in range(10)] # lots of approximations!
[0, 3.14159265358979, 6.28318530717959, 9.42477796076938, 12.5663706143592, 15.7079632679490, 18.8495559215388, 21.9911485751286, 25.1327412287183, 28.2743338823081]
I'm trying to solve the following equation.
(x * x) - 1 = 0
The result should be +1 or -1. But when I try to solve it via sympy, the result is an empty output.
import sympy as sy
x = sy.Symbol('x')
sy.solve((x**2)-1, 0)
# sy.solve((x * x)-1, 0) and sy.solve((x * x), 1) returns the same result
>>> []
What am I doing wrong here?
You should use,
sy.solve((x**2)-1,x)
Instead of,
sy.solve((x**2)-1,0)
The second argument x suggests that the equation should be solved for x. You are solving the equation for 0 which makes no sense.
Carefully read the documentation in the future :)
It is supposed to be
>>> from sympy.solvers import solve
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> solve(x**2 - 1, x)
Read the documentation for the function here
Either do
sp.solve((x**2)-1, x)
or
sp.solve((x**2) - 1)
For further information, you can check out https://docs.sympy.org/latest/modules/solvers/solvers.html
In nsolve the second argument is an initial guess for the value of the variable that will make the univariate expression equal to zero:
>>> nsolve(x**2-1, 0)
1.00000000000000
>>> nsolve(x**2-1, -3)
-1.00000000000000
In solve, however, an initial guess is not needed since the equation will be solved symbolically:
>>> nsolve(x**2-1)
[-1, 1]
But solve can also handle multivariate expressions and in that case the second argument is used to indicate which variable you want to solve for.
>>> solve(x**2-c)
[{c: x**2}]
>>> solve(x**2-c, x)
[-sqrt(c), sqrt(c)]
But you can solve for anything that appears in the expression, even numbers. That's why an error is not raised in your case (though perhaps zero should raise an error). Here are examples of solving for a number:
>>> solve(3*x**2-c, 3)
[c/x**2]
>>> solve(3*x**4-c, 4)
[log(c/3)/log(x)]
>>> solve(2*x**2-c, 2)
[LambertW(c*log(x))/log(x)]
Does anyone know why the below doesn't equal 0?
import numpy as np
np.sin(np.radians(180))
or:
np.sin(np.pi)
When I enter it into python it gives me 1.22e-16.
The number π cannot be represented exactly as a floating-point number. So, np.radians(180) doesn't give you π, it gives you 3.1415926535897931.
And sin(3.1415926535897931) is in fact something like 1.22e-16.
So, how do you deal with this?
You have to work out, or at least guess at, appropriate absolute and/or relative error bounds, and then instead of x == y, you write:
abs(y - x) < abs_bounds and abs(y-x) < rel_bounds * y
(This also means that you have to organize your computation so that the relative error is larger relative to y than to x. In your case, because y is the constant 0, that's trivial—just do it backward.)
Numpy provides a function that does this for you across a whole array, allclose:
np.allclose(x, y, rel_bounds, abs_bounds)
(This actually checks abs(y - x) < abs_ bounds + rel_bounds * y), but that's almost always sufficient, and you can easily reorganize your code when it's not.)
In your case:
np.allclose(0, np.sin(np.radians(180)), rel_bounds, abs_bounds)
So, how do you know what the right bounds are? There's no way to teach you enough error analysis in an SO answer. Propagation of uncertainty at Wikipedia gives a high-level overview. If you really have no clue, you can use the defaults, which are 1e-5 relative and 1e-8 absolute.
One solution is to switch to sympy when calculating sin's and cos's, then to switch back to numpy using sp.N(...) function:
>>> # Numpy not exactly zero
>>> import numpy as np
>>> value = np.cos(np.pi/2)
6.123233995736766e-17
# Sympy workaround
>>> import sympy as sp
>>> def scos(x): return sp.N(sp.cos(x))
>>> def ssin(x): return sp.N(sp.sin(x))
>>> value = scos(sp.pi/2)
0
just remember to use sp.pi instead of sp.np when using scos and ssin functions.
Faced same problem,
import numpy as np
print(np.cos(math.radians(90)))
>> 6.123233995736766e-17
and tried this,
print(np.around(np.cos(math.radians(90)), decimals=5))
>> 0
Worked in my case. I set decimal 5 not lose too many information. As you can think of round function get rid of after 5 digit values.
Try this... it zeros anything below a given tiny-ness value...
import numpy as np
def zero_tiny(x, threshold):
if (x.dtype == complex):
x_real = x.real
x_imag = x.imag
if (np.abs(x_real) < threshold): x_real = 0
if (np.abs(x_imag) < threshold): x_imag = 0
return x_real + 1j*x_imag
else:
return x if (np.abs(x) > threshold) else 0
value = np.cos(np.pi/2)
print(value)
value = zero_tiny(value, 10e-10)
print(value)
value = np.exp(-1j*np.pi/2)
print(value)
value = zero_tiny(value, 10e-10)
print(value)
Python uses the normal taylor expansion theory it solve its trig functions and since this expansion theory has infinite terms, its results doesn't reach exact but it only approximates.
For e.g
sin(x) = x - x³/3! + x⁵/5! - ...
=> Sin(180) = 180 - ... Never 0 bout approaches 0.
That is my own reason by prove.
Simple.
np.sin(np.pi).astype(int)
np.sin(np.pi/2).astype(int)
np.sin(3 * np.pi / 2).astype(int)
np.sin(2 * np.pi).astype(int)
returns
0
1
0
-1
Is there a python package for evaluating bounded first-order arithmetic formulas?
For example, it gets a bounded first-order arithmetic expression
>>> exp = 'forall x < z exists y < x ((2 * y + 1 = x) or (2 * y = x))'
and a value for the free variable z
>>> tau = [(z,20)]
and returns its value
>>> eval(exp, tau)
False
Maybe what you are looking for is something called "quantifier elimination". If so, take a look at QEPCAD. [1] It may be easier to create a Python interface for QEPCAD than to find a Python implementation.
[1] http://www.usna.edu/CS/~qepcad/B/QEPCAD.html
In Python 3, I am checking whether a given value is triangular, that is, it can be represented as n * (n + 1) / 2 for some positive integer n.
Can I just write:
import math
def is_triangular1(x):
num = (1 / 2) * (math.sqrt(8 * x + 1) - 1)
return int(num) == num
Or do I need to do check within a tolerance instead?
epsilon = 0.000000000001
def is_triangular2(x):
num = (1 / 2) * (math.sqrt(8 * x + 1) - 1)
return abs(int(num) - num) < epsilon
I checked that both of the functions return same results for x up to 1,000,000. But I am not sure if generally speaking int(x) == x will always correctly determine whether a number is integer, because of the cases when for example 5 is represented as 4.99999999999997 etc.
As far as I know, the second way is the correct one if I do it in C, but I am not sure about Python 3.
There is is_integer function in python float type:
>>> float(1.0).is_integer()
True
>>> float(1.001).is_integer()
False
>>>
Both your implementations have problems. It actually can happen that you end up with something like 4.999999999999997, so using int() is not an option.
I'd go for a completely different approach: First assume that your number is triangular, and compute what n would be in that case. In that first step, you can round generously, since it's only necessary to get the result right if the number actually is triangular. Next, compute n * (n + 1) / 2 for this n, and compare the result to x. Now, you are comparing two integers, so there are no inaccuracies left.
The computation of n can be simplified by expanding
(1/2) * (math.sqrt(8*x+1)-1) = math.sqrt(2 * x + 0.25) - 0.5
and utilizing that
round(y - 0.5) = int(y)
for positive y.
def is_triangular(x):
n = int(math.sqrt(2 * x))
return x == n * (n + 1) / 2
You'll want to do the latter. In Programming in Python 3 the following example is given as the most accurate way to compare
def equal_float(a, b):
#return abs(a - b) <= sys.float_info.epsilon
return abs(a - b) <= chosen_value #see edit below for more info
Also, since epsilon is the "smallest difference the machine can distinguish between two floating-point numbers", you'll want to use <= in your function.
Edit: After reading the comments below I have looked back at the book and it specifically says "Here is a simple function for comparing floats for equality to the limit of the machines accuracy". I believe this was just an example for comparing floats to extreme precision but the fact that error is introduced with many float calculations this should rarely if ever be used. I characterized it as the "most accurate" way to compare in my answer, which in some sense is true, but rarely what is intended when comparing floats or integers to floats. Choosing a value (ex: 0.00000000001) based on the "problem domain" of the function instead of using sys.float_info.epsilon is the correct approach.
Thanks to S.Lott and Sven Marnach for their corrections, and I apologize if I led anyone down the wrong path.
Python does have a Decimal class (in the decimal module), which you could use to avoid the imprecision of floats.
floats can exactly represent all integers in their range - floating-point equality is only tricky if you care about the bit after the point. So, as long as all of the calculations in your formula return whole numbers for the cases you're interested in, int(num) == num is perfectly safe.
So, we need to prove that for any triangular number, every piece of maths you do can be done with integer arithmetic (and anything coming out as a non-integer must imply that x is not triangular):
To start with, we can assume that x must be an integer - this is required in the definition of 'triangular number'.
This being the case, 8*x + 1 will also be an integer, since the integers are closed under + and * .
math.sqrt() returns float; but if x is triangular, then the square root will be a whole number - ie, again exactly represented.
So, for all x that should return true in your functions, int(num) == num will be true, and so your istriangular1 will always work. The only sticking point, as mentioned in the comments to the question, is that Python 2 by default does integer division in the same way as C - int/int => int, truncating if the result can't be represented exactly as an int. So, 1/2 == 0. This is fixed in Python 3, or by having the line
from __future__ import division
near the top of your code.
I think the module decimal is what you need
You can round your number to e.g. 14 decimal places or less:
>>> round(4.999999999999997, 14)
5.0
PS: double precision is about 15 decimal places
It is hard to argue with standards.
In C99 and POSIX, the standard for rounding a float to an int is defined by nearbyint() The important concept is the direction of rounding and the locale specific rounding convention.
Assuming the convention is common rounding, this is the same as the C99 convention in Python:
#!/usr/bin/python
import math
infinity = math.ldexp(1.0, 1023) * 2
def nearbyint(x):
"""returns the nearest int as the C99 standard would"""
# handle NaN
if x!=x:
return x
if x >= infinity:
return infinity
if x <= -infinity:
return -infinity
if x==0.0:
return x
return math.floor(x + 0.5)
If you want more control over rounding, consider using the Decimal module and choose the rounding convention you wish to employ. You may want to use Banker's Rounding for example.
Once you have decided on the convention, round to an int and compare to the other int.
Consider using NumPy, they take care of everything under the hood.
import numpy as np
result_bool = np.isclose(float1, float2)
Python has unlimited integer precision, but only 53 bits of float precision. When you square a number, you double the number of bits it requires. This means that the ULP of the original number is (approximately) twice the ULP of the square root.
You start running into issues with numbers around 50 bits or so, because the difference between the fractional representation of an irrational root and the nearest integer can be smaller than the ULP. Even in this case, checking if you are within tolerance will do more harm than good (by increasing the number of false positives).
For example:
>>> x = (1 << 26) - 1
>>> (math.sqrt(x**2)).is_integer()
True
>>> (math.sqrt(x**2 + 1)).is_integer()
False
>>> (math.sqrt(x**2 - 1)).is_integer()
False
>>> y = (1 << 27) - 1
>>> (math.sqrt(y**2)).is_integer()
True
>>> (math.sqrt(y**2 + 1)).is_integer()
True
>>> (math.sqrt(y**2 - 1)).is_integer()
True
>>> (math.sqrt(y**2 + 2)).is_integer()
False
>>> (math.sqrt(y**2 - 2)).is_integer()
True
>>> (math.sqrt(y**2 - 3)).is_integer()
False
You can therefore rework the formulation of your problem slightly. If an integer x is a triangular number, there exists an integer n such that x = n * (n + 1) // 2. The resulting quadratic is n**2 + n - 2 * x = 0. All you need to know is if the discriminant 1 + 8 * x is a perfect square. You can compute the integer square root of an integer using math.isqrt starting with python 3.8. Prior to that, you could use one of the algorithms from Wikipedia, implemented on SO here.
You can therefore stay entirely in python's infinite-precision integer domain with the following one-liner:
def is_triangular(x):
return math.isqrt(k := 8 * x + 1)**2 == k
Now you can do something like this:
>>> x = 58686775177009424410876674976531835606028390913650409380075
>>> math.isqrt(k := 8 * x + 1)**2 == k
True
>>> math.isqrt(k := 8 * (x + 1) + 1)**2 == k
False
>>> math.sqrt(k := 8 * x + 1)**2 == k
False
The first result is correct: x in this example is a triangular number computed with n = 342598234604352345342958762349.
Python still uses the same floating point representation and operations C does, so the second one is the correct way.
Under the hood, Python's float type is a C double.
The most robust way would be to get the nearest integer to num, then test if that integers satisfies the property you're after:
import math
def is_triangular1(x):
num = (1/2) * (math.sqrt(8*x+1)-1 )
inum = int(round(num))
return inum*(inum+1) == 2*x # This line uses only integer arithmetic